forked from github/multus-cni
gomodule is still in progress to migrate for now, hence multus team decide to keep vendor directory to support build without gomodule.
319 lines
8.4 KiB
Go
319 lines
8.4 KiB
Go
package jsoniter
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/modern-go/reflect2"
|
|
"io"
|
|
"reflect"
|
|
"sort"
|
|
"unsafe"
|
|
)
|
|
|
|
func decoderOfMap(ctx *ctx, typ reflect2.Type) ValDecoder {
|
|
mapType := typ.(*reflect2.UnsafeMapType)
|
|
keyDecoder := decoderOfMapKey(ctx.append("[mapKey]"), mapType.Key())
|
|
elemDecoder := decoderOfType(ctx.append("[mapElem]"), mapType.Elem())
|
|
return &mapDecoder{
|
|
mapType: mapType,
|
|
keyType: mapType.Key(),
|
|
elemType: mapType.Elem(),
|
|
keyDecoder: keyDecoder,
|
|
elemDecoder: elemDecoder,
|
|
}
|
|
}
|
|
|
|
func encoderOfMap(ctx *ctx, typ reflect2.Type) ValEncoder {
|
|
mapType := typ.(*reflect2.UnsafeMapType)
|
|
if ctx.sortMapKeys {
|
|
return &sortKeysMapEncoder{
|
|
mapType: mapType,
|
|
keyEncoder: encoderOfMapKey(ctx.append("[mapKey]"), mapType.Key()),
|
|
elemEncoder: encoderOfType(ctx.append("[mapElem]"), mapType.Elem()),
|
|
}
|
|
}
|
|
return &mapEncoder{
|
|
mapType: mapType,
|
|
keyEncoder: encoderOfMapKey(ctx.append("[mapKey]"), mapType.Key()),
|
|
elemEncoder: encoderOfType(ctx.append("[mapElem]"), mapType.Elem()),
|
|
}
|
|
}
|
|
|
|
func decoderOfMapKey(ctx *ctx, typ reflect2.Type) ValDecoder {
|
|
for _, extension := range ctx.extensions {
|
|
decoder := extension.CreateMapKeyDecoder(typ)
|
|
if decoder != nil {
|
|
return decoder
|
|
}
|
|
}
|
|
switch typ.Kind() {
|
|
case reflect.String:
|
|
return decoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String))
|
|
case reflect.Bool,
|
|
reflect.Uint8, reflect.Int8,
|
|
reflect.Uint16, reflect.Int16,
|
|
reflect.Uint32, reflect.Int32,
|
|
reflect.Uint64, reflect.Int64,
|
|
reflect.Uint, reflect.Int,
|
|
reflect.Float32, reflect.Float64,
|
|
reflect.Uintptr:
|
|
typ = reflect2.DefaultTypeOfKind(typ.Kind())
|
|
return &numericMapKeyDecoder{decoderOfType(ctx, typ)}
|
|
default:
|
|
ptrType := reflect2.PtrTo(typ)
|
|
if ptrType.Implements(textMarshalerType) {
|
|
return &referenceDecoder{
|
|
&textUnmarshalerDecoder{
|
|
valType: ptrType,
|
|
},
|
|
}
|
|
}
|
|
if typ.Implements(textMarshalerType) {
|
|
return &textUnmarshalerDecoder{
|
|
valType: typ,
|
|
}
|
|
}
|
|
return &lazyErrorDecoder{err: fmt.Errorf("unsupported map key type: %v", typ)}
|
|
}
|
|
}
|
|
|
|
func encoderOfMapKey(ctx *ctx, typ reflect2.Type) ValEncoder {
|
|
for _, extension := range ctx.extensions {
|
|
encoder := extension.CreateMapKeyEncoder(typ)
|
|
if encoder != nil {
|
|
return encoder
|
|
}
|
|
}
|
|
switch typ.Kind() {
|
|
case reflect.String:
|
|
return encoderOfType(ctx, reflect2.DefaultTypeOfKind(reflect.String))
|
|
case reflect.Bool,
|
|
reflect.Uint8, reflect.Int8,
|
|
reflect.Uint16, reflect.Int16,
|
|
reflect.Uint32, reflect.Int32,
|
|
reflect.Uint64, reflect.Int64,
|
|
reflect.Uint, reflect.Int,
|
|
reflect.Float32, reflect.Float64,
|
|
reflect.Uintptr:
|
|
typ = reflect2.DefaultTypeOfKind(typ.Kind())
|
|
return &numericMapKeyEncoder{encoderOfType(ctx, typ)}
|
|
default:
|
|
if typ == textMarshalerType {
|
|
return &directTextMarshalerEncoder{
|
|
stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
|
|
}
|
|
}
|
|
if typ.Implements(textMarshalerType) {
|
|
return &textMarshalerEncoder{
|
|
valType: typ,
|
|
stringEncoder: ctx.EncoderOf(reflect2.TypeOf("")),
|
|
}
|
|
}
|
|
if typ.Kind() == reflect.Interface {
|
|
return &dynamicMapKeyEncoder{ctx, typ}
|
|
}
|
|
return &lazyErrorEncoder{err: fmt.Errorf("unsupported map key type: %v", typ)}
|
|
}
|
|
}
|
|
|
|
type mapDecoder struct {
|
|
mapType *reflect2.UnsafeMapType
|
|
keyType reflect2.Type
|
|
elemType reflect2.Type
|
|
keyDecoder ValDecoder
|
|
elemDecoder ValDecoder
|
|
}
|
|
|
|
func (decoder *mapDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
|
mapType := decoder.mapType
|
|
c := iter.nextToken()
|
|
if c == 'n' {
|
|
iter.skipThreeBytes('u', 'l', 'l')
|
|
*(*unsafe.Pointer)(ptr) = nil
|
|
mapType.UnsafeSet(ptr, mapType.UnsafeNew())
|
|
return
|
|
}
|
|
if mapType.UnsafeIsNil(ptr) {
|
|
mapType.UnsafeSet(ptr, mapType.UnsafeMakeMap(0))
|
|
}
|
|
if c != '{' {
|
|
iter.ReportError("ReadMapCB", `expect { or n, but found `+string([]byte{c}))
|
|
return
|
|
}
|
|
c = iter.nextToken()
|
|
if c == '}' {
|
|
return
|
|
}
|
|
if c != '"' {
|
|
iter.ReportError("ReadMapCB", `expect " after }, but found `+string([]byte{c}))
|
|
return
|
|
}
|
|
iter.unreadByte()
|
|
key := decoder.keyType.UnsafeNew()
|
|
decoder.keyDecoder.Decode(key, iter)
|
|
c = iter.nextToken()
|
|
if c != ':' {
|
|
iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))
|
|
return
|
|
}
|
|
elem := decoder.elemType.UnsafeNew()
|
|
decoder.elemDecoder.Decode(elem, iter)
|
|
decoder.mapType.UnsafeSetIndex(ptr, key, elem)
|
|
for c = iter.nextToken(); c == ','; c = iter.nextToken() {
|
|
key := decoder.keyType.UnsafeNew()
|
|
decoder.keyDecoder.Decode(key, iter)
|
|
c = iter.nextToken()
|
|
if c != ':' {
|
|
iter.ReportError("ReadMapCB", "expect : after object field, but found "+string([]byte{c}))
|
|
return
|
|
}
|
|
elem := decoder.elemType.UnsafeNew()
|
|
decoder.elemDecoder.Decode(elem, iter)
|
|
decoder.mapType.UnsafeSetIndex(ptr, key, elem)
|
|
}
|
|
if c != '}' {
|
|
iter.ReportError("ReadMapCB", `expect }, but found `+string([]byte{c}))
|
|
}
|
|
}
|
|
|
|
type numericMapKeyDecoder struct {
|
|
decoder ValDecoder
|
|
}
|
|
|
|
func (decoder *numericMapKeyDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
|
|
c := iter.nextToken()
|
|
if c != '"' {
|
|
iter.ReportError("ReadMapCB", `expect ", but found `+string([]byte{c}))
|
|
return
|
|
}
|
|
decoder.decoder.Decode(ptr, iter)
|
|
c = iter.nextToken()
|
|
if c != '"' {
|
|
iter.ReportError("ReadMapCB", `expect ", but found `+string([]byte{c}))
|
|
return
|
|
}
|
|
}
|
|
|
|
type numericMapKeyEncoder struct {
|
|
encoder ValEncoder
|
|
}
|
|
|
|
func (encoder *numericMapKeyEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
|
stream.writeByte('"')
|
|
encoder.encoder.Encode(ptr, stream)
|
|
stream.writeByte('"')
|
|
}
|
|
|
|
func (encoder *numericMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
|
return false
|
|
}
|
|
|
|
type dynamicMapKeyEncoder struct {
|
|
ctx *ctx
|
|
valType reflect2.Type
|
|
}
|
|
|
|
func (encoder *dynamicMapKeyEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
|
obj := encoder.valType.UnsafeIndirect(ptr)
|
|
encoderOfMapKey(encoder.ctx, reflect2.TypeOf(obj)).Encode(reflect2.PtrOf(obj), stream)
|
|
}
|
|
|
|
func (encoder *dynamicMapKeyEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
|
obj := encoder.valType.UnsafeIndirect(ptr)
|
|
return encoderOfMapKey(encoder.ctx, reflect2.TypeOf(obj)).IsEmpty(reflect2.PtrOf(obj))
|
|
}
|
|
|
|
type mapEncoder struct {
|
|
mapType *reflect2.UnsafeMapType
|
|
keyEncoder ValEncoder
|
|
elemEncoder ValEncoder
|
|
}
|
|
|
|
func (encoder *mapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
|
stream.WriteObjectStart()
|
|
iter := encoder.mapType.UnsafeIterate(ptr)
|
|
for i := 0; iter.HasNext(); i++ {
|
|
if i != 0 {
|
|
stream.WriteMore()
|
|
}
|
|
key, elem := iter.UnsafeNext()
|
|
encoder.keyEncoder.Encode(key, stream)
|
|
if stream.indention > 0 {
|
|
stream.writeTwoBytes(byte(':'), byte(' '))
|
|
} else {
|
|
stream.writeByte(':')
|
|
}
|
|
encoder.elemEncoder.Encode(elem, stream)
|
|
}
|
|
stream.WriteObjectEnd()
|
|
}
|
|
|
|
func (encoder *mapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
|
iter := encoder.mapType.UnsafeIterate(ptr)
|
|
return !iter.HasNext()
|
|
}
|
|
|
|
type sortKeysMapEncoder struct {
|
|
mapType *reflect2.UnsafeMapType
|
|
keyEncoder ValEncoder
|
|
elemEncoder ValEncoder
|
|
}
|
|
|
|
func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
|
if *(*unsafe.Pointer)(ptr) == nil {
|
|
stream.WriteNil()
|
|
return
|
|
}
|
|
stream.WriteObjectStart()
|
|
mapIter := encoder.mapType.UnsafeIterate(ptr)
|
|
subStream := stream.cfg.BorrowStream(nil)
|
|
subIter := stream.cfg.BorrowIterator(nil)
|
|
keyValues := encodedKeyValues{}
|
|
for mapIter.HasNext() {
|
|
subStream.buf = make([]byte, 0, 64)
|
|
key, elem := mapIter.UnsafeNext()
|
|
encoder.keyEncoder.Encode(key, subStream)
|
|
if subStream.Error != nil && subStream.Error != io.EOF && stream.Error == nil {
|
|
stream.Error = subStream.Error
|
|
}
|
|
encodedKey := subStream.Buffer()
|
|
subIter.ResetBytes(encodedKey)
|
|
decodedKey := subIter.ReadString()
|
|
if stream.indention > 0 {
|
|
subStream.writeTwoBytes(byte(':'), byte(' '))
|
|
} else {
|
|
subStream.writeByte(':')
|
|
}
|
|
encoder.elemEncoder.Encode(elem, subStream)
|
|
keyValues = append(keyValues, encodedKV{
|
|
key: decodedKey,
|
|
keyValue: subStream.Buffer(),
|
|
})
|
|
}
|
|
sort.Sort(keyValues)
|
|
for i, keyValue := range keyValues {
|
|
if i != 0 {
|
|
stream.WriteMore()
|
|
}
|
|
stream.Write(keyValue.keyValue)
|
|
}
|
|
stream.WriteObjectEnd()
|
|
stream.cfg.ReturnStream(subStream)
|
|
stream.cfg.ReturnIterator(subIter)
|
|
}
|
|
|
|
func (encoder *sortKeysMapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
|
|
iter := encoder.mapType.UnsafeIterate(ptr)
|
|
return !iter.HasNext()
|
|
}
|
|
|
|
type encodedKeyValues []encodedKV
|
|
|
|
type encodedKV struct {
|
|
key string
|
|
keyValue []byte
|
|
}
|
|
|
|
func (sv encodedKeyValues) Len() int { return len(sv) }
|
|
func (sv encodedKeyValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
|
|
func (sv encodedKeyValues) Less(i, j int) bool { return sv[i].key < sv[j].key }
|