Refactor with encodeCompileContext

This commit is contained in:
Masaaki Goshima 2020-08-29 15:11:31 +09:00
parent e9ad334a8c
commit 7dcadbd6ce
3 changed files with 129 additions and 131 deletions

View File

@ -179,11 +179,19 @@ func (e *Encoder) encode(v interface{}) error {
// noescape trick for header.typ ( reflect.*rtype ) // noescape trick for header.typ ( reflect.*rtype )
copiedType := (*rtype)(unsafe.Pointer(typeptr)) copiedType := (*rtype)(unsafe.Pointer(typeptr))
codeIndent, err := e.compileHead(copiedType, true) codeIndent, err := e.compileHead(&encodeCompileContext{
typ: copiedType,
root: true,
withIndent: true,
})
if err != nil { if err != nil {
return err return err
} }
code, err := e.compileHead(copiedType, false) code, err := e.compileHead(&encodeCompileContext{
typ: copiedType,
root: true,
withIndent: false,
})
if err != nil { if err != nil {
return err return err
} }

View File

@ -6,8 +6,8 @@ import (
"unsafe" "unsafe"
) )
func (e *Encoder) compileHead(typ *rtype, withIndent bool) (*opcode, error) { func (e *Encoder) compileHead(ctx *encodeCompileContext) (*opcode, error) {
root := true typ := ctx.typ
switch { switch {
case typ.Implements(marshalJSONType): case typ.Implements(marshalJSONType):
return newOpCode(opMarshalJSON, typ, e.indent, newEndOp(e.indent)), nil return newOpCode(opMarshalJSON, typ, e.indent, newEndOp(e.indent)), nil
@ -24,11 +24,11 @@ func (e *Encoder) compileHead(typ *rtype, withIndent bool) (*opcode, error) {
isPtr = true isPtr = true
} }
if typ.Kind() == reflect.Map { if typ.Kind() == reflect.Map {
return e.compileMap(typ, isPtr, root, withIndent) return e.compileMap(ctx.withType(typ), isPtr)
} else if typ.Kind() == reflect.Struct { } else if typ.Kind() == reflect.Struct {
return e.compileStruct(typ, isPtr, root, withIndent) return e.compileStruct(ctx.withType(typ), isPtr)
} }
return e.compile(typ, root, withIndent) return e.compile(ctx.withType(typ))
} }
func (e *Encoder) implementsMarshaler(typ *rtype) bool { func (e *Encoder) implementsMarshaler(typ *rtype) bool {
@ -45,7 +45,8 @@ func (e *Encoder) implementsMarshaler(typ *rtype) bool {
return false return false
} }
func (e *Encoder) compile(typ *rtype, root, withIndent bool) (*opcode, error) { func (e *Encoder) compile(ctx *encodeCompileContext) (*opcode, error) {
typ := ctx.typ
switch { switch {
case typ.Implements(marshalJSONType): case typ.Implements(marshalJSONType):
return newOpCode(opMarshalJSON, typ, e.indent, newEndOp(e.indent)), nil return newOpCode(opMarshalJSON, typ, e.indent, newEndOp(e.indent)), nil
@ -58,56 +59,57 @@ func (e *Encoder) compile(typ *rtype, root, withIndent bool) (*opcode, error) {
} }
switch typ.Kind() { switch typ.Kind() {
case reflect.Ptr: case reflect.Ptr:
return e.compilePtr(typ, root, withIndent) return e.compilePtr(ctx)
case reflect.Slice: case reflect.Slice:
elem := typ.Elem() elem := typ.Elem()
if !e.implementsMarshaler(elem) && elem.Kind() == reflect.Uint8 { if !e.implementsMarshaler(elem) && elem.Kind() == reflect.Uint8 {
return e.compileBytes(typ) return e.compileBytes(ctx)
} }
return e.compileSlice(typ, root, withIndent) return e.compileSlice(ctx)
case reflect.Array: case reflect.Array:
return e.compileArray(typ, root, withIndent) return e.compileArray(ctx)
case reflect.Map: case reflect.Map:
return e.compileMap(typ, true, root, withIndent) return e.compileMap(ctx, true)
case reflect.Struct: case reflect.Struct:
return e.compileStruct(typ, false, root, withIndent) return e.compileStruct(ctx, false)
case reflect.Interface: case reflect.Interface:
return e.compileInterface(typ, root) return e.compileInterface(ctx)
case reflect.Int: case reflect.Int:
return e.compileInt(typ) return e.compileInt(ctx)
case reflect.Int8: case reflect.Int8:
return e.compileInt8(typ) return e.compileInt8(ctx)
case reflect.Int16: case reflect.Int16:
return e.compileInt16(typ) return e.compileInt16(ctx)
case reflect.Int32: case reflect.Int32:
return e.compileInt32(typ) return e.compileInt32(ctx)
case reflect.Int64: case reflect.Int64:
return e.compileInt64(typ) return e.compileInt64(ctx)
case reflect.Uint: case reflect.Uint:
return e.compileUint(typ) return e.compileUint(ctx)
case reflect.Uint8: case reflect.Uint8:
return e.compileUint8(typ) return e.compileUint8(ctx)
case reflect.Uint16: case reflect.Uint16:
return e.compileUint16(typ) return e.compileUint16(ctx)
case reflect.Uint32: case reflect.Uint32:
return e.compileUint32(typ) return e.compileUint32(ctx)
case reflect.Uint64: case reflect.Uint64:
return e.compileUint64(typ) return e.compileUint64(ctx)
case reflect.Uintptr: case reflect.Uintptr:
return e.compileUint(typ) return e.compileUint(ctx)
case reflect.Float32: case reflect.Float32:
return e.compileFloat32(typ) return e.compileFloat32(ctx)
case reflect.Float64: case reflect.Float64:
return e.compileFloat64(typ) return e.compileFloat64(ctx)
case reflect.String: case reflect.String:
return e.compileString(typ) return e.compileString(ctx)
case reflect.Bool: case reflect.Bool:
return e.compileBool(typ) return e.compileBool(ctx)
} }
return nil, &UnsupportedTypeError{Type: rtype2type(typ)} return nil, &UnsupportedTypeError{Type: rtype2type(typ)}
} }
func (e *Encoder) compileKey(typ *rtype, root, withIndent bool) (*opcode, error) { func (e *Encoder) compileKey(ctx *encodeCompileContext) (*opcode, error) {
typ := ctx.typ
switch { switch {
case typ.Implements(marshalJSONType): case typ.Implements(marshalJSONType):
return newOpCode(opMarshalJSON, typ, e.indent, newEndOp(e.indent)), nil return newOpCode(opMarshalJSON, typ, e.indent, newEndOp(e.indent)), nil
@ -120,44 +122,17 @@ func (e *Encoder) compileKey(typ *rtype, root, withIndent bool) (*opcode, error)
} }
switch typ.Kind() { switch typ.Kind() {
case reflect.Ptr: case reflect.Ptr:
return e.compilePtr(typ, root, withIndent) return e.compilePtr(ctx)
case reflect.Interface: case reflect.Interface:
return e.compileInterface(typ, root) return e.compileInterface(ctx)
case reflect.Int:
return e.compileInt(typ)
case reflect.Int8:
return e.compileInt8(typ)
case reflect.Int16:
return e.compileInt16(typ)
case reflect.Int32:
return e.compileInt32(typ)
case reflect.Int64:
return e.compileInt64(typ)
case reflect.Uint:
return e.compileUint(typ)
case reflect.Uint8:
return e.compileUint8(typ)
case reflect.Uint16:
return e.compileUint16(typ)
case reflect.Uint32:
return e.compileUint32(typ)
case reflect.Uint64:
return e.compileUint64(typ)
case reflect.Uintptr:
return e.compileUint(typ)
case reflect.Float32:
return e.compileFloat32(typ)
case reflect.Float64:
return e.compileFloat64(typ)
case reflect.String: case reflect.String:
return e.compileString(typ) return e.compileString(ctx)
case reflect.Bool:
return e.compileBool(typ)
} }
return nil, &UnsupportedTypeError{Type: rtype2type(typ)} return nil, &UnsupportedTypeError{Type: rtype2type(typ)}
} }
func (e *Encoder) optimizeStructFieldPtrHead(typ *rtype, code *opcode) *opcode { func (e *Encoder) optimizeStructFieldPtrHead(ctx *encodeCompileContext, code *opcode) *opcode {
typ := ctx.typ
ptrHeadOp := code.op.headToPtrHead() ptrHeadOp := code.op.headToPtrHead()
if code.op != ptrHeadOp { if code.op != ptrHeadOp {
code.op = ptrHeadOp code.op = ptrHeadOp
@ -166,92 +141,93 @@ func (e *Encoder) optimizeStructFieldPtrHead(typ *rtype, code *opcode) *opcode {
return newOpCode(opPtr, typ, e.indent, code) return newOpCode(opPtr, typ, e.indent, code)
} }
func (e *Encoder) compilePtr(typ *rtype, root, withIndent bool) (*opcode, error) { func (e *Encoder) compilePtr(ctx *encodeCompileContext) (*opcode, error) {
code, err := e.compile(typ.Elem(), root, withIndent) code, err := e.compile(ctx.withType(ctx.typ.Elem()))
if err != nil { if err != nil {
return nil, err return nil, err
} }
return e.optimizeStructFieldPtrHead(typ, code), nil return e.optimizeStructFieldPtrHead(ctx, code), nil
} }
func (e *Encoder) compileInt(typ *rtype) (*opcode, error) { func (e *Encoder) compileInt(ctx *encodeCompileContext) (*opcode, error) {
return newOpCode(opInt, typ, e.indent, newEndOp(e.indent)), nil return newOpCode(opInt, ctx.typ, e.indent, newEndOp(e.indent)), nil
} }
func (e *Encoder) compileInt8(typ *rtype) (*opcode, error) { func (e *Encoder) compileInt8(ctx *encodeCompileContext) (*opcode, error) {
return newOpCode(opInt8, typ, e.indent, newEndOp(e.indent)), nil return newOpCode(opInt8, ctx.typ, e.indent, newEndOp(e.indent)), nil
} }
func (e *Encoder) compileInt16(typ *rtype) (*opcode, error) { func (e *Encoder) compileInt16(ctx *encodeCompileContext) (*opcode, error) {
return newOpCode(opInt16, typ, e.indent, newEndOp(e.indent)), nil return newOpCode(opInt16, ctx.typ, e.indent, newEndOp(e.indent)), nil
} }
func (e *Encoder) compileInt32(typ *rtype) (*opcode, error) { func (e *Encoder) compileInt32(ctx *encodeCompileContext) (*opcode, error) {
return newOpCode(opInt32, typ, e.indent, newEndOp(e.indent)), nil return newOpCode(opInt32, ctx.typ, e.indent, newEndOp(e.indent)), nil
} }
func (e *Encoder) compileInt64(typ *rtype) (*opcode, error) { func (e *Encoder) compileInt64(ctx *encodeCompileContext) (*opcode, error) {
return newOpCode(opInt64, typ, e.indent, newEndOp(e.indent)), nil return newOpCode(opInt64, ctx.typ, e.indent, newEndOp(e.indent)), nil
} }
func (e *Encoder) compileUint(typ *rtype) (*opcode, error) { func (e *Encoder) compileUint(ctx *encodeCompileContext) (*opcode, error) {
return newOpCode(opUint, typ, e.indent, newEndOp(e.indent)), nil return newOpCode(opUint, ctx.typ, e.indent, newEndOp(e.indent)), nil
} }
func (e *Encoder) compileUint8(typ *rtype) (*opcode, error) { func (e *Encoder) compileUint8(ctx *encodeCompileContext) (*opcode, error) {
return newOpCode(opUint8, typ, e.indent, newEndOp(e.indent)), nil return newOpCode(opUint8, ctx.typ, e.indent, newEndOp(e.indent)), nil
} }
func (e *Encoder) compileUint16(typ *rtype) (*opcode, error) { func (e *Encoder) compileUint16(ctx *encodeCompileContext) (*opcode, error) {
return newOpCode(opUint16, typ, e.indent, newEndOp(e.indent)), nil return newOpCode(opUint16, ctx.typ, e.indent, newEndOp(e.indent)), nil
} }
func (e *Encoder) compileUint32(typ *rtype) (*opcode, error) { func (e *Encoder) compileUint32(ctx *encodeCompileContext) (*opcode, error) {
return newOpCode(opUint32, typ, e.indent, newEndOp(e.indent)), nil return newOpCode(opUint32, ctx.typ, e.indent, newEndOp(e.indent)), nil
} }
func (e *Encoder) compileUint64(typ *rtype) (*opcode, error) { func (e *Encoder) compileUint64(ctx *encodeCompileContext) (*opcode, error) {
return newOpCode(opUint64, typ, e.indent, newEndOp(e.indent)), nil return newOpCode(opUint64, ctx.typ, e.indent, newEndOp(e.indent)), nil
} }
func (e *Encoder) compileFloat32(typ *rtype) (*opcode, error) { func (e *Encoder) compileFloat32(ctx *encodeCompileContext) (*opcode, error) {
return newOpCode(opFloat32, typ, e.indent, newEndOp(e.indent)), nil return newOpCode(opFloat32, ctx.typ, e.indent, newEndOp(e.indent)), nil
} }
func (e *Encoder) compileFloat64(typ *rtype) (*opcode, error) { func (e *Encoder) compileFloat64(ctx *encodeCompileContext) (*opcode, error) {
return newOpCode(opFloat64, typ, e.indent, newEndOp(e.indent)), nil return newOpCode(opFloat64, ctx.typ, e.indent, newEndOp(e.indent)), nil
} }
func (e *Encoder) compileString(typ *rtype) (*opcode, error) { func (e *Encoder) compileString(ctx *encodeCompileContext) (*opcode, error) {
return newOpCode(opString, typ, e.indent, newEndOp(e.indent)), nil return newOpCode(opString, ctx.typ, e.indent, newEndOp(e.indent)), nil
} }
func (e *Encoder) compileBool(typ *rtype) (*opcode, error) { func (e *Encoder) compileBool(ctx *encodeCompileContext) (*opcode, error) {
return newOpCode(opBool, typ, e.indent, newEndOp(e.indent)), nil return newOpCode(opBool, ctx.typ, e.indent, newEndOp(e.indent)), nil
} }
func (e *Encoder) compileBytes(typ *rtype) (*opcode, error) { func (e *Encoder) compileBytes(ctx *encodeCompileContext) (*opcode, error) {
return newOpCode(opBytes, typ, e.indent, newEndOp(e.indent)), nil return newOpCode(opBytes, ctx.typ, e.indent, newEndOp(e.indent)), nil
} }
func (e *Encoder) compileInterface(typ *rtype, root bool) (*opcode, error) { func (e *Encoder) compileInterface(ctx *encodeCompileContext) (*opcode, error) {
return (*opcode)(unsafe.Pointer(&interfaceCode{ return (*opcode)(unsafe.Pointer(&interfaceCode{
opcodeHeader: &opcodeHeader{ opcodeHeader: &opcodeHeader{
op: opInterface, op: opInterface,
typ: typ, typ: ctx.typ,
indent: e.indent, indent: e.indent,
next: newEndOp(e.indent), next: newEndOp(e.indent),
}, },
root: root, root: ctx.root,
})), nil })), nil
} }
func (e *Encoder) compileSlice(typ *rtype, root, withIndent bool) (*opcode, error) { func (e *Encoder) compileSlice(ctx *encodeCompileContext) (*opcode, error) {
elem := typ.Elem() ctx.root = false
elem := ctx.typ.Elem()
size := elem.Size() size := elem.Size()
e.indent++ e.indent++
code, err := e.compile(elem, false, withIndent) code, err := e.compile(ctx.withType(ctx.typ.Elem()))
e.indent-- e.indent--
if err != nil { if err != nil {
@ -271,8 +247,8 @@ func (e *Encoder) compileSlice(typ *rtype, root, withIndent bool) (*opcode, erro
size: size, size: size,
} }
end := newOpCode(opSliceEnd, nil, e.indent, newEndOp(e.indent)) end := newOpCode(opSliceEnd, nil, e.indent, newEndOp(e.indent))
if withIndent { if ctx.withIndent {
if root { if ctx.root {
header.op = opRootSliceHeadIndent header.op = opRootSliceHeadIndent
elemCode.op = opRootSliceElemIndent elemCode.op = opRootSliceElemIndent
} else { } else {
@ -291,13 +267,15 @@ func (e *Encoder) compileSlice(typ *rtype, root, withIndent bool) (*opcode, erro
return (*opcode)(unsafe.Pointer(header)), nil return (*opcode)(unsafe.Pointer(header)), nil
} }
func (e *Encoder) compileArray(typ *rtype, root, withIndent bool) (*opcode, error) { func (e *Encoder) compileArray(ctx *encodeCompileContext) (*opcode, error) {
ctx.root = false
typ := ctx.typ
elem := typ.Elem() elem := typ.Elem()
alen := typ.Len() alen := typ.Len()
size := elem.Size() size := elem.Size()
e.indent++ e.indent++
code, err := e.compile(elem, false, withIndent) code, err := e.compile(ctx.withType(elem))
e.indent-- e.indent--
if err != nil { if err != nil {
@ -317,7 +295,7 @@ func (e *Encoder) compileArray(typ *rtype, root, withIndent bool) (*opcode, erro
} }
end := newOpCode(opArrayEnd, nil, e.indent, newEndOp(e.indent)) end := newOpCode(opArrayEnd, nil, e.indent, newEndOp(e.indent))
if withIndent { if ctx.withIndent {
header.op = opArrayHeadIndent header.op = opArrayHeadIndent
elemCode.op = opArrayElemIndent elemCode.op = opArrayElemIndent
end.op = opArrayEndIndent end.op = opArrayEndIndent
@ -348,18 +326,19 @@ func mapiternext(it unsafe.Pointer)
//go:noescape //go:noescape
func maplen(m unsafe.Pointer) int func maplen(m unsafe.Pointer) int
func (e *Encoder) compileMap(typ *rtype, withLoad, root, withIndent bool) (*opcode, error) { func (e *Encoder) compileMap(ctx *encodeCompileContext, withLoad bool) (*opcode, error) {
// header => code => value => code => key => code => value => code => end // header => code => value => code => key => code => value => code => end
// ^ | // ^ |
// |_______________________| // |_______________________|
e.indent++ e.indent++
keyType := typ.Key() typ := ctx.typ
keyCode, err := e.compileKey(keyType, false, withIndent) keyType := ctx.typ.Key()
keyCode, err := e.compileKey(ctx.withType(keyType))
if err != nil { if err != nil {
return nil, err return nil, err
} }
valueType := typ.Elem() valueType := typ.Elem()
valueCode, err := e.compile(valueType, false, withIndent) valueCode, err := e.compile(ctx.withType(valueType))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -374,9 +353,9 @@ func (e *Encoder) compileMap(typ *rtype, withLoad, root, withIndent bool) (*opco
header.value = value header.value = value
end := newOpCode(opMapEnd, nil, e.indent, newEndOp(e.indent)) end := newOpCode(opMapEnd, nil, e.indent, newEndOp(e.indent))
if withIndent { if ctx.withIndent {
if header.op == opMapHead { if header.op == opMapHead {
if root { if ctx.root {
header.op = opRootMapHeadIndent header.op = opRootMapHeadIndent
} else { } else {
header.op = opMapHeadIndent header.op = opMapHeadIndent
@ -384,7 +363,7 @@ func (e *Encoder) compileMap(typ *rtype, withLoad, root, withIndent bool) (*opco
} else { } else {
header.op = opMapHeadLoadIndent header.op = opMapHeadLoadIndent
} }
if root { if ctx.root {
key.op = opRootMapKeyIndent key.op = opRootMapKeyIndent
} else { } else {
key.op = opMapKeyIndent key.op = opMapKeyIndent
@ -549,11 +528,11 @@ func (e *Encoder) optimizeStructField(op opType, tag *structTag, withIndent bool
return fieldType return fieldType
} }
func (e *Encoder) recursiveCode(typ *rtype, code *compiledCode) *opcode { func (e *Encoder) recursiveCode(ctx *encodeCompileContext, code *compiledCode) *opcode {
return (*opcode)(unsafe.Pointer(&recursiveCode{ return (*opcode)(unsafe.Pointer(&recursiveCode{
opcodeHeader: &opcodeHeader{ opcodeHeader: &opcodeHeader{
op: opStructFieldRecursive, op: opStructFieldRecursive,
typ: typ, typ: ctx.typ,
indent: e.indent, indent: e.indent,
next: newEndOp(e.indent), next: newEndOp(e.indent),
}, },
@ -561,15 +540,16 @@ func (e *Encoder) recursiveCode(typ *rtype, code *compiledCode) *opcode {
})) }))
} }
func (e *Encoder) compiledCode(typ *rtype, withIndent bool) *opcode { func (e *Encoder) compiledCode(ctx *encodeCompileContext) *opcode {
typ := ctx.typ
typeptr := uintptr(unsafe.Pointer(typ)) typeptr := uintptr(unsafe.Pointer(typ))
if withIndent { if ctx.withIndent {
if compiledCode, exists := e.structTypeToCompiledIndentCode[typeptr]; exists { if compiledCode, exists := e.structTypeToCompiledIndentCode[typeptr]; exists {
return e.recursiveCode(typ, compiledCode) return e.recursiveCode(ctx, compiledCode)
} }
} else { } else {
if compiledCode, exists := e.structTypeToCompiledCode[typeptr]; exists { if compiledCode, exists := e.structTypeToCompiledCode[typeptr]; exists {
return e.recursiveCode(typ, compiledCode) return e.recursiveCode(ctx, compiledCode)
} }
} }
return nil return nil
@ -790,13 +770,15 @@ func (e *Encoder) optimizeConflictAnonymousFields(anonymousFields map[string][]s
} }
} }
func (e *Encoder) compileStruct(typ *rtype, isPtr, root, withIndent bool) (*opcode, error) { func (e *Encoder) compileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, error) {
if code := e.compiledCode(typ, withIndent); code != nil { ctx.root = false
if code := e.compiledCode(ctx); code != nil {
return code, nil return code, nil
} }
typ := ctx.typ
typeptr := uintptr(unsafe.Pointer(typ)) typeptr := uintptr(unsafe.Pointer(typ))
compiled := &compiledCode{} compiled := &compiledCode{}
if withIndent { if ctx.withIndent {
e.structTypeToCompiledIndentCode[typeptr] = compiled e.structTypeToCompiledIndentCode[typeptr] = compiled
} else { } else {
e.structTypeToCompiledCode[typeptr] = compiled e.structTypeToCompiledCode[typeptr] = compiled
@ -833,7 +815,7 @@ func (e *Encoder) compileStruct(typ *rtype, isPtr, root, withIndent bool) (*opco
fieldType = rtype_ptrTo(fieldType) fieldType = rtype_ptrTo(fieldType)
} }
} }
valueCode, err := e.compile(fieldType, false, withIndent) valueCode, err := e.compile(ctx.withType(fieldType))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -866,13 +848,13 @@ func (e *Encoder) compileStruct(typ *rtype, isPtr, root, withIndent bool) (*opco
offset: field.Offset, offset: field.Offset,
} }
if fieldIdx == 0 { if fieldIdx == 0 {
code = e.structHeader(fieldCode, valueCode, tag, withIndent) code = e.structHeader(fieldCode, valueCode, tag, ctx.withIndent)
head = fieldCode head = fieldCode
prevField = fieldCode prevField = fieldCode
} else { } else {
fcode := (*opcode)(unsafe.Pointer(fieldCode)) fcode := (*opcode)(unsafe.Pointer(fieldCode))
code.next = fcode code.next = fcode
code = e.structField(fieldCode, valueCode, tag, withIndent) code = e.structField(fieldCode, valueCode, tag, ctx.withIndent)
prevField.nextField = fcode prevField.nextField = fcode
prevField = fieldCode prevField = fieldCode
} }
@ -888,7 +870,7 @@ func (e *Encoder) compileStruct(typ *rtype, isPtr, root, withIndent bool) (*opco
}, },
})) }))
structEndCode.next = newEndOp(e.indent) structEndCode.next = newEndOp(e.indent)
if withIndent { if ctx.withIndent {
structEndCode.op = opStructEndIndent structEndCode.op = opStructEndIndent
} }
@ -906,7 +888,7 @@ func (e *Encoder) compileStruct(typ *rtype, isPtr, root, withIndent bool) (*opco
}, },
nextField: structEndCode, nextField: structEndCode,
} }
if withIndent { if ctx.withIndent {
head.op = opStructFieldHeadIndent head.op = opStructFieldHeadIndent
} }
code = (*opcode)(unsafe.Pointer(head)) code = (*opcode)(unsafe.Pointer(head))
@ -920,7 +902,7 @@ func (e *Encoder) compileStruct(typ *rtype, isPtr, root, withIndent bool) (*opco
ret := (*opcode)(unsafe.Pointer(head)) ret := (*opcode)(unsafe.Pointer(head))
compiled.code = ret compiled.code = ret
if withIndent { if ctx.withIndent {
delete(e.structTypeToCompiledIndentCode, typeptr) delete(e.structTypeToCompiledIndentCode, typeptr)
} else { } else {
delete(e.structTypeToCompiledCode, typeptr) delete(e.structTypeToCompiledCode, typeptr)

View File

@ -112,13 +112,21 @@ func (e *Encoder) run(code *opcode) error {
e.indent = ifaceCode.indent e.indent = ifaceCode.indent
var c *opcode var c *opcode
if typ.Kind() == reflect.Map { if typ.Kind() == reflect.Map {
code, err := e.compileMap(typ, false, ifaceCode.root, e.enabledIndent) code, err := e.compileMap(&encodeCompileContext{
typ: typ,
root: ifaceCode.root,
withIndent: e.enabledIndent,
}, false)
if err != nil { if err != nil {
return err return err
} }
c = code c = code
} else { } else {
code, err := e.compile(typ, ifaceCode.root, e.enabledIndent) code, err := e.compile(&encodeCompileContext{
typ: typ,
root: ifaceCode.root,
withIndent: e.enabledIndent,
})
if err != nil { if err != nil {
return err return err
} }