You've already forked json-iterator
							
							
				mirror of
				https://github.com/json-iterator/go.git
				synced 2025-10-31 00:07:40 +02:00 
			
		
		
		
	expose OptionalEncoder&OptionalDecoder; add attachment to Stream&Iterator for customized decoder/encoder
This commit is contained in:
		| @@ -1,10 +1,10 @@ | ||||
| package jsoniter | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"reflect" | ||||
| 	"errors" | ||||
| ) | ||||
|  | ||||
| // Any generic object representation. | ||||
|   | ||||
| @@ -77,6 +77,7 @@ type Iterator struct { | ||||
| 	captureStartedAt int | ||||
| 	captured         []byte | ||||
| 	Error            error | ||||
| 	Attachment       interface{} // open for customized decoder | ||||
| } | ||||
|  | ||||
| // NewIterator creates an empty Iterator instance | ||||
|   | ||||
| @@ -28,6 +28,7 @@ func (cfg *frozenConfig) BorrowStream(writer io.Writer) *Stream { | ||||
|  | ||||
| func (cfg *frozenConfig) ReturnStream(stream *Stream) { | ||||
| 	stream.Error = nil | ||||
| 	stream.Attachment = nil | ||||
| 	select { | ||||
| 	case cfg.streamPool <- stream: | ||||
| 		return | ||||
| @@ -48,6 +49,7 @@ func (cfg *frozenConfig) BorrowIterator(data []byte) *Iterator { | ||||
|  | ||||
| func (cfg *frozenConfig) ReturnIterator(iter *Iterator) { | ||||
| 	iter.Error = nil | ||||
| 	iter.Attachment = nil | ||||
| 	select { | ||||
| 	case cfg.iteratorPool <- iter: | ||||
| 		return | ||||
|   | ||||
| @@ -72,24 +72,24 @@ func init() { | ||||
| 	textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() | ||||
| } | ||||
|  | ||||
| type optionalDecoder struct { | ||||
| 	valueType    reflect.Type | ||||
| 	valueDecoder ValDecoder | ||||
| type OptionalDecoder struct { | ||||
| 	ValueType    reflect.Type | ||||
| 	ValueDecoder ValDecoder | ||||
| } | ||||
|  | ||||
| func (decoder *optionalDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { | ||||
| 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) | ||||
| 			value := reflect.New(decoder.ValueType) | ||||
| 			newPtr := extractInterface(value.Interface()).word | ||||
| 			decoder.valueDecoder.Decode(newPtr, iter) | ||||
| 			decoder.ValueDecoder.Decode(newPtr, iter) | ||||
| 			*((*uintptr)(ptr)) = uintptr(newPtr) | ||||
| 		} else { | ||||
| 			//reuse existing instance | ||||
| 			decoder.valueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter) | ||||
| 			decoder.ValueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -113,23 +113,23 @@ func (decoder *deferenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type optionalEncoder struct { | ||||
| 	valueEncoder ValEncoder | ||||
| type OptionalEncoder struct { | ||||
| 	ValueEncoder ValEncoder | ||||
| } | ||||
|  | ||||
| func (encoder *optionalEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { | ||||
| func (encoder *OptionalEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { | ||||
| 	if *((*unsafe.Pointer)(ptr)) == nil { | ||||
| 		stream.WriteNil() | ||||
| 	} else { | ||||
| 		encoder.valueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream) | ||||
| 		encoder.ValueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (encoder *optionalEncoder) EncodeInterface(val interface{}, stream *Stream) { | ||||
| func (encoder *OptionalEncoder) EncodeInterface(val interface{}, stream *Stream) { | ||||
| 	WriteToStream(val, stream, encoder) | ||||
| } | ||||
|  | ||||
| func (encoder *optionalEncoder) IsEmpty(ptr unsafe.Pointer) bool { | ||||
| func (encoder *OptionalEncoder) IsEmpty(ptr unsafe.Pointer) bool { | ||||
| 	return *((*unsafe.Pointer)(ptr)) == nil | ||||
| } | ||||
|  | ||||
| @@ -307,7 +307,7 @@ func createDecoderOfType(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error | ||||
| 		templateInterface := reflect.New(typ).Elem().Interface() | ||||
| 		var decoder ValDecoder = &unmarshalerDecoder{extractInterface(templateInterface)} | ||||
| 		if typ.Kind() == reflect.Ptr { | ||||
| 			decoder = &optionalDecoder{typ.Elem(), decoder} | ||||
| 			decoder = &OptionalDecoder{typ.Elem(), decoder} | ||||
| 		} | ||||
| 		return decoder, nil | ||||
| 	} | ||||
| @@ -320,7 +320,7 @@ func createDecoderOfType(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error | ||||
| 		templateInterface := reflect.New(typ).Elem().Interface() | ||||
| 		var decoder ValDecoder = &textUnmarshalerDecoder{extractInterface(templateInterface)} | ||||
| 		if typ.Kind() == reflect.Ptr { | ||||
| 			decoder = &optionalDecoder{typ.Elem(), decoder} | ||||
| 			decoder = &OptionalDecoder{typ.Elem(), decoder} | ||||
| 		} | ||||
| 		return decoder, nil | ||||
| 	} | ||||
| @@ -480,7 +480,7 @@ func createEncoderOfType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error | ||||
| 			checkIsEmpty:      checkIsEmpty, | ||||
| 		} | ||||
| 		if typ.Kind() == reflect.Ptr { | ||||
| 			encoder = &optionalEncoder{encoder} | ||||
| 			encoder = &OptionalEncoder{encoder} | ||||
| 		} | ||||
| 		return encoder, nil | ||||
| 	} | ||||
| @@ -507,7 +507,7 @@ func createEncoderOfType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error | ||||
| 			checkIsEmpty:      checkIsEmpty, | ||||
| 		} | ||||
| 		if typ.Kind() == reflect.Ptr { | ||||
| 			encoder = &optionalEncoder{encoder} | ||||
| 			encoder = &OptionalEncoder{encoder} | ||||
| 		} | ||||
| 		return encoder, nil | ||||
| 	} | ||||
| @@ -567,7 +567,7 @@ func createCheckIsEmpty(typ reflect.Type) (checkIsEmpty, error) { | ||||
| 	case reflect.Map: | ||||
| 		return &mapEncoder{}, nil | ||||
| 	case reflect.Ptr: | ||||
| 		return &optionalEncoder{}, nil | ||||
| 		return &OptionalEncoder{}, nil | ||||
| 	default: | ||||
| 		return nil, fmt.Errorf("unsupported type: %v", typ) | ||||
| 	} | ||||
| @@ -678,7 +678,7 @@ func decoderOfOptional(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return &optionalDecoder{elemType, decoder}, nil | ||||
| 	return &OptionalDecoder{elemType, decoder}, nil | ||||
| } | ||||
|  | ||||
| func encoderOfOptional(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) { | ||||
| @@ -687,9 +687,9 @@ func encoderOfOptional(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	encoder := &optionalEncoder{elemEncoder} | ||||
| 	encoder := &OptionalEncoder{elemEncoder} | ||||
| 	if elemType.Kind() == reflect.Map { | ||||
| 		encoder = &optionalEncoder{encoder} | ||||
| 		encoder = &OptionalEncoder{encoder} | ||||
| 	} | ||||
| 	return encoder, nil | ||||
| } | ||||
|   | ||||
| @@ -21,7 +21,7 @@ func encoderOfArray(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if typ.Elem().Kind() == reflect.Map { | ||||
| 		encoder = &optionalEncoder{encoder} | ||||
| 		encoder = &OptionalEncoder{encoder} | ||||
| 	} | ||||
| 	return &arrayEncoder{typ, typ.Elem(), encoder}, nil | ||||
| } | ||||
|   | ||||
| @@ -185,7 +185,7 @@ func _getTypeDecoderFromExtension(typ reflect.Type) ValDecoder { | ||||
| 	if typ.Kind() == reflect.Ptr { | ||||
| 		decoder := typeDecoders[typ.Elem().String()] | ||||
| 		if decoder != nil { | ||||
| 			return &optionalDecoder{typ.Elem(), decoder} | ||||
| 			return &OptionalDecoder{typ.Elem(), decoder} | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| @@ -216,7 +216,7 @@ func _getTypeEncoderFromExtension(typ reflect.Type) ValEncoder { | ||||
| 	if typ.Kind() == reflect.Ptr { | ||||
| 		encoder := typeEncoders[typ.Elem().String()] | ||||
| 		if encoder != nil { | ||||
| 			return &optionalEncoder{encoder} | ||||
| 			return &OptionalEncoder{encoder} | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| @@ -254,7 +254,7 @@ func describeStruct(cfg *frozenConfig, typ reflect.Type) (*StructDescriptor, err | ||||
| 				for _, binding := range structDescriptor.Fields { | ||||
| 					binding.levels = append([]int{i}, binding.levels...) | ||||
| 					omitempty := binding.Encoder.(*structFieldEncoder).omitempty | ||||
| 					binding.Encoder = &optionalEncoder{binding.Encoder} | ||||
| 					binding.Encoder = &OptionalEncoder{binding.Encoder} | ||||
| 					binding.Encoder = &structFieldEncoder{&field, binding.Encoder, omitempty} | ||||
| 					binding.Decoder = &deferenceDecoder{field.Type.Elem(), binding.Decoder} | ||||
| 					binding.Decoder = &structFieldDecoder{&field, binding.Decoder} | ||||
|   | ||||
| @@ -21,7 +21,7 @@ func encoderOfSlice(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if typ.Elem().Kind() == reflect.Map { | ||||
| 		encoder = &optionalEncoder{encoder} | ||||
| 		encoder = &OptionalEncoder{encoder} | ||||
| 	} | ||||
| 	return &sliceEncoder{typ, typ.Elem(), encoder}, nil | ||||
| } | ||||
|   | ||||
| @@ -4,15 +4,16 @@ import ( | ||||
| 	"io" | ||||
| ) | ||||
|  | ||||
| // Stream is a io.Writer like object, with JSON specific write functions. | ||||
| // stream is a io.Writer like object, with JSON specific write functions. | ||||
| // Error is not returned as return value, but stored as Error member on this stream instance. | ||||
| type Stream struct { | ||||
| 	cfg       *frozenConfig | ||||
| 	out       io.Writer | ||||
| 	buf       []byte | ||||
| 	n         int | ||||
| 	Error     error | ||||
| 	indention int | ||||
| 	cfg        *frozenConfig | ||||
| 	out        io.Writer | ||||
| 	buf        []byte | ||||
| 	n          int | ||||
| 	Error      error | ||||
| 	indention  int | ||||
| 	Attachment interface{} // open for customized encoder | ||||
| } | ||||
|  | ||||
| // NewStream create new stream instance. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user