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 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) { func TestCoverage(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
@ -21,44 +42,78 @@ func TestCoverage(t *testing.T) {
data interface{} data interface{}
}{ }{
{ {
name: "IntHead", name: "HeadIntZero",
expected: `{"a":0}`,
data: struct {
A int `json:"a"`
}{},
},
{
name: "HeadInt",
expected: `{"a":1}`, expected: `{"a":1}`,
data: struct { data: struct {
A int `json:"a"` A int `json:"a"`
}{A: 1}, }{A: 1},
}, },
{ {
name: "IntPtrHead", name: "HeadIntPtr",
expected: `{"a":1}`, expected: `{"a":1}`,
data: struct { data: struct {
A *int `json:"a"` A *int `json:"a"`
}{A: intptr(1)}, }{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}`, expected: `{"a":1}`,
data: &struct { data: &struct {
A int `json:"a"` A int `json:"a"`
}{A: 1}, }{A: 1},
}, },
{ {
name: "PtrIntPtrHead", name: "PtrHeadIntPtr",
expected: `{"a":1}`, expected: `{"a":1}`,
data: &struct { data: &struct {
A *int `json:"a"` A *int `json:"a"`
}{A: intptr(1)}, }{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}`, expected: `{"a":1,"b":2}`,
data: struct { data: struct {
A int `json:"a"` A int `json:"a"`
@ -66,13 +121,232 @@ func TestCoverage(t *testing.T) {
}{A: 1, B: 2}, }{A: 1, B: 2},
}, },
{ {
name: "IntPtrField", name: "HeadIntPtrMultiFields",
expected: `{"a":1,"b":2}`, expected: `{"a":1,"b":2}`,
data: struct { data: struct {
A *int `json:"a"` A *int `json:"a"`
B *int `json:"b"` B *int `json:"b"`
}{A: intptr(1), B: intptr(2)}, }{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", name: "Int8Head",
expected: `{"a":1}`, expected: `{"a":1}`,
@ -133,10 +407,10 @@ func TestCoverage(t *testing.T) {
enc := NewEncoder(&buf) enc := NewEncoder(&buf)
enc.SetEscapeHTML(htmlEscape) enc.SetEscapeHTML(htmlEscape)
if err := enc.Encode(test.data); err != nil { 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 { 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 return (*opcode)(unsafe.Pointer(header)), nil
} }
func (e *Encoder) typeToHeaderType(ctx *encodeCompileContext, code *opcode) opType { func (e *Encoder) typeToHeaderType(ctx *encodeCompileContext, code *opcode, isOnlyPtrField bool) opType {
switch code.op { if isOnlyPtrField {
case opPtr: // 1. pointer struct + primitive type field
ptrNum := 1 // 2. struct + primitive pointer type field
c := code switch code.op {
ctx.decIndex() case opPtr:
for { ptrNum := 1
if code.next.op == opPtr { c := code
ptrNum++ ctx.decIndex()
code = code.next for {
ctx.decIndex() 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 } else {
if ptrNum > 1 { switch code.op {
switch code.next.op { case opPtr:
case opInt: ptrNum := 1
return opStructFieldHeadIntNPtr c := code
case opInt8: ctx.decIndex()
return opStructFieldHeadInt8NPtr for {
case opInt16: if code.next.op == opPtr {
return opStructFieldHeadInt16NPtr ptrNum++
case opInt32: code = code.next
return opStructFieldHeadInt32NPtr ctx.decIndex()
case opInt64: }
return opStructFieldHeadInt64NPtr break
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 { c.ptrNum = ptrNum
switch code.next.op { if ptrNum > 1 {
case opInt: switch code.next.op {
return opStructFieldHeadIntPtr case opInt:
case opInt8: return opStructFieldHeadIntNPtr
return opStructFieldHeadInt8Ptr case opInt8:
case opInt16: return opStructFieldHeadInt8NPtr
return opStructFieldHeadInt16Ptr case opInt16:
case opInt32: return opStructFieldHeadInt16NPtr
return opStructFieldHeadInt32Ptr case opInt32:
case opInt64: return opStructFieldHeadInt32NPtr
return opStructFieldHeadInt64Ptr case opInt64:
case opUint: return opStructFieldHeadInt64NPtr
return opStructFieldHeadUintPtr case opUint:
case opUint8: return opStructFieldHeadUintNPtr
return opStructFieldHeadUint8Ptr case opUint8:
case opUint16: return opStructFieldHeadUint8NPtr
return opStructFieldHeadUint16Ptr case opUint16:
case opUint32: return opStructFieldHeadUint16NPtr
return opStructFieldHeadUint32Ptr case opUint32:
case opUint64: return opStructFieldHeadUint32NPtr
return opStructFieldHeadUint64Ptr case opUint64:
case opFloat32: return opStructFieldHeadUint64NPtr
return opStructFieldHeadFloat32Ptr case opFloat32:
case opFloat64: return opStructFieldHeadFloat32NPtr
return opStructFieldHeadFloat64Ptr case opFloat64:
case opString: return opStructFieldHeadFloat64NPtr
return opStructFieldHeadStringPtr case opString:
case opBool: return opStructFieldHeadStringNPtr
return opStructFieldHeadBoolPtr 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 return opStructFieldHead
} }
@ -784,8 +909,8 @@ func (e *Encoder) typeToFieldType(ctx *encodeCompileContext, code *opcode) opTyp
return opStructField return opStructField
} }
func (e *Encoder) optimizeStructHeader(ctx *encodeCompileContext, code *opcode, tag *structTag) opType { func (e *Encoder) optimizeStructHeader(ctx *encodeCompileContext, code *opcode, tag *structTag, isOnlyPtrField bool) opType {
headType := e.typeToHeaderType(ctx, code) headType := e.typeToHeaderType(ctx, code, isOnlyPtrField)
switch { switch {
case tag.isOmitEmpty: case tag.isOmitEmpty:
headType = headType.headToOmitEmptyHead() headType = headType.headToOmitEmptyHead()
@ -821,9 +946,9 @@ func (e *Encoder) compiledCode(ctx *encodeCompileContext) *opcode {
return nil 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-- fieldCode.indent--
op := e.optimizeStructHeader(ctx, valueCode, tag) op := e.optimizeStructHeader(ctx, valueCode, tag, isOnlyPtrField)
fieldCode.op = op fieldCode.op = op
fieldCode.ptrNum = valueCode.ptrNum fieldCode.ptrNum = valueCode.ptrNum
switch op { 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,
// if field number is one and primitive pointer type, // it should encode as special opcode.
// it should encode as **not** pointer . isOnlyPtrField := fieldNum == 1 && (valueCode.op == opPtr && !isPtr || valueCode.op != opPtr && isPtr)
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()
}
}
key := fmt.Sprintf(`"%s":`, tag.key) key := fmt.Sprintf(`"%s":`, tag.key)
escapedKey := fmt.Sprintf(`%s:`, string(encodeEscapedString([]byte{}, tag.key))) escapedKey := fmt.Sprintf(`%s:`, string(encodeEscapedString([]byte{}, tag.key)))
fieldCode := &opcode{ fieldCode := &opcode{
@ -1131,7 +1249,7 @@ func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode,
} }
if fieldIdx == 0 { if fieldIdx == 0 {
fieldCode.headIdx = fieldCode.idx fieldCode.headIdx = fieldCode.idx
code = e.structHeader(ctx, fieldCode, valueCode, tag) code = e.structHeader(ctx, fieldCode, valueCode, tag, isOnlyPtrField)
head = fieldCode head = fieldCode
prevField = fieldCode prevField = fieldCode
} else { } else {

View File

@ -1236,6 +1236,22 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
code = code.next code = code.next
store(ctxptr, code.idx, ptr) 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: case opStructFieldPtrHeadInt:
p := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if p == 0 { 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)) store(ctxptr, code.idx, e.ptrToPtr(p))
fallthrough fallthrough
case opStructFieldHeadInt: case opStructFieldHeadInt:
ptr := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if ptr == 0 { b = append(b, '{')
if code.op == opStructFieldPtrHeadInt { b = append(b, code.key...)
b = encodeNull(b) b = appendInt(b, int64(e.ptrToInt(p+code.offset)))
b = encodeComma(b) b = encodeComma(b)
} else { code = code.next
b = append(b, '{', '}', ',') case opStructEscapedFieldPtrHeadIntOnly:
} p := load(ctxptr, code.idx)
code = code.end.next if p == 0 {
} else { b = encodeNull(b)
b = append(b, '{')
b = append(b, code.key...)
b = appendInt(b, int64(e.ptrToInt(ptr+code.offset)))
b = encodeComma(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: case opStructEscapedFieldPtrHeadInt:
p := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if p == 0 { 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)) store(ctxptr, code.idx, e.ptrToPtr(p))
fallthrough fallthrough
case opStructEscapedFieldHeadInt: case opStructEscapedFieldHeadInt:
ptr := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if ptr == 0 { b = append(b, '{')
if code.op == opStructEscapedFieldPtrHeadInt { b = append(b, code.escapedKey...)
b = encodeNull(b) b = appendInt(b, int64(e.ptrToInt(p+code.offset)))
b = encodeComma(b) b = encodeComma(b)
} else { code = code.next
b = append(b, '{', '}', ',') case opStructFieldPtrHeadIntPtrOnly:
} p := load(ctxptr, code.idx)
code = code.end.next if p == 0 {
} else { b = encodeNull(b)
b = append(b, '{')
b = append(b, code.escapedKey...)
b = appendInt(b, int64(e.ptrToInt(ptr+code.offset)))
b = encodeComma(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: case opStructFieldPtrHeadIntPtr:
p := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if p == 0 { if p == 0 {
@ -1304,16 +1337,38 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
p := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if p == 0 { if p == 0 {
b = encodeNull(b) b = encodeNull(b)
b = encodeComma(b)
code = code.end.next code = code.end.next
break
}
b = append(b, '{')
b = append(b, code.key...)
p = e.ptrToPtr(p)
if p == 0 {
b = encodeNull(b)
} else { } else {
b = append(b, '{') b = appendInt(b, int64(e.ptrToInt(p+code.offset)))
b = append(b, code.key...) }
p = e.ptrToPtr(p) b = encodeComma(b)
if p == 0 { code = code.next
b = encodeNull(b) case opStructEscapedFieldPtrHeadIntPtrOnly:
} else { p := load(ctxptr, code.idx)
b = appendInt(b, int64(e.ptrToInt(p+code.offset))) 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) b = encodeComma(b)
code = code.next code = code.next
@ -1331,19 +1386,20 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
p := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if p == 0 { if p == 0 {
b = encodeNull(b) b = encodeNull(b)
b = encodeComma(b)
code = code.end.next code = code.end.next
break
}
b = append(b, '{')
b = append(b, code.escapedKey...)
p = e.ptrToPtr(p)
if p == 0 {
b = encodeNull(b)
} else { } else {
b = append(b, '{') b = appendInt(b, int64(e.ptrToInt(p+code.offset)))
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 = encodeComma(b) b = encodeComma(b)
code = code.next
case opStructFieldHeadIntNPtr: case opStructFieldHeadIntNPtr:
p := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if p == 0 { if p == 0 {
@ -1413,6 +1469,22 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = encodeComma(b) b = encodeComma(b)
code = code.next 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: case opStructFieldPtrHeadInt8:
p := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if p == 0 { if p == 0 {
@ -1440,6 +1512,22 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = encodeComma(b) b = encodeComma(b)
code = code.next 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: case opStructEscapedFieldPtrHeadInt8:
p := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if p == 0 { if p == 0 {
@ -1467,6 +1555,27 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = encodeComma(b) b = encodeComma(b)
code = code.next 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: case opStructFieldPtrHeadInt8Ptr:
p := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if p == 0 { if p == 0 {
@ -1494,6 +1603,27 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
code = code.next code = code.next
} }
b = encodeComma(b) 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: case opStructEscapedFieldPtrHeadInt8Ptr:
p := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if p == 0 { if p == 0 {
@ -2390,6 +2520,22 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = encodeComma(b) b = encodeComma(b)
code = code.next 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: case opStructEscapedFieldPtrHeadEscapedString:
p := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if p == 0 { if p == 0 {
@ -2470,6 +2616,22 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = encodeComma(b) b = encodeComma(b)
code = code.next 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: case opStructEscapedFieldPtrHeadBool:
p := load(ctxptr, code.idx) p := load(ctxptr, code.idx)
if p == 0 { if p == 0 {
@ -3827,6 +3989,24 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
code = code.next 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: case opStructEscapedFieldPtrHeadOmitEmptyInt:
ptr := load(ctxptr, code.idx) ptr := load(ctxptr, code.idx)
if ptr != 0 { if ptr != 0 {
@ -6782,6 +6962,22 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = encodeComma(b) b = encodeComma(b)
code = code.next 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: case opStructEscapedFieldPtrHeadStringTagInt64:
ptr := load(ctxptr, code.idx) ptr := load(ctxptr, code.idx)
if ptr != 0 { if ptr != 0 {
@ -7496,6 +7692,21 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte
b = encodeComma(b) b = encodeComma(b)
code = code.next 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: case opStructEscapedFieldPtrHeadStringTagBool:
ptr := load(ctxptr, code.idx) ptr := load(ctxptr, code.idx)
if ptr != 0 { if ptr != 0 {