| package jsoniter |
| |
| import ( |
| "encoding" |
| "encoding/json" |
| "fmt" |
| "reflect" |
| "sync/atomic" |
| "unsafe" |
| ) |
| |
| // Decoder is an internal type registered to cache as needed. |
| // Don't confuse jsoniter.Decoder with json.Decoder. |
| // For json.Decoder's adapter, refer to jsoniter.AdapterDecoder(todo link). |
| // |
| // Reflection on type to create decoders, which is then cached |
| // Reflection on value is avoided as we can, as the reflect.Value itself will allocate, with following exceptions |
| // 1. create instance of new value, for example *int will need a int to be allocated |
| // 2. append to slice, if the existing cap is not enough, allocate will be done using Reflect.New |
| // 3. assignment to map, both key and value will be reflect.Value |
| // For a simple struct binding, it will be reflect.Value free and allocation free |
| type Decoder interface { |
| decode(ptr unsafe.Pointer, iter *Iterator) |
| } |
| |
| // Encoder is an internal type registered to cache as needed. |
| // Don't confuse jsoniter.Encoder with json.Encoder. |
| // For json.Encoder's adapter, refer to jsoniter.AdapterEncoder(todo godoc link). |
| type Encoder interface { |
| isEmpty(ptr unsafe.Pointer) bool |
| encode(ptr unsafe.Pointer, stream *Stream) |
| encodeInterface(val interface{}, stream *Stream) |
| } |
| |
| func writeToStream(val interface{}, stream *Stream, encoder Encoder) { |
| e := (*emptyInterface)(unsafe.Pointer(&val)) |
| if reflect.TypeOf(val).Kind() == reflect.Ptr { |
| encoder.encode(unsafe.Pointer(&e.word), stream) |
| } else { |
| encoder.encode(e.word, stream) |
| } |
| } |
| |
| type DecoderFunc func(ptr unsafe.Pointer, iter *Iterator) |
| type EncoderFunc func(ptr unsafe.Pointer, stream *Stream) |
| type ExtensionFunc func(typ reflect.Type, field *reflect.StructField) ([]string, EncoderFunc, DecoderFunc) |
| |
| type funcDecoder struct { |
| fun DecoderFunc |
| } |
| |
| func (decoder *funcDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { |
| decoder.fun(ptr, iter) |
| } |
| |
| type funcEncoder struct { |
| fun EncoderFunc |
| } |
| |
| func (encoder *funcEncoder) encode(ptr unsafe.Pointer, stream *Stream) { |
| encoder.fun(ptr, stream) |
| } |
| |
| func (encoder *funcEncoder) encodeInterface(val interface{}, stream *Stream) { |
| writeToStream(val, stream, encoder) |
| } |
| |
| func (encoder *funcEncoder) isEmpty(ptr unsafe.Pointer) bool { |
| return false |
| } |
| |
| var DECODERS unsafe.Pointer |
| var ENCODERS unsafe.Pointer |
| |
| var typeDecoders map[string]Decoder |
| var fieldDecoders map[string]Decoder |
| var typeEncoders map[string]Encoder |
| var fieldEncoders map[string]Encoder |
| var extensions []ExtensionFunc |
| var jsonNumberType reflect.Type |
| var jsonRawMessageType reflect.Type |
| var anyType reflect.Type |
| var marshalerType reflect.Type |
| var unmarshalerType reflect.Type |
| var textUnmarshalerType reflect.Type |
| |
| func init() { |
| typeDecoders = map[string]Decoder{} |
| fieldDecoders = map[string]Decoder{} |
| typeEncoders = map[string]Encoder{} |
| fieldEncoders = map[string]Encoder{} |
| extensions = []ExtensionFunc{} |
| atomic.StorePointer(&DECODERS, unsafe.Pointer(&map[string]Decoder{})) |
| atomic.StorePointer(&ENCODERS, unsafe.Pointer(&map[string]Encoder{})) |
| jsonNumberType = reflect.TypeOf((*json.Number)(nil)).Elem() |
| jsonRawMessageType = reflect.TypeOf((*json.RawMessage)(nil)).Elem() |
| anyType = reflect.TypeOf((*Any)(nil)).Elem() |
| marshalerType = reflect.TypeOf((*json.Marshaler)(nil)).Elem() |
| unmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem() |
| textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() |
| } |
| |
| func addDecoderToCache(cacheKey reflect.Type, decoder Decoder) { |
| done := false |
| for !done { |
| ptr := atomic.LoadPointer(&DECODERS) |
| cache := *(*map[reflect.Type]Decoder)(ptr) |
| copied := map[reflect.Type]Decoder{} |
| for k, v := range cache { |
| copied[k] = v |
| } |
| copied[cacheKey] = decoder |
| done = atomic.CompareAndSwapPointer(&DECODERS, ptr, unsafe.Pointer(&copied)) |
| } |
| } |
| |
| func addEncoderToCache(cacheKey reflect.Type, encoder Encoder) { |
| done := false |
| for !done { |
| ptr := atomic.LoadPointer(&ENCODERS) |
| cache := *(*map[reflect.Type]Encoder)(ptr) |
| copied := map[reflect.Type]Encoder{} |
| for k, v := range cache { |
| copied[k] = v |
| } |
| copied[cacheKey] = encoder |
| done = atomic.CompareAndSwapPointer(&ENCODERS, ptr, unsafe.Pointer(&copied)) |
| } |
| } |
| |
| func getDecoderFromCache(cacheKey reflect.Type) Decoder { |
| ptr := atomic.LoadPointer(&DECODERS) |
| cache := *(*map[reflect.Type]Decoder)(ptr) |
| return cache[cacheKey] |
| } |
| |
| func getEncoderFromCache(cacheKey reflect.Type) Encoder { |
| ptr := atomic.LoadPointer(&ENCODERS) |
| cache := *(*map[reflect.Type]Encoder)(ptr) |
| return cache[cacheKey] |
| } |
| |
| // RegisterTypeDecoder can register a type for json object |
| func RegisterTypeDecoder(typ string, fun DecoderFunc) { |
| typeDecoders[typ] = &funcDecoder{fun} |
| } |
| |
| // RegisterFieldDecoder can register a type for json field |
| func RegisterFieldDecoder(typ string, field string, fun DecoderFunc) { |
| fieldDecoders[fmt.Sprintf("%s/%s", typ, field)] = &funcDecoder{fun} |
| } |
| |
| func RegisterTypeEncoder(typ string, fun EncoderFunc) { |
| typeEncoders[typ] = &funcEncoder{fun} |
| } |
| |
| func RegisterFieldEncoder(typ string, field string, fun EncoderFunc) { |
| fieldEncoders[fmt.Sprintf("%s/%s", typ, field)] = &funcEncoder{fun} |
| } |
| |
| // RegisterExtension can register a custom extension |
| func RegisterExtension(extension ExtensionFunc) { |
| extensions = append(extensions, extension) |
| } |
| |
| // CleanDecoders cleans decoders registered or cached |
| func CleanDecoders() { |
| typeDecoders = map[string]Decoder{} |
| fieldDecoders = map[string]Decoder{} |
| atomic.StorePointer(&DECODERS, unsafe.Pointer(&map[string]Decoder{})) |
| } |
| |
| // CleanEncoders cleans encoders registered or cached |
| func CleanEncoders() { |
| typeEncoders = map[string]Encoder{} |
| fieldEncoders = map[string]Encoder{} |
| atomic.StorePointer(&ENCODERS, unsafe.Pointer(&map[string]Encoder{})) |
| } |
| |
| type optionalDecoder struct { |
| valueType reflect.Type |
| valueDecoder Decoder |
| } |
| |
| func (decoder *optionalDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { |
| if iter.ReadNil() { |
| *((*unsafe.Pointer)(ptr)) = nil |
| } else { |
| if *((*unsafe.Pointer)(ptr)) == nil { |
| // pointer to null, we have to allocate memory to hold the value |
| value := reflect.New(decoder.valueType) |
| decoder.valueDecoder.decode(unsafe.Pointer(value.Pointer()), iter) |
| *((*uintptr)(ptr)) = value.Pointer() |
| } else { |
| // reuse existing instance |
| decoder.valueDecoder.decode(*((*unsafe.Pointer)(ptr)), iter) |
| } |
| } |
| } |
| |
| type optionalEncoder struct { |
| valueEncoder Encoder |
| } |
| |
| func (encoder *optionalEncoder) encode(ptr unsafe.Pointer, stream *Stream) { |
| if *((*unsafe.Pointer)(ptr)) == nil { |
| stream.WriteNil() |
| } else { |
| encoder.valueEncoder.encode(*((*unsafe.Pointer)(ptr)), stream) |
| } |
| } |
| |
| func (encoder *optionalEncoder) encodeInterface(val interface{}, stream *Stream) { |
| writeToStream(val, stream, encoder) |
| } |
| |
| func (encoder *optionalEncoder) isEmpty(ptr unsafe.Pointer) bool { |
| if *((*unsafe.Pointer)(ptr)) == nil { |
| return true |
| } else { |
| return encoder.valueEncoder.isEmpty(*((*unsafe.Pointer)(ptr))) |
| } |
| } |
| |
| type placeholderEncoder struct { |
| valueEncoder Encoder |
| } |
| |
| func (encoder *placeholderEncoder) encode(ptr unsafe.Pointer, stream *Stream) { |
| encoder.valueEncoder.encode(ptr, stream) |
| } |
| |
| func (encoder *placeholderEncoder) encodeInterface(val interface{}, stream *Stream) { |
| writeToStream(val, stream, encoder) |
| } |
| |
| func (encoder *placeholderEncoder) isEmpty(ptr unsafe.Pointer) bool { |
| return encoder.valueEncoder.isEmpty(ptr) |
| } |
| |
| type placeholderDecoder struct { |
| valueDecoder Decoder |
| } |
| |
| func (decoder *placeholderDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { |
| decoder.valueDecoder.decode(ptr, iter) |
| } |
| |
| // emptyInterface is the header for an interface{} value. |
| type emptyInterface struct { |
| typ unsafe.Pointer |
| word unsafe.Pointer |
| } |
| |
| // emptyInterface is the header for an interface with method (not interface{}) |
| type nonEmptyInterface struct { |
| // see ../runtime/iface.go:/Itab |
| itab *struct { |
| ityp unsafe.Pointer // static interface type |
| typ unsafe.Pointer // dynamic concrete type |
| link unsafe.Pointer |
| bad int32 |
| unused int32 |
| fun [100000]unsafe.Pointer // method table |
| } |
| word unsafe.Pointer |
| } |
| |
| // Read converts an Iterator instance into go interface, same as json.Unmarshal |
| func (iter *Iterator) ReadVal(obj interface{}) { |
| typ := reflect.TypeOf(obj) |
| cacheKey := typ.Elem() |
| cachedDecoder := getDecoderFromCache(cacheKey) |
| if cachedDecoder == nil { |
| decoder, err := decoderOfType(cacheKey) |
| if err != nil { |
| iter.Error = err |
| return |
| } |
| cachedDecoder = decoder |
| addDecoderToCache(cacheKey, decoder) |
| } |
| e := (*emptyInterface)(unsafe.Pointer(&obj)) |
| cachedDecoder.decode(e.word, iter) |
| } |
| |
| func (stream *Stream) WriteVal(val interface{}) { |
| if nil == val { |
| stream.WriteNil() |
| return |
| } |
| typ := reflect.TypeOf(val) |
| cacheKey := typ |
| cachedEncoder := getEncoderFromCache(cacheKey) |
| if cachedEncoder == nil { |
| encoder, err := encoderOfType(cacheKey) |
| if err != nil { |
| stream.Error = err |
| return |
| } |
| cachedEncoder = encoder |
| addEncoderToCache(cacheKey, encoder) |
| } |
| cachedEncoder.encodeInterface(val, stream) |
| } |
| |
| type prefix string |
| |
| func (p prefix) addToDecoder(decoder Decoder, err error) (Decoder, error) { |
| if err != nil { |
| return nil, fmt.Errorf("%s: %s", p, err.Error()) |
| } |
| return decoder, err |
| } |
| |
| func (p prefix) addToEncoder(encoder Encoder, err error) (Encoder, error) { |
| if err != nil { |
| return nil, fmt.Errorf("%s: %s", p, err.Error()) |
| } |
| return encoder, err |
| } |
| |
| func decoderOfType(typ reflect.Type) (Decoder, error) { |
| typeName := typ.String() |
| typeDecoder := typeDecoders[typeName] |
| if typeDecoder != nil { |
| return typeDecoder, nil |
| } |
| if typ.Kind() == reflect.Ptr { |
| typeDecoder := typeDecoders[typ.Elem().String()] |
| if typeDecoder != nil { |
| return &optionalDecoder{typ.Elem(), typeDecoder}, nil |
| } |
| } |
| cacheKey := typ |
| cachedDecoder := getDecoderFromCache(cacheKey) |
| if cachedDecoder != nil { |
| return cachedDecoder, nil |
| } |
| placeholder := &placeholderDecoder{} |
| addDecoderToCache(cacheKey, placeholder) |
| newDecoder, err := createDecoderOfType(typ) |
| placeholder.valueDecoder = newDecoder |
| addDecoderToCache(cacheKey, newDecoder) |
| return newDecoder, err |
| } |
| |
| func createDecoderOfType(typ reflect.Type) (Decoder, error) { |
| if typ.String() == "[]uint8" { |
| return &base64Codec{}, nil |
| } |
| if typ.AssignableTo(jsonRawMessageType) { |
| return &jsonRawMessageCodec{}, nil |
| } |
| if typ.AssignableTo(jsonNumberType) { |
| return &jsonNumberCodec{}, nil |
| } |
| if typ.ConvertibleTo(unmarshalerType) { |
| templateInterface := reflect.New(typ).Elem().Interface() |
| return &optionalDecoder{typ, &unmarshalerDecoder{extractInterface(templateInterface)}}, nil |
| } |
| if typ.ConvertibleTo(anyType) { |
| return &anyCodec{}, nil |
| } |
| switch typ.Kind() { |
| case reflect.String: |
| return &stringCodec{}, nil |
| case reflect.Int: |
| return &intCodec{}, nil |
| case reflect.Int8: |
| return &int8Codec{}, nil |
| case reflect.Int16: |
| return &int16Codec{}, nil |
| case reflect.Int32: |
| return &int32Codec{}, nil |
| case reflect.Int64: |
| return &int64Codec{}, nil |
| case reflect.Uint: |
| return &uintCodec{}, nil |
| case reflect.Uint8: |
| return &uint8Codec{}, nil |
| case reflect.Uint16: |
| return &uint16Codec{}, nil |
| case reflect.Uint32: |
| return &uint32Codec{}, nil |
| case reflect.Uint64: |
| return &uint64Codec{}, nil |
| case reflect.Float32: |
| return &float32Codec{}, nil |
| case reflect.Float64: |
| return &float64Codec{}, nil |
| case reflect.Bool: |
| return &boolCodec{}, nil |
| case reflect.Interface: |
| if typ.NumMethod() == 0 { |
| return &emptyInterfaceCodec{}, nil |
| } else { |
| return &nonEmptyInterfaceCodec{}, nil |
| } |
| case reflect.Struct: |
| return prefix(fmt.Sprintf("[%s]", typ.String())).addToDecoder(decoderOfStruct(typ)) |
| case reflect.Slice: |
| return prefix("[slice]").addToDecoder(decoderOfSlice(typ)) |
| case reflect.Map: |
| return prefix("[map]").addToDecoder(decoderOfMap(typ)) |
| case reflect.Ptr: |
| return prefix("[optional]").addToDecoder(decoderOfOptional(typ)) |
| default: |
| return nil, fmt.Errorf("unsupported type: %v", typ) |
| } |
| } |
| |
| func encoderOfType(typ reflect.Type) (Encoder, error) { |
| typeName := typ.String() |
| typeEncoder := typeEncoders[typeName] |
| if typeEncoder != nil { |
| return typeEncoder, nil |
| } |
| if typ.Kind() == reflect.Ptr { |
| typeEncoder := typeEncoders[typ.Elem().String()] |
| if typeEncoder != nil { |
| return &optionalEncoder{typeEncoder}, nil |
| } |
| } |
| cacheKey := typ |
| cachedEncoder := getEncoderFromCache(cacheKey) |
| if cachedEncoder != nil { |
| return cachedEncoder, nil |
| } |
| placeholder := &placeholderEncoder{} |
| addEncoderToCache(cacheKey, placeholder) |
| newEncoder, err := createEncoderOfType(typ) |
| placeholder.valueEncoder = newEncoder |
| addEncoderToCache(cacheKey, newEncoder) |
| return newEncoder, err |
| } |
| |
| func createEncoderOfType(typ reflect.Type) (Encoder, error) { |
| if typ.String() == "[]uint8" { |
| return &base64Codec{}, nil |
| } |
| if typ.AssignableTo(jsonRawMessageType) { |
| return &jsonRawMessageCodec{}, nil |
| } |
| if typ.AssignableTo(jsonNumberType) { |
| return &jsonNumberCodec{}, nil |
| } |
| if typ.ConvertibleTo(marshalerType) { |
| templateInterface := reflect.New(typ).Elem().Interface() |
| return &marshalerEncoder{extractInterface(templateInterface)}, nil |
| } |
| if typ.ConvertibleTo(anyType) { |
| return &anyCodec{}, nil |
| } |
| kind := typ.Kind() |
| switch kind { |
| case reflect.String: |
| return &stringCodec{}, nil |
| case reflect.Int: |
| return &intCodec{}, nil |
| case reflect.Int8: |
| return &int8Codec{}, nil |
| case reflect.Int16: |
| return &int16Codec{}, nil |
| case reflect.Int32: |
| return &int32Codec{}, nil |
| case reflect.Int64: |
| return &int64Codec{}, nil |
| case reflect.Uint: |
| return &uintCodec{}, nil |
| case reflect.Uint8: |
| return &uint8Codec{}, nil |
| case reflect.Uint16: |
| return &uint16Codec{}, nil |
| case reflect.Uint32: |
| return &uint32Codec{}, nil |
| case reflect.Uint64: |
| return &uint64Codec{}, nil |
| case reflect.Float32: |
| return &float32Codec{}, nil |
| case reflect.Float64: |
| return &float64Codec{}, nil |
| case reflect.Bool: |
| return &boolCodec{}, nil |
| case reflect.Interface: |
| if typ.NumMethod() == 0 { |
| return &emptyInterfaceCodec{}, nil |
| } else { |
| return &nonEmptyInterfaceCodec{}, nil |
| } |
| case reflect.Struct: |
| return prefix(fmt.Sprintf("[%s]", typ.String())).addToEncoder(encoderOfStruct(typ)) |
| case reflect.Slice: |
| return prefix("[slice]").addToEncoder(encoderOfSlice(typ)) |
| case reflect.Map: |
| return prefix("[map]").addToEncoder(encoderOfMap(typ)) |
| case reflect.Ptr: |
| return prefix("[optional]").addToEncoder(encoderOfOptional(typ)) |
| default: |
| return nil, fmt.Errorf("unsupported type: %v", typ) |
| } |
| } |
| |
| func decoderOfOptional(typ reflect.Type) (Decoder, error) { |
| elemType := typ.Elem() |
| decoder, err := decoderOfType(elemType) |
| if err != nil { |
| return nil, err |
| } |
| return &optionalDecoder{elemType, decoder}, nil |
| } |
| |
| func encoderOfOptional(typ reflect.Type) (Encoder, error) { |
| elemType := typ.Elem() |
| decoder, err := encoderOfType(elemType) |
| if err != nil { |
| return nil, err |
| } |
| return &optionalEncoder{decoder}, nil |
| } |
| |
| func decoderOfMap(typ reflect.Type) (Decoder, error) { |
| decoder, err := decoderOfType(typ.Elem()) |
| if err != nil { |
| return nil, err |
| } |
| mapInterface := reflect.New(typ).Interface() |
| return &mapDecoder{typ, typ.Key(), typ.Elem(), decoder, extractInterface(mapInterface)}, nil |
| } |
| |
| func extractInterface(val interface{}) emptyInterface { |
| return *((*emptyInterface)(unsafe.Pointer(&val))) |
| } |
| |
| func encoderOfMap(typ reflect.Type) (Encoder, error) { |
| elemType := typ.Elem() |
| encoder, err := encoderOfType(elemType) |
| if err != nil { |
| return nil, err |
| } |
| mapInterface := reflect.New(typ).Elem().Interface() |
| return &mapEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil |
| } |