Add test case for MarshalText type

This commit is contained in:
Masaaki Goshima 2021-03-06 11:47:51 +09:00
parent 3c85aa1ba4
commit 6034aea48a
6 changed files with 4866 additions and 1041 deletions

View File

@ -281,7 +281,7 @@ func (t opType) fieldToStringTagField() opType {
"array", "map", "mapLoad", "slice", "struct", "MarshalJSON", "MarshalText", "recursive", "array", "map", "mapLoad", "slice", "struct", "MarshalJSON", "MarshalText", "recursive",
"intString", "uintString", "intString", "uintString",
"intPtr", "uintPtr", "float32Ptr", "float64Ptr", "boolPtr", "stringPtr", "bytesPtr", "intPtr", "uintPtr", "float32Ptr", "float64Ptr", "boolPtr", "stringPtr", "bytesPtr",
"arrayPtr", "slicePtr", "mapPtr", "marshalJSONPtr", "arrayPtr", "slicePtr", "mapPtr", "marshalJSONPtr", "marshalTextPtr",
"intNPtr", "uintNPtr", "float32NPtr", "float64NPtr", "boolNPtr", "stringNPtr", "bytesNPtr", "intNPtr", "uintNPtr", "float32NPtr", "float64NPtr", "boolNPtr", "stringNPtr", "bytesNPtr",
} }
primitiveTypesUpper := []string{} primitiveTypesUpper := []string{}

View File

@ -2,7 +2,6 @@ package json_test
import ( import (
"bytes" "bytes"
"fmt"
"testing" "testing"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@ -3528,7 +3527,6 @@ func TestCoverMarshalJSON(t *testing.T) {
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{false} { for _, indent := range []bool{false} {
for _, htmlEscape := range []bool{false} { for _, htmlEscape := range []bool{false} {
fmt.Println(test.name)
var buf bytes.Buffer var buf bytes.Buffer
enc := json.NewEncoder(&buf) enc := json.NewEncoder(&buf)
enc.SetEscapeHTML(htmlEscape) enc.SetEscapeHTML(htmlEscape)

3546
cover_marshal_text_test.go Normal file

File diff suppressed because it is too large Load Diff

View File

@ -61,9 +61,9 @@ func encodeCompileHead(ctx *encodeCompileContext) (*opcode, error) {
return encodeCompileMarshalJSON(ctx) return encodeCompileMarshalJSON(ctx)
} }
case typ.Implements(marshalTextType): case typ.Implements(marshalTextType):
return encodeCompileMarshalText(ctx) if typ.Kind() != reflect.Ptr || !typ.Elem().Implements(marshalTextType) {
case rtype_ptrTo(typ).Implements(marshalTextType): return encodeCompileMarshalText(ctx)
return encodeCompileMarshalTextPtr(ctx) }
} }
isPtr := false isPtr := false
orgType := typ orgType := typ
@ -164,7 +164,8 @@ func encodeOptimizeStructEnd(c *opcode) {
strings.Contains(prevOp, "Slice") || strings.Contains(prevOp, "Slice") ||
strings.Contains(prevOp, "Array") || strings.Contains(prevOp, "Array") ||
strings.Contains(prevOp, "Map") || strings.Contains(prevOp, "Map") ||
strings.Contains(prevOp, "MarshalJSON") { strings.Contains(prevOp, "MarshalJSON") ||
strings.Contains(prevOp, "MarshalText") {
// not exists field // not exists field
code = code.next code = code.next
break break
@ -189,8 +190,6 @@ func encodeImplementsMarshaler(typ *rtype) bool {
return true return true
case typ.Implements(marshalTextType): case typ.Implements(marshalTextType):
return true return true
case rtype_ptrTo(typ).Implements(marshalTextType):
return true
} }
return false return false
} }
@ -200,10 +199,8 @@ func encodeCompile(ctx *encodeCompileContext, isPtr bool) (*opcode, error) {
switch { switch {
case typ.Implements(marshalJSONType) && (typ.Kind() != reflect.Ptr || !typ.Elem().Implements(marshalJSONType)): case typ.Implements(marshalJSONType) && (typ.Kind() != reflect.Ptr || !typ.Elem().Implements(marshalJSONType)):
return encodeCompileMarshalJSON(ctx) return encodeCompileMarshalJSON(ctx)
case typ.Implements(marshalTextType): case typ.Implements(marshalTextType) && (typ.Kind() != reflect.Ptr || !typ.Elem().Implements(marshalTextType)):
return encodeCompileMarshalText(ctx) return encodeCompileMarshalText(ctx)
case rtype_ptrTo(typ).Implements(marshalTextType):
return encodeCompileMarshalTextPtr(ctx)
} }
switch typ.Kind() { switch typ.Kind() {
case reflect.Ptr: case reflect.Ptr:
@ -753,6 +750,9 @@ func encodeTypeToHeaderType(ctx *encodeCompileContext, code *opcode) opType {
return opStructFieldHeadMapPtr return opStructFieldHeadMapPtr
case opMarshalJSON: case opMarshalJSON:
return opStructFieldHeadMarshalJSONPtr return opStructFieldHeadMarshalJSONPtr
case opMarshalText:
return opStructFieldHeadMarshalTextPtr
} }
} }
case opInt: case opInt:
@ -844,6 +844,8 @@ func encodeTypeToFieldType(ctx *encodeCompileContext, code *opcode) opType {
return opStructFieldMapPtr return opStructFieldMapPtr
case opMarshalJSON: case opMarshalJSON:
return opStructFieldMarshalJSONPtr return opStructFieldMarshalJSONPtr
case opMarshalText:
return opStructFieldMarshalTextPtr
} }
} }
case opInt: case opInt:
@ -954,7 +956,10 @@ func encodeStructHeader(ctx *encodeCompileContext, fieldCode *opcode, valueCode
return valueCode.beforeLastCode() return valueCode.beforeLastCode()
case opStructFieldHeadMarshalJSONPtr, case opStructFieldHeadMarshalJSONPtr,
opStructFieldHeadOmitEmptyMarshalJSONPtr, opStructFieldHeadOmitEmptyMarshalJSONPtr,
opStructFieldHeadStringTagMarshalJSONPtr: opStructFieldHeadStringTagMarshalJSONPtr,
opStructFieldHeadMarshalTextPtr,
opStructFieldHeadOmitEmptyMarshalTextPtr,
opStructFieldHeadStringTagMarshalTextPtr:
ctx.decOpcodeIndex() ctx.decOpcodeIndex()
fieldCode.typ = fieldCode.typ.Elem() fieldCode.typ = fieldCode.typ.Elem()
return (*opcode)(unsafe.Pointer(fieldCode)) return (*opcode)(unsafe.Pointer(fieldCode))
@ -1250,6 +1255,15 @@ func encodeCompileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, error)
nilcheck = false nilcheck = false
indirect = false indirect = false
disableIndirectConversion = true disableIndirectConversion = true
} else if i == 0 && fieldNum == 1 && isPtr && fieldType.Kind() != reflect.Ptr && rtype_ptrTo(fieldType).Implements(marshalTextType) && !fieldType.Implements(marshalTextType) {
code, err := encodeCompileMarshalText(ctx.withType(rtype_ptrTo(fieldType)))
if err != nil {
return nil, err
}
valueCode = code
nilcheck = false
indirect = false
disableIndirectConversion = true
} else if isPtr && fieldType.Kind() != reflect.Ptr && !fieldType.Implements(marshalJSONType) && rtype_ptrTo(fieldType).Implements(marshalJSONType) { } else if isPtr && fieldType.Kind() != reflect.Ptr && !fieldType.Implements(marshalJSONType) && rtype_ptrTo(fieldType).Implements(marshalJSONType) {
code, err := encodeCompileMarshalJSON(ctx.withType(rtype_ptrTo(fieldType))) code, err := encodeCompileMarshalJSON(ctx.withType(rtype_ptrTo(fieldType)))
if err != nil { if err != nil {
@ -1257,18 +1271,37 @@ func encodeCompileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, error)
} }
nilcheck = false nilcheck = false
valueCode = code valueCode = code
} else if isPtr && fieldType.Kind() != reflect.Ptr && !fieldType.Implements(marshalTextType) && rtype_ptrTo(fieldType).Implements(marshalTextType) {
code, err := encodeCompileMarshalText(ctx.withType(rtype_ptrTo(fieldType)))
if err != nil {
return nil, err
}
nilcheck = false
valueCode = code
} else if fieldType.Implements(marshalJSONType) && fieldType.Kind() != reflect.Ptr { } else if fieldType.Implements(marshalJSONType) && fieldType.Kind() != reflect.Ptr {
code, err := encodeCompileMarshalJSON(ctx.withType(fieldType)) code, err := encodeCompileMarshalJSON(ctx.withType(fieldType))
if err != nil { if err != nil {
return nil, err return nil, err
} }
valueCode = code valueCode = code
} else if fieldType.Implements(marshalTextType) && fieldType.Kind() != reflect.Ptr {
code, err := encodeCompileMarshalText(ctx.withType(fieldType))
if err != nil {
return nil, err
}
valueCode = code
} else if fieldType.Implements(marshalJSONType) && fieldType.Kind() == reflect.Ptr && !fieldType.Elem().Implements(marshalJSONType) { } else if fieldType.Implements(marshalJSONType) && fieldType.Kind() == reflect.Ptr && !fieldType.Elem().Implements(marshalJSONType) {
code, err := encodeCompileMarshalJSON(ctx.withType(fieldType)) code, err := encodeCompileMarshalJSON(ctx.withType(fieldType))
if err != nil { if err != nil {
return nil, err return nil, err
} }
valueCode = code valueCode = code
} else if fieldType.Implements(marshalTextType) && fieldType.Kind() == reflect.Ptr && !fieldType.Elem().Implements(marshalTextType) {
code, err := encodeCompileMarshalText(ctx.withType(fieldType))
if err != nil {
return nil, err
}
valueCode = code
} else { } else {
code, err := encodeCompile(ctx.withType(fieldType), isPtr) code, err := encodeCompile(ctx.withType(fieldType), isPtr)
if err != nil { if err != nil {

File diff suppressed because it is too large Load Diff

View File

@ -3245,8 +3245,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
if code.nilcheck && p == 0 { if code.nilcheck && p == 0 {
b = encodeNull(b) b = encodeNull(b)
} else { } else {
iface := ptrToInterface(code, p) bb, err := encodeMarshalJSON(b, ptrToInterface(code, p))
bb, err := encodeMarshalJSON(b, iface)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -3284,8 +3283,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
if code.nilcheck && p == 0 { if code.nilcheck && p == 0 {
b = encodeNull(b) b = encodeNull(b)
} else { } else {
iface := ptrToInterface(code, p) bb, err := encodeMarshalJSON(b, ptrToInterface(code, p))
bb, err := encodeMarshalJSON(b, iface)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -3323,7 +3321,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
code = code.nextField code = code.nextField
} else { } else {
b = append(b, code.key...) b = append(b, code.key...)
bb, err := encodeMarshalJSON(b, ptrToInterface(code, p+code.offset)) bb, err := encodeMarshalJSON(b, ptrToInterface(code, p))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -3391,7 +3389,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
code = code.nextField code = code.nextField
} else { } else {
b = append(b, code.key...) b = append(b, code.key...)
bb, err := encodeMarshalJSON(b, ptrToInterface(code, p+code.offset)) bb, err := encodeMarshalJSON(b, ptrToInterface(code, p))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -3424,7 +3422,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
if p == 0 && code.nilcheck { if p == 0 && code.nilcheck {
b = encodeNull(b) b = encodeNull(b)
} else { } else {
bb, err := encodeMarshalJSON(b, ptrToInterface(code, p+code.offset)) bb, err := encodeMarshalJSON(b, ptrToInterface(code, p))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -3457,7 +3455,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
if p == 0 && code.nilcheck { if p == 0 && code.nilcheck {
b = encodeNull(b) b = encodeNull(b)
} else { } else {
bb, err := encodeMarshalJSON(b, ptrToInterface(code, p+code.offset)) bb, err := encodeMarshalJSON(b, ptrToInterface(code, p))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -3519,7 +3517,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
code = code.nextField code = code.nextField
} else { } else {
b = append(b, code.key...) b = append(b, code.key...)
bb, err := encodeMarshalJSON(b, ptrToInterface(code, p+code.offset)) bb, err := encodeMarshalJSON(b, ptrToInterface(code, p))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -3564,7 +3562,9 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
code = code.end.next code = code.end.next
break break
} }
store(ctxptr, code.idx, ptrToPtr(p)) if code.indirect {
store(ctxptr, code.idx, ptrToPtr(p))
}
fallthrough fallthrough
case opStructFieldHeadMarshalText: case opStructFieldHeadMarshalText:
p := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
@ -3576,14 +3576,99 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
} }
b = append(b, '{') b = append(b, '{')
b = append(b, code.key...) b = append(b, code.key...)
bb, err := encodeMarshalText(b, ptrToInterface(code, p+code.offset)) if code.typ.Kind() == reflect.Ptr {
if err != nil { if code.indirect || code.op == opStructFieldPtrHeadMarshalText {
return nil, err p = ptrToPtr(p + code.offset)
}
}
if code.nilcheck && p == 0 {
b = encodeNull(b)
} else {
bb, err := encodeMarshalText(b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
} }
b = bb
b = encodeComma(b) b = encodeComma(b)
code = code.next code = code.next
case opStructFieldPtrAnonymousHeadMarshalText: case opStructFieldPtrHeadStringTagMarshalText:
p := load(ctxptr, code.idx)
if p == 0 {
b = encodeNull(b)
b = encodeComma(b)
code = code.end.next
break
}
if code.indirect {
store(ctxptr, code.idx, ptrToPtr(p))
}
fallthrough
case opStructFieldHeadStringTagMarshalText:
p := load(ctxptr, code.idx)
if p == 0 && code.indirect {
b = encodeNull(b)
b = encodeComma(b)
code = code.end.next
break
}
b = append(b, '{')
b = append(b, code.key...)
if code.typ.Kind() == reflect.Ptr {
if code.indirect || code.op == opStructFieldPtrHeadStringTagMarshalText {
p = ptrToPtr(p + code.offset)
}
}
if code.nilcheck && p == 0 {
b = encodeNull(b)
} else {
bb, err := encodeMarshalText(b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = encodeComma(b)
code = code.next
case opStructFieldPtrHeadOmitEmptyMarshalText:
p := load(ctxptr, code.idx)
if p == 0 {
b = encodeNull(b)
b = encodeComma(b)
code = code.end.next
break
}
if code.indirect {
store(ctxptr, code.idx, ptrToPtr(p))
}
fallthrough
case opStructFieldHeadOmitEmptyMarshalText:
p := load(ctxptr, code.idx)
if p == 0 && code.indirect {
b = encodeNull(b)
b = encodeComma(b)
code = code.end.next
break
}
b = append(b, '{')
if code.typ.Kind() == reflect.Ptr {
if code.indirect || code.op == opStructFieldPtrHeadOmitEmptyMarshalText {
p = ptrToPtr(p + code.offset)
}
}
if p == 0 && code.nilcheck {
code = code.nextField
} else {
b = append(b, code.key...)
bb, err := encodeMarshalText(b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
b = encodeComma(b)
code = code.next
}
case opStructFieldPtrHeadMarshalTextPtr, opStructFieldPtrHeadStringTagMarshalTextPtr:
p := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if p == 0 { if p == 0 {
b = encodeNull(b) b = encodeNull(b)
@ -3593,6 +3678,74 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
} }
store(ctxptr, code.idx, ptrToPtr(p)) store(ctxptr, code.idx, ptrToPtr(p))
fallthrough fallthrough
case opStructFieldHeadMarshalTextPtr, opStructFieldHeadStringTagMarshalTextPtr:
p := load(ctxptr, code.idx)
if p == 0 && code.indirect {
b = encodeNull(b)
b = encodeComma(b)
code = code.end.next
break
}
b = append(b, '{')
b = append(b, code.key...)
if code.indirect {
p = ptrToPtr(p + code.offset)
}
if p == 0 {
b = encodeNull(b)
} else {
bb, err := encodeMarshalText(b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = encodeComma(b)
code = code.next
case opStructFieldPtrHeadOmitEmptyMarshalTextPtr:
p := load(ctxptr, code.idx)
if p == 0 {
b = encodeNull(b)
b = encodeComma(b)
code = code.end.next
break
}
store(ctxptr, code.idx, ptrToPtr(p))
fallthrough
case opStructFieldHeadOmitEmptyMarshalTextPtr:
p := load(ctxptr, code.idx)
if p == 0 && code.indirect {
b = encodeNull(b)
b = encodeComma(b)
code = code.end.next
break
}
if code.indirect {
p = ptrToPtr(p + code.offset)
}
b = append(b, '{')
if p == 0 {
code = code.nextField
} else {
b = append(b, code.key...)
bb, err := encodeMarshalText(b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
b = encodeComma(b)
code = code.next
}
case opStructFieldPtrAnonymousHeadMarshalText:
p := load(ctxptr, code.idx)
if p == 0 {
code = code.end.next
break
}
if code.indirect {
store(ctxptr, code.idx, ptrToPtr(p))
}
fallthrough
case opStructFieldAnonymousHeadMarshalText: case opStructFieldAnonymousHeadMarshalText:
p := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if p == 0 && code.indirect { if p == 0 && code.indirect {
@ -3600,127 +3753,143 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
break break
} }
b = append(b, code.key...) b = append(b, code.key...)
bb, err := encodeMarshalText(b, ptrToInterface(code, p+code.offset)) if code.typ.Kind() == reflect.Ptr {
if err != nil { if code.indirect || code.op == opStructFieldPtrAnonymousHeadMarshalText {
return nil, err p = ptrToPtr(p + code.offset)
}
}
if p == 0 && code.nilcheck {
b = encodeNull(b)
} else {
bb, err := encodeMarshalText(b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
} }
b = bb
b = encodeComma(b) b = encodeComma(b)
code = code.next code = code.next
case opStructFieldPtrHeadOmitEmptyMarshalText:
ptr := load(ctxptr, code.idx)
if ptr != 0 {
store(ctxptr, code.idx, ptrToPtr(ptr))
}
fallthrough
case opStructFieldHeadOmitEmptyMarshalText:
ptr := load(ctxptr, code.idx)
if ptr == 0 {
b = encodeNull(b)
b = encodeComma(b)
code = code.end.next
} else {
b = append(b, '{')
ptr += code.offset
p := ptrToUnsafePtr(ptr)
isPtr := code.typ.Kind() == reflect.Ptr
if p == nil || (!isPtr && *(*unsafe.Pointer)(p) == nil) {
code = code.nextField
} else {
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{typ: code.typ, ptr: p}))
bytes, err := v.(encoding.TextMarshaler).MarshalText()
if err != nil {
return nil, &MarshalerError{
Type: rtype2type(code.typ),
Err: err,
}
}
b = append(b, code.key...)
b = encodeNoEscapedString(b, *(*string)(unsafe.Pointer(&bytes)))
b = encodeComma(b)
code = code.next
}
}
case opStructFieldPtrAnonymousHeadOmitEmptyMarshalText:
ptr := load(ctxptr, code.idx)
if ptr != 0 {
store(ctxptr, code.idx, ptrToPtr(ptr))
}
fallthrough
case opStructFieldAnonymousHeadOmitEmptyMarshalText:
ptr := load(ctxptr, code.idx)
if ptr == 0 {
code = code.end.next
} else {
ptr += code.offset
p := ptrToUnsafePtr(ptr)
isPtr := code.typ.Kind() == reflect.Ptr
if p == nil || (!isPtr && *(*unsafe.Pointer)(p) == nil) {
code = code.nextField
} else {
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{typ: code.typ, ptr: p}))
bytes, err := v.(encoding.TextMarshaler).MarshalText()
if err != nil {
return nil, &MarshalerError{
Type: rtype2type(code.typ),
Err: err,
}
}
b = append(b, code.key...)
b = encodeNoEscapedString(b, *(*string)(unsafe.Pointer(&bytes)))
b = encodeComma(b)
code = code.next
}
}
case opStructFieldPtrHeadStringTagMarshalText:
ptr := load(ctxptr, code.idx)
if ptr != 0 {
store(ctxptr, code.idx, ptrToPtr(ptr))
}
fallthrough
case opStructFieldHeadStringTagMarshalText:
ptr := load(ctxptr, code.idx)
if ptr == 0 {
b = encodeNull(b)
b = encodeComma(b)
code = code.end.next
} else {
b = append(b, '{')
ptr += code.offset
p := ptrToUnsafePtr(ptr)
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{typ: code.typ, ptr: p}))
bytes, err := v.(encoding.TextMarshaler).MarshalText()
if err != nil {
return nil, &MarshalerError{
Type: rtype2type(code.typ),
Err: err,
}
}
b = append(b, code.key...)
b = encodeNoEscapedString(b, *(*string)(unsafe.Pointer(&bytes)))
b = encodeComma(b)
code = code.next
}
case opStructFieldPtrAnonymousHeadStringTagMarshalText: case opStructFieldPtrAnonymousHeadStringTagMarshalText:
ptr := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if ptr != 0 { if p == 0 {
store(ctxptr, code.idx, ptrToPtr(ptr)) code = code.end.next
break
}
if code.indirect {
store(ctxptr, code.idx, ptrToPtr(p))
} }
fallthrough fallthrough
case opStructFieldAnonymousHeadStringTagMarshalText: case opStructFieldAnonymousHeadStringTagMarshalText:
ptr := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if ptr == 0 { if p == 0 && code.indirect {
code = code.end.next code = code.end.next
} else { break
ptr += code.offset }
p := ptrToUnsafePtr(ptr) b = append(b, code.key...)
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{typ: code.typ, ptr: p})) if code.typ.Kind() == reflect.Ptr {
bytes, err := v.(encoding.TextMarshaler).MarshalText() if code.indirect || code.op == opStructFieldPtrAnonymousHeadStringTagMarshalText {
if err != nil { p = ptrToPtr(p + code.offset)
return nil, errMarshaler(code, err)
} }
}
if p == 0 && code.nilcheck {
b = encodeNull(b)
} else {
bb, err := encodeMarshalText(b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = encodeComma(b)
code = code.next
case opStructFieldPtrAnonymousHeadMarshalTextPtr, opStructFieldPtrAnonymousHeadStringTagMarshalTextPtr:
p := load(ctxptr, code.idx)
if p == 0 {
code = code.end.next
break
}
store(ctxptr, code.idx, ptrToPtr(p))
fallthrough
case opStructFieldAnonymousHeadMarshalTextPtr, opStructFieldAnonymousHeadStringTagMarshalTextPtr:
p := load(ctxptr, code.idx)
if p == 0 && code.indirect {
code = code.end.next
break
}
b = append(b, code.key...)
if code.indirect {
p = ptrToPtr(p + code.offset)
}
if p == 0 {
b = encodeNull(b)
} else {
bb, err := encodeMarshalText(b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = encodeComma(b)
code = code.next
case opStructFieldPtrAnonymousHeadOmitEmptyMarshalText:
p := load(ctxptr, code.idx)
if p == 0 {
code = code.end.next
break
}
if code.indirect {
store(ctxptr, code.idx, ptrToPtr(p))
}
fallthrough
case opStructFieldAnonymousHeadOmitEmptyMarshalText:
p := load(ctxptr, code.idx)
if p == 0 && code.indirect {
code = code.end.next
break
}
if code.typ.Kind() == reflect.Ptr {
if code.indirect || code.op == opStructFieldPtrAnonymousHeadOmitEmptyMarshalText {
p = ptrToPtr(p + code.offset)
}
}
if p == 0 && code.nilcheck {
code = code.nextField
} else {
b = append(b, code.key...) b = append(b, code.key...)
b = encodeNoEscapedString(b, *(*string)(unsafe.Pointer(&bytes))) bb, err := encodeMarshalText(b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
b = encodeComma(b)
code = code.next
}
case opStructFieldPtrAnonymousHeadOmitEmptyMarshalTextPtr:
p := load(ctxptr, code.idx)
if p == 0 {
code = code.end.next
break
}
store(ctxptr, code.idx, ptrToPtr(p))
fallthrough
case opStructFieldAnonymousHeadOmitEmptyMarshalTextPtr:
p := load(ctxptr, code.idx)
if p == 0 && code.indirect {
code = code.end.next
break
}
if code.indirect {
p = ptrToPtr(p + code.offset)
}
if p == 0 {
code = code.nextField
} else {
b = append(b, code.key...)
bb, err := encodeMarshalText(b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
b = encodeComma(b) b = encodeComma(b)
code = code.next code = code.next
} }
@ -4187,8 +4356,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
if p == 0 && code.nilcheck { if p == 0 && code.nilcheck {
b = encodeNull(b) b = encodeNull(b)
} else { } else {
v := ptrToInterface(code, p) bb, err := encodeMarshalJSON(b, ptrToInterface(code, p))
bb, err := encodeMarshalJSON(b, v)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -4240,42 +4408,66 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco
b = encodeComma(bb) b = encodeComma(bb)
} }
code = code.next code = code.next
case opStructFieldMarshalText: case opStructFieldMarshalText, opStructFieldStringTagMarshalText:
ptr := load(ctxptr, code.headIdx) p := load(ctxptr, code.headIdx)
b = append(b, code.key...) b = append(b, code.key...)
p := ptr + code.offset p += code.offset
v := ptrToInterface(code, p) if code.typ.Kind() == reflect.Ptr {
bytes, err := v.(encoding.TextMarshaler).MarshalText() p = ptrToPtr(p)
if err != nil {
return nil, errMarshaler(code, err)
} }
b = encodeNoEscapedString(b, *(*string)(unsafe.Pointer(&bytes))) if p == 0 && code.nilcheck {
b = encodeComma(b) b = encodeNull(b)
code = code.next } else {
case opStructFieldStringTagMarshalText: bb, err := encodeMarshalText(b, ptrToInterface(code, p))
ptr := load(ctxptr, code.headIdx) if err != nil {
p := ptr + code.offset return nil, err
v := ptrToInterface(code, p) }
bytes, err := v.(encoding.TextMarshaler).MarshalText() b = bb
if err != nil {
return nil, errMarshaler(code, err)
} }
b = append(b, code.key...)
b = encodeNoEscapedString(b, *(*string)(unsafe.Pointer(&bytes)))
b = encodeComma(b) b = encodeComma(b)
code = code.next code = code.next
case opStructFieldOmitEmptyMarshalText: case opStructFieldOmitEmptyMarshalText:
ptr := load(ctxptr, code.headIdx) p := load(ctxptr, code.headIdx)
p := ptr + code.offset p += code.offset
v := ptrToInterface(code, p) if code.typ.Kind() == reflect.Ptr {
if v != nil { p = ptrToPtr(p)
bytes, err := v.(encoding.TextMarshaler).MarshalText() }
if p == 0 && code.nilcheck {
code = code.nextField
break
}
b = append(b, code.key...)
bb, err := encodeMarshalText(b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = encodeComma(bb)
code = code.next
case opStructFieldMarshalTextPtr, opStructFieldStringTagMarshalTextPtr:
p := load(ctxptr, code.headIdx)
b = append(b, code.key...)
p = ptrToPtr(p + code.offset)
if p == 0 {
b = encodeNull(b)
} else {
bb, err := encodeMarshalText(b, ptrToInterface(code, p))
if err != nil { if err != nil {
return nil, errMarshaler(code, err) return nil, err
} }
b = bb
}
b = encodeComma(b)
code = code.next
case opStructFieldOmitEmptyMarshalTextPtr:
p := load(ctxptr, code.headIdx)
p = ptrToPtr(p + code.offset)
if p != 0 {
b = append(b, code.key...) b = append(b, code.key...)
b = encodeNoEscapedString(b, *(*string)(unsafe.Pointer(&bytes))) bb, err := encodeMarshalText(b, ptrToInterface(code, p))
b = encodeComma(b) if err != nil {
return nil, err
}
b = encodeComma(bb)
} }
code = code.next code = code.next
case opStructFieldArray, opStructFieldStringTagArray: case opStructFieldArray, opStructFieldStringTagArray: