Fix encoding runner interface

This commit is contained in:
Masaaki Goshima 2021-01-24 15:17:39 +09:00
parent 86ae7d931a
commit 399354d64d
5 changed files with 34 additions and 34 deletions

View File

@ -112,6 +112,7 @@ func (e *Encoder) EncodeWithOption(v interface{}, opts ...EncodeOption) error {
} }
} }
header := (*interfaceHeader)(unsafe.Pointer(&v)) header := (*interfaceHeader)(unsafe.Pointer(&v))
e.ptr = header.ptr
buf, err := e.encode(header, v == nil) buf, err := e.encode(header, v == nil)
if err != nil { if err != nil {
return err return err
@ -192,23 +193,31 @@ func (e *Encoder) encode(header *interfaceHeader, isNil bool) ([]byte, error) {
typ := header.typ typ := header.typ
typeptr := uintptr(unsafe.Pointer(typ)) typeptr := uintptr(unsafe.Pointer(typ))
codeSet, err := e.compileToGetCodeSet(typeptr)
if err != nil {
return nil, err
}
ctx := e.ctx
p := uintptr(header.ptr)
ctx.init(p, codeSet.codeLength)
if e.enabledIndent {
if e.enabledHTMLEscape {
return e.runEscapedIndent(ctx, b, codeSet)
} else {
return e.runIndent(ctx, b, codeSet)
}
}
if e.enabledHTMLEscape {
return e.runEscaped(ctx, b, codeSet)
}
return e.run(ctx, b, codeSet)
}
func (e *Encoder) compileToGetCodeSet(typeptr uintptr) (*opcodeSet, error) {
opcodeMap := loadOpcodeMap() opcodeMap := loadOpcodeMap()
if codeSet, exists := opcodeMap[typeptr]; exists { if codeSet, exists := opcodeMap[typeptr]; exists {
ctx := e.ctx return codeSet, nil
p := uintptr(header.ptr)
ctx.init(p, codeSet.codeLength)
if e.enabledIndent {
if e.enabledHTMLEscape {
return e.runEscapedIndent(ctx, b, codeSet.code)
} else {
return e.runIndent(ctx, b, codeSet.code)
}
}
if e.enabledHTMLEscape {
return e.runEscaped(ctx, b, codeSet.code)
}
return e.run(ctx, b, codeSet.code)
} }
// noescape trick for header.typ ( reflect.*rtype ) // noescape trick for header.typ ( reflect.*rtype )
@ -230,21 +239,7 @@ func (e *Encoder) encode(header *interfaceHeader, isNil bool) ([]byte, error) {
} }
storeOpcodeSet(typeptr, codeSet, opcodeMap) storeOpcodeSet(typeptr, codeSet, opcodeMap)
p := uintptr(header.ptr) return codeSet, nil
ctx := e.ctx
ctx.init(p, codeLength)
if e.enabledIndent {
if e.enabledHTMLEscape {
return e.runEscapedIndent(ctx, b, codeSet.code)
} else {
return e.runIndent(ctx, b, codeSet.code)
}
}
if e.enabledHTMLEscape {
return e.runEscaped(ctx, b, codeSet.code)
}
return e.run(ctx, b, codeSet.code)
} }
func encodeFloat32(b []byte, v float32) []byte { func encodeFloat32(b []byte, v float32) []byte {

View File

@ -49,10 +49,11 @@ func errMarshaler(code *opcode, err error) *MarshalerError {
} }
} }
func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte, error) { func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet) ([]byte, error) {
recursiveLevel := 0 recursiveLevel := 0
ptrOffset := uintptr(0) ptrOffset := uintptr(0)
ctxptr := ctx.ptr() ctxptr := ctx.ptr()
code := codeSet.code
for { for {
switch code.op { switch code.op {

View File

@ -11,11 +11,13 @@ import (
"unsafe" "unsafe"
) )
func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte, error) { func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet) ([]byte, error) {
recursiveLevel := 0 recursiveLevel := 0
ptrOffset := uintptr(0) ptrOffset := uintptr(0)
ctxptr := ctx.ptr() ctxptr := ctx.ptr()
code := codeSet.code
for { for {
switch code.op { switch code.op {
default: default:

View File

@ -11,11 +11,12 @@ import (
"unsafe" "unsafe"
) )
func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte, error) { func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet) ([]byte, error) {
recursiveLevel := 0 recursiveLevel := 0
var seenPtr map[uintptr]struct{} var seenPtr map[uintptr]struct{}
ptrOffset := uintptr(0) ptrOffset := uintptr(0)
ctxptr := ctx.ptr() ctxptr := ctx.ptr()
code := codeSet.code
for { for {
switch code.op { switch code.op {

View File

@ -11,11 +11,12 @@ import (
"unsafe" "unsafe"
) )
func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte, error) { func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet) ([]byte, error) {
recursiveLevel := 0 recursiveLevel := 0
var seenPtr map[uintptr]struct{} var seenPtr map[uintptr]struct{}
ptrOffset := uintptr(0) ptrOffset := uintptr(0)
ctxptr := ctx.ptr() ctxptr := ctx.ptr()
code := codeSet.code
for { for {
switch code.op { switch code.op {