Merge pull request #301 from goccy/feature/encode-compiler-v2

Refactor compiler for encoder
This commit is contained in:
Masaaki Goshima 2021-11-28 13:55:17 +09:00 committed by GitHub
commit fa6c96f02c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 2415 additions and 2320 deletions

View File

@ -201,7 +201,6 @@ func (t OpType) FieldToOmitEmptyField() OpType {
createOpType("RecursivePtr", "Op"), createOpType("RecursivePtr", "Op"),
createOpType("RecursiveEnd", "Op"), createOpType("RecursiveEnd", "Op"),
createOpType("InterfaceEnd", "Op"), createOpType("InterfaceEnd", "Op"),
createOpType("StructAnonymousEnd", "StructEnd"),
} }
for _, typ := range primitiveTypesUpper { for _, typ := range primitiveTypesUpper {
typ := typ typ := typ

View File

@ -4349,8 +4349,6 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
code = code.Next code = code.Next
store(ctxptr, code.Idx, p) store(ctxptr, code.Idx, p)
} }
case encoder.OpStructAnonymousEnd:
code = code.Next
case encoder.OpStructEnd: case encoder.OpStructEnd:
b = appendStructEndSkipLast(ctx, code, b) b = appendStructEndSkipLast(ctx, code, b)
code = code.Next code = code.Next

875
internal/encoder/code.go Normal file
View File

@ -0,0 +1,875 @@
package encoder
import (
"fmt"
"unsafe"
"github.com/goccy/go-json/internal/runtime"
)
type Code interface {
Kind() CodeKind
ToOpcode(*compileContext) Opcodes
}
type AnonymousCode interface {
ToAnonymousOpcode(*compileContext) Opcodes
}
type Opcodes []*Opcode
func (o Opcodes) First() *Opcode {
if len(o) == 0 {
return nil
}
return o[0]
}
func (o Opcodes) Last() *Opcode {
if len(o) == 0 {
return nil
}
return o[len(o)-1]
}
func (o Opcodes) Add(codes ...*Opcode) Opcodes {
return append(o, codes...)
}
type CodeKind int
const (
CodeKindInterface CodeKind = iota
CodeKindPtr
CodeKindInt
CodeKindUint
CodeKindFloat
CodeKindString
CodeKindBool
CodeKindStruct
CodeKindMap
CodeKindSlice
CodeKindArray
CodeKindBytes
CodeKindMarshalJSON
CodeKindMarshalText
CodeKindRecursive
)
type IntCode struct {
typ *runtime.Type
bitSize uint8
isString bool
isPtr bool
}
func (c *IntCode) Kind() CodeKind {
return CodeKindInt
}
func (c *IntCode) ToOpcode(ctx *compileContext) Opcodes {
var code *Opcode
switch {
case c.isPtr:
code = newOpCode(ctx, c.typ, OpIntPtr)
case c.isString:
code = newOpCode(ctx, c.typ, OpIntString)
default:
code = newOpCode(ctx, c.typ, OpInt)
}
code.NumBitSize = c.bitSize
ctx.incIndex()
return Opcodes{code}
}
type UintCode struct {
typ *runtime.Type
bitSize uint8
isString bool
isPtr bool
}
func (c *UintCode) Kind() CodeKind {
return CodeKindUint
}
func (c *UintCode) ToOpcode(ctx *compileContext) Opcodes {
var code *Opcode
switch {
case c.isPtr:
code = newOpCode(ctx, c.typ, OpUintPtr)
case c.isString:
code = newOpCode(ctx, c.typ, OpUintString)
default:
code = newOpCode(ctx, c.typ, OpUint)
}
code.NumBitSize = c.bitSize
ctx.incIndex()
return Opcodes{code}
}
type FloatCode struct {
typ *runtime.Type
bitSize uint8
isPtr bool
}
func (c *FloatCode) Kind() CodeKind {
return CodeKindFloat
}
func (c *FloatCode) ToOpcode(ctx *compileContext) Opcodes {
var code *Opcode
switch {
case c.isPtr:
switch c.bitSize {
case 32:
code = newOpCode(ctx, c.typ, OpFloat32Ptr)
default:
code = newOpCode(ctx, c.typ, OpFloat64Ptr)
}
default:
switch c.bitSize {
case 32:
code = newOpCode(ctx, c.typ, OpFloat32)
default:
code = newOpCode(ctx, c.typ, OpFloat64)
}
}
ctx.incIndex()
return Opcodes{code}
}
type StringCode struct {
typ *runtime.Type
isPtr bool
}
func (c *StringCode) Kind() CodeKind {
return CodeKindString
}
func (c *StringCode) ToOpcode(ctx *compileContext) Opcodes {
isJSONNumberType := c.typ == runtime.Type2RType(jsonNumberType)
var code *Opcode
if c.isPtr {
if isJSONNumberType {
code = newOpCode(ctx, c.typ, OpNumberPtr)
} else {
code = newOpCode(ctx, c.typ, OpStringPtr)
}
} else {
if isJSONNumberType {
code = newOpCode(ctx, c.typ, OpNumber)
} else {
code = newOpCode(ctx, c.typ, OpString)
}
}
ctx.incIndex()
return Opcodes{code}
}
type BoolCode struct {
typ *runtime.Type
isPtr bool
}
func (c *BoolCode) Kind() CodeKind {
return CodeKindBool
}
func (c *BoolCode) ToOpcode(ctx *compileContext) Opcodes {
var code *Opcode
switch {
case c.isPtr:
code = newOpCode(ctx, c.typ, OpBoolPtr)
default:
code = newOpCode(ctx, c.typ, OpBool)
}
ctx.incIndex()
return Opcodes{code}
}
type BytesCode struct {
typ *runtime.Type
isPtr bool
}
func (c *BytesCode) Kind() CodeKind {
return CodeKindBytes
}
func (c *BytesCode) ToOpcode(ctx *compileContext) Opcodes {
var code *Opcode
switch {
case c.isPtr:
code = newOpCode(ctx, c.typ, OpBytesPtr)
default:
code = newOpCode(ctx, c.typ, OpBytes)
}
ctx.incIndex()
return Opcodes{code}
}
type SliceCode struct {
typ *runtime.Type
value Code
}
func (c *SliceCode) Kind() CodeKind {
return CodeKindSlice
}
func (c *SliceCode) ToOpcode(ctx *compileContext) Opcodes {
// header => opcode => elem => end
// ^ |
// |________|
size := c.typ.Elem().Size()
header := newSliceHeaderCode(ctx, c.typ)
ctx.incIndex()
ctx.incIndent()
codes := c.value.ToOpcode(ctx)
ctx.decIndent()
codes.First().Flags |= IndirectFlags
elemCode := newSliceElemCode(ctx, c.typ.Elem(), header, size)
ctx.incIndex()
end := newOpCode(ctx, c.typ, OpSliceEnd)
ctx.incIndex()
header.End = end
header.Next = codes.First()
codes.Last().Next = elemCode
elemCode.Next = codes.First()
elemCode.End = end
return Opcodes{header}.Add(codes...).Add(elemCode).Add(end)
}
type ArrayCode struct {
typ *runtime.Type
value Code
}
func (c *ArrayCode) Kind() CodeKind {
return CodeKindArray
}
func (c *ArrayCode) ToOpcode(ctx *compileContext) Opcodes {
// header => opcode => elem => end
// ^ |
// |________|
elem := c.typ.Elem()
alen := c.typ.Len()
size := elem.Size()
header := newArrayHeaderCode(ctx, c.typ, alen)
ctx.incIndex()
ctx.incIndent()
codes := c.value.ToOpcode(ctx)
ctx.decIndent()
codes.First().Flags |= IndirectFlags
elemCode := newArrayElemCode(ctx, elem, header, alen, size)
ctx.incIndex()
end := newOpCode(ctx, c.typ, OpArrayEnd)
ctx.incIndex()
header.End = end
header.Next = codes.First()
codes.Last().Next = elemCode
elemCode.Next = codes.First()
elemCode.End = end
return Opcodes{header}.Add(codes...).Add(elemCode).Add(end)
}
type MapCode struct {
typ *runtime.Type
key Code
value Code
}
func (c *MapCode) Kind() CodeKind {
return CodeKindMap
}
func (c *MapCode) ToOpcode(ctx *compileContext) Opcodes {
// header => code => value => code => key => code => value => code => end
// ^ |
// |_______________________|
header := newMapHeaderCode(ctx, c.typ)
ctx.incIndex()
keyCodes := c.key.ToOpcode(ctx)
value := newMapValueCode(ctx, c.typ.Elem(), header)
ctx.incIndex()
ctx.incIndent()
valueCodes := c.value.ToOpcode(ctx)
ctx.decIndent()
valueCodes.First().Flags |= IndirectFlags
key := newMapKeyCode(ctx, c.typ.Key(), header)
ctx.incIndex()
end := newMapEndCode(ctx, c.typ, header)
ctx.incIndex()
header.Next = keyCodes.First()
keyCodes.Last().Next = value
value.Next = valueCodes.First()
valueCodes.Last().Next = key
key.Next = keyCodes.First()
header.End = end
key.End = end
value.End = end
return Opcodes{header}.Add(keyCodes...).Add(value).Add(valueCodes...).Add(key).Add(end)
}
type StructCode struct {
typ *runtime.Type
fields []*StructFieldCode
isPtr bool
disableIndirectConversion bool
isIndirect bool
isRecursive bool
}
func (c *StructCode) Kind() CodeKind {
return CodeKindStruct
}
func (c *StructCode) lastFieldCode(field *StructFieldCode, firstField *Opcode) *Opcode {
if field.isAnonymous {
return c.lastAnonymousFieldCode(firstField)
}
lastField := firstField
for lastField.NextField != nil {
lastField = lastField.NextField
}
return lastField
}
func (c *StructCode) lastAnonymousFieldCode(firstField *Opcode) *Opcode {
// firstField is special StructHead operation for anonymous structure.
// So, StructHead's next operation is truly struct head operation.
lastField := firstField.Next
for lastField.NextField != nil {
lastField = lastField.NextField
}
return lastField
}
func (c *StructCode) ToOpcode(ctx *compileContext) Opcodes {
// header => code => structField => code => end
// ^ |
// |__________|
if c.isRecursive {
recursive := newRecursiveCode(ctx, c.typ, &CompiledCode{})
recursive.Type = c.typ
ctx.incIndex()
*ctx.recursiveCodes = append(*ctx.recursiveCodes, recursive)
return Opcodes{recursive}
}
codes := Opcodes{}
var prevField *Opcode
ctx.incIndent()
for idx, field := range c.fields {
isFirstField := idx == 0
isEndField := idx == len(c.fields)-1
fieldCodes := field.ToOpcode(ctx, isFirstField, isEndField)
for _, code := range fieldCodes {
if c.isIndirect {
code.Flags |= IndirectFlags
}
}
firstField := fieldCodes.First()
if len(codes) > 0 {
codes.Last().Next = firstField
firstField.Idx = codes.First().Idx
}
if prevField != nil {
prevField.NextField = firstField
}
if isEndField {
endField := fieldCodes.Last()
if len(codes) > 0 {
codes.First().End = endField
} else if field.isAnonymous {
firstField.End = endField
lastField := c.lastAnonymousFieldCode(firstField)
lastField.NextField = endField
} else {
firstField.End = endField
}
codes = codes.Add(fieldCodes...)
break
}
prevField = c.lastFieldCode(field, firstField)
codes = codes.Add(fieldCodes...)
}
if len(codes) == 0 {
head := &Opcode{
Op: OpStructHead,
Idx: opcodeOffset(ctx.ptrIndex),
Type: c.typ,
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
}
ctx.incOpcodeIndex()
end := &Opcode{
Op: OpStructEnd,
Idx: opcodeOffset(ctx.ptrIndex),
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
}
head.NextField = end
head.Next = end
head.End = end
codes = codes.Add(head, end)
ctx.incIndex()
}
ctx.decIndent()
ctx.structTypeToCodes[uintptr(unsafe.Pointer(c.typ))] = codes
return codes
}
func (c *StructCode) ToAnonymousOpcode(ctx *compileContext) Opcodes {
// header => code => structField => code => end
// ^ |
// |__________|
if c.isRecursive {
recursive := newRecursiveCode(ctx, c.typ, &CompiledCode{})
recursive.Type = c.typ
ctx.incIndex()
*ctx.recursiveCodes = append(*ctx.recursiveCodes, recursive)
return Opcodes{recursive}
}
codes := Opcodes{}
var prevField *Opcode
for idx, field := range c.fields {
isFirstField := idx == 0
isEndField := idx == len(c.fields)-1
fieldCodes := field.ToAnonymousOpcode(ctx, isFirstField, isEndField)
for _, code := range fieldCodes {
if c.isIndirect {
code.Flags |= IndirectFlags
}
}
firstField := fieldCodes.First()
if len(codes) > 0 {
codes.Last().Next = firstField
firstField.Idx = codes.First().Idx
}
if prevField != nil {
prevField.NextField = firstField
}
if isEndField {
lastField := fieldCodes.Last()
if len(codes) > 0 {
codes.First().End = lastField
} else {
firstField.End = lastField
}
}
prevField = firstField
codes = codes.Add(fieldCodes...)
}
return codes
}
func (c *StructCode) removeFieldsByTags(tags runtime.StructTags) {
fields := make([]*StructFieldCode, 0, len(c.fields))
for _, field := range c.fields {
if field.isAnonymous {
structCode := field.getAnonymousStruct()
if structCode != nil && !structCode.isRecursive {
structCode.removeFieldsByTags(tags)
if len(structCode.fields) > 0 {
fields = append(fields, field)
}
continue
}
}
if tags.ExistsKey(field.key) {
continue
}
fields = append(fields, field)
}
c.fields = fields
}
func (c *StructCode) enableIndirect() {
if c.isIndirect {
return
}
c.isIndirect = true
if len(c.fields) == 0 {
return
}
structCode := c.fields[0].getStruct()
if structCode == nil {
return
}
structCode.enableIndirect()
}
type StructFieldCode struct {
typ *runtime.Type
key string
tag *runtime.StructTag
value Code
offset uintptr
isAnonymous bool
isTaggedKey bool
isNilableType bool
isNilCheck bool
isAddrForMarshaler bool
isNextOpPtrType bool
}
func (c *StructFieldCode) getStruct() *StructCode {
value := c.value
ptr, ok := value.(*PtrCode)
if ok {
value = ptr.value
}
structCode, ok := value.(*StructCode)
if ok {
return structCode
}
return nil
}
func (c *StructFieldCode) getAnonymousStruct() *StructCode {
if !c.isAnonymous {
return nil
}
return c.getStruct()
}
func optimizeStructHeader(code *Opcode, tag *runtime.StructTag) OpType {
headType := code.ToHeaderType(tag.IsString)
if tag.IsOmitEmpty {
headType = headType.HeadToOmitEmptyHead()
}
return headType
}
func optimizeStructField(code *Opcode, tag *runtime.StructTag) OpType {
fieldType := code.ToFieldType(tag.IsString)
if tag.IsOmitEmpty {
fieldType = fieldType.FieldToOmitEmptyField()
}
return fieldType
}
func (c *StructFieldCode) headerOpcodes(ctx *compileContext, field *Opcode, valueCodes Opcodes) Opcodes {
value := valueCodes.First()
op := optimizeStructHeader(value, c.tag)
field.Op = op
field.NumBitSize = value.NumBitSize
field.PtrNum = value.PtrNum
fieldCodes := Opcodes{field}
if op.IsMultipleOpHead() {
field.Next = value
fieldCodes = fieldCodes.Add(valueCodes...)
} else {
ctx.decIndex()
}
return fieldCodes
}
func (c *StructFieldCode) fieldOpcodes(ctx *compileContext, field *Opcode, valueCodes Opcodes) Opcodes {
value := valueCodes.First()
op := optimizeStructField(value, c.tag)
field.Op = op
field.NumBitSize = value.NumBitSize
field.PtrNum = value.PtrNum
fieldCodes := Opcodes{field}
if op.IsMultipleOpField() {
field.Next = value
fieldCodes = fieldCodes.Add(valueCodes...)
} else {
ctx.decIndex()
}
return fieldCodes
}
func (c *StructFieldCode) addStructEndCode(ctx *compileContext, codes Opcodes) Opcodes {
end := &Opcode{
Op: OpStructEnd,
Idx: opcodeOffset(ctx.ptrIndex),
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
}
codes.Last().Next = end
codes.First().NextField = end
codes = codes.Add(end)
ctx.incOpcodeIndex()
return codes
}
func (c *StructFieldCode) structKey(ctx *compileContext) string {
if ctx.escapeKey {
rctx := &RuntimeContext{Option: &Option{Flag: HTMLEscapeOption}}
return fmt.Sprintf(`%s:`, string(AppendString(rctx, []byte{}, c.key)))
}
return fmt.Sprintf(`"%s":`, c.key)
}
func (c *StructFieldCode) flags() OpFlags {
var flags OpFlags
if c.isTaggedKey {
flags |= IsTaggedKeyFlags
}
if c.isNilableType {
flags |= IsNilableTypeFlags
}
if c.isNilCheck {
flags |= NilCheckFlags
}
if c.isAddrForMarshaler {
flags |= AddrForMarshalerFlags
}
if c.isNextOpPtrType {
flags |= IsNextOpPtrTypeFlags
}
if c.isAnonymous {
flags |= AnonymousKeyFlags
}
return flags
}
func (c *StructFieldCode) toValueOpcodes(ctx *compileContext) Opcodes {
if c.isAnonymous {
anonymCode, ok := c.value.(AnonymousCode)
if ok {
return anonymCode.ToAnonymousOpcode(ctx)
}
}
return c.value.ToOpcode(ctx)
}
func (c *StructFieldCode) ToOpcode(ctx *compileContext, isFirstField, isEndField bool) Opcodes {
field := &Opcode{
Idx: opcodeOffset(ctx.ptrIndex),
Flags: c.flags(),
Key: c.structKey(ctx),
Offset: uint32(c.offset),
Type: c.typ,
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
DisplayKey: c.key,
}
ctx.incIndex()
valueCodes := c.toValueOpcodes(ctx)
if isFirstField {
codes := c.headerOpcodes(ctx, field, valueCodes)
if isEndField {
codes = c.addStructEndCode(ctx, codes)
}
return codes
}
codes := c.fieldOpcodes(ctx, field, valueCodes)
if isEndField {
if isEnableStructEndOptimization(c.value) {
field.Op = field.Op.FieldToEnd()
} else {
codes = c.addStructEndCode(ctx, codes)
}
}
return codes
}
func (c *StructFieldCode) ToAnonymousOpcode(ctx *compileContext, isFirstField, isEndField bool) Opcodes {
field := &Opcode{
Idx: opcodeOffset(ctx.ptrIndex),
Flags: c.flags() | AnonymousHeadFlags,
Key: c.structKey(ctx),
Offset: uint32(c.offset),
Type: c.typ,
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
DisplayKey: c.key,
}
ctx.incIndex()
valueCodes := c.toValueOpcodes(ctx)
if isFirstField {
return c.headerOpcodes(ctx, field, valueCodes)
}
return c.fieldOpcodes(ctx, field, valueCodes)
}
func isEnableStructEndOptimization(value Code) bool {
switch value.Kind() {
case CodeKindInt,
CodeKindUint,
CodeKindFloat,
CodeKindString,
CodeKindBool,
CodeKindBytes:
return true
case CodeKindPtr:
return isEnableStructEndOptimization(value.(*PtrCode).value)
default:
return false
}
}
type InterfaceCode struct {
typ *runtime.Type
isPtr bool
}
func (c *InterfaceCode) Kind() CodeKind {
return CodeKindInterface
}
func (c *InterfaceCode) ToOpcode(ctx *compileContext) Opcodes {
var code *Opcode
switch {
case c.isPtr:
code = newOpCode(ctx, c.typ, OpInterfacePtr)
default:
code = newOpCode(ctx, c.typ, OpInterface)
}
if c.typ.NumMethod() > 0 {
code.Flags |= NonEmptyInterfaceFlags
}
ctx.incIndex()
return Opcodes{code}
}
type MarshalJSONCode struct {
typ *runtime.Type
isAddrForMarshaler bool
isNilableType bool
isMarshalerContext bool
}
func (c *MarshalJSONCode) Kind() CodeKind {
return CodeKindMarshalJSON
}
func (c *MarshalJSONCode) ToOpcode(ctx *compileContext) Opcodes {
code := newOpCode(ctx, c.typ, OpMarshalJSON)
if c.isAddrForMarshaler {
code.Flags |= AddrForMarshalerFlags
}
if c.isMarshalerContext {
code.Flags |= MarshalerContextFlags
}
if c.isNilableType {
code.Flags |= IsNilableTypeFlags
} else {
code.Flags &= ^IsNilableTypeFlags
}
ctx.incIndex()
return Opcodes{code}
}
type MarshalTextCode struct {
typ *runtime.Type
isAddrForMarshaler bool
isNilableType bool
}
func (c *MarshalTextCode) Kind() CodeKind {
return CodeKindMarshalText
}
func (c *MarshalTextCode) ToOpcode(ctx *compileContext) Opcodes {
code := newOpCode(ctx, c.typ, OpMarshalText)
if c.isAddrForMarshaler {
code.Flags |= AddrForMarshalerFlags
}
if c.isNilableType {
code.Flags |= IsNilableTypeFlags
} else {
code.Flags &= ^IsNilableTypeFlags
}
ctx.incIndex()
return Opcodes{code}
}
type PtrCode struct {
typ *runtime.Type
value Code
ptrNum uint8
}
func (c *PtrCode) Kind() CodeKind {
return CodeKindPtr
}
func (c *PtrCode) ToOpcode(ctx *compileContext) Opcodes {
codes := c.value.ToOpcode(ctx)
codes.First().Op = convertPtrOp(codes.First())
codes.First().PtrNum = c.ptrNum
return codes
}
func (c *PtrCode) ToAnonymousOpcode(ctx *compileContext) Opcodes {
var codes Opcodes
anonymCode, ok := c.value.(AnonymousCode)
if ok {
codes = anonymCode.ToAnonymousOpcode(ctx)
} else {
codes = c.value.ToOpcode(ctx)
}
codes.First().Op = convertPtrOp(codes.First())
codes.First().PtrNum = c.ptrNum
return codes
}
func convertPtrOp(code *Opcode) OpType {
ptrHeadOp := code.Op.HeadToPtrHead()
if code.Op != ptrHeadOp {
if code.PtrNum > 0 {
// ptr field and ptr head
code.PtrNum--
}
return ptrHeadOp
}
switch code.Op {
case OpInt:
return OpIntPtr
case OpUint:
return OpUintPtr
case OpFloat32:
return OpFloat32Ptr
case OpFloat64:
return OpFloat64Ptr
case OpString:
return OpStringPtr
case OpBool:
return OpBoolPtr
case OpBytes:
return OpBytesPtr
case OpNumber:
return OpNumberPtr
case OpArray:
return OpArrayPtr
case OpSlice:
return OpSlicePtr
case OpMap:
return OpMapPtr
case OpMarshalJSON:
return OpMarshalJSONPtr
case OpMarshalText:
return OpMarshalTextPtr
case OpInterface:
return OpInterfacePtr
case OpRecursive:
return OpRecursivePtr
}
return code.Op
}

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,8 @@
//go:build !race
// +build !race // +build !race
package encoder package encoder
import (
"unsafe"
"github.com/goccy/go-json/internal/runtime"
)
func CompileToGetCodeSet(typeptr uintptr) (*OpcodeSet, error) { func CompileToGetCodeSet(typeptr uintptr) (*OpcodeSet, error) {
if typeptr > typeAddr.MaxTypeAddr { if typeptr > typeAddr.MaxTypeAddr {
return compileToGetCodeSetSlowPath(typeptr) return compileToGetCodeSetSlowPath(typeptr)
@ -16,41 +11,10 @@ func CompileToGetCodeSet(typeptr uintptr) (*OpcodeSet, error) {
if codeSet := cachedOpcodeSets[index]; codeSet != nil { if codeSet := cachedOpcodeSets[index]; codeSet != nil {
return codeSet, nil return codeSet, nil
} }
codeSet, err := newCompiler().compile(typeptr)
// noescape trick for header.typ ( reflect.*rtype )
copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr))
noescapeKeyCode, err := compileHead(&compileContext{
typ: copiedType,
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
})
if err != nil { if err != nil {
return nil, err return nil, err
} }
escapeKeyCode, err := compileHead(&compileContext{
typ: copiedType,
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
escapeKey: true,
})
if err != nil {
return nil, err
}
noescapeKeyCode = copyOpcode(noescapeKeyCode)
escapeKeyCode = copyOpcode(escapeKeyCode)
setTotalLengthToInterfaceOp(noescapeKeyCode)
setTotalLengthToInterfaceOp(escapeKeyCode)
interfaceNoescapeKeyCode := copyToInterfaceOpcode(noescapeKeyCode)
interfaceEscapeKeyCode := copyToInterfaceOpcode(escapeKeyCode)
codeLength := noescapeKeyCode.TotalLength()
codeSet := &OpcodeSet{
Type: copiedType,
NoescapeKeyCode: noescapeKeyCode,
EscapeKeyCode: escapeKeyCode,
InterfaceNoescapeKeyCode: interfaceNoescapeKeyCode,
InterfaceEscapeKeyCode: interfaceEscapeKeyCode,
CodeLength: codeLength,
EndCode: ToEndCode(interfaceNoescapeKeyCode),
}
cachedOpcodeSets[index] = codeSet cachedOpcodeSets[index] = codeSet
return codeSet, nil return codeSet, nil
} }

View File

@ -1,12 +1,10 @@
//go:build race
// +build race // +build race
package encoder package encoder
import ( import (
"sync" "sync"
"unsafe"
"github.com/goccy/go-json/internal/runtime"
) )
var setsMu sync.RWMutex var setsMu sync.RWMutex
@ -23,41 +21,10 @@ func CompileToGetCodeSet(typeptr uintptr) (*OpcodeSet, error) {
} }
setsMu.RUnlock() setsMu.RUnlock()
// noescape trick for header.typ ( reflect.*rtype ) codeSet, err := newCompiler().compile(typeptr)
copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr))
noescapeKeyCode, err := compileHead(&compileContext{
typ: copiedType,
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
})
if err != nil { if err != nil {
return nil, err return nil, err
} }
escapeKeyCode, err := compileHead(&compileContext{
typ: copiedType,
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
escapeKey: true,
})
if err != nil {
return nil, err
}
noescapeKeyCode = copyOpcode(noescapeKeyCode)
escapeKeyCode = copyOpcode(escapeKeyCode)
setTotalLengthToInterfaceOp(noescapeKeyCode)
setTotalLengthToInterfaceOp(escapeKeyCode)
interfaceNoescapeKeyCode := copyToInterfaceOpcode(noescapeKeyCode)
interfaceEscapeKeyCode := copyToInterfaceOpcode(escapeKeyCode)
codeLength := noescapeKeyCode.TotalLength()
codeSet := &OpcodeSet{
Type: copiedType,
NoescapeKeyCode: noescapeKeyCode,
EscapeKeyCode: escapeKeyCode,
InterfaceNoescapeKeyCode: interfaceNoescapeKeyCode,
InterfaceEscapeKeyCode: interfaceEscapeKeyCode,
CodeLength: codeLength,
EndCode: ToEndCode(interfaceNoescapeKeyCode),
}
setsMu.Lock() setsMu.Lock()
cachedOpcodeSets[index] = codeSet cachedOpcodeSets[index] = codeSet
setsMu.Unlock() setsMu.Unlock()

View File

@ -9,44 +9,20 @@ import (
) )
type compileContext struct { type compileContext struct {
typ *runtime.Type opcodeIndex uint32
opcodeIndex uint32 ptrIndex int
ptrIndex int indent uint32
indent uint32 escapeKey bool
escapeKey bool structTypeToCodes map[uintptr]Opcodes
structTypeToCompiledCode map[uintptr]*CompiledCode recursiveCodes *Opcodes
parent *compileContext
} }
func (c *compileContext) context() *compileContext { func (c *compileContext) incIndent() {
return &compileContext{ c.indent++
typ: c.typ,
opcodeIndex: c.opcodeIndex,
ptrIndex: c.ptrIndex,
indent: c.indent,
escapeKey: c.escapeKey,
structTypeToCompiledCode: c.structTypeToCompiledCode,
parent: c,
}
} }
func (c *compileContext) withType(typ *runtime.Type) *compileContext { func (c *compileContext) decIndent() {
ctx := c.context() c.indent--
ctx.typ = typ
return ctx
}
func (c *compileContext) incIndent() *compileContext {
ctx := c.context()
ctx.indent++
return ctx
}
func (c *compileContext) decIndent() *compileContext {
ctx := c.context()
ctx.indent--
return ctx
} }
func (c *compileContext) incIndex() { func (c *compileContext) incIndex() {
@ -61,30 +37,18 @@ func (c *compileContext) decIndex() {
func (c *compileContext) incOpcodeIndex() { func (c *compileContext) incOpcodeIndex() {
c.opcodeIndex++ c.opcodeIndex++
if c.parent != nil {
c.parent.incOpcodeIndex()
}
} }
func (c *compileContext) decOpcodeIndex() { func (c *compileContext) decOpcodeIndex() {
c.opcodeIndex-- c.opcodeIndex--
if c.parent != nil {
c.parent.decOpcodeIndex()
}
} }
func (c *compileContext) incPtrIndex() { func (c *compileContext) incPtrIndex() {
c.ptrIndex++ c.ptrIndex++
if c.parent != nil {
c.parent.incPtrIndex()
}
} }
func (c *compileContext) decPtrIndex() { func (c *compileContext) decPtrIndex() {
c.ptrIndex-- c.ptrIndex--
if c.parent != nil {
c.parent.decPtrIndex()
}
} }
const ( const (

View File

@ -38,7 +38,6 @@ type Opcode struct {
Flags OpFlags Flags OpFlags
Type *runtime.Type // go type Type *runtime.Type // go type
PrevField *Opcode // prev struct field
Jmp *CompiledCode // for recursive call Jmp *CompiledCode // for recursive call
ElemIdx uint32 // offset to access array/slice/map elem ElemIdx uint32 // offset to access array/slice/map elem
Length uint32 // offset to access slice/map length or array length Length uint32 // offset to access slice/map length or array length
@ -50,18 +49,40 @@ type Opcode struct {
DisplayKey string // key text to display DisplayKey string // key text to display
} }
func (c *Opcode) IsStructHeadOp() bool { func (c *Opcode) Validate() error {
if c == nil { var prevIdx uint32
return false for code := c; !code.IsEnd(); {
if prevIdx != 0 {
if code.DisplayIdx != prevIdx+1 {
return fmt.Errorf(
"invalid index. previous display index is %d but next is %d. dump = %s",
prevIdx, code.DisplayIdx, c.Dump(),
)
}
}
prevIdx = code.DisplayIdx
code = code.IterNext()
} }
return strings.Contains(c.Op.String(), "Head") return nil
} }
func (c *Opcode) IsRecursiveOp() bool { func (c *Opcode) IterNext() *Opcode {
if c == nil { if c == nil {
return false return nil
} }
return strings.Contains(c.Op.String(), "Recursive") switch c.Op.CodeType() {
case CodeArrayElem, CodeSliceElem, CodeMapKey:
return c.End
default:
return c.Next
}
}
func (c *Opcode) IsEnd() bool {
if c == nil {
return true
}
return c.Op == OpEnd || c.Op == OpInterfaceEnd || c.Op == OpRecursiveEnd
} }
func (c *Opcode) MaxIdx() uint32 { func (c *Opcode) MaxIdx() uint32 {
@ -287,43 +308,76 @@ func (c *Opcode) ToFieldType(isString bool) OpType {
return OpStructField return OpStructField
} }
func newOpCode(ctx *compileContext, op OpType) *Opcode { func newOpCode(ctx *compileContext, typ *runtime.Type, op OpType) *Opcode {
return newOpCodeWithNext(ctx, op, newEndOp(ctx)) return newOpCodeWithNext(ctx, typ, op, newEndOp(ctx, typ))
} }
func opcodeOffset(idx int) uint32 { func opcodeOffset(idx int) uint32 {
return uint32(idx) * uintptrSize return uint32(idx) * uintptrSize
} }
func getCodeAddrByIdx(head *Opcode, idx uint32) *Opcode {
addr := uintptr(unsafe.Pointer(head)) + uintptr(idx)*unsafe.Sizeof(Opcode{})
return *(**Opcode)(unsafe.Pointer(&addr))
}
func copyOpcode(code *Opcode) *Opcode { func copyOpcode(code *Opcode) *Opcode {
codeMap := map[uintptr]*Opcode{} codeNum := ToEndCode(code).DisplayIdx + 1
return code.copy(codeMap) codeSlice := make([]Opcode, codeNum)
head := (*Opcode)((*runtime.SliceHeader)(unsafe.Pointer(&codeSlice)).Data)
ptr := head
c := code
for {
*ptr = Opcode{
Op: c.Op,
Key: c.Key,
PtrNum: c.PtrNum,
NumBitSize: c.NumBitSize,
Flags: c.Flags,
Idx: c.Idx,
Offset: c.Offset,
Type: c.Type,
DisplayIdx: c.DisplayIdx,
DisplayKey: c.DisplayKey,
ElemIdx: c.ElemIdx,
Length: c.Length,
MapIter: c.MapIter,
MapPos: c.MapPos,
Size: c.Size,
Indent: c.Indent,
Jmp: c.Jmp,
}
if c.End != nil {
ptr.End = getCodeAddrByIdx(head, c.End.DisplayIdx)
}
if c.NextField != nil {
ptr.NextField = getCodeAddrByIdx(head, c.NextField.DisplayIdx)
}
if c.Next != nil {
ptr.Next = getCodeAddrByIdx(head, c.Next.DisplayIdx)
}
if c.IsEnd() {
break
}
ptr = getCodeAddrByIdx(head, c.DisplayIdx+1)
c = c.IterNext()
}
return head
} }
func setTotalLengthToInterfaceOp(code *Opcode) { func setTotalLengthToInterfaceOp(code *Opcode) {
c := code for c := code; !c.IsEnd(); {
for c.Op != OpEnd && c.Op != OpInterfaceEnd {
if c.Op == OpInterface { if c.Op == OpInterface {
c.Length = uint32(code.TotalLength()) c.Length = uint32(code.TotalLength())
} }
switch c.Op.CodeType() { c = c.IterNext()
case CodeArrayElem, CodeSliceElem, CodeMapKey:
c = c.End
default:
c = c.Next
}
} }
} }
func ToEndCode(code *Opcode) *Opcode { func ToEndCode(code *Opcode) *Opcode {
c := code c := code
for c.Op != OpEnd && c.Op != OpInterfaceEnd { for !c.IsEnd() {
switch c.Op.CodeType() { c = c.IterNext()
case CodeArrayElem, CodeSliceElem, CodeMapKey:
c = c.End
default:
c = c.Next
}
} }
return c return c
} }
@ -339,77 +393,25 @@ func copyToInterfaceOpcode(code *Opcode) *Opcode {
return copied return copied
} }
func newOpCodeWithNext(ctx *compileContext, op OpType, next *Opcode) *Opcode { func newOpCodeWithNext(ctx *compileContext, typ *runtime.Type, op OpType, next *Opcode) *Opcode {
return &Opcode{ return &Opcode{
Op: op, Op: op,
Idx: opcodeOffset(ctx.ptrIndex), Idx: opcodeOffset(ctx.ptrIndex),
Next: next, Next: next,
Type: ctx.typ, Type: typ,
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent, Indent: ctx.indent,
} }
} }
func newEndOp(ctx *compileContext) *Opcode { func newEndOp(ctx *compileContext, typ *runtime.Type) *Opcode {
return newOpCodeWithNext(ctx, OpEnd, nil) return newOpCodeWithNext(ctx, typ, OpEnd, nil)
}
func (c *Opcode) copy(codeMap map[uintptr]*Opcode) *Opcode {
if c == nil {
return nil
}
addr := uintptr(unsafe.Pointer(c))
if code, exists := codeMap[addr]; exists {
return code
}
copied := &Opcode{
Op: c.Op,
Key: c.Key,
PtrNum: c.PtrNum,
NumBitSize: c.NumBitSize,
Flags: c.Flags,
Idx: c.Idx,
Offset: c.Offset,
Type: c.Type,
DisplayIdx: c.DisplayIdx,
DisplayKey: c.DisplayKey,
ElemIdx: c.ElemIdx,
Length: c.Length,
MapIter: c.MapIter,
MapPos: c.MapPos,
Size: c.Size,
Indent: c.Indent,
}
codeMap[addr] = copied
copied.End = c.End.copy(codeMap)
copied.PrevField = c.PrevField.copy(codeMap)
copied.NextField = c.NextField.copy(codeMap)
copied.Next = c.Next.copy(codeMap)
copied.Jmp = c.Jmp
return copied
}
func (c *Opcode) BeforeLastCode() *Opcode {
code := c
for {
var nextCode *Opcode
switch code.Op.CodeType() {
case CodeArrayElem, CodeSliceElem, CodeMapKey:
nextCode = code.End
default:
nextCode = code.Next
}
if nextCode.Op == OpEnd {
return code
}
code = nextCode
}
} }
func (c *Opcode) TotalLength() int { func (c *Opcode) TotalLength() int {
var idx int var idx int
code := c code := c
for code.Op != OpEnd && code.Op != OpInterfaceEnd { for !code.IsEnd() {
maxIdx := int(code.MaxIdx() / uintptrSize) maxIdx := int(code.MaxIdx() / uintptrSize)
if idx < maxIdx { if idx < maxIdx {
idx = maxIdx idx = maxIdx
@ -417,12 +419,7 @@ func (c *Opcode) TotalLength() int {
if code.Op == OpRecursiveEnd { if code.Op == OpRecursiveEnd {
break break
} }
switch code.Op.CodeType() { code = code.IterNext()
case CodeArrayElem, CodeSliceElem, CodeMapKey:
code = code.End
default:
code = code.Next
}
} }
maxIdx := int(code.MaxIdx() / uintptrSize) maxIdx := int(code.MaxIdx() / uintptrSize)
if idx < maxIdx { if idx < maxIdx {
@ -431,42 +428,6 @@ func (c *Opcode) TotalLength() int {
return idx + 1 return idx + 1
} }
func (c *Opcode) decOpcodeIndex() {
for code := c; code.Op != OpEnd; {
code.DisplayIdx--
if code.Idx > 0 {
code.Idx -= uintptrSize
}
if code.ElemIdx > 0 {
code.ElemIdx -= uintptrSize
}
if code.MapIter > 0 {
code.MapIter -= uintptrSize
}
if code.Length > 0 && code.Op.CodeType() != CodeArrayHead && code.Op.CodeType() != CodeArrayElem {
code.Length -= uintptrSize
}
switch code.Op.CodeType() {
case CodeArrayElem, CodeSliceElem, CodeMapKey:
code = code.End
default:
code = code.Next
}
}
}
func (c *Opcode) decIndent() {
for code := c; code.Op != OpEnd; {
code.Indent--
switch code.Op.CodeType() {
case CodeArrayElem, CodeSliceElem, CodeMapKey:
code = code.End
default:
code = code.Next
}
}
}
func (c *Opcode) dumpHead(code *Opcode) string { func (c *Opcode) dumpHead(code *Opcode) string {
var length uint32 var length uint32
if code.Op.CodeType() == CodeArrayHead { if code.Op.CodeType() == CodeArrayHead {
@ -475,7 +436,7 @@ func (c *Opcode) dumpHead(code *Opcode) string {
length = code.Length / uintptrSize length = code.Length / uintptrSize
} }
return fmt.Sprintf( return fmt.Sprintf(
`[%d]%s%s ([idx:%d][elemIdx:%d][length:%d])`, `[%03d]%s%s ([idx:%d][elemIdx:%d][length:%d])`,
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", int(code.Indent)), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
@ -487,7 +448,7 @@ func (c *Opcode) dumpHead(code *Opcode) string {
func (c *Opcode) dumpMapHead(code *Opcode) string { func (c *Opcode) dumpMapHead(code *Opcode) string {
return fmt.Sprintf( return fmt.Sprintf(
`[%d]%s%s ([idx:%d][elemIdx:%d][length:%d][mapIter:%d])`, `[%03d]%s%s ([idx:%d][elemIdx:%d][length:%d][mapIter:%d])`,
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", int(code.Indent)), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
@ -500,7 +461,7 @@ func (c *Opcode) dumpMapHead(code *Opcode) string {
func (c *Opcode) dumpMapEnd(code *Opcode) string { func (c *Opcode) dumpMapEnd(code *Opcode) string {
return fmt.Sprintf( return fmt.Sprintf(
`[%d]%s%s ([idx:%d][mapPos:%d][length:%d])`, `[%03d]%s%s ([idx:%d][mapPos:%d][length:%d])`,
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", int(code.Indent)), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
@ -518,7 +479,7 @@ func (c *Opcode) dumpElem(code *Opcode) string {
length = code.Length / uintptrSize length = code.Length / uintptrSize
} }
return fmt.Sprintf( return fmt.Sprintf(
`[%d]%s%s ([idx:%d][elemIdx:%d][length:%d][size:%d])`, `[%03d]%s%s ([idx:%d][elemIdx:%d][length:%d][size:%d])`,
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", int(code.Indent)), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
@ -531,7 +492,7 @@ func (c *Opcode) dumpElem(code *Opcode) string {
func (c *Opcode) dumpField(code *Opcode) string { func (c *Opcode) dumpField(code *Opcode) string {
return fmt.Sprintf( return fmt.Sprintf(
`[%d]%s%s ([idx:%d][key:%s][offset:%d])`, `[%03d]%s%s ([idx:%d][key:%s][offset:%d])`,
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", int(code.Indent)), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
@ -543,7 +504,7 @@ func (c *Opcode) dumpField(code *Opcode) string {
func (c *Opcode) dumpKey(code *Opcode) string { func (c *Opcode) dumpKey(code *Opcode) string {
return fmt.Sprintf( return fmt.Sprintf(
`[%d]%s%s ([idx:%d][elemIdx:%d][length:%d][mapIter:%d])`, `[%03d]%s%s ([idx:%d][elemIdx:%d][length:%d][mapIter:%d])`,
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", int(code.Indent)), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
@ -556,7 +517,7 @@ func (c *Opcode) dumpKey(code *Opcode) string {
func (c *Opcode) dumpValue(code *Opcode) string { func (c *Opcode) dumpValue(code *Opcode) string {
return fmt.Sprintf( return fmt.Sprintf(
`[%d]%s%s ([idx:%d][mapIter:%d])`, `[%03d]%s%s ([idx:%d][mapIter:%d])`,
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", int(code.Indent)), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
@ -567,7 +528,7 @@ func (c *Opcode) dumpValue(code *Opcode) string {
func (c *Opcode) Dump() string { func (c *Opcode) Dump() string {
codes := []string{} codes := []string{}
for code := c; code.Op != OpEnd && code.Op != OpInterfaceEnd; { for code := c; !code.IsEnd(); {
switch code.Op.CodeType() { switch code.Op.CodeType() {
case CodeSliceHead: case CodeSliceHead:
codes = append(codes, c.dumpHead(code)) codes = append(codes, c.dumpHead(code))
@ -595,7 +556,7 @@ func (c *Opcode) Dump() string {
code = code.Next code = code.Next
default: default:
codes = append(codes, fmt.Sprintf( codes = append(codes, fmt.Sprintf(
"[%d]%s%s ([idx:%d])", "[%03d]%s%s ([idx:%d])",
code.DisplayIdx, code.DisplayIdx,
strings.Repeat("-", int(code.Indent)), strings.Repeat("-", int(code.Indent)),
code.Op, code.Op,
@ -607,44 +568,7 @@ func (c *Opcode) Dump() string {
return strings.Join(codes, "\n") return strings.Join(codes, "\n")
} }
func prevField(code *Opcode, removedFields map[*Opcode]struct{}) *Opcode { func newSliceHeaderCode(ctx *compileContext, typ *runtime.Type) *Opcode {
if _, exists := removedFields[code]; exists {
return prevField(code.PrevField, removedFields)
}
return code
}
func nextField(code *Opcode, removedFields map[*Opcode]struct{}) *Opcode {
if _, exists := removedFields[code]; exists {
return nextField(code.NextField, removedFields)
}
return code
}
func linkPrevToNextField(cur *Opcode, removedFields map[*Opcode]struct{}) {
prev := prevField(cur.PrevField, removedFields)
prev.NextField = nextField(cur.NextField, removedFields)
code := prev
fcode := cur
for {
var nextCode *Opcode
switch code.Op.CodeType() {
case CodeArrayElem, CodeSliceElem, CodeMapKey:
nextCode = code.End
default:
nextCode = code.Next
}
if nextCode == fcode {
code.Next = fcode.NextField
break
} else if nextCode.Op == OpEnd {
break
}
code = nextCode
}
}
func newSliceHeaderCode(ctx *compileContext) *Opcode {
idx := opcodeOffset(ctx.ptrIndex) idx := opcodeOffset(ctx.ptrIndex)
ctx.incPtrIndex() ctx.incPtrIndex()
elemIdx := opcodeOffset(ctx.ptrIndex) elemIdx := opcodeOffset(ctx.ptrIndex)
@ -652,6 +576,7 @@ func newSliceHeaderCode(ctx *compileContext) *Opcode {
length := opcodeOffset(ctx.ptrIndex) length := opcodeOffset(ctx.ptrIndex)
return &Opcode{ return &Opcode{
Op: OpSlice, Op: OpSlice,
Type: typ,
Idx: idx, Idx: idx,
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
ElemIdx: elemIdx, ElemIdx: elemIdx,
@ -660,9 +585,10 @@ func newSliceHeaderCode(ctx *compileContext) *Opcode {
} }
} }
func newSliceElemCode(ctx *compileContext, head *Opcode, size uintptr) *Opcode { func newSliceElemCode(ctx *compileContext, typ *runtime.Type, head *Opcode, size uintptr) *Opcode {
return &Opcode{ return &Opcode{
Op: OpSliceElem, Op: OpSliceElem,
Type: typ,
Idx: head.Idx, Idx: head.Idx,
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
ElemIdx: head.ElemIdx, ElemIdx: head.ElemIdx,
@ -672,12 +598,13 @@ func newSliceElemCode(ctx *compileContext, head *Opcode, size uintptr) *Opcode {
} }
} }
func newArrayHeaderCode(ctx *compileContext, alen int) *Opcode { func newArrayHeaderCode(ctx *compileContext, typ *runtime.Type, alen int) *Opcode {
idx := opcodeOffset(ctx.ptrIndex) idx := opcodeOffset(ctx.ptrIndex)
ctx.incPtrIndex() ctx.incPtrIndex()
elemIdx := opcodeOffset(ctx.ptrIndex) elemIdx := opcodeOffset(ctx.ptrIndex)
return &Opcode{ return &Opcode{
Op: OpArray, Op: OpArray,
Type: typ,
Idx: idx, Idx: idx,
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
ElemIdx: elemIdx, ElemIdx: elemIdx,
@ -686,9 +613,10 @@ func newArrayHeaderCode(ctx *compileContext, alen int) *Opcode {
} }
} }
func newArrayElemCode(ctx *compileContext, head *Opcode, length int, size uintptr) *Opcode { func newArrayElemCode(ctx *compileContext, typ *runtime.Type, head *Opcode, length int, size uintptr) *Opcode {
return &Opcode{ return &Opcode{
Op: OpArrayElem, Op: OpArrayElem,
Type: typ,
Idx: head.Idx, Idx: head.Idx,
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
ElemIdx: head.ElemIdx, ElemIdx: head.ElemIdx,
@ -698,7 +626,7 @@ func newArrayElemCode(ctx *compileContext, head *Opcode, length int, size uintpt
} }
} }
func newMapHeaderCode(ctx *compileContext) *Opcode { func newMapHeaderCode(ctx *compileContext, typ *runtime.Type) *Opcode {
idx := opcodeOffset(ctx.ptrIndex) idx := opcodeOffset(ctx.ptrIndex)
ctx.incPtrIndex() ctx.incPtrIndex()
elemIdx := opcodeOffset(ctx.ptrIndex) elemIdx := opcodeOffset(ctx.ptrIndex)
@ -708,8 +636,8 @@ func newMapHeaderCode(ctx *compileContext) *Opcode {
mapIter := opcodeOffset(ctx.ptrIndex) mapIter := opcodeOffset(ctx.ptrIndex)
return &Opcode{ return &Opcode{
Op: OpMap, Op: OpMap,
Type: typ,
Idx: idx, Idx: idx,
Type: ctx.typ,
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
ElemIdx: elemIdx, ElemIdx: elemIdx,
Length: length, Length: length,
@ -718,9 +646,10 @@ func newMapHeaderCode(ctx *compileContext) *Opcode {
} }
} }
func newMapKeyCode(ctx *compileContext, head *Opcode) *Opcode { func newMapKeyCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode {
return &Opcode{ return &Opcode{
Op: OpMapKey, Op: OpMapKey,
Type: typ,
Idx: opcodeOffset(ctx.ptrIndex), Idx: opcodeOffset(ctx.ptrIndex),
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
ElemIdx: head.ElemIdx, ElemIdx: head.ElemIdx,
@ -730,9 +659,10 @@ func newMapKeyCode(ctx *compileContext, head *Opcode) *Opcode {
} }
} }
func newMapValueCode(ctx *compileContext, head *Opcode) *Opcode { func newMapValueCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode {
return &Opcode{ return &Opcode{
Op: OpMapValue, Op: OpMapValue,
Type: typ,
Idx: opcodeOffset(ctx.ptrIndex), Idx: opcodeOffset(ctx.ptrIndex),
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
ElemIdx: head.ElemIdx, ElemIdx: head.ElemIdx,
@ -742,14 +672,15 @@ func newMapValueCode(ctx *compileContext, head *Opcode) *Opcode {
} }
} }
func newMapEndCode(ctx *compileContext, head *Opcode) *Opcode { func newMapEndCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode {
mapPos := opcodeOffset(ctx.ptrIndex) mapPos := opcodeOffset(ctx.ptrIndex)
ctx.incPtrIndex() ctx.incPtrIndex()
idx := opcodeOffset(ctx.ptrIndex) idx := opcodeOffset(ctx.ptrIndex)
return &Opcode{ return &Opcode{
Op: OpMapEnd, Op: OpMapEnd,
Type: typ,
Idx: idx, Idx: idx,
Next: newEndOp(ctx), Next: newEndOp(ctx, typ),
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
Length: head.Length, Length: head.Length,
MapPos: mapPos, MapPos: mapPos,
@ -757,28 +688,12 @@ func newMapEndCode(ctx *compileContext, head *Opcode) *Opcode {
} }
} }
func newInterfaceCode(ctx *compileContext) *Opcode { func newRecursiveCode(ctx *compileContext, typ *runtime.Type, jmp *CompiledCode) *Opcode {
var flag OpFlags
if ctx.typ.NumMethod() > 0 {
flag |= NonEmptyInterfaceFlags
}
return &Opcode{
Op: OpInterface,
Idx: opcodeOffset(ctx.ptrIndex),
Next: newEndOp(ctx),
Type: ctx.typ,
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
Flags: flag,
}
}
func newRecursiveCode(ctx *compileContext, jmp *CompiledCode) *Opcode {
return &Opcode{ return &Opcode{
Op: OpRecursive, Op: OpRecursive,
Type: typ,
Idx: opcodeOffset(ctx.ptrIndex), Idx: opcodeOffset(ctx.ptrIndex),
Next: newEndOp(ctx), Next: newEndOp(ctx, typ),
Type: ctx.typ,
DisplayIdx: ctx.opcodeIndex, DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent, Indent: ctx.indent,
Jmp: jmp, Jmp: jmp,

View File

@ -22,7 +22,7 @@ const (
CodeStructEnd CodeType = 11 CodeStructEnd CodeType = 11
) )
var opTypeStrings = [401]string{ var opTypeStrings = [400]string{
"End", "End",
"Interface", "Interface",
"Ptr", "Ptr",
@ -37,7 +37,6 @@ var opTypeStrings = [401]string{
"RecursivePtr", "RecursivePtr",
"RecursiveEnd", "RecursiveEnd",
"InterfaceEnd", "InterfaceEnd",
"StructAnonymousEnd",
"Int", "Int",
"Uint", "Uint",
"Float32", "Float32",
@ -443,397 +442,396 @@ const (
OpRecursivePtr OpType = 11 OpRecursivePtr OpType = 11
OpRecursiveEnd OpType = 12 OpRecursiveEnd OpType = 12
OpInterfaceEnd OpType = 13 OpInterfaceEnd OpType = 13
OpStructAnonymousEnd OpType = 14 OpInt OpType = 14
OpInt OpType = 15 OpUint OpType = 15
OpUint OpType = 16 OpFloat32 OpType = 16
OpFloat32 OpType = 17 OpFloat64 OpType = 17
OpFloat64 OpType = 18 OpBool OpType = 18
OpBool OpType = 19 OpString OpType = 19
OpString OpType = 20 OpBytes OpType = 20
OpBytes OpType = 21 OpNumber OpType = 21
OpNumber OpType = 22 OpArray OpType = 22
OpArray OpType = 23 OpMap OpType = 23
OpMap OpType = 24 OpSlice OpType = 24
OpSlice OpType = 25 OpStruct OpType = 25
OpStruct OpType = 26 OpMarshalJSON OpType = 26
OpMarshalJSON OpType = 27 OpMarshalText OpType = 27
OpMarshalText OpType = 28 OpIntString OpType = 28
OpIntString OpType = 29 OpUintString OpType = 29
OpUintString OpType = 30 OpFloat32String OpType = 30
OpFloat32String OpType = 31 OpFloat64String OpType = 31
OpFloat64String OpType = 32 OpBoolString OpType = 32
OpBoolString OpType = 33 OpStringString OpType = 33
OpStringString OpType = 34 OpNumberString OpType = 34
OpNumberString OpType = 35 OpIntPtr OpType = 35
OpIntPtr OpType = 36 OpUintPtr OpType = 36
OpUintPtr OpType = 37 OpFloat32Ptr OpType = 37
OpFloat32Ptr OpType = 38 OpFloat64Ptr OpType = 38
OpFloat64Ptr OpType = 39 OpBoolPtr OpType = 39
OpBoolPtr OpType = 40 OpStringPtr OpType = 40
OpStringPtr OpType = 41 OpBytesPtr OpType = 41
OpBytesPtr OpType = 42 OpNumberPtr OpType = 42
OpNumberPtr OpType = 43 OpArrayPtr OpType = 43
OpArrayPtr OpType = 44 OpMapPtr OpType = 44
OpMapPtr OpType = 45 OpSlicePtr OpType = 45
OpSlicePtr OpType = 46 OpMarshalJSONPtr OpType = 46
OpMarshalJSONPtr OpType = 47 OpMarshalTextPtr OpType = 47
OpMarshalTextPtr OpType = 48 OpInterfacePtr OpType = 48
OpInterfacePtr OpType = 49 OpIntPtrString OpType = 49
OpIntPtrString OpType = 50 OpUintPtrString OpType = 50
OpUintPtrString OpType = 51 OpFloat32PtrString OpType = 51
OpFloat32PtrString OpType = 52 OpFloat64PtrString OpType = 52
OpFloat64PtrString OpType = 53 OpBoolPtrString OpType = 53
OpBoolPtrString OpType = 54 OpStringPtrString OpType = 54
OpStringPtrString OpType = 55 OpNumberPtrString OpType = 55
OpNumberPtrString OpType = 56 OpStructHeadInt OpType = 56
OpStructHeadInt OpType = 57 OpStructHeadOmitEmptyInt OpType = 57
OpStructHeadOmitEmptyInt OpType = 58 OpStructPtrHeadInt OpType = 58
OpStructPtrHeadInt OpType = 59 OpStructPtrHeadOmitEmptyInt OpType = 59
OpStructPtrHeadOmitEmptyInt OpType = 60 OpStructHeadUint OpType = 60
OpStructHeadUint OpType = 61 OpStructHeadOmitEmptyUint OpType = 61
OpStructHeadOmitEmptyUint OpType = 62 OpStructPtrHeadUint OpType = 62
OpStructPtrHeadUint OpType = 63 OpStructPtrHeadOmitEmptyUint OpType = 63
OpStructPtrHeadOmitEmptyUint OpType = 64 OpStructHeadFloat32 OpType = 64
OpStructHeadFloat32 OpType = 65 OpStructHeadOmitEmptyFloat32 OpType = 65
OpStructHeadOmitEmptyFloat32 OpType = 66 OpStructPtrHeadFloat32 OpType = 66
OpStructPtrHeadFloat32 OpType = 67 OpStructPtrHeadOmitEmptyFloat32 OpType = 67
OpStructPtrHeadOmitEmptyFloat32 OpType = 68 OpStructHeadFloat64 OpType = 68
OpStructHeadFloat64 OpType = 69 OpStructHeadOmitEmptyFloat64 OpType = 69
OpStructHeadOmitEmptyFloat64 OpType = 70 OpStructPtrHeadFloat64 OpType = 70
OpStructPtrHeadFloat64 OpType = 71 OpStructPtrHeadOmitEmptyFloat64 OpType = 71
OpStructPtrHeadOmitEmptyFloat64 OpType = 72 OpStructHeadBool OpType = 72
OpStructHeadBool OpType = 73 OpStructHeadOmitEmptyBool OpType = 73
OpStructHeadOmitEmptyBool OpType = 74 OpStructPtrHeadBool OpType = 74
OpStructPtrHeadBool OpType = 75 OpStructPtrHeadOmitEmptyBool OpType = 75
OpStructPtrHeadOmitEmptyBool OpType = 76 OpStructHeadString OpType = 76
OpStructHeadString OpType = 77 OpStructHeadOmitEmptyString OpType = 77
OpStructHeadOmitEmptyString OpType = 78 OpStructPtrHeadString OpType = 78
OpStructPtrHeadString OpType = 79 OpStructPtrHeadOmitEmptyString OpType = 79
OpStructPtrHeadOmitEmptyString OpType = 80 OpStructHeadBytes OpType = 80
OpStructHeadBytes OpType = 81 OpStructHeadOmitEmptyBytes OpType = 81
OpStructHeadOmitEmptyBytes OpType = 82 OpStructPtrHeadBytes OpType = 82
OpStructPtrHeadBytes OpType = 83 OpStructPtrHeadOmitEmptyBytes OpType = 83
OpStructPtrHeadOmitEmptyBytes OpType = 84 OpStructHeadNumber OpType = 84
OpStructHeadNumber OpType = 85 OpStructHeadOmitEmptyNumber OpType = 85
OpStructHeadOmitEmptyNumber OpType = 86 OpStructPtrHeadNumber OpType = 86
OpStructPtrHeadNumber OpType = 87 OpStructPtrHeadOmitEmptyNumber OpType = 87
OpStructPtrHeadOmitEmptyNumber OpType = 88 OpStructHeadArray OpType = 88
OpStructHeadArray OpType = 89 OpStructHeadOmitEmptyArray OpType = 89
OpStructHeadOmitEmptyArray OpType = 90 OpStructPtrHeadArray OpType = 90
OpStructPtrHeadArray OpType = 91 OpStructPtrHeadOmitEmptyArray OpType = 91
OpStructPtrHeadOmitEmptyArray OpType = 92 OpStructHeadMap OpType = 92
OpStructHeadMap OpType = 93 OpStructHeadOmitEmptyMap OpType = 93
OpStructHeadOmitEmptyMap OpType = 94 OpStructPtrHeadMap OpType = 94
OpStructPtrHeadMap OpType = 95 OpStructPtrHeadOmitEmptyMap OpType = 95
OpStructPtrHeadOmitEmptyMap OpType = 96 OpStructHeadSlice OpType = 96
OpStructHeadSlice OpType = 97 OpStructHeadOmitEmptySlice OpType = 97
OpStructHeadOmitEmptySlice OpType = 98 OpStructPtrHeadSlice OpType = 98
OpStructPtrHeadSlice OpType = 99 OpStructPtrHeadOmitEmptySlice OpType = 99
OpStructPtrHeadOmitEmptySlice OpType = 100 OpStructHeadStruct OpType = 100
OpStructHeadStruct OpType = 101 OpStructHeadOmitEmptyStruct OpType = 101
OpStructHeadOmitEmptyStruct OpType = 102 OpStructPtrHeadStruct OpType = 102
OpStructPtrHeadStruct OpType = 103 OpStructPtrHeadOmitEmptyStruct OpType = 103
OpStructPtrHeadOmitEmptyStruct OpType = 104 OpStructHeadMarshalJSON OpType = 104
OpStructHeadMarshalJSON OpType = 105 OpStructHeadOmitEmptyMarshalJSON OpType = 105
OpStructHeadOmitEmptyMarshalJSON OpType = 106 OpStructPtrHeadMarshalJSON OpType = 106
OpStructPtrHeadMarshalJSON OpType = 107 OpStructPtrHeadOmitEmptyMarshalJSON OpType = 107
OpStructPtrHeadOmitEmptyMarshalJSON OpType = 108 OpStructHeadMarshalText OpType = 108
OpStructHeadMarshalText OpType = 109 OpStructHeadOmitEmptyMarshalText OpType = 109
OpStructHeadOmitEmptyMarshalText OpType = 110 OpStructPtrHeadMarshalText OpType = 110
OpStructPtrHeadMarshalText OpType = 111 OpStructPtrHeadOmitEmptyMarshalText OpType = 111
OpStructPtrHeadOmitEmptyMarshalText OpType = 112 OpStructHeadIntString OpType = 112
OpStructHeadIntString OpType = 113 OpStructHeadOmitEmptyIntString OpType = 113
OpStructHeadOmitEmptyIntString OpType = 114 OpStructPtrHeadIntString OpType = 114
OpStructPtrHeadIntString OpType = 115 OpStructPtrHeadOmitEmptyIntString OpType = 115
OpStructPtrHeadOmitEmptyIntString OpType = 116 OpStructHeadUintString OpType = 116
OpStructHeadUintString OpType = 117 OpStructHeadOmitEmptyUintString OpType = 117
OpStructHeadOmitEmptyUintString OpType = 118 OpStructPtrHeadUintString OpType = 118
OpStructPtrHeadUintString OpType = 119 OpStructPtrHeadOmitEmptyUintString OpType = 119
OpStructPtrHeadOmitEmptyUintString OpType = 120 OpStructHeadFloat32String OpType = 120
OpStructHeadFloat32String OpType = 121 OpStructHeadOmitEmptyFloat32String OpType = 121
OpStructHeadOmitEmptyFloat32String OpType = 122 OpStructPtrHeadFloat32String OpType = 122
OpStructPtrHeadFloat32String OpType = 123 OpStructPtrHeadOmitEmptyFloat32String OpType = 123
OpStructPtrHeadOmitEmptyFloat32String OpType = 124 OpStructHeadFloat64String OpType = 124
OpStructHeadFloat64String OpType = 125 OpStructHeadOmitEmptyFloat64String OpType = 125
OpStructHeadOmitEmptyFloat64String OpType = 126 OpStructPtrHeadFloat64String OpType = 126
OpStructPtrHeadFloat64String OpType = 127 OpStructPtrHeadOmitEmptyFloat64String OpType = 127
OpStructPtrHeadOmitEmptyFloat64String OpType = 128 OpStructHeadBoolString OpType = 128
OpStructHeadBoolString OpType = 129 OpStructHeadOmitEmptyBoolString OpType = 129
OpStructHeadOmitEmptyBoolString OpType = 130 OpStructPtrHeadBoolString OpType = 130
OpStructPtrHeadBoolString OpType = 131 OpStructPtrHeadOmitEmptyBoolString OpType = 131
OpStructPtrHeadOmitEmptyBoolString OpType = 132 OpStructHeadStringString OpType = 132
OpStructHeadStringString OpType = 133 OpStructHeadOmitEmptyStringString OpType = 133
OpStructHeadOmitEmptyStringString OpType = 134 OpStructPtrHeadStringString OpType = 134
OpStructPtrHeadStringString OpType = 135 OpStructPtrHeadOmitEmptyStringString OpType = 135
OpStructPtrHeadOmitEmptyStringString OpType = 136 OpStructHeadNumberString OpType = 136
OpStructHeadNumberString OpType = 137 OpStructHeadOmitEmptyNumberString OpType = 137
OpStructHeadOmitEmptyNumberString OpType = 138 OpStructPtrHeadNumberString OpType = 138
OpStructPtrHeadNumberString OpType = 139 OpStructPtrHeadOmitEmptyNumberString OpType = 139
OpStructPtrHeadOmitEmptyNumberString OpType = 140 OpStructHeadIntPtr OpType = 140
OpStructHeadIntPtr OpType = 141 OpStructHeadOmitEmptyIntPtr OpType = 141
OpStructHeadOmitEmptyIntPtr OpType = 142 OpStructPtrHeadIntPtr OpType = 142
OpStructPtrHeadIntPtr OpType = 143 OpStructPtrHeadOmitEmptyIntPtr OpType = 143
OpStructPtrHeadOmitEmptyIntPtr OpType = 144 OpStructHeadUintPtr OpType = 144
OpStructHeadUintPtr OpType = 145 OpStructHeadOmitEmptyUintPtr OpType = 145
OpStructHeadOmitEmptyUintPtr OpType = 146 OpStructPtrHeadUintPtr OpType = 146
OpStructPtrHeadUintPtr OpType = 147 OpStructPtrHeadOmitEmptyUintPtr OpType = 147
OpStructPtrHeadOmitEmptyUintPtr OpType = 148 OpStructHeadFloat32Ptr OpType = 148
OpStructHeadFloat32Ptr OpType = 149 OpStructHeadOmitEmptyFloat32Ptr OpType = 149
OpStructHeadOmitEmptyFloat32Ptr OpType = 150 OpStructPtrHeadFloat32Ptr OpType = 150
OpStructPtrHeadFloat32Ptr OpType = 151 OpStructPtrHeadOmitEmptyFloat32Ptr OpType = 151
OpStructPtrHeadOmitEmptyFloat32Ptr OpType = 152 OpStructHeadFloat64Ptr OpType = 152
OpStructHeadFloat64Ptr OpType = 153 OpStructHeadOmitEmptyFloat64Ptr OpType = 153
OpStructHeadOmitEmptyFloat64Ptr OpType = 154 OpStructPtrHeadFloat64Ptr OpType = 154
OpStructPtrHeadFloat64Ptr OpType = 155 OpStructPtrHeadOmitEmptyFloat64Ptr OpType = 155
OpStructPtrHeadOmitEmptyFloat64Ptr OpType = 156 OpStructHeadBoolPtr OpType = 156
OpStructHeadBoolPtr OpType = 157 OpStructHeadOmitEmptyBoolPtr OpType = 157
OpStructHeadOmitEmptyBoolPtr OpType = 158 OpStructPtrHeadBoolPtr OpType = 158
OpStructPtrHeadBoolPtr OpType = 159 OpStructPtrHeadOmitEmptyBoolPtr OpType = 159
OpStructPtrHeadOmitEmptyBoolPtr OpType = 160 OpStructHeadStringPtr OpType = 160
OpStructHeadStringPtr OpType = 161 OpStructHeadOmitEmptyStringPtr OpType = 161
OpStructHeadOmitEmptyStringPtr OpType = 162 OpStructPtrHeadStringPtr OpType = 162
OpStructPtrHeadStringPtr OpType = 163 OpStructPtrHeadOmitEmptyStringPtr OpType = 163
OpStructPtrHeadOmitEmptyStringPtr OpType = 164 OpStructHeadBytesPtr OpType = 164
OpStructHeadBytesPtr OpType = 165 OpStructHeadOmitEmptyBytesPtr OpType = 165
OpStructHeadOmitEmptyBytesPtr OpType = 166 OpStructPtrHeadBytesPtr OpType = 166
OpStructPtrHeadBytesPtr OpType = 167 OpStructPtrHeadOmitEmptyBytesPtr OpType = 167
OpStructPtrHeadOmitEmptyBytesPtr OpType = 168 OpStructHeadNumberPtr OpType = 168
OpStructHeadNumberPtr OpType = 169 OpStructHeadOmitEmptyNumberPtr OpType = 169
OpStructHeadOmitEmptyNumberPtr OpType = 170 OpStructPtrHeadNumberPtr OpType = 170
OpStructPtrHeadNumberPtr OpType = 171 OpStructPtrHeadOmitEmptyNumberPtr OpType = 171
OpStructPtrHeadOmitEmptyNumberPtr OpType = 172 OpStructHeadArrayPtr OpType = 172
OpStructHeadArrayPtr OpType = 173 OpStructHeadOmitEmptyArrayPtr OpType = 173
OpStructHeadOmitEmptyArrayPtr OpType = 174 OpStructPtrHeadArrayPtr OpType = 174
OpStructPtrHeadArrayPtr OpType = 175 OpStructPtrHeadOmitEmptyArrayPtr OpType = 175
OpStructPtrHeadOmitEmptyArrayPtr OpType = 176 OpStructHeadMapPtr OpType = 176
OpStructHeadMapPtr OpType = 177 OpStructHeadOmitEmptyMapPtr OpType = 177
OpStructHeadOmitEmptyMapPtr OpType = 178 OpStructPtrHeadMapPtr OpType = 178
OpStructPtrHeadMapPtr OpType = 179 OpStructPtrHeadOmitEmptyMapPtr OpType = 179
OpStructPtrHeadOmitEmptyMapPtr OpType = 180 OpStructHeadSlicePtr OpType = 180
OpStructHeadSlicePtr OpType = 181 OpStructHeadOmitEmptySlicePtr OpType = 181
OpStructHeadOmitEmptySlicePtr OpType = 182 OpStructPtrHeadSlicePtr OpType = 182
OpStructPtrHeadSlicePtr OpType = 183 OpStructPtrHeadOmitEmptySlicePtr OpType = 183
OpStructPtrHeadOmitEmptySlicePtr OpType = 184 OpStructHeadMarshalJSONPtr OpType = 184
OpStructHeadMarshalJSONPtr OpType = 185 OpStructHeadOmitEmptyMarshalJSONPtr OpType = 185
OpStructHeadOmitEmptyMarshalJSONPtr OpType = 186 OpStructPtrHeadMarshalJSONPtr OpType = 186
OpStructPtrHeadMarshalJSONPtr OpType = 187 OpStructPtrHeadOmitEmptyMarshalJSONPtr OpType = 187
OpStructPtrHeadOmitEmptyMarshalJSONPtr OpType = 188 OpStructHeadMarshalTextPtr OpType = 188
OpStructHeadMarshalTextPtr OpType = 189 OpStructHeadOmitEmptyMarshalTextPtr OpType = 189
OpStructHeadOmitEmptyMarshalTextPtr OpType = 190 OpStructPtrHeadMarshalTextPtr OpType = 190
OpStructPtrHeadMarshalTextPtr OpType = 191 OpStructPtrHeadOmitEmptyMarshalTextPtr OpType = 191
OpStructPtrHeadOmitEmptyMarshalTextPtr OpType = 192 OpStructHeadInterfacePtr OpType = 192
OpStructHeadInterfacePtr OpType = 193 OpStructHeadOmitEmptyInterfacePtr OpType = 193
OpStructHeadOmitEmptyInterfacePtr OpType = 194 OpStructPtrHeadInterfacePtr OpType = 194
OpStructPtrHeadInterfacePtr OpType = 195 OpStructPtrHeadOmitEmptyInterfacePtr OpType = 195
OpStructPtrHeadOmitEmptyInterfacePtr OpType = 196 OpStructHeadIntPtrString OpType = 196
OpStructHeadIntPtrString OpType = 197 OpStructHeadOmitEmptyIntPtrString OpType = 197
OpStructHeadOmitEmptyIntPtrString OpType = 198 OpStructPtrHeadIntPtrString OpType = 198
OpStructPtrHeadIntPtrString OpType = 199 OpStructPtrHeadOmitEmptyIntPtrString OpType = 199
OpStructPtrHeadOmitEmptyIntPtrString OpType = 200 OpStructHeadUintPtrString OpType = 200
OpStructHeadUintPtrString OpType = 201 OpStructHeadOmitEmptyUintPtrString OpType = 201
OpStructHeadOmitEmptyUintPtrString OpType = 202 OpStructPtrHeadUintPtrString OpType = 202
OpStructPtrHeadUintPtrString OpType = 203 OpStructPtrHeadOmitEmptyUintPtrString OpType = 203
OpStructPtrHeadOmitEmptyUintPtrString OpType = 204 OpStructHeadFloat32PtrString OpType = 204
OpStructHeadFloat32PtrString OpType = 205 OpStructHeadOmitEmptyFloat32PtrString OpType = 205
OpStructHeadOmitEmptyFloat32PtrString OpType = 206 OpStructPtrHeadFloat32PtrString OpType = 206
OpStructPtrHeadFloat32PtrString OpType = 207 OpStructPtrHeadOmitEmptyFloat32PtrString OpType = 207
OpStructPtrHeadOmitEmptyFloat32PtrString OpType = 208 OpStructHeadFloat64PtrString OpType = 208
OpStructHeadFloat64PtrString OpType = 209 OpStructHeadOmitEmptyFloat64PtrString OpType = 209
OpStructHeadOmitEmptyFloat64PtrString OpType = 210 OpStructPtrHeadFloat64PtrString OpType = 210
OpStructPtrHeadFloat64PtrString OpType = 211 OpStructPtrHeadOmitEmptyFloat64PtrString OpType = 211
OpStructPtrHeadOmitEmptyFloat64PtrString OpType = 212 OpStructHeadBoolPtrString OpType = 212
OpStructHeadBoolPtrString OpType = 213 OpStructHeadOmitEmptyBoolPtrString OpType = 213
OpStructHeadOmitEmptyBoolPtrString OpType = 214 OpStructPtrHeadBoolPtrString OpType = 214
OpStructPtrHeadBoolPtrString OpType = 215 OpStructPtrHeadOmitEmptyBoolPtrString OpType = 215
OpStructPtrHeadOmitEmptyBoolPtrString OpType = 216 OpStructHeadStringPtrString OpType = 216
OpStructHeadStringPtrString OpType = 217 OpStructHeadOmitEmptyStringPtrString OpType = 217
OpStructHeadOmitEmptyStringPtrString OpType = 218 OpStructPtrHeadStringPtrString OpType = 218
OpStructPtrHeadStringPtrString OpType = 219 OpStructPtrHeadOmitEmptyStringPtrString OpType = 219
OpStructPtrHeadOmitEmptyStringPtrString OpType = 220 OpStructHeadNumberPtrString OpType = 220
OpStructHeadNumberPtrString OpType = 221 OpStructHeadOmitEmptyNumberPtrString OpType = 221
OpStructHeadOmitEmptyNumberPtrString OpType = 222 OpStructPtrHeadNumberPtrString OpType = 222
OpStructPtrHeadNumberPtrString OpType = 223 OpStructPtrHeadOmitEmptyNumberPtrString OpType = 223
OpStructPtrHeadOmitEmptyNumberPtrString OpType = 224 OpStructHead OpType = 224
OpStructHead OpType = 225 OpStructHeadOmitEmpty OpType = 225
OpStructHeadOmitEmpty OpType = 226 OpStructPtrHead OpType = 226
OpStructPtrHead OpType = 227 OpStructPtrHeadOmitEmpty OpType = 227
OpStructPtrHeadOmitEmpty OpType = 228 OpStructFieldInt OpType = 228
OpStructFieldInt OpType = 229 OpStructFieldOmitEmptyInt OpType = 229
OpStructFieldOmitEmptyInt OpType = 230 OpStructEndInt OpType = 230
OpStructEndInt OpType = 231 OpStructEndOmitEmptyInt OpType = 231
OpStructEndOmitEmptyInt OpType = 232 OpStructFieldUint OpType = 232
OpStructFieldUint OpType = 233 OpStructFieldOmitEmptyUint OpType = 233
OpStructFieldOmitEmptyUint OpType = 234 OpStructEndUint OpType = 234
OpStructEndUint OpType = 235 OpStructEndOmitEmptyUint OpType = 235
OpStructEndOmitEmptyUint OpType = 236 OpStructFieldFloat32 OpType = 236
OpStructFieldFloat32 OpType = 237 OpStructFieldOmitEmptyFloat32 OpType = 237
OpStructFieldOmitEmptyFloat32 OpType = 238 OpStructEndFloat32 OpType = 238
OpStructEndFloat32 OpType = 239 OpStructEndOmitEmptyFloat32 OpType = 239
OpStructEndOmitEmptyFloat32 OpType = 240 OpStructFieldFloat64 OpType = 240
OpStructFieldFloat64 OpType = 241 OpStructFieldOmitEmptyFloat64 OpType = 241
OpStructFieldOmitEmptyFloat64 OpType = 242 OpStructEndFloat64 OpType = 242
OpStructEndFloat64 OpType = 243 OpStructEndOmitEmptyFloat64 OpType = 243
OpStructEndOmitEmptyFloat64 OpType = 244 OpStructFieldBool OpType = 244
OpStructFieldBool OpType = 245 OpStructFieldOmitEmptyBool OpType = 245
OpStructFieldOmitEmptyBool OpType = 246 OpStructEndBool OpType = 246
OpStructEndBool OpType = 247 OpStructEndOmitEmptyBool OpType = 247
OpStructEndOmitEmptyBool OpType = 248 OpStructFieldString OpType = 248
OpStructFieldString OpType = 249 OpStructFieldOmitEmptyString OpType = 249
OpStructFieldOmitEmptyString OpType = 250 OpStructEndString OpType = 250
OpStructEndString OpType = 251 OpStructEndOmitEmptyString OpType = 251
OpStructEndOmitEmptyString OpType = 252 OpStructFieldBytes OpType = 252
OpStructFieldBytes OpType = 253 OpStructFieldOmitEmptyBytes OpType = 253
OpStructFieldOmitEmptyBytes OpType = 254 OpStructEndBytes OpType = 254
OpStructEndBytes OpType = 255 OpStructEndOmitEmptyBytes OpType = 255
OpStructEndOmitEmptyBytes OpType = 256 OpStructFieldNumber OpType = 256
OpStructFieldNumber OpType = 257 OpStructFieldOmitEmptyNumber OpType = 257
OpStructFieldOmitEmptyNumber OpType = 258 OpStructEndNumber OpType = 258
OpStructEndNumber OpType = 259 OpStructEndOmitEmptyNumber OpType = 259
OpStructEndOmitEmptyNumber OpType = 260 OpStructFieldArray OpType = 260
OpStructFieldArray OpType = 261 OpStructFieldOmitEmptyArray OpType = 261
OpStructFieldOmitEmptyArray OpType = 262 OpStructEndArray OpType = 262
OpStructEndArray OpType = 263 OpStructEndOmitEmptyArray OpType = 263
OpStructEndOmitEmptyArray OpType = 264 OpStructFieldMap OpType = 264
OpStructFieldMap OpType = 265 OpStructFieldOmitEmptyMap OpType = 265
OpStructFieldOmitEmptyMap OpType = 266 OpStructEndMap OpType = 266
OpStructEndMap OpType = 267 OpStructEndOmitEmptyMap OpType = 267
OpStructEndOmitEmptyMap OpType = 268 OpStructFieldSlice OpType = 268
OpStructFieldSlice OpType = 269 OpStructFieldOmitEmptySlice OpType = 269
OpStructFieldOmitEmptySlice OpType = 270 OpStructEndSlice OpType = 270
OpStructEndSlice OpType = 271 OpStructEndOmitEmptySlice OpType = 271
OpStructEndOmitEmptySlice OpType = 272 OpStructFieldStruct OpType = 272
OpStructFieldStruct OpType = 273 OpStructFieldOmitEmptyStruct OpType = 273
OpStructFieldOmitEmptyStruct OpType = 274 OpStructEndStruct OpType = 274
OpStructEndStruct OpType = 275 OpStructEndOmitEmptyStruct OpType = 275
OpStructEndOmitEmptyStruct OpType = 276 OpStructFieldMarshalJSON OpType = 276
OpStructFieldMarshalJSON OpType = 277 OpStructFieldOmitEmptyMarshalJSON OpType = 277
OpStructFieldOmitEmptyMarshalJSON OpType = 278 OpStructEndMarshalJSON OpType = 278
OpStructEndMarshalJSON OpType = 279 OpStructEndOmitEmptyMarshalJSON OpType = 279
OpStructEndOmitEmptyMarshalJSON OpType = 280 OpStructFieldMarshalText OpType = 280
OpStructFieldMarshalText OpType = 281 OpStructFieldOmitEmptyMarshalText OpType = 281
OpStructFieldOmitEmptyMarshalText OpType = 282 OpStructEndMarshalText OpType = 282
OpStructEndMarshalText OpType = 283 OpStructEndOmitEmptyMarshalText OpType = 283
OpStructEndOmitEmptyMarshalText OpType = 284 OpStructFieldIntString OpType = 284
OpStructFieldIntString OpType = 285 OpStructFieldOmitEmptyIntString OpType = 285
OpStructFieldOmitEmptyIntString OpType = 286 OpStructEndIntString OpType = 286
OpStructEndIntString OpType = 287 OpStructEndOmitEmptyIntString OpType = 287
OpStructEndOmitEmptyIntString OpType = 288 OpStructFieldUintString OpType = 288
OpStructFieldUintString OpType = 289 OpStructFieldOmitEmptyUintString OpType = 289
OpStructFieldOmitEmptyUintString OpType = 290 OpStructEndUintString OpType = 290
OpStructEndUintString OpType = 291 OpStructEndOmitEmptyUintString OpType = 291
OpStructEndOmitEmptyUintString OpType = 292 OpStructFieldFloat32String OpType = 292
OpStructFieldFloat32String OpType = 293 OpStructFieldOmitEmptyFloat32String OpType = 293
OpStructFieldOmitEmptyFloat32String OpType = 294 OpStructEndFloat32String OpType = 294
OpStructEndFloat32String OpType = 295 OpStructEndOmitEmptyFloat32String OpType = 295
OpStructEndOmitEmptyFloat32String OpType = 296 OpStructFieldFloat64String OpType = 296
OpStructFieldFloat64String OpType = 297 OpStructFieldOmitEmptyFloat64String OpType = 297
OpStructFieldOmitEmptyFloat64String OpType = 298 OpStructEndFloat64String OpType = 298
OpStructEndFloat64String OpType = 299 OpStructEndOmitEmptyFloat64String OpType = 299
OpStructEndOmitEmptyFloat64String OpType = 300 OpStructFieldBoolString OpType = 300
OpStructFieldBoolString OpType = 301 OpStructFieldOmitEmptyBoolString OpType = 301
OpStructFieldOmitEmptyBoolString OpType = 302 OpStructEndBoolString OpType = 302
OpStructEndBoolString OpType = 303 OpStructEndOmitEmptyBoolString OpType = 303
OpStructEndOmitEmptyBoolString OpType = 304 OpStructFieldStringString OpType = 304
OpStructFieldStringString OpType = 305 OpStructFieldOmitEmptyStringString OpType = 305
OpStructFieldOmitEmptyStringString OpType = 306 OpStructEndStringString OpType = 306
OpStructEndStringString OpType = 307 OpStructEndOmitEmptyStringString OpType = 307
OpStructEndOmitEmptyStringString OpType = 308 OpStructFieldNumberString OpType = 308
OpStructFieldNumberString OpType = 309 OpStructFieldOmitEmptyNumberString OpType = 309
OpStructFieldOmitEmptyNumberString OpType = 310 OpStructEndNumberString OpType = 310
OpStructEndNumberString OpType = 311 OpStructEndOmitEmptyNumberString OpType = 311
OpStructEndOmitEmptyNumberString OpType = 312 OpStructFieldIntPtr OpType = 312
OpStructFieldIntPtr OpType = 313 OpStructFieldOmitEmptyIntPtr OpType = 313
OpStructFieldOmitEmptyIntPtr OpType = 314 OpStructEndIntPtr OpType = 314
OpStructEndIntPtr OpType = 315 OpStructEndOmitEmptyIntPtr OpType = 315
OpStructEndOmitEmptyIntPtr OpType = 316 OpStructFieldUintPtr OpType = 316
OpStructFieldUintPtr OpType = 317 OpStructFieldOmitEmptyUintPtr OpType = 317
OpStructFieldOmitEmptyUintPtr OpType = 318 OpStructEndUintPtr OpType = 318
OpStructEndUintPtr OpType = 319 OpStructEndOmitEmptyUintPtr OpType = 319
OpStructEndOmitEmptyUintPtr OpType = 320 OpStructFieldFloat32Ptr OpType = 320
OpStructFieldFloat32Ptr OpType = 321 OpStructFieldOmitEmptyFloat32Ptr OpType = 321
OpStructFieldOmitEmptyFloat32Ptr OpType = 322 OpStructEndFloat32Ptr OpType = 322
OpStructEndFloat32Ptr OpType = 323 OpStructEndOmitEmptyFloat32Ptr OpType = 323
OpStructEndOmitEmptyFloat32Ptr OpType = 324 OpStructFieldFloat64Ptr OpType = 324
OpStructFieldFloat64Ptr OpType = 325 OpStructFieldOmitEmptyFloat64Ptr OpType = 325
OpStructFieldOmitEmptyFloat64Ptr OpType = 326 OpStructEndFloat64Ptr OpType = 326
OpStructEndFloat64Ptr OpType = 327 OpStructEndOmitEmptyFloat64Ptr OpType = 327
OpStructEndOmitEmptyFloat64Ptr OpType = 328 OpStructFieldBoolPtr OpType = 328
OpStructFieldBoolPtr OpType = 329 OpStructFieldOmitEmptyBoolPtr OpType = 329
OpStructFieldOmitEmptyBoolPtr OpType = 330 OpStructEndBoolPtr OpType = 330
OpStructEndBoolPtr OpType = 331 OpStructEndOmitEmptyBoolPtr OpType = 331
OpStructEndOmitEmptyBoolPtr OpType = 332 OpStructFieldStringPtr OpType = 332
OpStructFieldStringPtr OpType = 333 OpStructFieldOmitEmptyStringPtr OpType = 333
OpStructFieldOmitEmptyStringPtr OpType = 334 OpStructEndStringPtr OpType = 334
OpStructEndStringPtr OpType = 335 OpStructEndOmitEmptyStringPtr OpType = 335
OpStructEndOmitEmptyStringPtr OpType = 336 OpStructFieldBytesPtr OpType = 336
OpStructFieldBytesPtr OpType = 337 OpStructFieldOmitEmptyBytesPtr OpType = 337
OpStructFieldOmitEmptyBytesPtr OpType = 338 OpStructEndBytesPtr OpType = 338
OpStructEndBytesPtr OpType = 339 OpStructEndOmitEmptyBytesPtr OpType = 339
OpStructEndOmitEmptyBytesPtr OpType = 340 OpStructFieldNumberPtr OpType = 340
OpStructFieldNumberPtr OpType = 341 OpStructFieldOmitEmptyNumberPtr OpType = 341
OpStructFieldOmitEmptyNumberPtr OpType = 342 OpStructEndNumberPtr OpType = 342
OpStructEndNumberPtr OpType = 343 OpStructEndOmitEmptyNumberPtr OpType = 343
OpStructEndOmitEmptyNumberPtr OpType = 344 OpStructFieldArrayPtr OpType = 344
OpStructFieldArrayPtr OpType = 345 OpStructFieldOmitEmptyArrayPtr OpType = 345
OpStructFieldOmitEmptyArrayPtr OpType = 346 OpStructEndArrayPtr OpType = 346
OpStructEndArrayPtr OpType = 347 OpStructEndOmitEmptyArrayPtr OpType = 347
OpStructEndOmitEmptyArrayPtr OpType = 348 OpStructFieldMapPtr OpType = 348
OpStructFieldMapPtr OpType = 349 OpStructFieldOmitEmptyMapPtr OpType = 349
OpStructFieldOmitEmptyMapPtr OpType = 350 OpStructEndMapPtr OpType = 350
OpStructEndMapPtr OpType = 351 OpStructEndOmitEmptyMapPtr OpType = 351
OpStructEndOmitEmptyMapPtr OpType = 352 OpStructFieldSlicePtr OpType = 352
OpStructFieldSlicePtr OpType = 353 OpStructFieldOmitEmptySlicePtr OpType = 353
OpStructFieldOmitEmptySlicePtr OpType = 354 OpStructEndSlicePtr OpType = 354
OpStructEndSlicePtr OpType = 355 OpStructEndOmitEmptySlicePtr OpType = 355
OpStructEndOmitEmptySlicePtr OpType = 356 OpStructFieldMarshalJSONPtr OpType = 356
OpStructFieldMarshalJSONPtr OpType = 357 OpStructFieldOmitEmptyMarshalJSONPtr OpType = 357
OpStructFieldOmitEmptyMarshalJSONPtr OpType = 358 OpStructEndMarshalJSONPtr OpType = 358
OpStructEndMarshalJSONPtr OpType = 359 OpStructEndOmitEmptyMarshalJSONPtr OpType = 359
OpStructEndOmitEmptyMarshalJSONPtr OpType = 360 OpStructFieldMarshalTextPtr OpType = 360
OpStructFieldMarshalTextPtr OpType = 361 OpStructFieldOmitEmptyMarshalTextPtr OpType = 361
OpStructFieldOmitEmptyMarshalTextPtr OpType = 362 OpStructEndMarshalTextPtr OpType = 362
OpStructEndMarshalTextPtr OpType = 363 OpStructEndOmitEmptyMarshalTextPtr OpType = 363
OpStructEndOmitEmptyMarshalTextPtr OpType = 364 OpStructFieldInterfacePtr OpType = 364
OpStructFieldInterfacePtr OpType = 365 OpStructFieldOmitEmptyInterfacePtr OpType = 365
OpStructFieldOmitEmptyInterfacePtr OpType = 366 OpStructEndInterfacePtr OpType = 366
OpStructEndInterfacePtr OpType = 367 OpStructEndOmitEmptyInterfacePtr OpType = 367
OpStructEndOmitEmptyInterfacePtr OpType = 368 OpStructFieldIntPtrString OpType = 368
OpStructFieldIntPtrString OpType = 369 OpStructFieldOmitEmptyIntPtrString OpType = 369
OpStructFieldOmitEmptyIntPtrString OpType = 370 OpStructEndIntPtrString OpType = 370
OpStructEndIntPtrString OpType = 371 OpStructEndOmitEmptyIntPtrString OpType = 371
OpStructEndOmitEmptyIntPtrString OpType = 372 OpStructFieldUintPtrString OpType = 372
OpStructFieldUintPtrString OpType = 373 OpStructFieldOmitEmptyUintPtrString OpType = 373
OpStructFieldOmitEmptyUintPtrString OpType = 374 OpStructEndUintPtrString OpType = 374
OpStructEndUintPtrString OpType = 375 OpStructEndOmitEmptyUintPtrString OpType = 375
OpStructEndOmitEmptyUintPtrString OpType = 376 OpStructFieldFloat32PtrString OpType = 376
OpStructFieldFloat32PtrString OpType = 377 OpStructFieldOmitEmptyFloat32PtrString OpType = 377
OpStructFieldOmitEmptyFloat32PtrString OpType = 378 OpStructEndFloat32PtrString OpType = 378
OpStructEndFloat32PtrString OpType = 379 OpStructEndOmitEmptyFloat32PtrString OpType = 379
OpStructEndOmitEmptyFloat32PtrString OpType = 380 OpStructFieldFloat64PtrString OpType = 380
OpStructFieldFloat64PtrString OpType = 381 OpStructFieldOmitEmptyFloat64PtrString OpType = 381
OpStructFieldOmitEmptyFloat64PtrString OpType = 382 OpStructEndFloat64PtrString OpType = 382
OpStructEndFloat64PtrString OpType = 383 OpStructEndOmitEmptyFloat64PtrString OpType = 383
OpStructEndOmitEmptyFloat64PtrString OpType = 384 OpStructFieldBoolPtrString OpType = 384
OpStructFieldBoolPtrString OpType = 385 OpStructFieldOmitEmptyBoolPtrString OpType = 385
OpStructFieldOmitEmptyBoolPtrString OpType = 386 OpStructEndBoolPtrString OpType = 386
OpStructEndBoolPtrString OpType = 387 OpStructEndOmitEmptyBoolPtrString OpType = 387
OpStructEndOmitEmptyBoolPtrString OpType = 388 OpStructFieldStringPtrString OpType = 388
OpStructFieldStringPtrString OpType = 389 OpStructFieldOmitEmptyStringPtrString OpType = 389
OpStructFieldOmitEmptyStringPtrString OpType = 390 OpStructEndStringPtrString OpType = 390
OpStructEndStringPtrString OpType = 391 OpStructEndOmitEmptyStringPtrString OpType = 391
OpStructEndOmitEmptyStringPtrString OpType = 392 OpStructFieldNumberPtrString OpType = 392
OpStructFieldNumberPtrString OpType = 393 OpStructFieldOmitEmptyNumberPtrString OpType = 393
OpStructFieldOmitEmptyNumberPtrString OpType = 394 OpStructEndNumberPtrString OpType = 394
OpStructEndNumberPtrString OpType = 395 OpStructEndOmitEmptyNumberPtrString OpType = 395
OpStructEndOmitEmptyNumberPtrString OpType = 396 OpStructField OpType = 396
OpStructField OpType = 397 OpStructFieldOmitEmpty OpType = 397
OpStructFieldOmitEmpty OpType = 398 OpStructEnd OpType = 398
OpStructEnd OpType = 399 OpStructEndOmitEmpty OpType = 399
OpStructEndOmitEmpty OpType = 400
) )
func (t OpType) String() string { func (t OpType) String() string {
if int(t) >= 401 { if int(t) >= 400 {
return "" return ""
} }
return opTypeStrings[int(t)] return opTypeStrings[int(t)]

View File

@ -4349,8 +4349,6 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
code = code.Next code = code.Next
store(ctxptr, code.Idx, p) store(ctxptr, code.Idx, p)
} }
case encoder.OpStructAnonymousEnd:
code = code.Next
case encoder.OpStructEnd: case encoder.OpStructEnd:
b = appendStructEndSkipLast(ctx, code, b) b = appendStructEndSkipLast(ctx, code, b)
code = code.Next code = code.Next

View File

@ -4349,8 +4349,6 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
code = code.Next code = code.Next
store(ctxptr, code.Idx, p) store(ctxptr, code.Idx, p)
} }
case encoder.OpStructAnonymousEnd:
code = code.Next
case encoder.OpStructEnd: case encoder.OpStructEnd:
b = appendStructEndSkipLast(ctx, code, b) b = appendStructEndSkipLast(ctx, code, b)
code = code.Next code = code.Next

View File

@ -4349,8 +4349,6 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
code = code.Next code = code.Next
store(ctxptr, code.Idx, p) store(ctxptr, code.Idx, p)
} }
case encoder.OpStructAnonymousEnd:
code = code.Next
case encoder.OpStructEnd: case encoder.OpStructEnd:
b = appendStructEndSkipLast(ctx, code, b) b = appendStructEndSkipLast(ctx, code, b)
code = code.Next code = code.Next

View File

@ -4349,8 +4349,6 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
code = code.Next code = code.Next
store(ctxptr, code.Idx, p) store(ctxptr, code.Idx, p)
} }
case encoder.OpStructAnonymousEnd:
code = code.Next
case encoder.OpStructEnd: case encoder.OpStructEnd:
b = appendStructEndSkipLast(ctx, code, b) b = appendStructEndSkipLast(ctx, code, b)
code = code.Next code = code.Next

View File

@ -11,8 +11,8 @@ func TestOpcodeSize(t *testing.T) {
const uintptrSize = 4 << (^uintptr(0) >> 63) const uintptrSize = 4 << (^uintptr(0) >> 63)
if uintptrSize == 8 { if uintptrSize == 8 {
size := unsafe.Sizeof(encoder.Opcode{}) size := unsafe.Sizeof(encoder.Opcode{})
if size != 128 { if size != 120 {
t.Fatalf("unexpected opcode size: expected 128bytes but got %dbytes", size) t.Fatalf("unexpected opcode size: expected 120bytes but got %dbytes", size)
} }
} }
} }

View File

@ -2,6 +2,7 @@ package json_test
import ( import (
"bytes" "bytes"
"fmt"
"testing" "testing"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@ -1840,19 +1841,21 @@ func TestCoverArray(t *testing.T) {
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{true, false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
enc := json.NewEncoder(&buf) var buf bytes.Buffer
enc.SetEscapeHTML(htmlEscape) enc := json.NewEncoder(&buf)
if indent { enc.SetEscapeHTML(htmlEscape)
enc.SetIndent("", " ") if indent {
} enc.SetIndent("", " ")
if err := enc.Encode(test.data); err != nil { }
t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err) if err := enc.Encode(test.data); err != nil {
} t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err)
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) }
if buf.String() != stdresult { stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String()) if buf.String() != stdresult {
} t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
}
})
} }
} }
} }

View File

@ -3,6 +3,7 @@ package json_test
import ( import (
"bytes" "bytes"
stdjson "encoding/json" stdjson "encoding/json"
"fmt"
"testing" "testing"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@ -2653,19 +2654,21 @@ func TestCoverBool(t *testing.T) {
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{true, false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
enc := json.NewEncoder(&buf) var buf bytes.Buffer
enc.SetEscapeHTML(htmlEscape) enc := json.NewEncoder(&buf)
if indent { enc.SetEscapeHTML(htmlEscape)
enc.SetIndent("", " ") if indent {
} enc.SetIndent("", " ")
if err := enc.Encode(test.data); err != nil { }
t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err) if err := enc.Encode(test.data); err != nil {
} t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err)
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) }
if buf.String() != stdresult { stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String()) if buf.String() != stdresult {
} t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
}
})
} }
} }
} }

View File

@ -2,6 +2,7 @@ package json_test
import ( import (
"bytes" "bytes"
"fmt"
"testing" "testing"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@ -1807,19 +1808,21 @@ func TestCoverBytes(t *testing.T) {
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{true, false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
enc := json.NewEncoder(&buf) var buf bytes.Buffer
enc.SetEscapeHTML(htmlEscape) enc := json.NewEncoder(&buf)
if indent { enc.SetEscapeHTML(htmlEscape)
enc.SetIndent("", " ") if indent {
} enc.SetIndent("", " ")
if err := enc.Encode(test.data); err != nil { }
t.Fatalf("%s(htmlEscape:%v,indent:%v): %v: %s", test.name, htmlEscape, indent, test.data, err) if err := enc.Encode(test.data); err != nil {
} t.Fatalf("%s(htmlEscape:%v,indent:%v): %v: %s", test.name, htmlEscape, indent, test.data, err)
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) }
if buf.String() != stdresult { stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String()) if buf.String() != stdresult {
} t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
}
})
} }
} }
} }

View File

@ -2,6 +2,7 @@ package json_test
import ( import (
"bytes" "bytes"
"fmt"
"testing" "testing"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@ -2334,19 +2335,21 @@ func TestCoverFloat32(t *testing.T) {
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{true, false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
enc := json.NewEncoder(&buf) var buf bytes.Buffer
enc.SetEscapeHTML(htmlEscape) enc := json.NewEncoder(&buf)
if indent { enc.SetEscapeHTML(htmlEscape)
enc.SetIndent("", " ") if indent {
} enc.SetIndent("", " ")
if err := enc.Encode(test.data); err != nil { }
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err) if err := enc.Encode(test.data); err != nil {
} t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) }
if buf.String() != stdresult { stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String()) if buf.String() != stdresult {
} t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
}
})
} }
} }
} }

View File

@ -2,6 +2,7 @@ package json_test
import ( import (
"bytes" "bytes"
"fmt"
"testing" "testing"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@ -2334,19 +2335,21 @@ func TestCoverFloat64(t *testing.T) {
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{true, false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
enc := json.NewEncoder(&buf) var buf bytes.Buffer
enc.SetEscapeHTML(htmlEscape) enc := json.NewEncoder(&buf)
if indent { enc.SetEscapeHTML(htmlEscape)
enc.SetIndent("", " ") if indent {
} enc.SetIndent("", " ")
if err := enc.Encode(test.data); err != nil { }
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err) if err := enc.Encode(test.data); err != nil {
} t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) }
if buf.String() != stdresult { stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String()) if buf.String() != stdresult {
} t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
}
})
} }
} }
} }

View File

@ -2,6 +2,7 @@ package json_test
import ( import (
"bytes" "bytes"
"fmt"
"testing" "testing"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@ -1811,19 +1812,21 @@ func TestCoverInt16(t *testing.T) {
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{true, false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
enc := json.NewEncoder(&buf) var buf bytes.Buffer
enc.SetEscapeHTML(htmlEscape) enc := json.NewEncoder(&buf)
if indent { enc.SetEscapeHTML(htmlEscape)
enc.SetIndent("", " ") if indent {
} enc.SetIndent("", " ")
if err := enc.Encode(test.data); err != nil { }
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err) if err := enc.Encode(test.data); err != nil {
} t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) }
if buf.String() != stdresult { stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String()) if buf.String() != stdresult {
} t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
}
})
} }
} }
} }

View File

@ -2,6 +2,7 @@ package json_test
import ( import (
"bytes" "bytes"
"fmt"
"testing" "testing"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@ -1788,19 +1789,21 @@ func TestCoverInt32(t *testing.T) {
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{true, false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
enc := json.NewEncoder(&buf) var buf bytes.Buffer
enc.SetEscapeHTML(htmlEscape) enc := json.NewEncoder(&buf)
if indent { enc.SetEscapeHTML(htmlEscape)
enc.SetIndent("", " ") if indent {
} enc.SetIndent("", " ")
if err := enc.Encode(test.data); err != nil { }
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err) if err := enc.Encode(test.data); err != nil {
} t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) }
if buf.String() != stdresult { stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String()) if buf.String() != stdresult {
} t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
}
})
} }
} }
} }

View File

@ -2,6 +2,7 @@ package json_test
import ( import (
"bytes" "bytes"
"fmt"
"testing" "testing"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@ -1788,19 +1789,21 @@ func TestCoverInt64(t *testing.T) {
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{true, false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
enc := json.NewEncoder(&buf) var buf bytes.Buffer
enc.SetEscapeHTML(htmlEscape) enc := json.NewEncoder(&buf)
if indent { enc.SetEscapeHTML(htmlEscape)
enc.SetIndent("", " ") if indent {
} enc.SetIndent("", " ")
if err := enc.Encode(test.data); err != nil { }
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err) if err := enc.Encode(test.data); err != nil {
} t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) }
if buf.String() != stdresult { stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String()) if buf.String() != stdresult {
} t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
}
})
} }
} }
} }

View File

@ -2,6 +2,7 @@ package json_test
import ( import (
"bytes" "bytes"
"fmt"
"testing" "testing"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@ -1788,19 +1789,21 @@ func TestCoverInt8(t *testing.T) {
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{true, false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
enc := json.NewEncoder(&buf) var buf bytes.Buffer
enc.SetEscapeHTML(htmlEscape) enc := json.NewEncoder(&buf)
if indent { enc.SetEscapeHTML(htmlEscape)
enc.SetIndent("", " ") if indent {
} enc.SetIndent("", " ")
if err := enc.Encode(test.data); err != nil { }
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err) if err := enc.Encode(test.data); err != nil {
} t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) }
if buf.String() != stdresult { stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String()) if buf.String() != stdresult {
} t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
}
})
} }
} }
} }

View File

@ -2,6 +2,7 @@ package json_test
import ( import (
"bytes" "bytes"
"fmt"
"testing" "testing"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@ -2410,19 +2411,21 @@ func TestCoverInt(t *testing.T) {
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{true, false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
enc := json.NewEncoder(&buf) var buf bytes.Buffer
enc.SetEscapeHTML(htmlEscape) enc := json.NewEncoder(&buf)
if indent { enc.SetEscapeHTML(htmlEscape)
enc.SetIndent("", " ") if indent {
} enc.SetIndent("", " ")
if err := enc.Encode(test.data); err != nil { }
t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err) if err := enc.Encode(test.data); err != nil {
} t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err)
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) }
if buf.String() != stdresult { stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String()) if buf.String() != stdresult {
} t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
}
})
} }
} }
} }

View File

@ -2,6 +2,7 @@ package json_test
import ( import (
"bytes" "bytes"
"fmt"
"testing" "testing"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@ -1881,19 +1882,21 @@ func TestCoverMap(t *testing.T) {
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{true, false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
enc := json.NewEncoder(&buf) var buf bytes.Buffer
enc.SetEscapeHTML(htmlEscape) enc := json.NewEncoder(&buf)
if indent { enc.SetEscapeHTML(htmlEscape)
enc.SetIndent("", " ") if indent {
} enc.SetIndent("", " ")
if err := enc.Encode(test.data); err != nil { }
t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err) if err := enc.Encode(test.data); err != nil {
} t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err)
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) }
if buf.String() != stdresult { stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String()) if buf.String() != stdresult {
} t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
}
})
} }
} }
} }

View File

@ -3690,19 +3690,21 @@ func TestCoverMarshalJSON(t *testing.T) {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
for _, indent := range []bool{true, false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
enc := json.NewEncoder(&buf) var buf bytes.Buffer
enc.SetEscapeHTML(htmlEscape) enc := json.NewEncoder(&buf)
if indent { enc.SetEscapeHTML(htmlEscape)
enc.SetIndent("", " ") if indent {
} enc.SetIndent("", " ")
if err := enc.Encode(test.data); err != nil { }
t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err) if err := enc.Encode(test.data); err != nil {
} t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err)
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) }
if buf.String() != stdresult { stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String()) if buf.String() != stdresult {
} t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
}
})
} }
} }
}) })

View File

@ -2,6 +2,7 @@ package json_test
import ( import (
"bytes" "bytes"
"fmt"
"testing" "testing"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@ -3527,19 +3528,21 @@ func TestCoverMarshalText(t *testing.T) {
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{true, false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
enc := json.NewEncoder(&buf) var buf bytes.Buffer
enc.SetEscapeHTML(htmlEscape) enc := json.NewEncoder(&buf)
if indent { enc.SetEscapeHTML(htmlEscape)
enc.SetIndent("", " ") if indent {
} enc.SetIndent("", " ")
if err := enc.Encode(test.data); err != nil { }
t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err) if err := enc.Encode(test.data); err != nil {
} t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err)
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) }
if buf.String() != stdresult { stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String()) if buf.String() != stdresult {
} t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
}
})
} }
} }
} }

View File

@ -2,6 +2,7 @@ package json_test
import ( import (
"bytes" "bytes"
"fmt"
"testing" "testing"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@ -2334,19 +2335,21 @@ func TestCoverNumber(t *testing.T) {
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{true, false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
enc := json.NewEncoder(&buf) var buf bytes.Buffer
enc.SetEscapeHTML(htmlEscape) enc := json.NewEncoder(&buf)
if indent { enc.SetEscapeHTML(htmlEscape)
enc.SetIndent("", " ") if indent {
} enc.SetIndent("", " ")
if err := enc.Encode(test.data); err != nil { }
t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err) if err := enc.Encode(test.data); err != nil {
} t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err)
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) }
if buf.String() != stdresult { stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String()) if buf.String() != stdresult {
} t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
}
})
} }
} }
} }

View File

@ -2,6 +2,7 @@ package json_test
import ( import (
"bytes" "bytes"
"fmt"
"testing" "testing"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@ -2047,9 +2048,9 @@ func TestCoverSlice(t *testing.T) {
}, },
} }
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(t *testing.T) { for _, indent := range []bool{true, false} {
for _, indent := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
var buf bytes.Buffer var buf bytes.Buffer
enc := json.NewEncoder(&buf) enc := json.NewEncoder(&buf)
enc.SetEscapeHTML(htmlEscape) enc.SetEscapeHTML(htmlEscape)
@ -2063,8 +2064,8 @@ func TestCoverSlice(t *testing.T) {
if buf.String() != stdresult { if buf.String() != stdresult {
t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String()) t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
} }
} })
} }
}) }
} }
} }

View File

@ -2,6 +2,7 @@ package json_test
import ( import (
"bytes" "bytes"
"fmt"
"testing" "testing"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@ -2370,19 +2371,21 @@ func TestCoverString(t *testing.T) {
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{true, false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
enc := json.NewEncoder(&buf) var buf bytes.Buffer
enc.SetEscapeHTML(htmlEscape) enc := json.NewEncoder(&buf)
if indent { enc.SetEscapeHTML(htmlEscape)
enc.SetIndent("", " ") if indent {
} enc.SetIndent("", " ")
if err := enc.Encode(test.data); err != nil { }
t.Fatalf("%s(htmlEscape:%v,indent:%v): %v: %s", test.name, htmlEscape, indent, test.data, err) if err := enc.Encode(test.data); err != nil {
} t.Fatalf("%s(htmlEscape:%v,indent:%v): %v: %s", test.name, htmlEscape, indent, test.data, err)
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) }
if buf.String() != stdresult { stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String()) if buf.String() != stdresult {
} t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
}
})
} }
} }
} }

View File

@ -2,6 +2,7 @@ package json_test
import ( import (
"bytes" "bytes"
"fmt"
"testing" "testing"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@ -1788,19 +1789,21 @@ func TestCoverUint16(t *testing.T) {
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{true, false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
enc := json.NewEncoder(&buf) var buf bytes.Buffer
enc.SetEscapeHTML(htmlEscape) enc := json.NewEncoder(&buf)
if indent { enc.SetEscapeHTML(htmlEscape)
enc.SetIndent("", " ") if indent {
} enc.SetIndent("", " ")
if err := enc.Encode(test.data); err != nil { }
t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err) if err := enc.Encode(test.data); err != nil {
} t.Fatalf("%s(htmlEscape:%v,indent:%v): %+v: %s", test.name, htmlEscape, indent, test.data, err)
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) }
if buf.String() != stdresult { stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String()) if buf.String() != stdresult {
} t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String())
}
})
} }
} }
} }

View File

@ -2,6 +2,7 @@ package json_test
import ( import (
"bytes" "bytes"
"fmt"
"testing" "testing"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@ -1788,19 +1789,21 @@ func TestCoverUint32(t *testing.T) {
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{true, false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
enc := json.NewEncoder(&buf) var buf bytes.Buffer
enc.SetEscapeHTML(htmlEscape) enc := json.NewEncoder(&buf)
if indent { enc.SetEscapeHTML(htmlEscape)
enc.SetIndent("", " ") if indent {
} enc.SetIndent("", " ")
if err := enc.Encode(test.data); err != nil { }
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err) if err := enc.Encode(test.data); err != nil {
} t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) }
if buf.String() != stdresult { stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String()) if buf.String() != stdresult {
} t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
}
})
} }
} }
} }

View File

@ -2,6 +2,7 @@ package json_test
import ( import (
"bytes" "bytes"
"fmt"
"testing" "testing"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@ -1788,19 +1789,21 @@ func TestCoverUint64(t *testing.T) {
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{true, false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
enc := json.NewEncoder(&buf) var buf bytes.Buffer
enc.SetEscapeHTML(htmlEscape) enc := json.NewEncoder(&buf)
if indent { enc.SetEscapeHTML(htmlEscape)
enc.SetIndent("", " ") if indent {
} enc.SetIndent("", " ")
if err := enc.Encode(test.data); err != nil { }
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err) if err := enc.Encode(test.data); err != nil {
} t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) }
if buf.String() != stdresult { stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String()) if buf.String() != stdresult {
} t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
}
})
} }
} }
} }

View File

@ -2,6 +2,7 @@ package json_test
import ( import (
"bytes" "bytes"
"fmt"
"testing" "testing"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@ -1788,19 +1789,21 @@ func TestCoverUint8(t *testing.T) {
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{true, false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
enc := json.NewEncoder(&buf) var buf bytes.Buffer
enc.SetEscapeHTML(htmlEscape) enc := json.NewEncoder(&buf)
if indent { enc.SetEscapeHTML(htmlEscape)
enc.SetIndent("", " ") if indent {
} enc.SetIndent("", " ")
if err := enc.Encode(test.data); err != nil { }
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err) if err := enc.Encode(test.data); err != nil {
} t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) }
if buf.String() != stdresult { stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String()) if buf.String() != stdresult {
} t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
}
})
} }
} }
} }

View File

@ -2,6 +2,7 @@ package json_test
import ( import (
"bytes" "bytes"
"fmt"
"testing" "testing"
"github.com/goccy/go-json" "github.com/goccy/go-json"
@ -2334,19 +2335,21 @@ func TestCoverUint(t *testing.T) {
for _, test := range tests { for _, test := range tests {
for _, indent := range []bool{true, false} { for _, indent := range []bool{true, false} {
for _, htmlEscape := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} {
var buf bytes.Buffer t.Run(fmt.Sprintf("%s_indent_%t_escape_%t", test.name, indent, htmlEscape), func(t *testing.T) {
enc := json.NewEncoder(&buf) var buf bytes.Buffer
enc.SetEscapeHTML(htmlEscape) enc := json.NewEncoder(&buf)
if indent { enc.SetEscapeHTML(htmlEscape)
enc.SetIndent("", " ") if indent {
} enc.SetIndent("", " ")
if err := enc.Encode(test.data); err != nil { }
t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err) if err := enc.Encode(test.data); err != nil {
} t.Fatalf("%s(htmlEscape:%T): %+v: %s", test.name, htmlEscape, test.data, err)
stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) }
if buf.String() != stdresult { stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape)
t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String()) if buf.String() != stdresult {
} t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String())
}
})
} }
} }
} }