forked from mirror/go-json
Add only type
This commit is contained in:
parent
058b3ae1ea
commit
8411c9142c
308
coverage_test.go
308
coverage_test.go
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
301
encode_vm.go
301
encode_vm.go
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue