mirror of https://github.com/goccy/go-json.git
Add MarshalIndent
This commit is contained in:
parent
03a21193fc
commit
3d7267abc8
116
encode.go
116
encode.go
|
@ -1,6 +1,7 @@
|
||||||
package json
|
package json
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -13,6 +14,10 @@ type Encoder struct {
|
||||||
w io.Writer
|
w io.Writer
|
||||||
buf []byte
|
buf []byte
|
||||||
pool sync.Pool
|
pool sync.Pool
|
||||||
|
enabledIndent bool
|
||||||
|
prefix []byte
|
||||||
|
indentStr []byte
|
||||||
|
indent int
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -23,14 +28,19 @@ type opcodeMap struct {
|
||||||
sync.Map
|
sync.Map
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *opcodeMap) Get(k *rtype) *opcode {
|
type opcodeSet struct {
|
||||||
|
codeIndent *opcode
|
||||||
|
code *opcode
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *opcodeMap) get(k *rtype) *opcodeSet {
|
||||||
if v, ok := m.Load(k); ok {
|
if v, ok := m.Load(k); ok {
|
||||||
return v.(*opcode)
|
return v.(*opcodeSet)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *opcodeMap) Set(k *rtype, op *opcode) {
|
func (m *opcodeMap) set(k *rtype, op *opcodeSet) {
|
||||||
m.Store(k, op)
|
m.Store(k, op)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +65,7 @@ func init() {
|
||||||
func NewEncoder(w io.Writer) *Encoder {
|
func NewEncoder(w io.Writer) *Encoder {
|
||||||
enc := encPool.Get().(*Encoder)
|
enc := encPool.Get().(*Encoder)
|
||||||
enc.w = w
|
enc.w = w
|
||||||
|
enc.indent = 0
|
||||||
enc.reset()
|
enc.reset()
|
||||||
return enc
|
return enc
|
||||||
}
|
}
|
||||||
|
@ -72,15 +83,6 @@ func (e *Encoder) Encode(v interface{}) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) encodeForMarshal(v interface{}) ([]byte, error) {
|
|
||||||
if err := e.encode(v); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
copied := make([]byte, len(e.buf))
|
|
||||||
copy(copied, e.buf)
|
|
||||||
return copied, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetEscapeHTML specifies whether problematic HTML characters should be escaped inside JSON quoted strings.
|
// SetEscapeHTML specifies whether problematic HTML characters should be escaped inside JSON quoted strings.
|
||||||
// The default behavior is to escape &, <, and > to \u0026, \u003c, and \u003e to avoid certain safety problems that can arise when embedding JSON in HTML.
|
// The default behavior is to escape &, <, and > to \u0026, \u003c, and \u003e to avoid certain safety problems that can arise when embedding JSON in HTML.
|
||||||
//
|
//
|
||||||
|
@ -92,7 +94,13 @@ func (e *Encoder) SetEscapeHTML(on bool) {
|
||||||
// SetIndent instructs the encoder to format each subsequent encoded value as if indented by the package-level function Indent(dst, src, prefix, indent).
|
// SetIndent instructs the encoder to format each subsequent encoded value as if indented by the package-level function Indent(dst, src, prefix, indent).
|
||||||
// Calling SetIndent("", "") disables indentation.
|
// Calling SetIndent("", "") disables indentation.
|
||||||
func (e *Encoder) SetIndent(prefix, indent string) {
|
func (e *Encoder) SetIndent(prefix, indent string) {
|
||||||
|
if prefix == "" && indent == "" {
|
||||||
|
e.enabledIndent = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.prefix = []byte(prefix)
|
||||||
|
e.indentStr = []byte(indent)
|
||||||
|
e.enabledIndent = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) release() {
|
func (e *Encoder) release() {
|
||||||
|
@ -104,6 +112,63 @@ func (e *Encoder) reset() {
|
||||||
e.buf = e.buf[:0]
|
e.buf = e.buf[:0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) encodeForMarshal(v interface{}) ([]byte, error) {
|
||||||
|
if err := e.encode(v); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if e.enabledIndent {
|
||||||
|
last := len(e.buf) - 1
|
||||||
|
if e.buf[last] == '\n' {
|
||||||
|
last--
|
||||||
|
}
|
||||||
|
length := last + 1
|
||||||
|
copied := make([]byte, length)
|
||||||
|
copy(copied, e.buf[0:length])
|
||||||
|
return copied, nil
|
||||||
|
}
|
||||||
|
copied := make([]byte, len(e.buf))
|
||||||
|
copy(copied, e.buf)
|
||||||
|
return copied, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) encode(v interface{}) error {
|
||||||
|
header := (*interfaceHeader)(unsafe.Pointer(&v))
|
||||||
|
typ := header.typ
|
||||||
|
if typ.Kind() == reflect.Ptr {
|
||||||
|
typ = typ.Elem()
|
||||||
|
}
|
||||||
|
if codeSet := cachedOpcode.get(typ); codeSet != nil {
|
||||||
|
var code *opcode
|
||||||
|
if e.enabledIndent {
|
||||||
|
code = codeSet.codeIndent
|
||||||
|
} else {
|
||||||
|
code = codeSet.code
|
||||||
|
}
|
||||||
|
p := uintptr(header.ptr)
|
||||||
|
code.ptr = p
|
||||||
|
if err := e.run(code); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
codeIndent, err := e.compile(typ, true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
code, err := e.compile(typ, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
codeSet := &opcodeSet{codeIndent: codeIndent, code: code}
|
||||||
|
cachedOpcode.set(typ, codeSet)
|
||||||
|
p := uintptr(header.ptr)
|
||||||
|
code.ptr = p
|
||||||
|
if e.enabledIndent {
|
||||||
|
return e.run(codeIndent)
|
||||||
|
}
|
||||||
|
return e.run(code)
|
||||||
|
}
|
||||||
|
|
||||||
func (e *Encoder) encodeInt(v int) {
|
func (e *Encoder) encodeInt(v int) {
|
||||||
e.encodeInt64(int64(v))
|
e.encodeInt64(int64(v))
|
||||||
}
|
}
|
||||||
|
@ -169,26 +234,7 @@ func (e *Encoder) encodeByte(b byte) {
|
||||||
e.buf = append(e.buf, b)
|
e.buf = append(e.buf, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) encode(v interface{}) error {
|
func (e *Encoder) encodeIndent(indent int) {
|
||||||
header := (*interfaceHeader)(unsafe.Pointer(&v))
|
e.buf = append(e.buf, e.prefix...)
|
||||||
typ := header.typ
|
e.buf = append(e.buf, bytes.Repeat(e.indentStr, indent)...)
|
||||||
if typ.Kind() == reflect.Ptr {
|
|
||||||
typ = typ.Elem()
|
|
||||||
}
|
|
||||||
if code := cachedOpcode.Get(typ); code != nil {
|
|
||||||
p := uintptr(header.ptr)
|
|
||||||
code.ptr = p
|
|
||||||
if err := e.run(code); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
code, err := e.compile(typ)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
cachedOpcode.Set(typ, code)
|
|
||||||
p := uintptr(header.ptr)
|
|
||||||
code.ptr = p
|
|
||||||
return e.run(code)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,18 +9,18 @@ import (
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (e *Encoder) compile(typ *rtype) (*opcode, error) {
|
func (e *Encoder) compile(typ *rtype, withIndent bool) (*opcode, error) {
|
||||||
switch typ.Kind() {
|
switch typ.Kind() {
|
||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
return e.compilePtr(typ)
|
return e.compilePtr(typ, withIndent)
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
return e.compileSlice(typ)
|
return e.compileSlice(typ, withIndent)
|
||||||
case reflect.Array:
|
case reflect.Array:
|
||||||
return e.compileArray(typ)
|
return e.compileArray(typ, withIndent)
|
||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
return e.compileMap(typ)
|
return e.compileMap(typ, withIndent)
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
return e.compileStruct(typ)
|
return e.compileStruct(typ, withIndent)
|
||||||
case reflect.Int:
|
case reflect.Int:
|
||||||
return e.compileInt(typ)
|
return e.compileInt(typ)
|
||||||
case reflect.Int8:
|
case reflect.Int8:
|
||||||
|
@ -119,14 +119,75 @@ func (e *Encoder) optimizeStructFieldPtrHead(typ *rtype, code *opcode) *opcode {
|
||||||
code.op = opStructFieldPtrHeadStringOmitEmpty
|
code.op = opStructFieldPtrHeadStringOmitEmpty
|
||||||
case opStructFieldHeadBoolOmitEmpty:
|
case opStructFieldHeadBoolOmitEmpty:
|
||||||
code.op = opStructFieldPtrHeadBoolOmitEmpty
|
code.op = opStructFieldPtrHeadBoolOmitEmpty
|
||||||
|
|
||||||
|
case opStructFieldHeadIndent:
|
||||||
|
code.op = opStructFieldPtrHeadIndent
|
||||||
|
case opStructFieldHeadIntIndent:
|
||||||
|
code.op = opStructFieldPtrHeadIntIndent
|
||||||
|
case opStructFieldHeadInt8Indent:
|
||||||
|
code.op = opStructFieldPtrHeadInt8Indent
|
||||||
|
case opStructFieldHeadInt16Indent:
|
||||||
|
code.op = opStructFieldPtrHeadInt16Indent
|
||||||
|
case opStructFieldHeadInt32Indent:
|
||||||
|
code.op = opStructFieldPtrHeadInt32Indent
|
||||||
|
case opStructFieldHeadInt64Indent:
|
||||||
|
code.op = opStructFieldPtrHeadInt64Indent
|
||||||
|
case opStructFieldHeadUintIndent:
|
||||||
|
code.op = opStructFieldPtrHeadUintIndent
|
||||||
|
case opStructFieldHeadUint8Indent:
|
||||||
|
code.op = opStructFieldPtrHeadUint8Indent
|
||||||
|
case opStructFieldHeadUint16Indent:
|
||||||
|
code.op = opStructFieldPtrHeadUint16Indent
|
||||||
|
case opStructFieldHeadUint32Indent:
|
||||||
|
code.op = opStructFieldPtrHeadUint32Indent
|
||||||
|
case opStructFieldHeadUint64Indent:
|
||||||
|
code.op = opStructFieldPtrHeadUint64Indent
|
||||||
|
case opStructFieldHeadFloat32Indent:
|
||||||
|
code.op = opStructFieldPtrHeadFloat32Indent
|
||||||
|
case opStructFieldHeadFloat64Indent:
|
||||||
|
code.op = opStructFieldPtrHeadFloat64Indent
|
||||||
|
case opStructFieldHeadStringIndent:
|
||||||
|
code.op = opStructFieldPtrHeadStringIndent
|
||||||
|
case opStructFieldHeadBoolIndent:
|
||||||
|
code.op = opStructFieldPtrHeadBoolIndent
|
||||||
|
case opStructFieldHeadOmitEmptyIndent:
|
||||||
|
code.op = opStructFieldPtrHeadOmitEmptyIndent
|
||||||
|
case opStructFieldHeadIntOmitEmptyIndent:
|
||||||
|
code.op = opStructFieldPtrHeadIntOmitEmptyIndent
|
||||||
|
case opStructFieldHeadInt8OmitEmptyIndent:
|
||||||
|
code.op = opStructFieldPtrHeadInt8OmitEmptyIndent
|
||||||
|
case opStructFieldHeadInt16OmitEmptyIndent:
|
||||||
|
code.op = opStructFieldPtrHeadInt16OmitEmptyIndent
|
||||||
|
case opStructFieldHeadInt32OmitEmptyIndent:
|
||||||
|
code.op = opStructFieldPtrHeadInt32OmitEmptyIndent
|
||||||
|
case opStructFieldHeadInt64OmitEmptyIndent:
|
||||||
|
code.op = opStructFieldPtrHeadInt64OmitEmptyIndent
|
||||||
|
case opStructFieldHeadUintOmitEmptyIndent:
|
||||||
|
code.op = opStructFieldPtrHeadUintOmitEmptyIndent
|
||||||
|
case opStructFieldHeadUint8OmitEmptyIndent:
|
||||||
|
code.op = opStructFieldPtrHeadUint8OmitEmptyIndent
|
||||||
|
case opStructFieldHeadUint16OmitEmptyIndent:
|
||||||
|
code.op = opStructFieldPtrHeadUint16OmitEmptyIndent
|
||||||
|
case opStructFieldHeadUint32OmitEmptyIndent:
|
||||||
|
code.op = opStructFieldPtrHeadUint32OmitEmptyIndent
|
||||||
|
case opStructFieldHeadUint64OmitEmptyIndent:
|
||||||
|
code.op = opStructFieldPtrHeadUint64OmitEmptyIndent
|
||||||
|
case opStructFieldHeadFloat32OmitEmptyIndent:
|
||||||
|
code.op = opStructFieldPtrHeadFloat32OmitEmptyIndent
|
||||||
|
case opStructFieldHeadFloat64OmitEmptyIndent:
|
||||||
|
code.op = opStructFieldPtrHeadFloat64OmitEmptyIndent
|
||||||
|
case opStructFieldHeadStringOmitEmptyIndent:
|
||||||
|
code.op = opStructFieldPtrHeadStringOmitEmptyIndent
|
||||||
|
case opStructFieldHeadBoolOmitEmptyIndent:
|
||||||
|
code.op = opStructFieldPtrHeadBoolOmitEmptyIndent
|
||||||
default:
|
default:
|
||||||
return newOpCode(opPtr, typ, code)
|
return newOpCode(opPtr, typ, e.indent, code)
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) compilePtr(typ *rtype) (*opcode, error) {
|
func (e *Encoder) compilePtr(typ *rtype, withIndent bool) (*opcode, error) {
|
||||||
code, err := e.compile(typ.Elem())
|
code, err := e.compile(typ.Elem(), withIndent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -134,69 +195,73 @@ func (e *Encoder) compilePtr(typ *rtype) (*opcode, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) compileInt(typ *rtype) (*opcode, error) {
|
func (e *Encoder) compileInt(typ *rtype) (*opcode, error) {
|
||||||
return newOpCode(opInt, typ, newEndOp()), nil
|
return newOpCode(opInt, typ, e.indent, newEndOp(e.indent)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) compileInt8(typ *rtype) (*opcode, error) {
|
func (e *Encoder) compileInt8(typ *rtype) (*opcode, error) {
|
||||||
return newOpCode(opInt8, typ, newEndOp()), nil
|
return newOpCode(opInt8, typ, e.indent, newEndOp(e.indent)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) compileInt16(typ *rtype) (*opcode, error) {
|
func (e *Encoder) compileInt16(typ *rtype) (*opcode, error) {
|
||||||
return newOpCode(opInt16, typ, newEndOp()), nil
|
return newOpCode(opInt16, typ, e.indent, newEndOp(e.indent)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) compileInt32(typ *rtype) (*opcode, error) {
|
func (e *Encoder) compileInt32(typ *rtype) (*opcode, error) {
|
||||||
return newOpCode(opInt32, typ, newEndOp()), nil
|
return newOpCode(opInt32, typ, e.indent, newEndOp(e.indent)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) compileInt64(typ *rtype) (*opcode, error) {
|
func (e *Encoder) compileInt64(typ *rtype) (*opcode, error) {
|
||||||
return newOpCode(opInt64, typ, newEndOp()), nil
|
return newOpCode(opInt64, typ, e.indent, newEndOp(e.indent)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) compileUint(typ *rtype) (*opcode, error) {
|
func (e *Encoder) compileUint(typ *rtype) (*opcode, error) {
|
||||||
return newOpCode(opUint, typ, newEndOp()), nil
|
return newOpCode(opUint, typ, e.indent, newEndOp(e.indent)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) compileUint8(typ *rtype) (*opcode, error) {
|
func (e *Encoder) compileUint8(typ *rtype) (*opcode, error) {
|
||||||
return newOpCode(opUint8, typ, newEndOp()), nil
|
return newOpCode(opUint8, typ, e.indent, newEndOp(e.indent)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) compileUint16(typ *rtype) (*opcode, error) {
|
func (e *Encoder) compileUint16(typ *rtype) (*opcode, error) {
|
||||||
return newOpCode(opUint16, typ, newEndOp()), nil
|
return newOpCode(opUint16, typ, e.indent, newEndOp(e.indent)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) compileUint32(typ *rtype) (*opcode, error) {
|
func (e *Encoder) compileUint32(typ *rtype) (*opcode, error) {
|
||||||
return newOpCode(opUint32, typ, newEndOp()), nil
|
return newOpCode(opUint32, typ, e.indent, newEndOp(e.indent)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) compileUint64(typ *rtype) (*opcode, error) {
|
func (e *Encoder) compileUint64(typ *rtype) (*opcode, error) {
|
||||||
return newOpCode(opUint64, typ, newEndOp()), nil
|
return newOpCode(opUint64, typ, e.indent, newEndOp(e.indent)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) compileFloat32(typ *rtype) (*opcode, error) {
|
func (e *Encoder) compileFloat32(typ *rtype) (*opcode, error) {
|
||||||
return newOpCode(opFloat32, typ, newEndOp()), nil
|
return newOpCode(opFloat32, typ, e.indent, newEndOp(e.indent)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) compileFloat64(typ *rtype) (*opcode, error) {
|
func (e *Encoder) compileFloat64(typ *rtype) (*opcode, error) {
|
||||||
return newOpCode(opFloat64, typ, newEndOp()), nil
|
return newOpCode(opFloat64, typ, e.indent, newEndOp(e.indent)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) compileString(typ *rtype) (*opcode, error) {
|
func (e *Encoder) compileString(typ *rtype) (*opcode, error) {
|
||||||
return newOpCode(opString, typ, newEndOp()), nil
|
return newOpCode(opString, typ, e.indent, newEndOp(e.indent)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) compileBool(typ *rtype) (*opcode, error) {
|
func (e *Encoder) compileBool(typ *rtype) (*opcode, error) {
|
||||||
return newOpCode(opBool, typ, newEndOp()), nil
|
return newOpCode(opBool, typ, e.indent, newEndOp(e.indent)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) compileInterface(typ *rtype) (*opcode, error) {
|
func (e *Encoder) compileInterface(typ *rtype) (*opcode, error) {
|
||||||
return newOpCode(opInterface, typ, newEndOp()), nil
|
return newOpCode(opInterface, typ, e.indent, newEndOp(e.indent)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) compileSlice(typ *rtype) (*opcode, error) {
|
func (e *Encoder) compileSlice(typ *rtype, withIndent bool) (*opcode, error) {
|
||||||
elem := typ.Elem()
|
elem := typ.Elem()
|
||||||
size := elem.Size()
|
size := elem.Size()
|
||||||
code, err := e.compile(elem)
|
|
||||||
|
e.indent++
|
||||||
|
code, err := e.compile(elem, withIndent)
|
||||||
|
e.indent--
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -205,9 +270,20 @@ func (e *Encoder) compileSlice(typ *rtype) (*opcode, error) {
|
||||||
// ^ |
|
// ^ |
|
||||||
// |________|
|
// |________|
|
||||||
|
|
||||||
header := newSliceHeaderCode()
|
header := newSliceHeaderCode(e.indent)
|
||||||
elemCode := &sliceElemCode{opcodeHeader: &opcodeHeader{op: opSliceElem}, size: size}
|
elemCode := &sliceElemCode{
|
||||||
end := newOpCode(opSliceEnd, nil, newEndOp())
|
opcodeHeader: &opcodeHeader{
|
||||||
|
op: opSliceElem,
|
||||||
|
indent: e.indent,
|
||||||
|
},
|
||||||
|
size: size,
|
||||||
|
}
|
||||||
|
end := newOpCode(opSliceEnd, nil, e.indent, newEndOp(e.indent))
|
||||||
|
if withIndent {
|
||||||
|
header.op = opSliceHeadIndent
|
||||||
|
elemCode.op = opSliceElemIndent
|
||||||
|
end.op = opSliceEndIndent
|
||||||
|
}
|
||||||
|
|
||||||
header.elem = elemCode
|
header.elem = elemCode
|
||||||
header.end = end
|
header.end = end
|
||||||
|
@ -218,11 +294,15 @@ func (e *Encoder) compileSlice(typ *rtype) (*opcode, error) {
|
||||||
return (*opcode)(unsafe.Pointer(header)), nil
|
return (*opcode)(unsafe.Pointer(header)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) compileArray(typ *rtype) (*opcode, error) {
|
func (e *Encoder) compileArray(typ *rtype, withIndent bool) (*opcode, error) {
|
||||||
elem := typ.Elem()
|
elem := typ.Elem()
|
||||||
alen := typ.Len()
|
alen := typ.Len()
|
||||||
size := elem.Size()
|
size := elem.Size()
|
||||||
code, err := e.compile(elem)
|
|
||||||
|
e.indent++
|
||||||
|
code, err := e.compile(elem, withIndent)
|
||||||
|
e.indent--
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -230,7 +310,7 @@ func (e *Encoder) compileArray(typ *rtype) (*opcode, error) {
|
||||||
// ^ |
|
// ^ |
|
||||||
// |________|
|
// |________|
|
||||||
|
|
||||||
header := newArrayHeaderCode(alen)
|
header := newArrayHeaderCode(e.indent, alen)
|
||||||
elemCode := &arrayElemCode{
|
elemCode := &arrayElemCode{
|
||||||
opcodeHeader: &opcodeHeader{
|
opcodeHeader: &opcodeHeader{
|
||||||
op: opArrayElem,
|
op: opArrayElem,
|
||||||
|
@ -238,7 +318,13 @@ func (e *Encoder) compileArray(typ *rtype) (*opcode, error) {
|
||||||
len: uintptr(alen),
|
len: uintptr(alen),
|
||||||
size: size,
|
size: size,
|
||||||
}
|
}
|
||||||
end := newOpCode(opArrayEnd, nil, newEndOp())
|
end := newOpCode(opArrayEnd, nil, e.indent, newEndOp(e.indent))
|
||||||
|
|
||||||
|
if withIndent {
|
||||||
|
header.op = opArrayHeadIndent
|
||||||
|
elemCode.op = opArrayElemIndent
|
||||||
|
end.op = opArrayEndIndent
|
||||||
|
}
|
||||||
|
|
||||||
header.elem = elemCode
|
header.elem = elemCode
|
||||||
header.end = end
|
header.end = end
|
||||||
|
@ -265,26 +351,38 @@ 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) (*opcode, error) {
|
func (e *Encoder) compileMap(typ *rtype, withIndent bool) (*opcode, error) {
|
||||||
// header => code => value => code => key => code => value => code => end
|
// header => code => value => code => key => code => value => code => end
|
||||||
// ^ |
|
// ^ |
|
||||||
// |_______________________|
|
// |_______________________|
|
||||||
|
e.indent++
|
||||||
keyType := typ.Key()
|
keyType := typ.Key()
|
||||||
keyCode, err := e.compile(keyType)
|
keyCode, err := e.compile(keyType, withIndent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
valueType := typ.Elem()
|
valueType := typ.Elem()
|
||||||
valueCode, err := e.compile(valueType)
|
valueCode, err := e.compile(valueType, withIndent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
header := newMapHeaderCode(typ)
|
|
||||||
key := newMapKeyCode()
|
key := newMapKeyCode(e.indent)
|
||||||
value := newMapValueCode()
|
value := newMapValueCode(e.indent)
|
||||||
|
|
||||||
|
e.indent--
|
||||||
|
|
||||||
|
header := newMapHeaderCode(typ, e.indent)
|
||||||
header.key = key
|
header.key = key
|
||||||
header.value = value
|
header.value = value
|
||||||
end := newOpCode(opMapEnd, nil, newEndOp())
|
end := newOpCode(opMapEnd, nil, e.indent, newEndOp(e.indent))
|
||||||
|
|
||||||
|
if withIndent {
|
||||||
|
header.op = opMapHeadIndent
|
||||||
|
key.op = opMapKeyIndent
|
||||||
|
value.op = opMapValueIndent
|
||||||
|
end.op = opMapEndIndent
|
||||||
|
}
|
||||||
|
|
||||||
header.next = keyCode
|
header.next = keyCode
|
||||||
keyCode.beforeLastCode().next = (*opcode)(unsafe.Pointer(value))
|
keyCode.beforeLastCode().next = (*opcode)(unsafe.Pointer(value))
|
||||||
|
@ -314,7 +412,297 @@ func (e *Encoder) isIgnoredStructField(field reflect.StructField) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Encoder) compileStruct(typ *rtype) (*opcode, error) {
|
func (e *Encoder) optimizeStructHeaderOmitEmptyIndent(op opType) opType {
|
||||||
|
switch op {
|
||||||
|
case opInt:
|
||||||
|
return opStructFieldHeadIntOmitEmptyIndent
|
||||||
|
case opInt8:
|
||||||
|
return opStructFieldHeadInt8OmitEmptyIndent
|
||||||
|
case opInt16:
|
||||||
|
return opStructFieldHeadInt16OmitEmptyIndent
|
||||||
|
case opInt32:
|
||||||
|
return opStructFieldHeadInt32OmitEmptyIndent
|
||||||
|
case opInt64:
|
||||||
|
return opStructFieldHeadInt64OmitEmptyIndent
|
||||||
|
case opUint:
|
||||||
|
return opStructFieldHeadUintOmitEmptyIndent
|
||||||
|
case opUint8:
|
||||||
|
return opStructFieldHeadUint8OmitEmptyIndent
|
||||||
|
case opUint16:
|
||||||
|
return opStructFieldHeadUint16OmitEmptyIndent
|
||||||
|
case opUint32:
|
||||||
|
return opStructFieldHeadUint32OmitEmptyIndent
|
||||||
|
case opUint64:
|
||||||
|
return opStructFieldHeadUint64OmitEmptyIndent
|
||||||
|
case opFloat32:
|
||||||
|
return opStructFieldHeadFloat32OmitEmptyIndent
|
||||||
|
case opFloat64:
|
||||||
|
return opStructFieldHeadFloat64OmitEmptyIndent
|
||||||
|
case opString:
|
||||||
|
return opStructFieldHeadStringOmitEmptyIndent
|
||||||
|
case opBool:
|
||||||
|
return opStructFieldHeadBoolOmitEmptyIndent
|
||||||
|
}
|
||||||
|
return opStructFieldHeadOmitEmptyIndent
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) optimizeStructHeaderIndent(op opType, isOmitEmpty bool) opType {
|
||||||
|
if isOmitEmpty {
|
||||||
|
return e.optimizeStructHeaderOmitEmptyIndent(op)
|
||||||
|
}
|
||||||
|
switch op {
|
||||||
|
case opInt:
|
||||||
|
return opStructFieldHeadIntIndent
|
||||||
|
case opInt8:
|
||||||
|
return opStructFieldHeadInt8Indent
|
||||||
|
case opInt16:
|
||||||
|
return opStructFieldHeadInt16Indent
|
||||||
|
case opInt32:
|
||||||
|
return opStructFieldHeadInt32Indent
|
||||||
|
case opInt64:
|
||||||
|
return opStructFieldHeadInt64Indent
|
||||||
|
case opUint:
|
||||||
|
return opStructFieldHeadUintIndent
|
||||||
|
case opUint8:
|
||||||
|
return opStructFieldHeadUint8Indent
|
||||||
|
case opUint16:
|
||||||
|
return opStructFieldHeadUint16Indent
|
||||||
|
case opUint32:
|
||||||
|
return opStructFieldHeadUint32Indent
|
||||||
|
case opUint64:
|
||||||
|
return opStructFieldHeadUint64Indent
|
||||||
|
case opFloat32:
|
||||||
|
return opStructFieldHeadFloat32Indent
|
||||||
|
case opFloat64:
|
||||||
|
return opStructFieldHeadFloat64Indent
|
||||||
|
case opString:
|
||||||
|
return opStructFieldHeadStringIndent
|
||||||
|
case opBool:
|
||||||
|
return opStructFieldHeadBoolIndent
|
||||||
|
}
|
||||||
|
return opStructFieldHeadIndent
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) optimizeStructHeaderOmitEmpty(op opType) opType {
|
||||||
|
switch op {
|
||||||
|
case opInt:
|
||||||
|
return opStructFieldHeadIntOmitEmpty
|
||||||
|
case opInt8:
|
||||||
|
return opStructFieldHeadInt8OmitEmpty
|
||||||
|
case opInt16:
|
||||||
|
return opStructFieldHeadInt16OmitEmpty
|
||||||
|
case opInt32:
|
||||||
|
return opStructFieldHeadInt32OmitEmpty
|
||||||
|
case opInt64:
|
||||||
|
return opStructFieldHeadInt64OmitEmpty
|
||||||
|
case opUint:
|
||||||
|
return opStructFieldHeadUintOmitEmpty
|
||||||
|
case opUint8:
|
||||||
|
return opStructFieldHeadUint8OmitEmpty
|
||||||
|
case opUint16:
|
||||||
|
return opStructFieldHeadUint16OmitEmpty
|
||||||
|
case opUint32:
|
||||||
|
return opStructFieldHeadUint32OmitEmpty
|
||||||
|
case opUint64:
|
||||||
|
return opStructFieldHeadUint64OmitEmpty
|
||||||
|
case opFloat32:
|
||||||
|
return opStructFieldHeadFloat32OmitEmpty
|
||||||
|
case opFloat64:
|
||||||
|
return opStructFieldHeadFloat64OmitEmpty
|
||||||
|
case opString:
|
||||||
|
return opStructFieldHeadStringOmitEmpty
|
||||||
|
case opBool:
|
||||||
|
return opStructFieldHeadBoolOmitEmpty
|
||||||
|
}
|
||||||
|
return opStructFieldHeadOmitEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) optimizeStructHeader(op opType, isOmitEmpty, withIndent bool) opType {
|
||||||
|
if withIndent {
|
||||||
|
return e.optimizeStructHeaderIndent(op, isOmitEmpty)
|
||||||
|
}
|
||||||
|
if isOmitEmpty {
|
||||||
|
return e.optimizeStructHeaderOmitEmpty(op)
|
||||||
|
}
|
||||||
|
switch op {
|
||||||
|
case opInt:
|
||||||
|
return opStructFieldHeadInt
|
||||||
|
case opInt8:
|
||||||
|
return opStructFieldHeadInt8
|
||||||
|
case opInt16:
|
||||||
|
return opStructFieldHeadInt16
|
||||||
|
case opInt32:
|
||||||
|
return opStructFieldHeadInt32
|
||||||
|
case opInt64:
|
||||||
|
return opStructFieldHeadInt64
|
||||||
|
case opUint:
|
||||||
|
return opStructFieldHeadUint
|
||||||
|
case opUint8:
|
||||||
|
return opStructFieldHeadUint8
|
||||||
|
case opUint16:
|
||||||
|
return opStructFieldHeadUint16
|
||||||
|
case opUint32:
|
||||||
|
return opStructFieldHeadUint32
|
||||||
|
case opUint64:
|
||||||
|
return opStructFieldHeadUint64
|
||||||
|
case opFloat32:
|
||||||
|
return opStructFieldHeadFloat32
|
||||||
|
case opFloat64:
|
||||||
|
return opStructFieldHeadFloat64
|
||||||
|
case opString:
|
||||||
|
return opStructFieldHeadString
|
||||||
|
case opBool:
|
||||||
|
return opStructFieldHeadBool
|
||||||
|
}
|
||||||
|
return opStructFieldHead
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) optimizeStructFieldOmitEmptyIndent(op opType) opType {
|
||||||
|
switch op {
|
||||||
|
case opInt:
|
||||||
|
return opStructFieldIntOmitEmptyIndent
|
||||||
|
case opInt8:
|
||||||
|
return opStructFieldInt8OmitEmptyIndent
|
||||||
|
case opInt16:
|
||||||
|
return opStructFieldInt16OmitEmptyIndent
|
||||||
|
case opInt32:
|
||||||
|
return opStructFieldInt32OmitEmptyIndent
|
||||||
|
case opInt64:
|
||||||
|
return opStructFieldInt64OmitEmptyIndent
|
||||||
|
case opUint:
|
||||||
|
return opStructFieldUintOmitEmptyIndent
|
||||||
|
case opUint8:
|
||||||
|
return opStructFieldUint8OmitEmptyIndent
|
||||||
|
case opUint16:
|
||||||
|
return opStructFieldUint16OmitEmptyIndent
|
||||||
|
case opUint32:
|
||||||
|
return opStructFieldUint32OmitEmptyIndent
|
||||||
|
case opUint64:
|
||||||
|
return opStructFieldUint64OmitEmptyIndent
|
||||||
|
case opFloat32:
|
||||||
|
return opStructFieldFloat32OmitEmptyIndent
|
||||||
|
case opFloat64:
|
||||||
|
return opStructFieldFloat64OmitEmptyIndent
|
||||||
|
case opString:
|
||||||
|
return opStructFieldStringOmitEmptyIndent
|
||||||
|
case opBool:
|
||||||
|
return opStructFieldBoolOmitEmptyIndent
|
||||||
|
}
|
||||||
|
return opStructFieldOmitEmptyIndent
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) optimizeStructFieldIndent(op opType, isOmitEmpty bool) opType {
|
||||||
|
if isOmitEmpty {
|
||||||
|
return e.optimizeStructFieldOmitEmptyIndent(op)
|
||||||
|
}
|
||||||
|
switch op {
|
||||||
|
case opInt:
|
||||||
|
return opStructFieldIntIndent
|
||||||
|
case opInt8:
|
||||||
|
return opStructFieldInt8Indent
|
||||||
|
case opInt16:
|
||||||
|
return opStructFieldInt16Indent
|
||||||
|
case opInt32:
|
||||||
|
return opStructFieldInt32Indent
|
||||||
|
case opInt64:
|
||||||
|
return opStructFieldInt64Indent
|
||||||
|
case opUint:
|
||||||
|
return opStructFieldUintIndent
|
||||||
|
case opUint8:
|
||||||
|
return opStructFieldUint8Indent
|
||||||
|
case opUint16:
|
||||||
|
return opStructFieldUint16Indent
|
||||||
|
case opUint32:
|
||||||
|
return opStructFieldUint32Indent
|
||||||
|
case opUint64:
|
||||||
|
return opStructFieldUint64Indent
|
||||||
|
case opFloat32:
|
||||||
|
return opStructFieldFloat32Indent
|
||||||
|
case opFloat64:
|
||||||
|
return opStructFieldFloat64Indent
|
||||||
|
case opString:
|
||||||
|
return opStructFieldStringIndent
|
||||||
|
case opBool:
|
||||||
|
return opStructFieldBoolIndent
|
||||||
|
}
|
||||||
|
return opStructFieldIndent
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) optimizeStructFieldOmitEmpty(op opType) opType {
|
||||||
|
switch op {
|
||||||
|
case opInt:
|
||||||
|
return opStructFieldIntOmitEmpty
|
||||||
|
case opInt8:
|
||||||
|
return opStructFieldInt8OmitEmpty
|
||||||
|
case opInt16:
|
||||||
|
return opStructFieldInt16OmitEmpty
|
||||||
|
case opInt32:
|
||||||
|
return opStructFieldInt32OmitEmpty
|
||||||
|
case opInt64:
|
||||||
|
return opStructFieldInt64OmitEmpty
|
||||||
|
case opUint:
|
||||||
|
return opStructFieldUintOmitEmpty
|
||||||
|
case opUint8:
|
||||||
|
return opStructFieldUint8OmitEmpty
|
||||||
|
case opUint16:
|
||||||
|
return opStructFieldUint16OmitEmpty
|
||||||
|
case opUint32:
|
||||||
|
return opStructFieldUint32OmitEmpty
|
||||||
|
case opUint64:
|
||||||
|
return opStructFieldUint64OmitEmpty
|
||||||
|
case opFloat32:
|
||||||
|
return opStructFieldFloat32OmitEmpty
|
||||||
|
case opFloat64:
|
||||||
|
return opStructFieldFloat64OmitEmpty
|
||||||
|
case opString:
|
||||||
|
return opStructFieldStringOmitEmpty
|
||||||
|
case opBool:
|
||||||
|
return opStructFieldBoolOmitEmpty
|
||||||
|
}
|
||||||
|
return opStructFieldOmitEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) optimizeStructField(op opType, isOmitEmpty, withIndent bool) opType {
|
||||||
|
if withIndent {
|
||||||
|
return e.optimizeStructFieldIndent(op, isOmitEmpty)
|
||||||
|
}
|
||||||
|
if isOmitEmpty {
|
||||||
|
return e.optimizeStructFieldOmitEmpty(op)
|
||||||
|
}
|
||||||
|
switch op {
|
||||||
|
case opInt:
|
||||||
|
return opStructFieldInt
|
||||||
|
case opInt8:
|
||||||
|
return opStructFieldInt8
|
||||||
|
case opInt16:
|
||||||
|
return opStructFieldInt16
|
||||||
|
case opInt32:
|
||||||
|
return opStructFieldInt32
|
||||||
|
case opInt64:
|
||||||
|
return opStructFieldInt64
|
||||||
|
case opUint:
|
||||||
|
return opStructFieldUint
|
||||||
|
case opUint8:
|
||||||
|
return opStructFieldUint8
|
||||||
|
case opUint16:
|
||||||
|
return opStructFieldUint16
|
||||||
|
case opUint32:
|
||||||
|
return opStructFieldUint32
|
||||||
|
case opUint64:
|
||||||
|
return opStructFieldUint64
|
||||||
|
case opFloat32:
|
||||||
|
return opStructFieldFloat32
|
||||||
|
case opFloat64:
|
||||||
|
return opStructFieldFloat64
|
||||||
|
case opString:
|
||||||
|
return opStructFieldString
|
||||||
|
case opBool:
|
||||||
|
return opStructFieldBool
|
||||||
|
}
|
||||||
|
return opStructField
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Encoder) compileStruct(typ *rtype, withIndent bool) (*opcode, error) {
|
||||||
// header => code => structField => code => end
|
// header => code => structField => code => end
|
||||||
// ^ |
|
// ^ |
|
||||||
// |__________|
|
// |__________|
|
||||||
|
@ -325,6 +713,7 @@ func (e *Encoder) compileStruct(typ *rtype) (*opcode, error) {
|
||||||
code *opcode
|
code *opcode
|
||||||
prevField *structFieldCode
|
prevField *structFieldCode
|
||||||
)
|
)
|
||||||
|
e.indent++
|
||||||
for i := 0; i < fieldNum; i++ {
|
for i := 0; i < fieldNum; i++ {
|
||||||
field := typ.Field(i)
|
field := typ.Field(i)
|
||||||
if e.isIgnoredStructField(field) {
|
if e.isIgnoredStructField(field) {
|
||||||
|
@ -343,7 +732,7 @@ func (e *Encoder) compileStruct(typ *rtype) (*opcode, error) {
|
||||||
isOmitEmpty = opts[1] == "omitempty"
|
isOmitEmpty = opts[1] == "omitempty"
|
||||||
}
|
}
|
||||||
fieldType := type2rtype(field.Type)
|
fieldType := type2rtype(field.Type)
|
||||||
valueCode, err := e.compile(fieldType)
|
valueCode, err := e.compile(fieldType, withIndent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -352,162 +741,49 @@ func (e *Encoder) compileStruct(typ *rtype) (*opcode, error) {
|
||||||
opcodeHeader: &opcodeHeader{
|
opcodeHeader: &opcodeHeader{
|
||||||
typ: fieldType,
|
typ: fieldType,
|
||||||
next: valueCode,
|
next: valueCode,
|
||||||
|
indent: e.indent,
|
||||||
},
|
},
|
||||||
key: []byte(key),
|
key: []byte(key),
|
||||||
offset: field.Offset,
|
offset: field.Offset,
|
||||||
}
|
}
|
||||||
if fieldIdx == 0 {
|
if fieldIdx == 0 {
|
||||||
|
fieldCode.indent--
|
||||||
head = fieldCode
|
head = fieldCode
|
||||||
code = (*opcode)(unsafe.Pointer(fieldCode))
|
code = (*opcode)(unsafe.Pointer(fieldCode))
|
||||||
prevField = fieldCode
|
prevField = fieldCode
|
||||||
if isOmitEmpty {
|
op := e.optimizeStructHeader(valueCode.op, isOmitEmpty, withIndent)
|
||||||
fieldCode.op = opStructFieldHeadOmitEmpty
|
fieldCode.op = op
|
||||||
switch valueCode.op {
|
switch op {
|
||||||
case opInt:
|
case opStructFieldHead,
|
||||||
fieldCode.op = opStructFieldHeadIntOmitEmpty
|
opStructFieldHeadOmitEmpty,
|
||||||
case opInt8:
|
opStructFieldHeadIndent,
|
||||||
fieldCode.op = opStructFieldHeadInt8OmitEmpty
|
opStructFieldHeadOmitEmptyIndent:
|
||||||
case opInt16:
|
|
||||||
fieldCode.op = opStructFieldHeadInt16OmitEmpty
|
|
||||||
case opInt32:
|
|
||||||
fieldCode.op = opStructFieldHeadInt32OmitEmpty
|
|
||||||
case opInt64:
|
|
||||||
fieldCode.op = opStructFieldHeadInt64OmitEmpty
|
|
||||||
case opUint:
|
|
||||||
fieldCode.op = opStructFieldHeadUintOmitEmpty
|
|
||||||
case opUint8:
|
|
||||||
fieldCode.op = opStructFieldHeadUint8OmitEmpty
|
|
||||||
case opUint16:
|
|
||||||
fieldCode.op = opStructFieldHeadUint16OmitEmpty
|
|
||||||
case opUint32:
|
|
||||||
fieldCode.op = opStructFieldHeadUint32OmitEmpty
|
|
||||||
case opUint64:
|
|
||||||
fieldCode.op = opStructFieldHeadUint64OmitEmpty
|
|
||||||
case opFloat32:
|
|
||||||
fieldCode.op = opStructFieldHeadFloat32OmitEmpty
|
|
||||||
case opFloat64:
|
|
||||||
fieldCode.op = opStructFieldHeadFloat64OmitEmpty
|
|
||||||
case opString:
|
|
||||||
fieldCode.op = opStructFieldHeadStringOmitEmpty
|
|
||||||
case opBool:
|
|
||||||
fieldCode.op = opStructFieldHeadBoolOmitEmpty
|
|
||||||
default:
|
|
||||||
code = valueCode.beforeLastCode()
|
code = valueCode.beforeLastCode()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fieldCode.op = opStructFieldHead
|
|
||||||
switch valueCode.op {
|
|
||||||
case opInt:
|
|
||||||
fieldCode.op = opStructFieldHeadInt
|
|
||||||
case opInt8:
|
|
||||||
fieldCode.op = opStructFieldHeadInt8
|
|
||||||
case opInt16:
|
|
||||||
fieldCode.op = opStructFieldHeadInt16
|
|
||||||
case opInt32:
|
|
||||||
fieldCode.op = opStructFieldHeadInt32
|
|
||||||
case opInt64:
|
|
||||||
fieldCode.op = opStructFieldHeadInt64
|
|
||||||
case opUint:
|
|
||||||
fieldCode.op = opStructFieldHeadUint
|
|
||||||
case opUint8:
|
|
||||||
fieldCode.op = opStructFieldHeadUint8
|
|
||||||
case opUint16:
|
|
||||||
fieldCode.op = opStructFieldHeadUint16
|
|
||||||
case opUint32:
|
|
||||||
fieldCode.op = opStructFieldHeadUint32
|
|
||||||
case opUint64:
|
|
||||||
fieldCode.op = opStructFieldHeadUint64
|
|
||||||
case opFloat32:
|
|
||||||
fieldCode.op = opStructFieldHeadFloat32
|
|
||||||
case opFloat64:
|
|
||||||
fieldCode.op = opStructFieldHeadFloat64
|
|
||||||
case opString:
|
|
||||||
fieldCode.op = opStructFieldHeadString
|
|
||||||
case opBool:
|
|
||||||
fieldCode.op = opStructFieldHeadBool
|
|
||||||
default:
|
|
||||||
code = valueCode.beforeLastCode()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fieldCode.op = opStructField
|
|
||||||
code.next = (*opcode)(unsafe.Pointer(fieldCode))
|
code.next = (*opcode)(unsafe.Pointer(fieldCode))
|
||||||
prevField.nextField = (*opcode)(unsafe.Pointer(fieldCode))
|
prevField.nextField = (*opcode)(unsafe.Pointer(fieldCode))
|
||||||
prevField = fieldCode
|
prevField = fieldCode
|
||||||
code = (*opcode)(unsafe.Pointer(fieldCode))
|
code = (*opcode)(unsafe.Pointer(fieldCode))
|
||||||
if isOmitEmpty {
|
op := e.optimizeStructField(valueCode.op, isOmitEmpty, withIndent)
|
||||||
fieldCode.op = opStructFieldOmitEmpty
|
fieldCode.op = op
|
||||||
switch valueCode.op {
|
switch op {
|
||||||
case opInt:
|
case opStructField,
|
||||||
fieldCode.op = opStructFieldIntOmitEmpty
|
opStructFieldOmitEmpty,
|
||||||
case opInt8:
|
opStructFieldIndent,
|
||||||
fieldCode.op = opStructFieldInt8OmitEmpty
|
opStructFieldOmitEmptyIndent:
|
||||||
case opInt16:
|
|
||||||
fieldCode.op = opStructFieldInt16OmitEmpty
|
|
||||||
case opInt32:
|
|
||||||
fieldCode.op = opStructFieldInt32OmitEmpty
|
|
||||||
case opInt64:
|
|
||||||
fieldCode.op = opStructFieldInt64OmitEmpty
|
|
||||||
case opUint:
|
|
||||||
fieldCode.op = opStructFieldUintOmitEmpty
|
|
||||||
case opUint8:
|
|
||||||
fieldCode.op = opStructFieldUint8OmitEmpty
|
|
||||||
case opUint16:
|
|
||||||
fieldCode.op = opStructFieldUint16OmitEmpty
|
|
||||||
case opUint32:
|
|
||||||
fieldCode.op = opStructFieldUint32OmitEmpty
|
|
||||||
case opUint64:
|
|
||||||
fieldCode.op = opStructFieldUint64OmitEmpty
|
|
||||||
case opFloat32:
|
|
||||||
fieldCode.op = opStructFieldFloat32OmitEmpty
|
|
||||||
case opFloat64:
|
|
||||||
fieldCode.op = opStructFieldFloat64OmitEmpty
|
|
||||||
case opString:
|
|
||||||
fieldCode.op = opStructFieldStringOmitEmpty
|
|
||||||
case opBool:
|
|
||||||
fieldCode.op = opStructFieldBoolOmitEmpty
|
|
||||||
default:
|
|
||||||
code = valueCode.beforeLastCode()
|
code = valueCode.beforeLastCode()
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
switch valueCode.op {
|
|
||||||
case opInt:
|
|
||||||
fieldCode.op = opStructFieldInt
|
|
||||||
case opInt8:
|
|
||||||
fieldCode.op = opStructFieldInt8
|
|
||||||
case opInt16:
|
|
||||||
fieldCode.op = opStructFieldInt16
|
|
||||||
case opInt32:
|
|
||||||
fieldCode.op = opStructFieldInt32
|
|
||||||
case opInt64:
|
|
||||||
fieldCode.op = opStructFieldInt64
|
|
||||||
case opUint:
|
|
||||||
fieldCode.op = opStructFieldUint
|
|
||||||
case opUint8:
|
|
||||||
fieldCode.op = opStructFieldUint8
|
|
||||||
case opUint16:
|
|
||||||
fieldCode.op = opStructFieldUint16
|
|
||||||
case opUint32:
|
|
||||||
fieldCode.op = opStructFieldUint32
|
|
||||||
case opUint64:
|
|
||||||
fieldCode.op = opStructFieldUint64
|
|
||||||
case opFloat32:
|
|
||||||
fieldCode.op = opStructFieldFloat32
|
|
||||||
case opFloat64:
|
|
||||||
fieldCode.op = opStructFieldFloat64
|
|
||||||
case opString:
|
|
||||||
fieldCode.op = opStructFieldString
|
|
||||||
case opBool:
|
|
||||||
fieldCode.op = opStructFieldBool
|
|
||||||
default:
|
|
||||||
code = valueCode.beforeLastCode()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
fieldIdx++
|
fieldIdx++
|
||||||
}
|
}
|
||||||
|
e.indent--
|
||||||
|
|
||||||
structEndCode := newOpCode(opStructEnd, nil, nil)
|
structEndCode := newOpCode(opStructEnd, nil, e.indent, nil)
|
||||||
|
|
||||||
|
if withIndent {
|
||||||
|
structEndCode.op = opStructEndIndent
|
||||||
|
}
|
||||||
|
|
||||||
if prevField != nil && prevField.nextField == nil {
|
if prevField != nil && prevField.nextField == nil {
|
||||||
prevField.nextField = structEndCode
|
prevField.nextField = structEndCode
|
||||||
|
@ -519,13 +795,17 @@ func (e *Encoder) compileStruct(typ *rtype) (*opcode, error) {
|
||||||
opcodeHeader: &opcodeHeader{
|
opcodeHeader: &opcodeHeader{
|
||||||
op: opStructFieldHead,
|
op: opStructFieldHead,
|
||||||
typ: typ,
|
typ: typ,
|
||||||
|
indent: e.indent,
|
||||||
},
|
},
|
||||||
nextField: structEndCode,
|
nextField: structEndCode,
|
||||||
}
|
}
|
||||||
|
if withIndent {
|
||||||
|
head.op = opStructFieldHeadIndent
|
||||||
|
}
|
||||||
code = (*opcode)(unsafe.Pointer(head))
|
code = (*opcode)(unsafe.Pointer(head))
|
||||||
}
|
}
|
||||||
head.end = structEndCode
|
head.end = structEndCode
|
||||||
code.next = structEndCode
|
code.next = structEndCode
|
||||||
structEndCode.next = newEndOp()
|
structEndCode.next = newEndOp(e.indent)
|
||||||
return (*opcode)(unsafe.Pointer(head)), nil
|
return (*opcode)(unsafe.Pointer(head)), nil
|
||||||
}
|
}
|
||||||
|
|
366
encode_opcode.go
366
encode_opcode.go
|
@ -27,17 +27,33 @@ const (
|
||||||
opBool
|
opBool
|
||||||
opInterface
|
opInterface
|
||||||
opPtr
|
opPtr
|
||||||
|
|
||||||
opSliceHead
|
opSliceHead
|
||||||
opSliceElem
|
opSliceElem
|
||||||
opSliceEnd
|
opSliceEnd
|
||||||
|
|
||||||
|
opSliceHeadIndent
|
||||||
|
opSliceElemIndent
|
||||||
|
opSliceEndIndent
|
||||||
|
|
||||||
opArrayHead
|
opArrayHead
|
||||||
opArrayElem
|
opArrayElem
|
||||||
opArrayEnd
|
opArrayEnd
|
||||||
|
|
||||||
|
opArrayHeadIndent
|
||||||
|
opArrayElemIndent
|
||||||
|
opArrayEndIndent
|
||||||
|
|
||||||
opMapHead
|
opMapHead
|
||||||
opMapKey
|
opMapKey
|
||||||
opMapValue
|
opMapValue
|
||||||
opMapEnd
|
opMapEnd
|
||||||
|
|
||||||
|
opMapHeadIndent
|
||||||
|
opMapKeyIndent
|
||||||
|
opMapValueIndent
|
||||||
|
opMapEndIndent
|
||||||
|
|
||||||
// StructFieldHead
|
// StructFieldHead
|
||||||
opStructFieldHead
|
opStructFieldHead
|
||||||
opStructFieldHeadInt
|
opStructFieldHeadInt
|
||||||
|
@ -55,6 +71,22 @@ const (
|
||||||
opStructFieldHeadString
|
opStructFieldHeadString
|
||||||
opStructFieldHeadBool
|
opStructFieldHeadBool
|
||||||
|
|
||||||
|
opStructFieldHeadIndent
|
||||||
|
opStructFieldHeadIntIndent
|
||||||
|
opStructFieldHeadInt8Indent
|
||||||
|
opStructFieldHeadInt16Indent
|
||||||
|
opStructFieldHeadInt32Indent
|
||||||
|
opStructFieldHeadInt64Indent
|
||||||
|
opStructFieldHeadUintIndent
|
||||||
|
opStructFieldHeadUint8Indent
|
||||||
|
opStructFieldHeadUint16Indent
|
||||||
|
opStructFieldHeadUint32Indent
|
||||||
|
opStructFieldHeadUint64Indent
|
||||||
|
opStructFieldHeadFloat32Indent
|
||||||
|
opStructFieldHeadFloat64Indent
|
||||||
|
opStructFieldHeadStringIndent
|
||||||
|
opStructFieldHeadBoolIndent
|
||||||
|
|
||||||
// StructFieldHead with omitempty
|
// StructFieldHead with omitempty
|
||||||
opStructFieldHeadOmitEmpty
|
opStructFieldHeadOmitEmpty
|
||||||
opStructFieldHeadIntOmitEmpty
|
opStructFieldHeadIntOmitEmpty
|
||||||
|
@ -72,6 +104,22 @@ const (
|
||||||
opStructFieldHeadStringOmitEmpty
|
opStructFieldHeadStringOmitEmpty
|
||||||
opStructFieldHeadBoolOmitEmpty
|
opStructFieldHeadBoolOmitEmpty
|
||||||
|
|
||||||
|
opStructFieldHeadOmitEmptyIndent
|
||||||
|
opStructFieldHeadIntOmitEmptyIndent
|
||||||
|
opStructFieldHeadInt8OmitEmptyIndent
|
||||||
|
opStructFieldHeadInt16OmitEmptyIndent
|
||||||
|
opStructFieldHeadInt32OmitEmptyIndent
|
||||||
|
opStructFieldHeadInt64OmitEmptyIndent
|
||||||
|
opStructFieldHeadUintOmitEmptyIndent
|
||||||
|
opStructFieldHeadUint8OmitEmptyIndent
|
||||||
|
opStructFieldHeadUint16OmitEmptyIndent
|
||||||
|
opStructFieldHeadUint32OmitEmptyIndent
|
||||||
|
opStructFieldHeadUint64OmitEmptyIndent
|
||||||
|
opStructFieldHeadFloat32OmitEmptyIndent
|
||||||
|
opStructFieldHeadFloat64OmitEmptyIndent
|
||||||
|
opStructFieldHeadStringOmitEmptyIndent
|
||||||
|
opStructFieldHeadBoolOmitEmptyIndent
|
||||||
|
|
||||||
// StructFieldHead for pointer structure
|
// StructFieldHead for pointer structure
|
||||||
opStructFieldPtrHead
|
opStructFieldPtrHead
|
||||||
opStructFieldPtrHeadInt
|
opStructFieldPtrHeadInt
|
||||||
|
@ -89,6 +137,22 @@ const (
|
||||||
opStructFieldPtrHeadString
|
opStructFieldPtrHeadString
|
||||||
opStructFieldPtrHeadBool
|
opStructFieldPtrHeadBool
|
||||||
|
|
||||||
|
opStructFieldPtrHeadIndent
|
||||||
|
opStructFieldPtrHeadIntIndent
|
||||||
|
opStructFieldPtrHeadInt8Indent
|
||||||
|
opStructFieldPtrHeadInt16Indent
|
||||||
|
opStructFieldPtrHeadInt32Indent
|
||||||
|
opStructFieldPtrHeadInt64Indent
|
||||||
|
opStructFieldPtrHeadUintIndent
|
||||||
|
opStructFieldPtrHeadUint8Indent
|
||||||
|
opStructFieldPtrHeadUint16Indent
|
||||||
|
opStructFieldPtrHeadUint32Indent
|
||||||
|
opStructFieldPtrHeadUint64Indent
|
||||||
|
opStructFieldPtrHeadFloat32Indent
|
||||||
|
opStructFieldPtrHeadFloat64Indent
|
||||||
|
opStructFieldPtrHeadStringIndent
|
||||||
|
opStructFieldPtrHeadBoolIndent
|
||||||
|
|
||||||
// StructFieldPtrHead with omitempty
|
// StructFieldPtrHead with omitempty
|
||||||
opStructFieldPtrHeadOmitEmpty
|
opStructFieldPtrHeadOmitEmpty
|
||||||
opStructFieldPtrHeadIntOmitEmpty
|
opStructFieldPtrHeadIntOmitEmpty
|
||||||
|
@ -106,6 +170,22 @@ const (
|
||||||
opStructFieldPtrHeadStringOmitEmpty
|
opStructFieldPtrHeadStringOmitEmpty
|
||||||
opStructFieldPtrHeadBoolOmitEmpty
|
opStructFieldPtrHeadBoolOmitEmpty
|
||||||
|
|
||||||
|
opStructFieldPtrHeadOmitEmptyIndent
|
||||||
|
opStructFieldPtrHeadIntOmitEmptyIndent
|
||||||
|
opStructFieldPtrHeadInt8OmitEmptyIndent
|
||||||
|
opStructFieldPtrHeadInt16OmitEmptyIndent
|
||||||
|
opStructFieldPtrHeadInt32OmitEmptyIndent
|
||||||
|
opStructFieldPtrHeadInt64OmitEmptyIndent
|
||||||
|
opStructFieldPtrHeadUintOmitEmptyIndent
|
||||||
|
opStructFieldPtrHeadUint8OmitEmptyIndent
|
||||||
|
opStructFieldPtrHeadUint16OmitEmptyIndent
|
||||||
|
opStructFieldPtrHeadUint32OmitEmptyIndent
|
||||||
|
opStructFieldPtrHeadUint64OmitEmptyIndent
|
||||||
|
opStructFieldPtrHeadFloat32OmitEmptyIndent
|
||||||
|
opStructFieldPtrHeadFloat64OmitEmptyIndent
|
||||||
|
opStructFieldPtrHeadStringOmitEmptyIndent
|
||||||
|
opStructFieldPtrHeadBoolOmitEmptyIndent
|
||||||
|
|
||||||
// StructField
|
// StructField
|
||||||
opStructField
|
opStructField
|
||||||
opStructFieldInt
|
opStructFieldInt
|
||||||
|
@ -123,6 +203,22 @@ const (
|
||||||
opStructFieldString
|
opStructFieldString
|
||||||
opStructFieldBool
|
opStructFieldBool
|
||||||
|
|
||||||
|
opStructFieldIndent
|
||||||
|
opStructFieldIntIndent
|
||||||
|
opStructFieldInt8Indent
|
||||||
|
opStructFieldInt16Indent
|
||||||
|
opStructFieldInt32Indent
|
||||||
|
opStructFieldInt64Indent
|
||||||
|
opStructFieldUintIndent
|
||||||
|
opStructFieldUint8Indent
|
||||||
|
opStructFieldUint16Indent
|
||||||
|
opStructFieldUint32Indent
|
||||||
|
opStructFieldUint64Indent
|
||||||
|
opStructFieldFloat32Indent
|
||||||
|
opStructFieldFloat64Indent
|
||||||
|
opStructFieldStringIndent
|
||||||
|
opStructFieldBoolIndent
|
||||||
|
|
||||||
// StructField with omitempty
|
// StructField with omitempty
|
||||||
opStructFieldOmitEmpty
|
opStructFieldOmitEmpty
|
||||||
opStructFieldIntOmitEmpty
|
opStructFieldIntOmitEmpty
|
||||||
|
@ -140,7 +236,24 @@ const (
|
||||||
opStructFieldStringOmitEmpty
|
opStructFieldStringOmitEmpty
|
||||||
opStructFieldBoolOmitEmpty
|
opStructFieldBoolOmitEmpty
|
||||||
|
|
||||||
|
opStructFieldOmitEmptyIndent
|
||||||
|
opStructFieldIntOmitEmptyIndent
|
||||||
|
opStructFieldInt8OmitEmptyIndent
|
||||||
|
opStructFieldInt16OmitEmptyIndent
|
||||||
|
opStructFieldInt32OmitEmptyIndent
|
||||||
|
opStructFieldInt64OmitEmptyIndent
|
||||||
|
opStructFieldUintOmitEmptyIndent
|
||||||
|
opStructFieldUint8OmitEmptyIndent
|
||||||
|
opStructFieldUint16OmitEmptyIndent
|
||||||
|
opStructFieldUint32OmitEmptyIndent
|
||||||
|
opStructFieldUint64OmitEmptyIndent
|
||||||
|
opStructFieldFloat32OmitEmptyIndent
|
||||||
|
opStructFieldFloat64OmitEmptyIndent
|
||||||
|
opStructFieldStringOmitEmptyIndent
|
||||||
|
opStructFieldBoolOmitEmptyIndent
|
||||||
|
|
||||||
opStructEnd
|
opStructEnd
|
||||||
|
opStructEndIndent
|
||||||
)
|
)
|
||||||
|
|
||||||
func (t opType) String() string {
|
func (t opType) String() string {
|
||||||
|
@ -179,19 +292,36 @@ func (t opType) String() string {
|
||||||
return "INTERFACE"
|
return "INTERFACE"
|
||||||
case opPtr:
|
case opPtr:
|
||||||
return "PTR"
|
return "PTR"
|
||||||
|
|
||||||
case opSliceHead:
|
case opSliceHead:
|
||||||
return "SLICE_HEAD"
|
return "SLICE_HEAD"
|
||||||
case opSliceElem:
|
case opSliceElem:
|
||||||
return "SLICE_ELEM"
|
return "SLICE_ELEM"
|
||||||
case opSliceEnd:
|
case opSliceEnd:
|
||||||
return "SLICE_END"
|
return "SLICE_END"
|
||||||
|
|
||||||
|
case opSliceHeadIndent:
|
||||||
|
return "SLICE_HEAD_INDENT"
|
||||||
|
case opSliceElemIndent:
|
||||||
|
return "SLICE_ELEM_INDENT"
|
||||||
|
case opSliceEndIndent:
|
||||||
|
return "SLICE_END_INDENT"
|
||||||
|
|
||||||
case opArrayHead:
|
case opArrayHead:
|
||||||
return "ARRAY_HEAD"
|
return "ARRAY_HEAD"
|
||||||
case opArrayElem:
|
case opArrayElem:
|
||||||
return "ARRAY_ELEM"
|
return "ARRAY_ELEM"
|
||||||
case opArrayEnd:
|
case opArrayEnd:
|
||||||
return "ARRAY_END"
|
return "ARRAY_END"
|
||||||
|
|
||||||
|
case opArrayHeadIndent:
|
||||||
|
return "ARRAY_HEAD_INDENT"
|
||||||
|
case opArrayElemIndent:
|
||||||
|
return "ARRAY_ELEM_INDENT"
|
||||||
|
case opArrayEndIndent:
|
||||||
|
return "ARRAY_END_INDENT"
|
||||||
case opMapHead:
|
case opMapHead:
|
||||||
|
|
||||||
return "MAP_HEAD"
|
return "MAP_HEAD"
|
||||||
case opMapKey:
|
case opMapKey:
|
||||||
return "MAP_KEY"
|
return "MAP_KEY"
|
||||||
|
@ -200,6 +330,15 @@ func (t opType) String() string {
|
||||||
case opMapEnd:
|
case opMapEnd:
|
||||||
return "MAP_END"
|
return "MAP_END"
|
||||||
|
|
||||||
|
case opMapHeadIndent:
|
||||||
|
return "MAP_HEAD_INDENT"
|
||||||
|
case opMapKeyIndent:
|
||||||
|
return "MAP_KEY_INDENT"
|
||||||
|
case opMapValueIndent:
|
||||||
|
return "MAP_VALUE_INDENT"
|
||||||
|
case opMapEndIndent:
|
||||||
|
return "MAP_END_INDENT"
|
||||||
|
|
||||||
case opStructFieldHead:
|
case opStructFieldHead:
|
||||||
return "STRUCT_FIELD_HEAD"
|
return "STRUCT_FIELD_HEAD"
|
||||||
case opStructFieldHeadInt:
|
case opStructFieldHeadInt:
|
||||||
|
@ -231,6 +370,37 @@ func (t opType) String() string {
|
||||||
case opStructFieldHeadBool:
|
case opStructFieldHeadBool:
|
||||||
return "STRUCT_FIELD_HEAD_BOOL"
|
return "STRUCT_FIELD_HEAD_BOOL"
|
||||||
|
|
||||||
|
case opStructFieldHeadIndent:
|
||||||
|
return "STRUCT_FIELD_HEAD_INDENT"
|
||||||
|
case opStructFieldHeadIntIndent:
|
||||||
|
return "STRUCT_FIELD_HEAD_INT_INDENT"
|
||||||
|
case opStructFieldHeadInt8Indent:
|
||||||
|
return "STRUCT_FIELD_HEAD_INT8_INDENT"
|
||||||
|
case opStructFieldHeadInt16Indent:
|
||||||
|
return "STRUCT_FIELD_HEAD_INT16_INDENT"
|
||||||
|
case opStructFieldHeadInt32Indent:
|
||||||
|
return "STRUCT_FIELD_HEAD_INT32_INDENT"
|
||||||
|
case opStructFieldHeadInt64Indent:
|
||||||
|
return "STRUCT_FIELD_HEAD_INT64_INDENT"
|
||||||
|
case opStructFieldHeadUintIndent:
|
||||||
|
return "STRUCT_FIELD_HEAD_UINT_INDENT"
|
||||||
|
case opStructFieldHeadUint8Indent:
|
||||||
|
return "STRUCT_FIELD_HEAD_UINT8_INDENT"
|
||||||
|
case opStructFieldHeadUint16Indent:
|
||||||
|
return "STRUCT_FIELD_HEAD_UINT16_INDENT"
|
||||||
|
case opStructFieldHeadUint32Indent:
|
||||||
|
return "STRUCT_FIELD_HEAD_UINT32_INDENT"
|
||||||
|
case opStructFieldHeadUint64Indent:
|
||||||
|
return "STRUCT_FIELD_HEAD_UINT64_INDENT"
|
||||||
|
case opStructFieldHeadFloat32Indent:
|
||||||
|
return "STRUCT_FIELD_HEAD_FLOAT32_INDENT"
|
||||||
|
case opStructFieldHeadFloat64Indent:
|
||||||
|
return "STRUCT_FIELD_HEAD_FLOAT64_INDENT"
|
||||||
|
case opStructFieldHeadStringIndent:
|
||||||
|
return "STRUCT_FIELD_HEAD_STRING_INDENT"
|
||||||
|
case opStructFieldHeadBoolIndent:
|
||||||
|
return "STRUCT_FIELD_HEAD_BOOL_INDENT"
|
||||||
|
|
||||||
case opStructFieldHeadOmitEmpty:
|
case opStructFieldHeadOmitEmpty:
|
||||||
return "STRUCT_FIELD_HEAD_OMIT_EMPTY"
|
return "STRUCT_FIELD_HEAD_OMIT_EMPTY"
|
||||||
case opStructFieldHeadIntOmitEmpty:
|
case opStructFieldHeadIntOmitEmpty:
|
||||||
|
@ -262,6 +432,37 @@ func (t opType) String() string {
|
||||||
case opStructFieldHeadBoolOmitEmpty:
|
case opStructFieldHeadBoolOmitEmpty:
|
||||||
return "STRUCT_FIELD_HEAD_BOOL_OMIT_EMPTY"
|
return "STRUCT_FIELD_HEAD_BOOL_OMIT_EMPTY"
|
||||||
|
|
||||||
|
case opStructFieldHeadOmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_HEAD_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldHeadIntOmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_HEAD_INT_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldHeadInt8OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_HEAD_INT8_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldHeadInt16OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_HEAD_INT16_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldHeadInt32OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_HEAD_INT32_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldHeadInt64OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_HEAD_INT64_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldHeadUintOmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_HEAD_UINT_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldHeadUint8OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_HEAD_UINT8_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldHeadUint16OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_HEAD_UINT16_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldHeadUint32OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_HEAD_UINT32_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldHeadUint64OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_HEAD_UINT64_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldHeadFloat32OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_HEAD_FLOAT32_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldHeadFloat64OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_HEAD_FLOAT64_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldHeadStringOmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_HEAD_STRING_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldHeadBoolOmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_HEAD_BOOL_OMIT_EMPTY_INDENT"
|
||||||
|
|
||||||
case opStructFieldPtrHead:
|
case opStructFieldPtrHead:
|
||||||
return "STRUCT_FIELD_PTR_HEAD"
|
return "STRUCT_FIELD_PTR_HEAD"
|
||||||
case opStructFieldPtrHeadInt:
|
case opStructFieldPtrHeadInt:
|
||||||
|
@ -293,6 +494,37 @@ func (t opType) String() string {
|
||||||
case opStructFieldPtrHeadBool:
|
case opStructFieldPtrHeadBool:
|
||||||
return "STRUCT_FIELD_PTR_HEAD_BOOL"
|
return "STRUCT_FIELD_PTR_HEAD_BOOL"
|
||||||
|
|
||||||
|
case opStructFieldPtrHeadIndent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_INDENT"
|
||||||
|
case opStructFieldPtrHeadIntIndent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_INT_INDENT"
|
||||||
|
case opStructFieldPtrHeadInt8Indent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_INT8_INDENT"
|
||||||
|
case opStructFieldPtrHeadInt16Indent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_INT16_INDENT"
|
||||||
|
case opStructFieldPtrHeadInt32Indent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_INT32_INDENT"
|
||||||
|
case opStructFieldPtrHeadInt64Indent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_INT64_INDENT"
|
||||||
|
case opStructFieldPtrHeadUintIndent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_UINT_INDENT"
|
||||||
|
case opStructFieldPtrHeadUint8Indent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_UINT8_INDENT"
|
||||||
|
case opStructFieldPtrHeadUint16Indent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_UINT16_INDENT"
|
||||||
|
case opStructFieldPtrHeadUint32Indent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_UINT32_INDENT"
|
||||||
|
case opStructFieldPtrHeadUint64Indent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_UINT64_INDENT"
|
||||||
|
case opStructFieldPtrHeadFloat32Indent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_FLOAT32_INDENT"
|
||||||
|
case opStructFieldPtrHeadFloat64Indent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_FLOAT64_INDENT"
|
||||||
|
case opStructFieldPtrHeadStringIndent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_STRING_INDENT"
|
||||||
|
case opStructFieldPtrHeadBoolIndent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_BOOL_INDENT"
|
||||||
|
|
||||||
case opStructFieldPtrHeadOmitEmpty:
|
case opStructFieldPtrHeadOmitEmpty:
|
||||||
return "STRUCT_FIELD_PTR_HEAD_OMIT_EMPTY"
|
return "STRUCT_FIELD_PTR_HEAD_OMIT_EMPTY"
|
||||||
case opStructFieldPtrHeadIntOmitEmpty:
|
case opStructFieldPtrHeadIntOmitEmpty:
|
||||||
|
@ -324,6 +556,37 @@ func (t opType) String() string {
|
||||||
case opStructFieldPtrHeadBoolOmitEmpty:
|
case opStructFieldPtrHeadBoolOmitEmpty:
|
||||||
return "STRUCT_FIELD_PTR_HEAD_BOOL_OMIT_EMPTY"
|
return "STRUCT_FIELD_PTR_HEAD_BOOL_OMIT_EMPTY"
|
||||||
|
|
||||||
|
case opStructFieldPtrHeadOmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldPtrHeadIntOmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_INT_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldPtrHeadInt8OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_INT8_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldPtrHeadInt16OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_INT16_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldPtrHeadInt32OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_INT32_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldPtrHeadInt64OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_INT64_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldPtrHeadUintOmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_UINT_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldPtrHeadUint8OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_UINT8_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldPtrHeadUint16OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_UINT16_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldPtrHeadUint32OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_UINT32_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldPtrHeadUint64OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_UINT64_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldPtrHeadFloat32OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_FLOAT32_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldPtrHeadFloat64OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_FLOAT64_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldPtrHeadStringOmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_STRING_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldPtrHeadBoolOmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_PTR_HEAD_BOOL_OMIT_EMPTY_INDENT"
|
||||||
|
|
||||||
case opStructField:
|
case opStructField:
|
||||||
return "STRUCT_FIELD"
|
return "STRUCT_FIELD"
|
||||||
case opStructFieldInt:
|
case opStructFieldInt:
|
||||||
|
@ -355,6 +618,37 @@ func (t opType) String() string {
|
||||||
case opStructFieldBool:
|
case opStructFieldBool:
|
||||||
return "STRUCT_FIELD_BOOL"
|
return "STRUCT_FIELD_BOOL"
|
||||||
|
|
||||||
|
case opStructFieldIndent:
|
||||||
|
return "STRUCT_FIELD_INDENT"
|
||||||
|
case opStructFieldIntIndent:
|
||||||
|
return "STRUCT_FIELD_INT_INDENT"
|
||||||
|
case opStructFieldInt8Indent:
|
||||||
|
return "STRUCT_FIELD_INT8_INDENT"
|
||||||
|
case opStructFieldInt16Indent:
|
||||||
|
return "STRUCT_FIELD_INT16_INDENT"
|
||||||
|
case opStructFieldInt32Indent:
|
||||||
|
return "STRUCT_FIELD_INT32_INDENT"
|
||||||
|
case opStructFieldInt64Indent:
|
||||||
|
return "STRUCT_FIELD_INT64_INDENT"
|
||||||
|
case opStructFieldUintIndent:
|
||||||
|
return "STRUCT_FIELD_UINT_INDENT"
|
||||||
|
case opStructFieldUint8Indent:
|
||||||
|
return "STRUCT_FIELD_UINT8_INDENT"
|
||||||
|
case opStructFieldUint16Indent:
|
||||||
|
return "STRUCT_FIELD_UINT16_INDENT"
|
||||||
|
case opStructFieldUint32Indent:
|
||||||
|
return "STRUCT_FIELD_UINT32_INDENT"
|
||||||
|
case opStructFieldUint64Indent:
|
||||||
|
return "STRUCT_FIELD_UINT64_INDENT"
|
||||||
|
case opStructFieldFloat32Indent:
|
||||||
|
return "STRUCT_FIELD_FLOAT32_INDENT"
|
||||||
|
case opStructFieldFloat64Indent:
|
||||||
|
return "STRUCT_FIELD_FLOAT64_INDENT"
|
||||||
|
case opStructFieldStringIndent:
|
||||||
|
return "STRUCT_FIELD_STRING_INDENT"
|
||||||
|
case opStructFieldBoolIndent:
|
||||||
|
return "STRUCT_FIELD_BOOL_INDENT"
|
||||||
|
|
||||||
case opStructFieldOmitEmpty:
|
case opStructFieldOmitEmpty:
|
||||||
return "STRUCT_FIELD_OMIT_EMPTY"
|
return "STRUCT_FIELD_OMIT_EMPTY"
|
||||||
case opStructFieldIntOmitEmpty:
|
case opStructFieldIntOmitEmpty:
|
||||||
|
@ -386,8 +680,42 @@ func (t opType) String() string {
|
||||||
case opStructFieldBoolOmitEmpty:
|
case opStructFieldBoolOmitEmpty:
|
||||||
return "STRUCT_FIELD_BOOL_OMIT_EMPTY"
|
return "STRUCT_FIELD_BOOL_OMIT_EMPTY"
|
||||||
|
|
||||||
|
case opStructFieldOmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldIntOmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_INT_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldInt8OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_INT8_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldInt16OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_INT16_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldInt32OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_INT32_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldInt64OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_INT64_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldUintOmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_UINT_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldUint8OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_UINT8_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldUint16OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_UINT16_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldUint32OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_UINT32_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldUint64OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_UINT64_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldFloat32OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_FLOAT32_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldFloat64OmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_FLOAT64_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldStringOmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_STRING_OMIT_EMPTY_INDENT"
|
||||||
|
case opStructFieldBoolOmitEmptyIndent:
|
||||||
|
return "STRUCT_FIELD_BOOL_OMIT_EMPTY_INDENT"
|
||||||
|
|
||||||
case opStructEnd:
|
case opStructEnd:
|
||||||
return "STRUCT_END"
|
return "STRUCT_END"
|
||||||
|
case opStructEndIndent:
|
||||||
|
return "STRUCT_END_INDENT"
|
||||||
|
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -396,6 +724,7 @@ type opcodeHeader struct {
|
||||||
op opType
|
op opType
|
||||||
typ *rtype
|
typ *rtype
|
||||||
ptr uintptr
|
ptr uintptr
|
||||||
|
indent int
|
||||||
next *opcode
|
next *opcode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,18 +732,19 @@ type opcode struct {
|
||||||
*opcodeHeader
|
*opcodeHeader
|
||||||
}
|
}
|
||||||
|
|
||||||
func newOpCode(op opType, typ *rtype, next *opcode) *opcode {
|
func newOpCode(op opType, typ *rtype, indent int, next *opcode) *opcode {
|
||||||
return &opcode{
|
return &opcode{
|
||||||
opcodeHeader: &opcodeHeader{
|
opcodeHeader: &opcodeHeader{
|
||||||
op: op,
|
op: op,
|
||||||
typ: typ,
|
typ: typ,
|
||||||
|
indent: indent,
|
||||||
next: next,
|
next: next,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newEndOp() *opcode {
|
func newEndOp(indent int) *opcode {
|
||||||
return newOpCode(opEnd, nil, nil)
|
return newOpCode(opEnd, nil, indent, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *opcode) beforeLastCode() *opcode {
|
func (c *opcode) beforeLastCode() *opcode {
|
||||||
|
@ -422,11 +752,11 @@ func (c *opcode) beforeLastCode() *opcode {
|
||||||
for {
|
for {
|
||||||
var nextCode *opcode
|
var nextCode *opcode
|
||||||
switch code.op {
|
switch code.op {
|
||||||
case opArrayElem:
|
case opArrayElem, opArrayElemIndent:
|
||||||
nextCode = code.toArrayElemCode().end
|
nextCode = code.toArrayElemCode().end
|
||||||
case opSliceElem:
|
case opSliceElem, opSliceElemIndent:
|
||||||
nextCode = code.toSliceElemCode().end
|
nextCode = code.toSliceElemCode().end
|
||||||
case opMapKey:
|
case opMapKey, opMapKeyIndent:
|
||||||
nextCode = code.toMapKeyCode().end
|
nextCode = code.toMapKeyCode().end
|
||||||
default:
|
default:
|
||||||
nextCode = code.next
|
nextCode = code.next
|
||||||
|
@ -442,13 +772,14 @@ func (c *opcode) beforeLastCode() *opcode {
|
||||||
func (c *opcode) dump() string {
|
func (c *opcode) dump() string {
|
||||||
codes := []string{}
|
codes := []string{}
|
||||||
for code := c; code.op != opEnd; {
|
for code := c; code.op != opEnd; {
|
||||||
codes = append(codes, fmt.Sprintf("%s", code.op))
|
indent := strings.Repeat(" ", code.indent)
|
||||||
|
codes = append(codes, fmt.Sprintf("%s%s", indent, code.op))
|
||||||
switch code.op {
|
switch code.op {
|
||||||
case opArrayElem:
|
case opArrayElem, opArrayElemIndent:
|
||||||
code = code.toArrayElemCode().end
|
code = code.toArrayElemCode().end
|
||||||
case opSliceElem:
|
case opSliceElem, opSliceElemIndent:
|
||||||
code = code.toSliceElemCode().end
|
code = code.toSliceElemCode().end
|
||||||
case opMapKey:
|
case opMapKey, opMapKeyIndent:
|
||||||
code = code.toMapKeyCode().end
|
code = code.toMapKeyCode().end
|
||||||
default:
|
default:
|
||||||
code = code.next
|
code = code.next
|
||||||
|
@ -495,10 +826,11 @@ type sliceHeaderCode struct {
|
||||||
end *opcode
|
end *opcode
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSliceHeaderCode() *sliceHeaderCode {
|
func newSliceHeaderCode(indent int) *sliceHeaderCode {
|
||||||
return &sliceHeaderCode{
|
return &sliceHeaderCode{
|
||||||
opcodeHeader: &opcodeHeader{
|
opcodeHeader: &opcodeHeader{
|
||||||
op: opSliceHead,
|
op: opSliceHead,
|
||||||
|
indent: indent,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -525,10 +857,11 @@ type arrayHeaderCode struct {
|
||||||
end *opcode
|
end *opcode
|
||||||
}
|
}
|
||||||
|
|
||||||
func newArrayHeaderCode(alen int) *arrayHeaderCode {
|
func newArrayHeaderCode(indent, alen int) *arrayHeaderCode {
|
||||||
return &arrayHeaderCode{
|
return &arrayHeaderCode{
|
||||||
opcodeHeader: &opcodeHeader{
|
opcodeHeader: &opcodeHeader{
|
||||||
op: opArrayHead,
|
op: opArrayHead,
|
||||||
|
indent: indent,
|
||||||
},
|
},
|
||||||
len: uintptr(alen),
|
len: uintptr(alen),
|
||||||
}
|
}
|
||||||
|
@ -580,27 +913,30 @@ func (c *mapValueCode) set(iter unsafe.Pointer) {
|
||||||
c.iter = iter
|
c.iter = iter
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMapHeaderCode(typ *rtype) *mapHeaderCode {
|
func newMapHeaderCode(typ *rtype, indent int) *mapHeaderCode {
|
||||||
return &mapHeaderCode{
|
return &mapHeaderCode{
|
||||||
opcodeHeader: &opcodeHeader{
|
opcodeHeader: &opcodeHeader{
|
||||||
op: opMapHead,
|
op: opMapHead,
|
||||||
typ: typ,
|
typ: typ,
|
||||||
|
indent: indent,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMapKeyCode() *mapKeyCode {
|
func newMapKeyCode(indent int) *mapKeyCode {
|
||||||
return &mapKeyCode{
|
return &mapKeyCode{
|
||||||
opcodeHeader: &opcodeHeader{
|
opcodeHeader: &opcodeHeader{
|
||||||
op: opMapKey,
|
op: opMapKey,
|
||||||
|
indent: indent,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMapValueCode() *mapValueCode {
|
func newMapValueCode(indent int) *mapValueCode {
|
||||||
return &mapValueCode{
|
return &mapValueCode{
|
||||||
opcodeHeader: &opcodeHeader{
|
opcodeHeader: &opcodeHeader{
|
||||||
op: opMapValue,
|
op: opMapValue,
|
||||||
|
indent: indent,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_Encoder(t *testing.T) {
|
func Test_Marshal(t *testing.T) {
|
||||||
t.Run("int", func(t *testing.T) {
|
t.Run("int", func(t *testing.T) {
|
||||||
bytes, err := json.Marshal(-10)
|
bytes, err := json.Marshal(-10)
|
||||||
assertErr(t, err)
|
assertErr(t, err)
|
||||||
|
@ -205,3 +205,77 @@ func Test_Encoder(t *testing.T) {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_MarshalIndent(t *testing.T) {
|
||||||
|
prefix := "-"
|
||||||
|
indent := "\t"
|
||||||
|
t.Run("struct", func(t *testing.T) {
|
||||||
|
bytes, err := json.MarshalIndent(struct {
|
||||||
|
A int `json:"a"`
|
||||||
|
B uint `json:"b"`
|
||||||
|
C string `json:"c"`
|
||||||
|
D int `json:"-"` // ignore field
|
||||||
|
a int `json:"aa"` // private field
|
||||||
|
}{
|
||||||
|
A: -1,
|
||||||
|
B: 1,
|
||||||
|
C: "hello world",
|
||||||
|
}, prefix, indent)
|
||||||
|
assertErr(t, err)
|
||||||
|
result := "{\n-\t\"a\": -1,\n-\t\"b\": 1,\n-\t\"c\": \"hello world\"\n-}"
|
||||||
|
assertEq(t, "struct", result, string(bytes))
|
||||||
|
})
|
||||||
|
t.Run("slice", func(t *testing.T) {
|
||||||
|
t.Run("[]int", func(t *testing.T) {
|
||||||
|
bytes, err := json.MarshalIndent([]int{1, 2, 3, 4}, prefix, indent)
|
||||||
|
assertErr(t, err)
|
||||||
|
result := "[\n-\t1,\n-\t2,\n-\t3,\n-\t4\n-]"
|
||||||
|
assertEq(t, "[]int", result, string(bytes))
|
||||||
|
})
|
||||||
|
t.Run("[]interface{}", func(t *testing.T) {
|
||||||
|
bytes, err := json.MarshalIndent([]interface{}{1, 2.1, "hello"}, prefix, indent)
|
||||||
|
assertErr(t, err)
|
||||||
|
result := "[\n-\t1,\n-\t2.1,\n-\t\"hello\"\n-]"
|
||||||
|
assertEq(t, "[]interface{}", result, string(bytes))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("array", func(t *testing.T) {
|
||||||
|
bytes, err := json.MarshalIndent([4]int{1, 2, 3, 4}, prefix, indent)
|
||||||
|
assertErr(t, err)
|
||||||
|
result := "[\n-\t1,\n-\t2,\n-\t3,\n-\t4\n-]"
|
||||||
|
assertEq(t, "array", result, string(bytes))
|
||||||
|
})
|
||||||
|
t.Run("map", func(t *testing.T) {
|
||||||
|
t.Run("map[string]int", func(t *testing.T) {
|
||||||
|
bytes, err := json.MarshalIndent(map[string]int{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2,
|
||||||
|
"c": 3,
|
||||||
|
"d": 4,
|
||||||
|
}, prefix, indent)
|
||||||
|
assertErr(t, err)
|
||||||
|
result := "{\n-\t\"a\": 1,\n-\t\"b\": 2,\n-\t\"c\": 3,\n-\t\"d\": 4\n-}"
|
||||||
|
assertEq(t, "map", len(result), len(string(bytes)))
|
||||||
|
})
|
||||||
|
t.Run("map[string]interface{}", func(t *testing.T) {
|
||||||
|
type T struct {
|
||||||
|
E int
|
||||||
|
F int
|
||||||
|
}
|
||||||
|
v := map[string]interface{}{
|
||||||
|
"a": 1,
|
||||||
|
"b": 2.1,
|
||||||
|
"c": &T{
|
||||||
|
E: 10,
|
||||||
|
F: 11,
|
||||||
|
},
|
||||||
|
"d": 4,
|
||||||
|
}
|
||||||
|
bytes, err := json.MarshalIndent(v, prefix, indent)
|
||||||
|
assertErr(t, err)
|
||||||
|
result := "{\n-\t\"a\": 1,\n-\t\"b\": 2.1,\n-\t\"c\": {\n-\t\t\"E\": 10,\n-\t\t\"F\": 11\n-\t},\n-\t\"d\": 4\n-}"
|
||||||
|
assertEq(t, "map[string]interface{}", len(result), len(string(bytes)))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
1210
encode_vm.go
1210
encode_vm.go
File diff suppressed because it is too large
Load Diff
14
json.go
14
json.go
|
@ -5,6 +5,20 @@ import "bytes"
|
||||||
func Marshal(v interface{}) ([]byte, error) {
|
func Marshal(v interface{}) ([]byte, error) {
|
||||||
var b *bytes.Buffer
|
var b *bytes.Buffer
|
||||||
enc := NewEncoder(b)
|
enc := NewEncoder(b)
|
||||||
|
enc.SetIndent("", "")
|
||||||
|
bytes, err := enc.encodeForMarshal(v)
|
||||||
|
if err != nil {
|
||||||
|
enc.release()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
enc.release()
|
||||||
|
return bytes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
|
||||||
|
var b *bytes.Buffer
|
||||||
|
enc := NewEncoder(b)
|
||||||
|
enc.SetIndent(prefix, indent)
|
||||||
bytes, err := enc.encodeForMarshal(v)
|
bytes, err := enc.encodeForMarshal(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
enc.release()
|
enc.release()
|
||||||
|
|
Loading…
Reference in New Issue