Refactor encoder

This commit is contained in:
Masaaki Goshima 2020-04-30 13:52:24 +09:00
parent 090887bf7e
commit 4edbe3a346
3 changed files with 114 additions and 673 deletions

639
encode.go
View File

@ -1,15 +1,11 @@
package json package json
import ( import (
"fmt"
"io" "io"
"reflect" "reflect"
"strconv" "strconv"
"strings"
"sync" "sync"
"unsafe" "unsafe"
"golang.org/x/xerrors"
) )
// An Encoder writes JSON values to an output stream. // An Encoder writes JSON values to an output stream.
@ -19,31 +15,28 @@ type Encoder struct {
pool sync.Pool pool sync.Pool
} }
type EncodeOp func(*Encoder, *rtype, uintptr) error
const ( const (
bufSize = 1024 bufSize = 1024
) )
type EncodeOpMap struct { type opcodeMap struct {
sync.Map sync.Map
} }
func (m *EncodeOpMap) Get(k string) *opcode { //EncodeOp { func (m *opcodeMap) Get(k string) *opcode {
if v, ok := m.Load(k); ok { if v, ok := m.Load(k); ok {
return v.(*opcode) //(EncodeOp) return v.(*opcode)
} }
return nil return nil
} }
func (m *EncodeOpMap) Set(k string, op *opcode) { // EncodeOp) { func (m *opcodeMap) Set(k string, op *opcode) {
m.Store(k, op) m.Store(k, op)
} }
var ( var (
encPool sync.Pool encPool sync.Pool
cachedEncodeOp EncodeOpMap cachedOpcode opcodeMap
errCompileSlowPath = xerrors.New("json: detect dynamic type ( interface{} ) and compile with slow path")
) )
func init() { func init() {
@ -55,7 +48,7 @@ func init() {
} }
}, },
} }
cachedEncodeOp = EncodeOpMap{} cachedOpcode = opcodeMap{}
} }
// NewEncoder returns a new encoder that writes to w. // NewEncoder returns a new encoder that writes to w.
@ -183,624 +176,22 @@ func (e *Encoder) encode(v interface{}) error {
typ = typ.Elem() typ = typ.Elem()
} }
name := typ.String() name := typ.String()
if op := cachedEncodeOp.Get(name); op != nil { if code := cachedOpcode.Get(name); code != nil {
p := uintptr(header.ptr) p := uintptr(header.ptr)
op.ptr = p code.ptr = p
if err := e.run(op); err != nil { if err := e.run(code); err != nil {
return err return err
} }
//op(e, typ, p)
return nil return nil
} }
op, err := e.compileOp(typ) code, err := e.compile(typ)
if err != nil { if err != nil {
if err == errCompileSlowPath { return err
/*
slowOp, err := e.compileSlowPath(typ)
if err != nil {
return err
}
op = slowOp
*/
} else {
return err
}
} }
if name != "" { if name != "" {
cachedEncodeOp.Set(name, op) cachedOpcode.Set(name, code)
} }
p := uintptr(header.ptr) p := uintptr(header.ptr)
op.ptr = p code.ptr = p
e.run(op) return e.run(code)
//op(e, typ, p)
return nil
} }
func (e *Encoder) compile(typ *rtype) (EncodeOp, error) {
switch typ.Kind() {
case reflect.Ptr:
return e.compilePtr(typ)
case reflect.Slice:
return e.compileSlice(typ)
case reflect.Struct:
return e.compileStruct(typ)
case reflect.Map:
return e.compileMap(typ)
case reflect.Array:
return e.compileArray(typ)
case reflect.Int:
return e.compileInt()
case reflect.Int8:
return e.compileInt8()
case reflect.Int16:
return e.compileInt16()
case reflect.Int32:
return e.compileInt32()
case reflect.Int64:
return e.compileInt64()
case reflect.Uint:
return e.compileUint()
case reflect.Uint8:
return e.compileUint8()
case reflect.Uint16:
return e.compileUint16()
case reflect.Uint32:
return e.compileUint32()
case reflect.Uint64:
return e.compileUint64()
case reflect.Uintptr:
return e.compileUint()
case reflect.Float32:
return e.compileFloat32()
case reflect.Float64:
return e.compileFloat64()
case reflect.String:
return e.compileString()
case reflect.Bool:
return e.compileBool()
case reflect.Interface:
return nil, errCompileSlowPath
}
return nil, xerrors.Errorf("failed to encode type %s: %w", typ.String(), ErrUnsupportedType)
}
func (e *Encoder) compileSlowPath(typ *rtype) (EncodeOp, error) {
switch typ.Kind() {
case reflect.Ptr:
return e.compilePtrSlowPath(typ)
case reflect.Slice:
return e.compileSliceSlowPath(typ)
case reflect.Struct:
return e.compileStructSlowPath(typ)
case reflect.Map:
return e.compileMapSlowPath(typ)
case reflect.Array:
return e.compileArraySlowPath(typ)
case reflect.Int:
return e.compileInt()
case reflect.Int8:
return e.compileInt8()
case reflect.Int16:
return e.compileInt16()
case reflect.Int32:
return e.compileInt32()
case reflect.Int64:
return e.compileInt64()
case reflect.Uint:
return e.compileUint()
case reflect.Uint8:
return e.compileUint8()
case reflect.Uint16:
return e.compileUint16()
case reflect.Uint32:
return e.compileUint32()
case reflect.Uint64:
return e.compileUint64()
case reflect.Uintptr:
return e.compileUint()
case reflect.Float32:
return e.compileFloat32()
case reflect.Float64:
return e.compileFloat64()
case reflect.String:
return e.compileString()
case reflect.Bool:
return e.compileBool()
case reflect.Interface:
return e.compileInterface()
}
return nil, xerrors.Errorf("failed to encode type %s: %w", typ.String(), ErrUnsupportedType)
}
func (e *Encoder) compilePtr(typ *rtype) (EncodeOp, error) {
elem := typ.Elem()
op, err := e.compile(elem)
if err != nil {
return nil, err
}
return func(enc *Encoder, typ *rtype, p uintptr) error {
return op(enc, elem, e.ptrToPtr(p))
}, nil
}
func (e *Encoder) compilePtrSlowPath(typ *rtype) (EncodeOp, error) {
elem := typ.Elem()
op, err := e.compileSlowPath(elem)
if err != nil {
return nil, err
}
return func(enc *Encoder, typ *rtype, p uintptr) error {
return op(enc, typ.Elem(), e.ptrToPtr(p))
}, nil
}
func (e *Encoder) compileInt() (EncodeOp, error) {
return func(enc *Encoder, typ *rtype, p uintptr) error {
enc.encodeInt(e.ptrToInt(p))
return nil
}, nil
}
func (e *Encoder) compileInt8() (EncodeOp, error) {
return func(enc *Encoder, typ *rtype, p uintptr) error {
enc.encodeInt8(e.ptrToInt8(p))
return nil
}, nil
}
func (e *Encoder) compileInt16() (EncodeOp, error) {
return func(enc *Encoder, typ *rtype, p uintptr) error {
enc.encodeInt16(e.ptrToInt16(p))
return nil
}, nil
}
func (e *Encoder) compileInt32() (EncodeOp, error) {
return func(enc *Encoder, typ *rtype, p uintptr) error {
enc.encodeInt32(e.ptrToInt32(p))
return nil
}, nil
}
func (e *Encoder) compileInt64() (EncodeOp, error) {
return func(enc *Encoder, typ *rtype, p uintptr) error {
enc.encodeInt64(e.ptrToInt64(p))
return nil
}, nil
}
func (e *Encoder) compileUint() (EncodeOp, error) {
return func(enc *Encoder, typ *rtype, p uintptr) error {
enc.encodeUint(e.ptrToUint(p))
return nil
}, nil
}
func (e *Encoder) compileUint8() (EncodeOp, error) {
return func(enc *Encoder, typ *rtype, p uintptr) error {
enc.encodeUint8(e.ptrToUint8(p))
return nil
}, nil
}
func (e *Encoder) compileUint16() (EncodeOp, error) {
return func(enc *Encoder, typ *rtype, p uintptr) error {
enc.encodeUint16(e.ptrToUint16(p))
return nil
}, nil
}
func (e *Encoder) compileUint32() (EncodeOp, error) {
return func(enc *Encoder, typ *rtype, p uintptr) error {
enc.encodeUint32(e.ptrToUint32(p))
return nil
}, nil
}
func (e *Encoder) compileUint64() (EncodeOp, error) {
return func(enc *Encoder, typ *rtype, p uintptr) error {
enc.encodeUint64(e.ptrToUint64(p))
return nil
}, nil
}
func (e *Encoder) compileFloat32() (EncodeOp, error) {
return func(enc *Encoder, typ *rtype, p uintptr) error {
enc.encodeFloat32(e.ptrToFloat32(p))
return nil
}, nil
}
func (e *Encoder) compileFloat64() (EncodeOp, error) {
return func(enc *Encoder, typ *rtype, p uintptr) error {
enc.encodeFloat64(e.ptrToFloat64(p))
return nil
}, nil
}
func (e *Encoder) compileString() (EncodeOp, error) {
return func(enc *Encoder, typ *rtype, p uintptr) error {
enc.encodeEscapedString(e.ptrToString(p))
return nil
}, nil
}
func (e *Encoder) compileBool() (EncodeOp, error) {
return func(enc *Encoder, typ *rtype, p uintptr) error {
enc.encodeBool(e.ptrToBool(p))
return nil
}, nil
}
func (e *Encoder) compileSlice(typ *rtype) (EncodeOp, error) {
elem := typ.Elem()
size := elem.Size()
op, err := e.compile(elem)
if err != nil {
return nil, err
}
return func(enc *Encoder, typ *rtype, base uintptr) error {
if base == 0 {
enc.encodeString("null")
return nil
}
enc.encodeByte('[')
slice := (*reflect.SliceHeader)(unsafe.Pointer(base))
num := slice.Len
for i := 0; i < num; i++ {
if err := op(enc, elem, slice.Data+uintptr(i)*size); err != nil {
return err
}
if i != num-1 {
enc.encodeByte(',')
}
}
enc.encodeByte(']')
return nil
}, nil
}
func (e *Encoder) compileSliceSlowPath(typ *rtype) (EncodeOp, error) {
op, err := e.compileSlowPath(typ.Elem())
if err != nil {
return nil, err
}
return func(enc *Encoder, typ *rtype, base uintptr) error {
if base == 0 {
enc.encodeString("null")
return nil
}
size := typ.Elem().Size()
enc.encodeByte('[')
slice := (*reflect.SliceHeader)(unsafe.Pointer(base))
num := slice.Len
for i := 0; i < num; i++ {
if err := op(enc, typ.Elem(), slice.Data+uintptr(i)*size); err != nil {
return err
}
if i != num-1 {
enc.encodeByte(',')
}
}
enc.encodeByte(']')
return nil
}, nil
}
func (e *Encoder) compileArray(typ *rtype) (EncodeOp, error) {
elem := typ.Elem()
alen := typ.Len()
size := elem.Size()
op, err := e.compile(elem)
if err != nil {
return nil, err
}
return func(enc *Encoder, typ *rtype, base uintptr) error {
if base == 0 {
enc.encodeString("null")
return nil
}
enc.encodeByte('[')
for i := 0; i < alen; i++ {
if i != 0 {
enc.encodeByte(',')
}
if err := op(enc, elem, base+uintptr(i)*size); err != nil {
return err
}
}
enc.encodeByte(']')
return nil
}, nil
}
func (e *Encoder) compileArraySlowPath(typ *rtype) (EncodeOp, error) {
elem := typ.Elem()
alen := typ.Len()
op, err := e.compileSlowPath(elem)
if err != nil {
return nil, err
}
return func(enc *Encoder, typ *rtype, base uintptr) error {
if base == 0 {
enc.encodeString("null")
return nil
}
elem := typ.Elem()
size := elem.Size()
enc.encodeByte('[')
for i := 0; i < alen; i++ {
if i != 0 {
enc.encodeByte(',')
}
if err := op(enc, elem, base+uintptr(i)*size); err != nil {
return err
}
}
enc.encodeByte(']')
return nil
}, nil
}
func (e *Encoder) getTag(field reflect.StructField) string {
return field.Tag.Get("json")
}
func (e *Encoder) isIgnoredStructField(field reflect.StructField) bool {
if field.PkgPath != "" && !field.Anonymous {
// private field
return true
}
tag := e.getTag(field)
if tag == "-" {
return true
}
return false
}
type encodeStructField struct {
op EncodeOp
fieldIndex int
}
func (e *Encoder) compileStruct(typ *rtype) (EncodeOp, error) {
fieldNum := typ.NumField()
opQueue := make([]*encodeStructField, 0, fieldNum)
for i := 0; i < fieldNum; i++ {
field := typ.Field(i)
if e.isIgnoredStructField(field) {
continue
}
keyName := field.Name
tag := e.getTag(field)
opts := strings.Split(tag, ",")
if len(opts) > 0 {
if opts[0] != "" {
keyName = opts[0]
}
}
fieldType := type2rtype(field.Type)
op, err := e.compile(fieldType)
if err != nil {
return nil, err
}
key := fmt.Sprintf(`"%s":`, keyName)
structField := &encodeStructField{fieldIndex: i}
structField.op = func(enc *Encoder, typ *rtype, base uintptr) error {
enc.encodeString(key)
return op(enc, fieldType, base+field.Offset)
}
opQueue = append(opQueue, structField)
}
queueNum := len(opQueue)
return func(enc *Encoder, typ *rtype, base uintptr) error {
if base == 0 {
enc.encodeString("null")
return nil
}
enc.encodeByte('{')
for i := 0; i < queueNum; i++ {
if err := opQueue[i].op(enc, typ, base); err != nil {
return err
}
if i != queueNum-1 {
enc.encodeByte(',')
}
}
enc.encodeByte('}')
return nil
}, nil
}
func (e *Encoder) compileStructSlowPath(typ *rtype) (EncodeOp, error) {
fieldNum := typ.NumField()
opQueue := make([]*encodeStructField, 0, fieldNum)
for i := 0; i < fieldNum; i++ {
field := typ.Field(i)
if e.isIgnoredStructField(field) {
continue
}
keyName := field.Name
tag := e.getTag(field)
opts := strings.Split(tag, ",")
if len(opts) > 0 {
if opts[0] != "" {
keyName = opts[0]
}
}
fieldType := type2rtype(field.Type)
op, err := e.compileSlowPath(fieldType)
if err != nil {
return nil, err
}
key := fmt.Sprintf(`"%s":`, keyName)
structField := &encodeStructField{fieldIndex: i}
structField.op = func(enc *Encoder, typ *rtype, base uintptr) error {
enc.encodeString(key)
fieldType := type2rtype(typ.Field(structField.fieldIndex).Type)
return op(enc, fieldType, base+field.Offset)
}
opQueue = append(opQueue, structField)
}
queueNum := len(opQueue)
return func(enc *Encoder, typ *rtype, base uintptr) error {
if base == 0 {
enc.encodeString("null")
return nil
}
enc.encodeByte('{')
for i := 0; i < queueNum; i++ {
if err := opQueue[i].op(enc, typ, base); err != nil {
return err
}
if i != queueNum-1 {
enc.encodeByte(',')
}
}
enc.encodeByte('}')
return nil
}, nil
}
//go:linkname mapiterinit reflect.mapiterinit
//go:noescape
func mapiterinit(mapType *rtype, m unsafe.Pointer) unsafe.Pointer
//go:linkname mapiterkey reflect.mapiterkey
//go:noescape
func mapiterkey(it unsafe.Pointer) unsafe.Pointer
//go:linkname mapiternext reflect.mapiternext
//go:noescape
func mapiternext(it unsafe.Pointer)
//go:linkname maplen reflect.maplen
//go:noescape
func maplen(m unsafe.Pointer) int
type valueType struct {
typ unsafe.Pointer
ptr unsafe.Pointer
}
func (e *Encoder) compileMap(typ *rtype) (EncodeOp, error) {
keyType := typ.Key()
keyOp, err := e.compile(keyType)
if err != nil {
return nil, err
}
valueType := typ.Elem()
valueOp, err := e.compile(valueType)
if err != nil {
return nil, err
}
return func(enc *Encoder, typ *rtype, base uintptr) error {
if base == 0 {
enc.encodeString("null")
return nil
}
enc.encodeByte('{')
mlen := maplen(unsafe.Pointer(base))
iter := mapiterinit(typ, unsafe.Pointer(base))
for i := 0; i < mlen; i++ {
key := mapiterkey(iter)
if i != 0 {
enc.encodeByte(',')
}
value := mapitervalue(iter)
keyptr := uintptr(key)
if err := keyOp(enc, keyType, keyptr); err != nil {
return err
}
enc.encodeByte(':')
valueptr := uintptr(value)
if err := valueOp(enc, valueType, valueptr); err != nil {
return err
}
mapiternext(iter)
}
enc.encodeByte('}')
return nil
}, nil
}
func (e *Encoder) compileMapSlowPath(typ *rtype) (EncodeOp, error) {
keyOp, err := e.compileSlowPath(typ.Key())
if err != nil {
return nil, err
}
valueOp, err := e.compileSlowPath(typ.Elem())
if err != nil {
return nil, err
}
return func(enc *Encoder, typ *rtype, base uintptr) error {
if base == 0 {
enc.encodeString("null")
return nil
}
enc.encodeByte('{')
mlen := maplen(unsafe.Pointer(base))
iter := mapiterinit(typ, unsafe.Pointer(base))
for i := 0; i < mlen; i++ {
key := mapiterkey(iter)
if i != 0 {
enc.encodeByte(',')
}
value := mapitervalue(iter)
keyptr := uintptr(key)
if err := keyOp(enc, typ.Key(), keyptr); err != nil {
return err
}
enc.encodeByte(':')
valueptr := uintptr(value)
if err := valueOp(enc, typ.Elem(), valueptr); err != nil {
return err
}
mapiternext(iter)
}
enc.encodeByte('}')
return nil
}, nil
}
func (e *Encoder) compileInterface() (EncodeOp, error) {
return func(enc *Encoder, typ *rtype, base uintptr) error {
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{
typ: typ,
ptr: unsafe.Pointer(base),
}))
vv := reflect.ValueOf(v).Interface()
header := (*interfaceHeader)(unsafe.Pointer(&vv))
t := header.typ
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
op, err := e.compileSlowPath(t)
if err != nil {
return err
}
return op(enc, t, uintptr(header.ptr))
}, nil
}
func (e *Encoder) ptrToPtr(p uintptr) uintptr { return *(*uintptr)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToInt(p uintptr) int { return *(*int)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToInt8(p uintptr) int8 { return *(*int8)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToInt16(p uintptr) int16 { return *(*int16)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToInt32(p uintptr) int32 { return *(*int32)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToInt64(p uintptr) int64 { return *(*int64)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToUint(p uintptr) uint { return *(*uint)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToUint8(p uintptr) uint8 { return *(*uint8)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToUint16(p uintptr) uint16 { return *(*uint16)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToUint32(p uintptr) uint32 { return *(*uint32)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToUint64(p uintptr) uint64 { return *(*uint64)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToFloat32(p uintptr) float32 { return *(*float32)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToFloat64(p uintptr) float64 { return *(*float64)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToBool(p uintptr) bool { return *(*bool)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToByte(p uintptr) byte { return *(*byte)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToBytes(p uintptr) []byte { return *(*[]byte)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToString(p uintptr) string { return *(*string)(unsafe.Pointer(p)) }

View File

@ -9,50 +9,50 @@ import (
"golang.org/x/xerrors" "golang.org/x/xerrors"
) )
func (e *Encoder) compileOp(typ *rtype) (*opcode, error) { func (e *Encoder) compile(typ *rtype) (*opcode, error) {
switch typ.Kind() { switch typ.Kind() {
case reflect.Ptr: case reflect.Ptr:
return e.compilePtrOp(typ) return e.compilePtr(typ)
case reflect.Slice: case reflect.Slice:
return e.compileSliceOp(typ) return e.compileSlice(typ)
case reflect.Array: case reflect.Array:
return e.compileArrayOp(typ) return e.compileArray(typ)
case reflect.Map: case reflect.Map:
return e.compileMapOp(typ) return e.compileMap(typ)
case reflect.Struct: case reflect.Struct:
return e.compileStructOp(typ) return e.compileStruct(typ)
case reflect.Int: case reflect.Int:
return e.compileIntOp(typ) return e.compileInt(typ)
case reflect.Int8: case reflect.Int8:
return e.compileInt8Op(typ) return e.compileInt8(typ)
case reflect.Int16: case reflect.Int16:
return e.compileInt16Op(typ) return e.compileInt16(typ)
case reflect.Int32: case reflect.Int32:
return e.compileInt32Op(typ) return e.compileInt32(typ)
case reflect.Int64: case reflect.Int64:
return e.compileInt64Op(typ) return e.compileInt64(typ)
case reflect.Uint: case reflect.Uint:
return e.compileUintOp(typ) return e.compileUint(typ)
case reflect.Uint8: case reflect.Uint8:
return e.compileUint8Op(typ) return e.compileUint8(typ)
case reflect.Uint16: case reflect.Uint16:
return e.compileUint16Op(typ) return e.compileUint16(typ)
case reflect.Uint32: case reflect.Uint32:
return e.compileUint32Op(typ) return e.compileUint32(typ)
case reflect.Uint64: case reflect.Uint64:
return e.compileUint64Op(typ) return e.compileUint64(typ)
case reflect.Uintptr: case reflect.Uintptr:
return e.compileUintOp(typ) return e.compileUint(typ)
case reflect.Float32: case reflect.Float32:
return e.compileFloat32Op(typ) return e.compileFloat32(typ)
case reflect.Float64: case reflect.Float64:
return e.compileFloat64Op(typ) return e.compileFloat64(typ)
case reflect.String: case reflect.String:
return e.compileStringOp(typ) return e.compileString(typ)
case reflect.Bool: case reflect.Bool:
return e.compileBoolOp(typ) return e.compileBool(typ)
case reflect.Interface: case reflect.Interface:
return e.compileInterfaceOp(typ) return e.compileInterface(typ)
} }
return nil, xerrors.Errorf("failed to encode type %s: %w", typ.String(), ErrUnsupportedType) return nil, xerrors.Errorf("failed to encode type %s: %w", typ.String(), ErrUnsupportedType)
} }
@ -95,78 +95,78 @@ func (e *Encoder) optimizeStructFieldPtrHead(typ *rtype, code *opcode) *opcode {
return code return code
} }
func (e *Encoder) compilePtrOp(typ *rtype) (*opcode, error) { func (e *Encoder) compilePtr(typ *rtype) (*opcode, error) {
code, err := e.compileOp(typ.Elem()) code, err := e.compile(typ.Elem())
if err != nil { if err != nil {
return nil, err return nil, err
} }
return e.optimizeStructFieldPtrHead(typ, code), nil return e.optimizeStructFieldPtrHead(typ, code), nil
} }
func (e *Encoder) compileIntOp(typ *rtype) (*opcode, error) { func (e *Encoder) compileInt(typ *rtype) (*opcode, error) {
return newOpCode(opInt, typ, newEndOp()), nil return newOpCode(opInt, typ, newEndOp()), nil
} }
func (e *Encoder) compileInt8Op(typ *rtype) (*opcode, error) { func (e *Encoder) compileInt8(typ *rtype) (*opcode, error) {
return newOpCode(opInt8, typ, newEndOp()), nil return newOpCode(opInt8, typ, newEndOp()), nil
} }
func (e *Encoder) compileInt16Op(typ *rtype) (*opcode, error) { func (e *Encoder) compileInt16(typ *rtype) (*opcode, error) {
return newOpCode(opInt16, typ, newEndOp()), nil return newOpCode(opInt16, typ, newEndOp()), nil
} }
func (e *Encoder) compileInt32Op(typ *rtype) (*opcode, error) { func (e *Encoder) compileInt32(typ *rtype) (*opcode, error) {
return newOpCode(opInt32, typ, newEndOp()), nil return newOpCode(opInt32, typ, newEndOp()), nil
} }
func (e *Encoder) compileInt64Op(typ *rtype) (*opcode, error) { func (e *Encoder) compileInt64(typ *rtype) (*opcode, error) {
return newOpCode(opInt64, typ, newEndOp()), nil return newOpCode(opInt64, typ, newEndOp()), nil
} }
func (e *Encoder) compileUintOp(typ *rtype) (*opcode, error) { func (e *Encoder) compileUint(typ *rtype) (*opcode, error) {
return newOpCode(opUint, typ, newEndOp()), nil return newOpCode(opUint, typ, newEndOp()), nil
} }
func (e *Encoder) compileUint8Op(typ *rtype) (*opcode, error) { func (e *Encoder) compileUint8(typ *rtype) (*opcode, error) {
return newOpCode(opUint8, typ, newEndOp()), nil return newOpCode(opUint8, typ, newEndOp()), nil
} }
func (e *Encoder) compileUint16Op(typ *rtype) (*opcode, error) { func (e *Encoder) compileUint16(typ *rtype) (*opcode, error) {
return newOpCode(opUint16, typ, newEndOp()), nil return newOpCode(opUint16, typ, newEndOp()), nil
} }
func (e *Encoder) compileUint32Op(typ *rtype) (*opcode, error) { func (e *Encoder) compileUint32(typ *rtype) (*opcode, error) {
return newOpCode(opUint32, typ, newEndOp()), nil return newOpCode(opUint32, typ, newEndOp()), nil
} }
func (e *Encoder) compileUint64Op(typ *rtype) (*opcode, error) { func (e *Encoder) compileUint64(typ *rtype) (*opcode, error) {
return newOpCode(opUint64, typ, newEndOp()), nil return newOpCode(opUint64, typ, newEndOp()), nil
} }
func (e *Encoder) compileFloat32Op(typ *rtype) (*opcode, error) { func (e *Encoder) compileFloat32(typ *rtype) (*opcode, error) {
return newOpCode(opFloat32, typ, newEndOp()), nil return newOpCode(opFloat32, typ, newEndOp()), nil
} }
func (e *Encoder) compileFloat64Op(typ *rtype) (*opcode, error) { func (e *Encoder) compileFloat64(typ *rtype) (*opcode, error) {
return newOpCode(opFloat64, typ, newEndOp()), nil return newOpCode(opFloat64, typ, newEndOp()), nil
} }
func (e *Encoder) compileStringOp(typ *rtype) (*opcode, error) { func (e *Encoder) compileString(typ *rtype) (*opcode, error) {
return newOpCode(opString, typ, newEndOp()), nil return newOpCode(opString, typ, newEndOp()), nil
} }
func (e *Encoder) compileBoolOp(typ *rtype) (*opcode, error) { func (e *Encoder) compileBool(typ *rtype) (*opcode, error) {
return newOpCode(opBool, typ, newEndOp()), nil return newOpCode(opBool, typ, newEndOp()), nil
} }
func (e *Encoder) compileInterfaceOp(typ *rtype) (*opcode, error) { func (e *Encoder) compileInterface(typ *rtype) (*opcode, error) {
return newOpCode(opInterface, typ, newEndOp()), nil return newOpCode(opInterface, typ, newEndOp()), nil
} }
func (e *Encoder) compileSliceOp(typ *rtype) (*opcode, error) { func (e *Encoder) compileSlice(typ *rtype) (*opcode, error) {
elem := typ.Elem() elem := typ.Elem()
size := elem.Size() size := elem.Size()
code, err := e.compileOp(elem) code, err := e.compile(elem)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -188,11 +188,11 @@ func (e *Encoder) compileSliceOp(typ *rtype) (*opcode, error) {
return (*opcode)(unsafe.Pointer(header)), nil return (*opcode)(unsafe.Pointer(header)), nil
} }
func (e *Encoder) compileArrayOp(typ *rtype) (*opcode, error) { func (e *Encoder) compileArray(typ *rtype) (*opcode, error) {
elem := typ.Elem() elem := typ.Elem()
alen := typ.Len() alen := typ.Len()
size := elem.Size() size := elem.Size()
code, err := e.compileOp(elem) code, err := e.compile(elem)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -219,17 +219,33 @@ func (e *Encoder) compileArrayOp(typ *rtype) (*opcode, error) {
return (*opcode)(unsafe.Pointer(header)), nil return (*opcode)(unsafe.Pointer(header)), nil
} }
func (e *Encoder) compileMapOp(typ *rtype) (*opcode, error) { //go:linkname mapiterinit reflect.mapiterinit
//go:noescape
func mapiterinit(mapType *rtype, m unsafe.Pointer) unsafe.Pointer
//go:linkname mapiterkey reflect.mapiterkey
//go:noescape
func mapiterkey(it unsafe.Pointer) unsafe.Pointer
//go:linkname mapiternext reflect.mapiternext
//go:noescape
func mapiternext(it unsafe.Pointer)
//go:linkname maplen reflect.maplen
//go:noescape
func maplen(m unsafe.Pointer) int
func (e *Encoder) compileMap(typ *rtype) (*opcode, error) {
// header => code => value => code => key => code => value => code => end // header => code => value => code => key => code => value => code => end
// ^ | // ^ |
// |_______________________| // |_______________________|
keyType := typ.Key() keyType := typ.Key()
keyCode, err := e.compileOp(keyType) keyCode, err := e.compile(keyType)
if err != nil { if err != nil {
return nil, err return nil, err
} }
valueType := typ.Elem() valueType := typ.Elem()
valueCode, err := e.compileOp(valueType) valueCode, err := e.compile(valueType)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -252,7 +268,23 @@ func (e *Encoder) compileMapOp(typ *rtype) (*opcode, error) {
return (*opcode)(unsafe.Pointer(header)), nil return (*opcode)(unsafe.Pointer(header)), nil
} }
func (e *Encoder) compileStructOp(typ *rtype) (*opcode, error) { func (e *Encoder) getTag(field reflect.StructField) string {
return field.Tag.Get("json")
}
func (e *Encoder) isIgnoredStructField(field reflect.StructField) bool {
if field.PkgPath != "" && !field.Anonymous {
// private field
return true
}
tag := e.getTag(field)
if tag == "-" {
return true
}
return false
}
func (e *Encoder) compileStruct(typ *rtype) (*opcode, error) {
// header => code => structField => code => end // header => code => structField => code => end
// ^ | // ^ |
// |__________| // |__________|
@ -277,7 +309,7 @@ func (e *Encoder) compileStructOp(typ *rtype) (*opcode, error) {
} }
} }
fieldType := type2rtype(field.Type) fieldType := type2rtype(field.Type)
valueCode, err := e.compileOp(fieldType) valueCode, err := e.compile(fieldType)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -66,7 +66,7 @@ func (e *Encoder) run(code *opcode) error {
if typ.Kind() == reflect.Ptr { if typ.Kind() == reflect.Ptr {
typ = typ.Elem() typ = typ.Elem()
} }
c, err := e.compileOp(typ) c, err := e.compile(typ)
if err != nil { if err != nil {
return err return err
} }
@ -525,3 +525,21 @@ func (e *Encoder) run(code *opcode) error {
END: END:
return nil return nil
} }
func (e *Encoder) ptrToPtr(p uintptr) uintptr { return *(*uintptr)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToInt(p uintptr) int { return *(*int)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToInt8(p uintptr) int8 { return *(*int8)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToInt16(p uintptr) int16 { return *(*int16)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToInt32(p uintptr) int32 { return *(*int32)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToInt64(p uintptr) int64 { return *(*int64)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToUint(p uintptr) uint { return *(*uint)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToUint8(p uintptr) uint8 { return *(*uint8)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToUint16(p uintptr) uint16 { return *(*uint16)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToUint32(p uintptr) uint32 { return *(*uint32)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToUint64(p uintptr) uint64 { return *(*uint64)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToFloat32(p uintptr) float32 { return *(*float32)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToFloat64(p uintptr) float64 { return *(*float64)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToBool(p uintptr) bool { return *(*bool)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToByte(p uintptr) byte { return *(*byte)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToBytes(p uintptr) []byte { return *(*[]byte)(unsafe.Pointer(p)) }
func (e *Encoder) ptrToString(p uintptr) string { return *(*string)(unsafe.Pointer(p)) }