Add only type

This commit is contained in:
Masaaki Goshima 2021-01-01 17:20:39 +09:00
parent 058b3ae1ea
commit 8411c9142c
3 changed files with 796 additions and 193 deletions

View File

@ -14,6 +14,27 @@ func int8ptr(v int8) *int8 {
return &v
}
func headIntPtrNilNotRoot() interface{} {
v := struct {
A struct {
A *int `json:"a"`
}
}{}
return v
}
func ptrHeadIntNotRoot() interface{} {
v := struct {
A *struct {
A int `json:"a"`
}
}{A: new(struct {
A int `json:"a"`
})}
v.A.A = 1
return v
}
func TestCoverage(t *testing.T) {
tests := []struct {
name string
@ -21,44 +42,78 @@ func TestCoverage(t *testing.T) {
data interface{}
}{
{
name: "IntHead",
name: "HeadIntZero",
expected: `{"a":0}`,
data: struct {
A int `json:"a"`
}{},
},
{
name: "HeadInt",
expected: `{"a":1}`,
data: struct {
A int `json:"a"`
}{A: 1},
},
{
name: "IntPtrHead",
name: "HeadIntPtr",
expected: `{"a":1}`,
data: struct {
A *int `json:"a"`
}{A: intptr(1)},
},
/*
{
name: "IntPtrNilHead",
expected: `{"a":null}`,
data: struct {
A *int `json:"a"`
}{A: nil},
},
*/
{
name: "PtrIntHead",
name: "HeadIntPtrNil",
expected: `{"a":null}`,
data: struct {
A *int `json:"a"`
}{A: nil},
},
{
name: "PtrHeadIntZero",
expected: `{"a":0}`,
data: &struct {
A int `json:"a"`
}{},
},
{
name: "PtrHeadInt",
expected: `{"a":1}`,
data: &struct {
A int `json:"a"`
}{A: 1},
},
{
name: "PtrIntPtrHead",
name: "PtrHeadIntPtr",
expected: `{"a":1}`,
data: &struct {
A *int `json:"a"`
}{A: intptr(1)},
},
{
name: "IntField",
name: "PtrHeadIntPtrNil",
expected: `{"a":null}`,
data: &struct {
A *int `json:"a"`
}{A: nil},
},
{
name: "PtrHeadIntNil",
expected: `null`,
data: (*struct {
A *int `json:"a"`
})(nil),
},
{
name: "HeadIntZeroMultiFields",
expected: `{"a":0,"b":0}`,
data: struct {
A int `json:"a"`
B int `json:"b"`
}{},
},
{
name: "HeadIntMultiFields",
expected: `{"a":1,"b":2}`,
data: struct {
A int `json:"a"`
@ -66,13 +121,232 @@ func TestCoverage(t *testing.T) {
}{A: 1, B: 2},
},
{
name: "IntPtrField",
name: "HeadIntPtrMultiFields",
expected: `{"a":1,"b":2}`,
data: struct {
A *int `json:"a"`
B *int `json:"b"`
}{A: intptr(1), B: intptr(2)},
},
{
name: "HeadIntPtrNilMultiFieldsd",
expected: `{"a":null,"b":null}`,
data: struct {
A *int `json:"a"`
B *int `json:"b"`
}{A: nil, B: nil},
},
{
name: "PtrHeadIntZeroMultiFields",
expected: `{"a":0,"b":0}`,
data: &struct {
A int `json:"a"`
B int `json:"b"`
}{},
},
{
name: "PtrHeadIntMultiFields",
expected: `{"a":1,"b":2}`,
data: &struct {
A int `json:"a"`
B int `json:"b"`
}{A: 1, B: 2},
},
{
name: "PtrHeadIntPtrMultiFields",
expected: `{"a":1,"b":2}`,
data: &struct {
A *int `json:"a"`
B *int `json:"b"`
}{A: intptr(1), B: intptr(2)},
},
{
name: "PtrHeadIntPtrNilMultiFields",
expected: `{"a":null,"b":null}`,
data: &struct {
A *int `json:"a"`
B *int `json:"b"`
}{A: nil, B: nil},
},
{
name: "PtrHeadIntNilMultiFields",
expected: `null`,
data: (*struct {
A *int `json:"a"`
B *int `json:"b"`
})(nil),
},
{
name: "HeadIntZeroNotRoot",
expected: `{"A":{"a":0}}`,
data: struct {
A struct {
A int `json:"a"`
}
}{},
},
{
name: "HeadIntNotRoot",
expected: `{"A":{"a":1}}`,
data: struct {
A struct {
A int `json:"a"`
}
}{A: struct {
A int `json:"a"`
}{A: 1}},
},
{
name: "HeadIntPtrNotRoot",
expected: `{"A":{"a":1}}`,
data: struct {
A struct {
A *int `json:"a"`
}
}{A: struct {
A *int `json:"a"`
}{intptr(1)}},
},
/*
{
name: "HeadIntPtrNilNotRoot",
expected: `{"A":{"a":null}}`,
data: struct {
A struct {
A *int `json:"a"`
}
}{},
},
{
name: "PtrHeadIntZeroNotRoot",
expected: `{"A":{"a":0}}`,
data: struct {
A *struct {
A int `json:"a"`
}
}{A: new(struct {
A int `json:"a"`
})},
},
{
name: "PtrHeadIntNotRoot",
expected: `{"A":{"a":1}}`,
data: struct {
A *struct {
A int `json:"a"`
}
}{A: &(struct {
A int `json:"a"`
}{A: 1})},
},
{
name: "PtrHeadIntPtrNotRoot",
expected: `{"A":{"a":1}}`,
data: struct {
A *struct {
A *int `json:"a"`
}
}{A: &(struct {
A *int `json:"a"`
}{A: intptr(1)})},
},
{
name: "PtrHeadIntPtrNilNotRoot",
expected: `{"A":{"a":null}}`,
data: struct {
A *struct {
A *int `json:"a"`
}
}{A: &(struct {
A *int `json:"a"`
}{A: nil})},
},
*/
/*
{
name: "PtrHeadIntNilNotRoot",
expected: `{"A":null}`,
data: struct {
A *struct {
A *int `json:"a"`
}
}{A: nil},
},
*/
{
name: "HeadIntZeroMultiFields",
expected: `{"a":0,"b":0}`,
data: struct {
A int `json:"a"`
B int `json:"b"`
}{},
},
{
name: "HeadIntMultiFields",
expected: `{"a":1,"b":2}`,
data: struct {
A int `json:"a"`
B int `json:"b"`
}{A: 1, B: 2},
},
{
name: "HeadIntPtrMultiFields",
expected: `{"a":1,"b":2}`,
data: struct {
A *int `json:"a"`
B *int `json:"b"`
}{A: intptr(1), B: intptr(2)},
},
{
name: "HeadIntPtrNilMultiFieldsd",
expected: `{"a":null,"b":null}`,
data: struct {
A *int `json:"a"`
B *int `json:"b"`
}{A: nil, B: nil},
},
{
name: "PtrHeadIntZeroMultiFields",
expected: `{"a":0,"b":0}`,
data: &struct {
A int `json:"a"`
B int `json:"b"`
}{},
},
{
name: "PtrHeadIntMultiFields",
expected: `{"a":1,"b":2}`,
data: &struct {
A int `json:"a"`
B int `json:"b"`
}{A: 1, B: 2},
},
{
name: "PtrHeadIntPtrMultiFields",
expected: `{"a":1,"b":2}`,
data: &struct {
A *int `json:"a"`
B *int `json:"b"`
}{A: intptr(1), B: intptr(2)},
},
{
name: "PtrHeadIntPtrNilMultiFields",
expected: `{"a":null,"b":null}`,
data: &struct {
A *int `json:"a"`
B *int `json:"b"`
}{A: nil, B: nil},
},
{
name: "PtrHeadIntNilMultiFields",
expected: `null`,
data: (*struct {
A *int `json:"a"`
B *int `json:"b"`
})(nil),
},
{
name: "Int8Head",
expected: `{"a":1}`,
@ -133,10 +407,10 @@ func TestCoverage(t *testing.T) {
enc := NewEncoder(&buf)
enc.SetEscapeHTML(htmlEscape)
if err := enc.Encode(test.data); err != nil {
t.Fatalf("%s(htmlEscape:%T): %s: %s", test.name, htmlEscape, test.expected, err)
t.Errorf("%s(htmlEscape:%T): %s: %s", test.name, htmlEscape, test.expected, err)
}
if strings.TrimRight(buf.String(), "\n") != test.expected {
t.Fatalf("%s(htmlEscape:%T): expected %q but got %q", test.name, htmlEscape, test.expected, buf.String())
t.Errorf("%s(htmlEscape:%T): expected %q but got %q", test.name, htmlEscape, test.expected, buf.String())
}
}
}

View File

@ -536,126 +536,251 @@ func (e *Encoder) compileMap(ctx *encodeCompileContext, withLoad bool) (*opcode,
return (*opcode)(unsafe.Pointer(header)), nil
}
func (e *Encoder) typeToHeaderType(ctx *encodeCompileContext, code *opcode) opType {
switch code.op {
case opPtr:
ptrNum := 1
c := code
ctx.decIndex()
for {
if code.next.op == opPtr {
ptrNum++
code = code.next
ctx.decIndex()
func (e *Encoder) typeToHeaderType(ctx *encodeCompileContext, code *opcode, isOnlyPtrField bool) opType {
if isOnlyPtrField {
// 1. pointer struct + primitive type field
// 2. struct + primitive pointer type field
switch code.op {
case opPtr:
ptrNum := 1
c := code
ctx.decIndex()
for {
if code.next.op == opPtr {
ptrNum++
code = code.next
ctx.decIndex()
}
break
}
break
c.ptrNum = ptrNum
if ptrNum > 1 {
switch code.next.op {
case opInt:
return opStructFieldHeadIntNPtrOnly
case opInt8:
return opStructFieldHeadInt8NPtrOnly
case opInt16:
return opStructFieldHeadInt16NPtrOnly
case opInt32:
return opStructFieldHeadInt32NPtrOnly
case opInt64:
return opStructFieldHeadInt64NPtrOnly
case opUint:
return opStructFieldHeadUintNPtrOnly
case opUint8:
return opStructFieldHeadUint8NPtrOnly
case opUint16:
return opStructFieldHeadUint16NPtrOnly
case opUint32:
return opStructFieldHeadUint32NPtrOnly
case opUint64:
return opStructFieldHeadUint64NPtrOnly
case opFloat32:
return opStructFieldHeadFloat32NPtrOnly
case opFloat64:
return opStructFieldHeadFloat64NPtrOnly
case opString:
return opStructFieldHeadStringNPtrOnly
case opBool:
return opStructFieldHeadBoolNPtrOnly
}
} else {
switch code.next.op {
case opInt:
return opStructFieldHeadIntPtrOnly
case opInt8:
return opStructFieldHeadInt8PtrOnly
case opInt16:
return opStructFieldHeadInt16PtrOnly
case opInt32:
return opStructFieldHeadInt32PtrOnly
case opInt64:
return opStructFieldHeadInt64PtrOnly
case opUint:
return opStructFieldHeadUintPtrOnly
case opUint8:
return opStructFieldHeadUint8PtrOnly
case opUint16:
return opStructFieldHeadUint16PtrOnly
case opUint32:
return opStructFieldHeadUint32PtrOnly
case opUint64:
return opStructFieldHeadUint64PtrOnly
case opFloat32:
return opStructFieldHeadFloat32PtrOnly
case opFloat64:
return opStructFieldHeadFloat64PtrOnly
case opString:
return opStructFieldHeadStringPtrOnly
case opBool:
return opStructFieldHeadBoolPtrOnly
}
}
case opInt:
return opStructFieldHeadIntOnly
case opInt8:
return opStructFieldHeadInt8Only
case opInt16:
return opStructFieldHeadInt16Only
case opInt32:
return opStructFieldHeadInt32Only
case opInt64:
return opStructFieldHeadInt64Only
case opUint:
return opStructFieldHeadUintOnly
case opUint8:
return opStructFieldHeadUint8Only
case opUint16:
return opStructFieldHeadUint16Only
case opUint32:
return opStructFieldHeadUint32Only
case opUint64:
return opStructFieldHeadUint64Only
case opFloat32:
return opStructFieldHeadFloat32Only
case opFloat64:
return opStructFieldHeadFloat64Only
case opString:
return opStructFieldHeadStringOnly
case opBool:
return opStructFieldHeadBoolOnly
case opMapHead:
return opStructFieldHeadMap
case opMapHeadLoad:
return opStructFieldHeadMapLoad
case opArrayHead:
return opStructFieldHeadArray
case opSliceHead:
return opStructFieldHeadSlice
case opStructFieldHead:
return opStructFieldHeadStruct
case opMarshalJSON:
return opStructFieldHeadMarshalJSON
case opMarshalText:
return opStructFieldHeadMarshalText
}
c.ptrNum = ptrNum
if ptrNum > 1 {
switch code.next.op {
case opInt:
return opStructFieldHeadIntNPtr
case opInt8:
return opStructFieldHeadInt8NPtr
case opInt16:
return opStructFieldHeadInt16NPtr
case opInt32:
return opStructFieldHeadInt32NPtr
case opInt64:
return opStructFieldHeadInt64NPtr
case opUint:
return opStructFieldHeadUintNPtr
case opUint8:
return opStructFieldHeadUint8NPtr
case opUint16:
return opStructFieldHeadUint16NPtr
case opUint32:
return opStructFieldHeadUint32NPtr
case opUint64:
return opStructFieldHeadUint64NPtr
case opFloat32:
return opStructFieldHeadFloat32NPtr
case opFloat64:
return opStructFieldHeadFloat64NPtr
case opString:
return opStructFieldHeadStringNPtr
case opBool:
return opStructFieldHeadBoolNPtr
} else {
switch code.op {
case opPtr:
ptrNum := 1
c := code
ctx.decIndex()
for {
if code.next.op == opPtr {
ptrNum++
code = code.next
ctx.decIndex()
}
break
}
} else {
switch code.next.op {
case opInt:
return opStructFieldHeadIntPtr
case opInt8:
return opStructFieldHeadInt8Ptr
case opInt16:
return opStructFieldHeadInt16Ptr
case opInt32:
return opStructFieldHeadInt32Ptr
case opInt64:
return opStructFieldHeadInt64Ptr
case opUint:
return opStructFieldHeadUintPtr
case opUint8:
return opStructFieldHeadUint8Ptr
case opUint16:
return opStructFieldHeadUint16Ptr
case opUint32:
return opStructFieldHeadUint32Ptr
case opUint64:
return opStructFieldHeadUint64Ptr
case opFloat32:
return opStructFieldHeadFloat32Ptr
case opFloat64:
return opStructFieldHeadFloat64Ptr
case opString:
return opStructFieldHeadStringPtr
case opBool:
return opStructFieldHeadBoolPtr
c.ptrNum = ptrNum
if ptrNum > 1 {
switch code.next.op {
case opInt:
return opStructFieldHeadIntNPtr
case opInt8:
return opStructFieldHeadInt8NPtr
case opInt16:
return opStructFieldHeadInt16NPtr
case opInt32:
return opStructFieldHeadInt32NPtr
case opInt64:
return opStructFieldHeadInt64NPtr
case opUint:
return opStructFieldHeadUintNPtr
case opUint8:
return opStructFieldHeadUint8NPtr
case opUint16:
return opStructFieldHeadUint16NPtr
case opUint32:
return opStructFieldHeadUint32NPtr
case opUint64:
return opStructFieldHeadUint64NPtr
case opFloat32:
return opStructFieldHeadFloat32NPtr
case opFloat64:
return opStructFieldHeadFloat64NPtr
case opString:
return opStructFieldHeadStringNPtr
case opBool:
return opStructFieldHeadBoolNPtr
}
} else {
switch code.next.op {
case opInt:
return opStructFieldHeadIntPtr
case opInt8:
return opStructFieldHeadInt8Ptr
case opInt16:
return opStructFieldHeadInt16Ptr
case opInt32:
return opStructFieldHeadInt32Ptr
case opInt64:
return opStructFieldHeadInt64Ptr
case opUint:
return opStructFieldHeadUintPtr
case opUint8:
return opStructFieldHeadUint8Ptr
case opUint16:
return opStructFieldHeadUint16Ptr
case opUint32:
return opStructFieldHeadUint32Ptr
case opUint64:
return opStructFieldHeadUint64Ptr
case opFloat32:
return opStructFieldHeadFloat32Ptr
case opFloat64:
return opStructFieldHeadFloat64Ptr
case opString:
return opStructFieldHeadStringPtr
case opBool:
return opStructFieldHeadBoolPtr
}
}
case opInt:
return opStructFieldHeadInt
case opInt8:
return opStructFieldHeadInt8
case opInt16:
return opStructFieldHeadInt16
case opInt32:
return opStructFieldHeadInt32
case opInt64:
return opStructFieldHeadInt64
case opUint:
return opStructFieldHeadUint
case opUint8:
return opStructFieldHeadUint8
case opUint16:
return opStructFieldHeadUint16
case opUint32:
return opStructFieldHeadUint32
case opUint64:
return opStructFieldHeadUint64
case opFloat32:
return opStructFieldHeadFloat32
case opFloat64:
return opStructFieldHeadFloat64
case opString:
return opStructFieldHeadString
case opBool:
return opStructFieldHeadBool
case opMapHead:
return opStructFieldHeadMap
case opMapHeadLoad:
return opStructFieldHeadMapLoad
case opArrayHead:
return opStructFieldHeadArray
case opSliceHead:
return opStructFieldHeadSlice
case opStructFieldHead:
return opStructFieldHeadStruct
case opMarshalJSON:
return opStructFieldHeadMarshalJSON
case opMarshalText:
return opStructFieldHeadMarshalText
}
case opInt:
return opStructFieldHeadInt
case opInt8:
return opStructFieldHeadInt8
case opInt16:
return opStructFieldHeadInt16
case opInt32:
return opStructFieldHeadInt32
case opInt64:
return opStructFieldHeadInt64
case opUint:
return opStructFieldHeadUint
case opUint8:
return opStructFieldHeadUint8
case opUint16:
return opStructFieldHeadUint16
case opUint32:
return opStructFieldHeadUint32
case opUint64:
return opStructFieldHeadUint64
case opFloat32:
return opStructFieldHeadFloat32
case opFloat64:
return opStructFieldHeadFloat64
case opString:
return opStructFieldHeadString
case opBool:
return opStructFieldHeadBool
case opMapHead:
return opStructFieldHeadMap
case opMapHeadLoad:
return opStructFieldHeadMapLoad
case opArrayHead:
return opStructFieldHeadArray
case opSliceHead:
return opStructFieldHeadSlice
case opStructFieldHead:
return opStructFieldHeadStruct
case opMarshalJSON:
return opStructFieldHeadMarshalJSON
case opMarshalText:
return opStructFieldHeadMarshalText
}
return opStructFieldHead
}
@ -784,8 +909,8 @@ func (e *Encoder) typeToFieldType(ctx *encodeCompileContext, code *opcode) opTyp
return opStructField
}
func (e *Encoder) optimizeStructHeader(ctx *encodeCompileContext, code *opcode, tag *structTag) opType {
headType := e.typeToHeaderType(ctx, code)
func (e *Encoder) optimizeStructHeader(ctx *encodeCompileContext, code *opcode, tag *structTag, isOnlyPtrField bool) opType {
headType := e.typeToHeaderType(ctx, code, isOnlyPtrField)
switch {
case tag.isOmitEmpty:
headType = headType.headToOmitEmptyHead()
@ -821,9 +946,9 @@ func (e *Encoder) compiledCode(ctx *encodeCompileContext) *opcode {
return nil
}
func (e *Encoder) structHeader(ctx *encodeCompileContext, fieldCode *opcode, valueCode *opcode, tag *structTag) *opcode {
func (e *Encoder) structHeader(ctx *encodeCompileContext, fieldCode *opcode, valueCode *opcode, tag *structTag, isOnlyPtrField bool) *opcode {
fieldCode.indent--
op := e.optimizeStructHeader(ctx, valueCode, tag)
op := e.optimizeStructHeader(ctx, valueCode, tag, isOnlyPtrField)
fieldCode.op = op
fieldCode.ptrNum = valueCode.ptrNum
switch op {
@ -1103,17 +1228,10 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode,
}
}
if fieldNum == 1 && valueCode.op == opPtr && !isPtr {
// if field number is one and primitive pointer type,
// it should encode as **not** pointer .
switch valueCode.next.op {
case opInt, opInt8, opInt16, opInt32, opInt64,
opUint, opUint8, opUint16, opUint32, opUint64,
opFloat32, opFloat64, opBool, opString, opBytes:
valueCode = valueCode.next
ctx.decOpcodeIndex()
}
}
// if field number is one and primitive pointer type,
// it should encode as special opcode.
isOnlyPtrField := fieldNum == 1 && (valueCode.op == opPtr && !isPtr || valueCode.op != opPtr && isPtr)
key := fmt.Sprintf(`"%s":`, tag.key)
escapedKey := fmt.Sprintf(`%s:`, string(encodeEscapedString([]byte{}, tag.key)))
fieldCode := &opcode{
@ -1131,7 +1249,7 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode,
}
if fieldIdx == 0 {
fieldCode.headIdx = fieldCode.idx
code = e.structHeader(ctx, fieldCode, valueCode, tag)
code = e.structHeader(ctx, fieldCode, valueCode, tag, isOnlyPtrField)
head = fieldCode
prevField = fieldCode
} else {

View File

@ -1236,6 +1236,22 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
code = code.next
store(ctxptr, code.idx, ptr)
}
case opStructFieldPtrHeadIntOnly:
p := load(ctxptr, code.idx)
if p == 0 {
b = encodeNull(b)
b = encodeComma(b)
code = code.end.next
break
}
fallthrough
case opStructFieldHeadIntOnly:
p := load(ctxptr, code.idx)
b = append(b, '{')
b = append(b, code.key...)
b = appendInt(b, int64(e.ptrToInt(p)))
b = encodeComma(b)
code = code.next
case opStructFieldPtrHeadInt:
p := load(ctxptr, code.idx)
if p == 0 {
@ -1247,22 +1263,28 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
store(ctxptr, code.idx, e.ptrToPtr(p))
fallthrough
case opStructFieldHeadInt:
ptr := load(ctxptr, code.idx)
if ptr == 0 {
if code.op == opStructFieldPtrHeadInt {
b = encodeNull(b)
b = encodeComma(b)
} else {
b = append(b, '{', '}', ',')
}
code = code.end.next
} else {
b = append(b, '{')
b = append(b, code.key...)
b = appendInt(b, int64(e.ptrToInt(ptr+code.offset)))
p := load(ctxptr, code.idx)
b = append(b, '{')
b = append(b, code.key...)
b = appendInt(b, int64(e.ptrToInt(p+code.offset)))
b = encodeComma(b)
code = code.next
case opStructEscapedFieldPtrHeadIntOnly:
p := load(ctxptr, code.idx)
if p == 0 {
b = encodeNull(b)
b = encodeComma(b)
code = code.next
code = code.end.next
break
}
fallthrough
case opStructEscapedFieldHeadIntOnly:
p := load(ctxptr, code.idx)
b = append(b, '{')
b = append(b, code.escapedKey...)
b = appendInt(b, int64(e.ptrToInt(p)))
b = encodeComma(b)
code = code.next
case opStructEscapedFieldPtrHeadInt:
p := load(ctxptr, code.idx)
if p == 0 {
@ -1274,22 +1296,33 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
store(ctxptr, code.idx, e.ptrToPtr(p))
fallthrough
case opStructEscapedFieldHeadInt:
ptr := load(ctxptr, code.idx)
if ptr == 0 {
if code.op == opStructEscapedFieldPtrHeadInt {
b = encodeNull(b)
b = encodeComma(b)
} else {
b = append(b, '{', '}', ',')
}
code = code.end.next
} else {
b = append(b, '{')
b = append(b, code.escapedKey...)
b = appendInt(b, int64(e.ptrToInt(ptr+code.offset)))
p := load(ctxptr, code.idx)
b = append(b, '{')
b = append(b, code.escapedKey...)
b = appendInt(b, int64(e.ptrToInt(p+code.offset)))
b = encodeComma(b)
code = code.next
case opStructFieldPtrHeadIntPtrOnly:
p := load(ctxptr, code.idx)
if p == 0 {
b = encodeNull(b)
b = encodeComma(b)
code = code.next
code = code.end.next
break
}
store(ctxptr, code.idx, e.ptrToPtr(p))
fallthrough
case opStructFieldHeadIntPtrOnly:
p := load(ctxptr, code.idx)
b = append(b, '{')
b = append(b, code.key...)
if p == 0 {
b = encodeNull(b)
} else {
b = appendInt(b, int64(e.ptrToInt(p+code.offset)))
}
b = encodeComma(b)
code = code.next
case opStructFieldPtrHeadIntPtr:
p := load(ctxptr, code.idx)
if p == 0 {
@ -1304,16 +1337,38 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
p := load(ctxptr, code.idx)
if p == 0 {
b = encodeNull(b)
b = encodeComma(b)
code = code.end.next
break
}
b = append(b, '{')
b = append(b, code.key...)
p = e.ptrToPtr(p)
if p == 0 {
b = encodeNull(b)
} else {
b = append(b, '{')
b = append(b, code.key...)
p = e.ptrToPtr(p)
if p == 0 {
b = encodeNull(b)
} else {
b = appendInt(b, int64(e.ptrToInt(p+code.offset)))
}
b = appendInt(b, int64(e.ptrToInt(p+code.offset)))
}
b = encodeComma(b)
code = code.next
case opStructEscapedFieldPtrHeadIntPtrOnly:
p := load(ctxptr, code.idx)
if p == 0 {
b = encodeNull(b)
b = encodeComma(b)
code = code.end.next
break
}
store(ctxptr, code.idx, e.ptrToPtr(p))
fallthrough
case opStructEscapedFieldHeadIntPtrOnly:
p := load(ctxptr, code.idx)
b = append(b, '{')
b = append(b, code.escapedKey...)
if p == 0 {
b = encodeNull(b)
} else {
b = appendInt(b, int64(e.ptrToInt(p+code.offset)))
}
b = encodeComma(b)
code = code.next
@ -1331,19 +1386,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
p := load(ctxptr, code.idx)
if p == 0 {
b = encodeNull(b)
b = encodeComma(b)
code = code.end.next
break
}
b = append(b, '{')
b = append(b, code.escapedKey...)
p = e.ptrToPtr(p)
if p == 0 {
b = encodeNull(b)
} else {
b = append(b, '{')
b = append(b, code.escapedKey...)
p = e.ptrToPtr(p)
if p == 0 {
b = encodeNull(b)
} else {
b = appendInt(b, int64(e.ptrToInt(p+code.offset)))
}
code = code.next
b = appendInt(b, int64(e.ptrToInt(p+code.offset)))
}
b = encodeComma(b)
code = code.next
case opStructFieldHeadIntNPtr:
p := load(ctxptr, code.idx)
if p == 0 {
@ -1413,6 +1469,22 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = encodeComma(b)
code = code.next
}
case opStructFieldPtrHeadInt8Only:
p := load(ctxptr, code.idx)
if p == 0 {
b = encodeNull(b)
b = encodeComma(b)
code = code.end.next
break
}
fallthrough
case opStructFieldHeadInt8Only:
p := load(ctxptr, code.idx)
b = append(b, '{')
b = append(b, code.key...)
b = appendInt(b, int64(e.ptrToInt8(p)))
b = encodeComma(b)
code = code.next
case opStructFieldPtrHeadInt8:
p := load(ctxptr, code.idx)
if p == 0 {
@ -1440,6 +1512,22 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = encodeComma(b)
code = code.next
}
case opStructEscapedFieldPtrHeadInt8Only:
p := load(ctxptr, code.idx)
if p == 0 {
b = encodeNull(b)
b = encodeComma(b)
code = code.end.next
break
}
fallthrough
case opStructEscapedFieldHeadInt8Only:
p := load(ctxptr, code.idx)
b = append(b, '{')
b = append(b, code.escapedKey...)
b = appendInt(b, int64(e.ptrToInt8(p)))
b = encodeComma(b)
code = code.next
case opStructEscapedFieldPtrHeadInt8:
p := load(ctxptr, code.idx)
if p == 0 {
@ -1467,6 +1555,27 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = encodeComma(b)
code = code.next
}
case opStructFieldPtrHeadInt8PtrOnly:
p := load(ctxptr, code.idx)
if p == 0 {
b = encodeNull(b)
b = encodeComma(b)
code = code.end.next
break
}
store(ctxptr, code.idx, e.ptrToPtr(p))
fallthrough
case opStructFieldHeadInt8PtrOnly:
p := load(ctxptr, code.idx)
b = append(b, '{')
b = append(b, code.key...)
if p == 0 {
b = encodeNull(b)
} else {
b = appendInt(b, int64(e.ptrToInt8(p)))
}
b = encodeComma(b)
code = code.next
case opStructFieldPtrHeadInt8Ptr:
p := load(ctxptr, code.idx)
if p == 0 {
@ -1494,6 +1603,27 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
code = code.next
}
b = encodeComma(b)
case opStructEscapedFieldPtrHeadInt8PtrOnly:
p := load(ctxptr, code.idx)
if p == 0 {
b = encodeNull(b)
b = encodeComma(b)
code = code.end.next
break
}
store(ctxptr, code.idx, e.ptrToPtr(p))
fallthrough
case opStructEscapedFieldHeadInt8PtrOnly:
p := load(ctxptr, code.idx)
b = append(b, '{')
b = append(b, code.escapedKey...)
if p == 0 {
b = encodeNull(b)
} else {
b = appendInt(b, int64(e.ptrToInt8(p)))
}
b = encodeComma(b)
code = code.next
case opStructEscapedFieldPtrHeadInt8Ptr:
p := load(ctxptr, code.idx)
if p == 0 {
@ -2390,6 +2520,22 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = encodeComma(b)
code = code.next
}
case opStructEscapedFieldPtrHeadEscapedStringOnly:
p := load(ctxptr, code.idx)
if p == 0 {
b = encodeNull(b)
b = encodeComma(b)
code = code.end.next
break
}
fallthrough
case opStructEscapedFieldHeadEscapedStringOnly:
p := load(ctxptr, code.idx)
b = append(b, '{')
b = append(b, code.escapedKey...)
b = encodeEscapedString(b, e.ptrToString(p))
b = encodeComma(b)
code = code.next
case opStructEscapedFieldPtrHeadEscapedString:
p := load(ctxptr, code.idx)
if p == 0 {
@ -2470,6 +2616,22 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = encodeComma(b)
code = code.next
}
case opStructEscapedFieldPtrHeadBoolOnly:
p := load(ctxptr, code.idx)
if p == 0 {
b = encodeNull(b)
b = encodeComma(b)
code = code.end.next
break
}
fallthrough
case opStructEscapedFieldHeadBoolOnly:
p := load(ctxptr, code.idx)
b = append(b, '{')
b = append(b, code.escapedKey...)
b = encodeBool(b, e.ptrToBool(p))
b = encodeComma(b)
code = code.next
case opStructEscapedFieldPtrHeadBool:
p := load(ctxptr, code.idx)
if p == 0 {
@ -3827,6 +3989,24 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
code = code.next
}
}
case opStructEscapedFieldPtrHeadOmitEmptyIntOnly:
ptr := load(ctxptr, code.idx)
if ptr != 0 {
store(ctxptr, code.idx, e.ptrToPtr(ptr))
}
fallthrough
case opStructEscapedFieldHeadOmitEmptyIntOnly:
p := load(ctxptr, code.idx)
b = append(b, '{')
v := e.ptrToInt(p)
if v == 0 {
code = code.nextField
} else {
b = append(b, code.escapedKey...)
b = appendInt(b, int64(v))
b = encodeComma(b)
code = code.next
}
case opStructEscapedFieldPtrHeadOmitEmptyInt:
ptr := load(ctxptr, code.idx)
if ptr != 0 {
@ -6782,6 +6962,22 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = encodeComma(b)
code = code.next
}
case opStructEscapedFieldPtrHeadStringTagInt64PtrOnly:
ptr := load(ctxptr, code.idx)
if ptr != 0 {
store(ctxptr, code.idx, e.ptrToPtr(ptr))
}
fallthrough
case opStructEscapedFieldHeadStringTagInt64PtrOnly:
p := load(ctxptr, code.idx)
b = append(b, '{')
b = append(b, code.escapedKey...)
b = append(b, '"')
b = appendInt(b, e.ptrToInt64(p))
b = append(b, '"')
b = encodeComma(b)
code = code.next
case opStructEscapedFieldPtrHeadStringTagInt64:
ptr := load(ctxptr, code.idx)
if ptr != 0 {
@ -7496,6 +7692,21 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = encodeComma(b)
code = code.next
}
case opStructEscapedFieldPtrHeadStringTagBoolOnly:
ptr := load(ctxptr, code.idx)
if ptr != 0 {
store(ctxptr, code.idx, e.ptrToPtr(ptr))
}
fallthrough
case opStructEscapedFieldHeadStringTagBoolOnly:
p := load(ctxptr, code.idx)
b = append(b, '{')
b = append(b, code.escapedKey...)
b = append(b, '"')
b = encodeBool(b, e.ptrToBool(p))
b = append(b, '"')
b = encodeComma(b)
code = code.next
case opStructEscapedFieldPtrHeadStringTagBool:
ptr := load(ctxptr, code.idx)
if ptr != 0 {