소스 검색

fix #207 delay unsupported type error reporting

Tao Wen 8 년 전
부모
커밋
a9b9c73b4d

+ 233 - 357
feature_reflect.go

@@ -72,166 +72,11 @@ func init() {
 	textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
 }
 
-type OptionalDecoder struct {
-	ValueType    reflect.Type
-	ValueDecoder ValDecoder
-}
-
-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)
-			newPtr := extractInterface(value.Interface()).word
-			decoder.ValueDecoder.Decode(newPtr, iter)
-			*((*uintptr)(ptr)) = uintptr(newPtr)
-		} else {
-			//reuse existing instance
-			decoder.ValueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
-		}
-	}
-}
-
-type deferenceDecoder struct {
-	// only to deference a pointer
-	valueType    reflect.Type
-	valueDecoder ValDecoder
-}
-
-func (decoder *deferenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
-	if *((*unsafe.Pointer)(ptr)) == nil {
-		//pointer to null, we have to allocate memory to hold the value
-		value := reflect.New(decoder.valueType)
-		newPtr := extractInterface(value.Interface()).word
-		decoder.valueDecoder.Decode(newPtr, iter)
-		*((*uintptr)(ptr)) = uintptr(newPtr)
-	} else {
-		//reuse existing instance
-		decoder.valueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
-	}
-}
-
-type OptionalEncoder struct {
-	ValueEncoder ValEncoder
-}
-
-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 {
-	return *((*unsafe.Pointer)(ptr)) == nil
-}
-
-type optionalMapEncoder struct {
-	valueEncoder ValEncoder
-}
-
-func (encoder *optionalMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
-	if *((*unsafe.Pointer)(ptr)) == nil {
-		stream.WriteNil()
-	} else {
-		encoder.valueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
-	}
-}
-
-func (encoder *optionalMapEncoder) EncodeInterface(val interface{}, stream *Stream) {
-	WriteToStream(val, stream, encoder)
-}
-
-func (encoder *optionalMapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
-	p := *((*unsafe.Pointer)(ptr))
-	return p == nil || encoder.valueEncoder.IsEmpty(p)
-}
-
-type placeholderEncoder struct {
-	cfg      *frozenConfig
-	cacheKey reflect.Type
-}
-
-func (encoder *placeholderEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
-	encoder.getRealEncoder().Encode(ptr, stream)
-}
-
-func (encoder *placeholderEncoder) EncodeInterface(val interface{}, stream *Stream) {
-	encoder.getRealEncoder().EncodeInterface(val, stream)
-}
-
-func (encoder *placeholderEncoder) IsEmpty(ptr unsafe.Pointer) bool {
-	return encoder.getRealEncoder().IsEmpty(ptr)
-}
-
-func (encoder *placeholderEncoder) getRealEncoder() ValEncoder {
-	for i := 0; i < 500; i++ {
-		realDecoder := encoder.cfg.getEncoderFromCache(encoder.cacheKey)
-		_, isPlaceholder := realDecoder.(*placeholderEncoder)
-		if isPlaceholder {
-			time.Sleep(10 * time.Millisecond)
-		} else {
-			return realDecoder
-		}
-	}
-	panic(fmt.Sprintf("real encoder not found for cache key: %v", encoder.cacheKey))
-}
-
-type placeholderDecoder struct {
-	cfg      *frozenConfig
-	cacheKey reflect.Type
-}
-
-func (decoder *placeholderDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
-	for i := 0; i < 500; i++ {
-		realDecoder := decoder.cfg.getDecoderFromCache(decoder.cacheKey)
-		_, isPlaceholder := realDecoder.(*placeholderDecoder)
-		if isPlaceholder {
-			time.Sleep(10 * time.Millisecond)
-		} else {
-			realDecoder.Decode(ptr, iter)
-			return
-		}
-	}
-	panic(fmt.Sprintf("real decoder not found for cache key: %v", decoder.cacheKey))
-}
-
-// 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
-}
-
 // ReadVal copy the underlying JSON into go interface, same as json.Unmarshal
 func (iter *Iterator) ReadVal(obj interface{}) {
 	typ := reflect.TypeOf(obj)
 	cacheKey := typ.Elem()
-	decoder, err := decoderOfType(iter.cfg, cacheKey)
-	if err != nil {
-		iter.Error = err
-		return
-	}
+	decoder := decoderOfType(iter.cfg, "", cacheKey)
 	e := (*emptyInterface)(unsafe.Pointer(&obj))
 	if e.word == nil {
 		iter.ReportError("ReadVal", "can not read into nil pointer")
@@ -248,44 +93,24 @@ func (stream *Stream) WriteVal(val interface{}) {
 	}
 	typ := reflect.TypeOf(val)
 	cacheKey := typ
-	encoder, err := encoderOfType(stream.cfg, cacheKey)
-	if err != nil {
-		stream.Error = err
-		return
-	}
+	encoder := encoderOfType(stream.cfg, "", cacheKey)
 	encoder.EncodeInterface(val, stream)
 }
 
-type prefix string
-
-func (p prefix) addToDecoder(decoder ValDecoder, err error) (ValDecoder, error) {
-	if err != nil {
-		return nil, fmt.Errorf("%s: %s", p, err.Error())
-	}
-	return decoder, err
-}
-
-func (p prefix) addToEncoder(encoder ValEncoder, err error) (ValEncoder, error) {
-	if err != nil {
-		return nil, fmt.Errorf("%s: %s", p, err.Error())
-	}
-	return encoder, err
-}
-
-func decoderOfType(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
+func decoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
 	cacheKey := typ
 	decoder := cfg.getDecoderFromCache(cacheKey)
 	if decoder != nil {
-		return decoder, nil
+		return decoder
 	}
 	decoder = getTypeDecoderFromExtension(cfg, typ)
 	if decoder != nil {
 		cfg.addDecoderToCache(cacheKey, decoder)
-		return decoder, nil
+		return decoder
 	}
 	decoder = &placeholderDecoder{cfg: cfg, cacheKey: cacheKey}
 	cfg.addDecoderToCache(cacheKey, decoder)
-	decoder, err := createDecoderOfType(cfg, typ)
+	decoder = createDecoderOfType(cfg, prefix, typ)
 	for _, extension := range extensions {
 		decoder = extension.DecorateDecoder(typ, decoder)
 	}
@@ -293,22 +118,22 @@ func decoderOfType(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
 		decoder = extension.DecorateDecoder(typ, decoder)
 	}
 	cfg.addDecoderToCache(cacheKey, decoder)
-	return decoder, err
+	return decoder
 }
 
-func createDecoderOfType(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
+func createDecoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
 	typeName := typ.String()
 	if typ == jsonRawMessageType {
-		return &jsonRawMessageCodec{}, nil
+		return &jsonRawMessageCodec{}
 	}
 	if typ == jsoniterRawMessageType {
-		return &jsoniterRawMessageCodec{}, nil
+		return &jsoniterRawMessageCodec{}
 	}
 	if typ.AssignableTo(jsonNumberType) {
-		return &jsonNumberCodec{}, nil
+		return &jsonNumberCodec{}
 	}
 	if typ.AssignableTo(jsoniterNumberType) {
-		return &jsoniterNumberCodec{}, nil
+		return &jsoniterNumberCodec{}
 	}
 	if typ.Implements(unmarshalerType) {
 		templateInterface := reflect.New(typ).Elem().Interface()
@@ -316,12 +141,12 @@ func createDecoderOfType(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error
 		if typ.Kind() == reflect.Ptr {
 			decoder = &OptionalDecoder{typ.Elem(), decoder}
 		}
-		return decoder, nil
+		return decoder
 	}
 	if reflect.PtrTo(typ).Implements(unmarshalerType) {
 		templateInterface := reflect.New(typ).Interface()
 		var decoder ValDecoder = &unmarshalerDecoder{extractInterface(templateInterface)}
-		return decoder, nil
+		return decoder
 	}
 	if typ.Implements(textUnmarshalerType) {
 		templateInterface := reflect.New(typ).Elem().Interface()
@@ -329,133 +154,130 @@ func createDecoderOfType(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error
 		if typ.Kind() == reflect.Ptr {
 			decoder = &OptionalDecoder{typ.Elem(), decoder}
 		}
-		return decoder, nil
+		return decoder
 	}
 	if reflect.PtrTo(typ).Implements(textUnmarshalerType) {
 		templateInterface := reflect.New(typ).Interface()
 		var decoder ValDecoder = &textUnmarshalerDecoder{extractInterface(templateInterface)}
-		return decoder, nil
+		return decoder
 	}
 	if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
-		sliceDecoder, err := prefix("[slice]").addToDecoder(decoderOfSlice(cfg, typ))
-		if err != nil {
-			return nil, err
-		}
-		return &base64Codec{sliceDecoder: sliceDecoder}, nil
+		sliceDecoder := decoderOfSlice(cfg, prefix, typ)
+		return &base64Codec{sliceDecoder: sliceDecoder}
 	}
 	if typ.Implements(anyType) {
-		return &anyCodec{}, nil
+		return &anyCodec{}
 	}
 	switch typ.Kind() {
 	case reflect.String:
 		if typeName != "string" {
-			return decoderOfType(cfg, reflect.TypeOf((*string)(nil)).Elem())
+			return decoderOfType(cfg, prefix, reflect.TypeOf((*string)(nil)).Elem())
 		}
-		return &stringCodec{}, nil
+		return &stringCodec{}
 	case reflect.Int:
 		if typeName != "int" {
-			return decoderOfType(cfg, reflect.TypeOf((*int)(nil)).Elem())
+			return decoderOfType(cfg, prefix, reflect.TypeOf((*int)(nil)).Elem())
 		}
-		return &intCodec{}, nil
+		return &intCodec{}
 	case reflect.Int8:
 		if typeName != "int8" {
-			return decoderOfType(cfg, reflect.TypeOf((*int8)(nil)).Elem())
+			return decoderOfType(cfg, prefix, reflect.TypeOf((*int8)(nil)).Elem())
 		}
-		return &int8Codec{}, nil
+		return &int8Codec{}
 	case reflect.Int16:
 		if typeName != "int16" {
-			return decoderOfType(cfg, reflect.TypeOf((*int16)(nil)).Elem())
+			return decoderOfType(cfg, prefix, reflect.TypeOf((*int16)(nil)).Elem())
 		}
-		return &int16Codec{}, nil
+		return &int16Codec{}
 	case reflect.Int32:
 		if typeName != "int32" {
-			return decoderOfType(cfg, reflect.TypeOf((*int32)(nil)).Elem())
+			return decoderOfType(cfg, prefix, reflect.TypeOf((*int32)(nil)).Elem())
 		}
-		return &int32Codec{}, nil
+		return &int32Codec{}
 	case reflect.Int64:
 		if typeName != "int64" {
-			return decoderOfType(cfg, reflect.TypeOf((*int64)(nil)).Elem())
+			return decoderOfType(cfg, prefix, reflect.TypeOf((*int64)(nil)).Elem())
 		}
-		return &int64Codec{}, nil
+		return &int64Codec{}
 	case reflect.Uint:
 		if typeName != "uint" {
-			return decoderOfType(cfg, reflect.TypeOf((*uint)(nil)).Elem())
+			return decoderOfType(cfg, prefix, reflect.TypeOf((*uint)(nil)).Elem())
 		}
-		return &uintCodec{}, nil
+		return &uintCodec{}
 	case reflect.Uint8:
 		if typeName != "uint8" {
-			return decoderOfType(cfg, reflect.TypeOf((*uint8)(nil)).Elem())
+			return decoderOfType(cfg, prefix, reflect.TypeOf((*uint8)(nil)).Elem())
 		}
-		return &uint8Codec{}, nil
+		return &uint8Codec{}
 	case reflect.Uint16:
 		if typeName != "uint16" {
-			return decoderOfType(cfg, reflect.TypeOf((*uint16)(nil)).Elem())
+			return decoderOfType(cfg, prefix, reflect.TypeOf((*uint16)(nil)).Elem())
 		}
-		return &uint16Codec{}, nil
+		return &uint16Codec{}
 	case reflect.Uint32:
 		if typeName != "uint32" {
-			return decoderOfType(cfg, reflect.TypeOf((*uint32)(nil)).Elem())
+			return decoderOfType(cfg, prefix, reflect.TypeOf((*uint32)(nil)).Elem())
 		}
-		return &uint32Codec{}, nil
+		return &uint32Codec{}
 	case reflect.Uintptr:
 		if typeName != "uintptr" {
-			return decoderOfType(cfg, reflect.TypeOf((*uintptr)(nil)).Elem())
+			return decoderOfType(cfg, prefix, reflect.TypeOf((*uintptr)(nil)).Elem())
 		}
-		return &uintptrCodec{}, nil
+		return &uintptrCodec{}
 	case reflect.Uint64:
 		if typeName != "uint64" {
-			return decoderOfType(cfg, reflect.TypeOf((*uint64)(nil)).Elem())
+			return decoderOfType(cfg, prefix, reflect.TypeOf((*uint64)(nil)).Elem())
 		}
-		return &uint64Codec{}, nil
+		return &uint64Codec{}
 	case reflect.Float32:
 		if typeName != "float32" {
-			return decoderOfType(cfg, reflect.TypeOf((*float32)(nil)).Elem())
+			return decoderOfType(cfg, prefix, reflect.TypeOf((*float32)(nil)).Elem())
 		}
-		return &float32Codec{}, nil
+		return &float32Codec{}
 	case reflect.Float64:
 		if typeName != "float64" {
-			return decoderOfType(cfg, reflect.TypeOf((*float64)(nil)).Elem())
+			return decoderOfType(cfg, prefix, reflect.TypeOf((*float64)(nil)).Elem())
 		}
-		return &float64Codec{}, nil
+		return &float64Codec{}
 	case reflect.Bool:
 		if typeName != "bool" {
-			return decoderOfType(cfg, reflect.TypeOf((*bool)(nil)).Elem())
+			return decoderOfType(cfg, prefix, reflect.TypeOf((*bool)(nil)).Elem())
 		}
-		return &boolCodec{}, nil
+		return &boolCodec{}
 	case reflect.Interface:
 		if typ.NumMethod() == 0 {
-			return &emptyInterfaceCodec{}, nil
+			return &emptyInterfaceCodec{}
 		}
-		return &nonEmptyInterfaceCodec{}, nil
+		return &nonEmptyInterfaceCodec{}
 	case reflect.Struct:
-		return prefix(fmt.Sprintf("[%s]", typeName)).addToDecoder(decoderOfStruct(cfg, typ))
+		return decoderOfStruct(cfg, prefix, typ)
 	case reflect.Array:
-		return prefix("[array]").addToDecoder(decoderOfArray(cfg, typ))
+		return decoderOfArray(cfg, prefix, typ)
 	case reflect.Slice:
-		return prefix("[slice]").addToDecoder(decoderOfSlice(cfg, typ))
+		return decoderOfSlice(cfg, prefix, typ)
 	case reflect.Map:
-		return prefix("[map]").addToDecoder(decoderOfMap(cfg, typ))
+		return decoderOfMap(cfg, prefix, typ)
 	case reflect.Ptr:
-		return prefix("[optional]").addToDecoder(decoderOfOptional(cfg, typ))
+		return decoderOfOptional(cfg, prefix, typ)
 	default:
-		return nil, fmt.Errorf("unsupported type: %v", typ)
+		return &lazyErrorDecoder{err: fmt.Errorf("%s%s is unsupported type", prefix, typ.String())}
 	}
 }
 
-func encoderOfType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
+func encoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
 	cacheKey := typ
 	encoder := cfg.getEncoderFromCache(cacheKey)
 	if encoder != nil {
-		return encoder, nil
+		return encoder
 	}
 	encoder = getTypeEncoderFromExtension(cfg, typ)
 	if encoder != nil {
 		cfg.addEncoderToCache(cacheKey, encoder)
-		return encoder, nil
+		return encoder
 	}
 	encoder = &placeholderEncoder{cfg: cfg, cacheKey: cacheKey}
 	cfg.addEncoderToCache(cacheKey, encoder)
-	encoder, err := createEncoderOfType(cfg, typ)
+	encoder = createEncoderOfType(cfg, prefix, typ)
 	for _, extension := range extensions {
 		encoder = extension.DecorateEncoder(typ, encoder)
 	}
@@ -463,27 +285,24 @@ func encoderOfType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
 		encoder = extension.DecorateEncoder(typ, encoder)
 	}
 	cfg.addEncoderToCache(cacheKey, encoder)
-	return encoder, err
+	return encoder
 }
 
-func createEncoderOfType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
+func createEncoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
 	if typ == jsonRawMessageType {
-		return &jsonRawMessageCodec{}, nil
+		return &jsonRawMessageCodec{}
 	}
 	if typ == jsoniterRawMessageType {
-		return &jsoniterRawMessageCodec{}, nil
+		return &jsoniterRawMessageCodec{}
 	}
 	if typ.AssignableTo(jsonNumberType) {
-		return &jsonNumberCodec{}, nil
+		return &jsonNumberCodec{}
 	}
 	if typ.AssignableTo(jsoniterNumberType) {
-		return &jsoniterNumberCodec{}, nil
+		return &jsoniterNumberCodec{}
 	}
 	if typ.Implements(marshalerType) {
-		checkIsEmpty, err := createCheckIsEmpty(cfg, typ)
-		if err != nil {
-			return nil, err
-		}
+		checkIsEmpty := createCheckIsEmpty(cfg, typ)
 		templateInterface := reflect.New(typ).Elem().Interface()
 		var encoder ValEncoder = &marshalerEncoder{
 			templateInterface: extractInterface(templateInterface),
@@ -492,25 +311,19 @@ func createEncoderOfType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error
 		if typ.Kind() == reflect.Ptr {
 			encoder = &OptionalEncoder{encoder}
 		}
-		return encoder, nil
+		return encoder
 	}
 	if reflect.PtrTo(typ).Implements(marshalerType) {
-		checkIsEmpty, err := createCheckIsEmpty(cfg, reflect.PtrTo(typ))
-		if err != nil {
-			return nil, err
-		}
+		checkIsEmpty := createCheckIsEmpty(cfg, reflect.PtrTo(typ))
 		templateInterface := reflect.New(typ).Interface()
 		var encoder ValEncoder = &marshalerEncoder{
 			templateInterface: extractInterface(templateInterface),
 			checkIsEmpty:      checkIsEmpty,
 		}
-		return encoder, nil
+		return encoder
 	}
 	if typ.Implements(textMarshalerType) {
-		checkIsEmpty, err := createCheckIsEmpty(cfg, typ)
-		if err != nil {
-			return nil, err
-		}
+		checkIsEmpty := createCheckIsEmpty(cfg, typ)
 		templateInterface := reflect.New(typ).Elem().Interface()
 		var encoder ValEncoder = &textMarshalerEncoder{
 			templateInterface: extractInterface(templateInterface),
@@ -519,213 +332,276 @@ func createEncoderOfType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error
 		if typ.Kind() == reflect.Ptr {
 			encoder = &OptionalEncoder{encoder}
 		}
-		return encoder, nil
+		return encoder
 	}
 	if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
-		return &base64Codec{}, nil
+		return &base64Codec{}
 	}
 	if typ.Implements(anyType) {
-		return &anyCodec{}, nil
+		return &anyCodec{}
 	}
-	return createEncoderOfSimpleType(cfg, typ)
+	return createEncoderOfSimpleType(cfg, prefix, typ)
 }
 
-func createCheckIsEmpty(cfg *frozenConfig, typ reflect.Type) (checkIsEmpty, error) {
+func createCheckIsEmpty(cfg *frozenConfig, typ reflect.Type) checkIsEmpty {
 	kind := typ.Kind()
 	switch kind {
 	case reflect.String:
-		return &stringCodec{}, nil
+		return &stringCodec{}
 	case reflect.Int:
-		return &intCodec{}, nil
+		return &intCodec{}
 	case reflect.Int8:
-		return &int8Codec{}, nil
+		return &int8Codec{}
 	case reflect.Int16:
-		return &int16Codec{}, nil
+		return &int16Codec{}
 	case reflect.Int32:
-		return &int32Codec{}, nil
+		return &int32Codec{}
 	case reflect.Int64:
-		return &int64Codec{}, nil
+		return &int64Codec{}
 	case reflect.Uint:
-		return &uintCodec{}, nil
+		return &uintCodec{}
 	case reflect.Uint8:
-		return &uint8Codec{}, nil
+		return &uint8Codec{}
 	case reflect.Uint16:
-		return &uint16Codec{}, nil
+		return &uint16Codec{}
 	case reflect.Uint32:
-		return &uint32Codec{}, nil
+		return &uint32Codec{}
 	case reflect.Uintptr:
-		return &uintptrCodec{}, nil
+		return &uintptrCodec{}
 	case reflect.Uint64:
-		return &uint64Codec{}, nil
+		return &uint64Codec{}
 	case reflect.Float32:
-		return &float32Codec{}, nil
+		return &float32Codec{}
 	case reflect.Float64:
-		return &float64Codec{}, nil
+		return &float64Codec{}
 	case reflect.Bool:
-		return &boolCodec{}, nil
+		return &boolCodec{}
 	case reflect.Interface:
 		if typ.NumMethod() == 0 {
-			return &emptyInterfaceCodec{}, nil
+			return &emptyInterfaceCodec{}
 		}
-		return &nonEmptyInterfaceCodec{}, nil
+		return &nonEmptyInterfaceCodec{}
 	case reflect.Struct:
-		return &structEncoder{}, nil
+		return &structEncoder{typ: typ}
 	case reflect.Array:
-		return &arrayEncoder{}, nil
+		return &arrayEncoder{}
 	case reflect.Slice:
-		return &sliceEncoder{}, nil
+		return &sliceEncoder{}
 	case reflect.Map:
-		return encoderOfMap(cfg, typ)
+		return encoderOfMap(cfg, "", typ)
 	case reflect.Ptr:
-		return &OptionalEncoder{}, nil
+		return &OptionalEncoder{}
 	default:
-		return nil, fmt.Errorf("unsupported type: %v", typ)
+		return &lazyErrorEncoder{err: fmt.Errorf("unsupported type: %v", typ)}
 	}
 }
 
-func createEncoderOfSimpleType(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
+func createEncoderOfSimpleType(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
 	typeName := typ.String()
 	kind := typ.Kind()
 	switch kind {
 	case reflect.String:
 		if typeName != "string" {
-			return encoderOfType(cfg, reflect.TypeOf((*string)(nil)).Elem())
+			return encoderOfType(cfg, prefix, reflect.TypeOf((*string)(nil)).Elem())
 		}
-		return &stringCodec{}, nil
+		return &stringCodec{}
 	case reflect.Int:
 		if typeName != "int" {
-			return encoderOfType(cfg, reflect.TypeOf((*int)(nil)).Elem())
+			return encoderOfType(cfg, prefix, reflect.TypeOf((*int)(nil)).Elem())
 		}
-		return &intCodec{}, nil
+		return &intCodec{}
 	case reflect.Int8:
 		if typeName != "int8" {
-			return encoderOfType(cfg, reflect.TypeOf((*int8)(nil)).Elem())
+			return encoderOfType(cfg, prefix, reflect.TypeOf((*int8)(nil)).Elem())
 		}
-		return &int8Codec{}, nil
+		return &int8Codec{}
 	case reflect.Int16:
 		if typeName != "int16" {
-			return encoderOfType(cfg, reflect.TypeOf((*int16)(nil)).Elem())
+			return encoderOfType(cfg, prefix, reflect.TypeOf((*int16)(nil)).Elem())
 		}
-		return &int16Codec{}, nil
+		return &int16Codec{}
 	case reflect.Int32:
 		if typeName != "int32" {
-			return encoderOfType(cfg, reflect.TypeOf((*int32)(nil)).Elem())
+			return encoderOfType(cfg, prefix, reflect.TypeOf((*int32)(nil)).Elem())
 		}
-		return &int32Codec{}, nil
+		return &int32Codec{}
 	case reflect.Int64:
 		if typeName != "int64" {
-			return encoderOfType(cfg, reflect.TypeOf((*int64)(nil)).Elem())
+			return encoderOfType(cfg, prefix, reflect.TypeOf((*int64)(nil)).Elem())
 		}
-		return &int64Codec{}, nil
+		return &int64Codec{}
 	case reflect.Uint:
 		if typeName != "uint" {
-			return encoderOfType(cfg, reflect.TypeOf((*uint)(nil)).Elem())
+			return encoderOfType(cfg, prefix, reflect.TypeOf((*uint)(nil)).Elem())
 		}
-		return &uintCodec{}, nil
+		return &uintCodec{}
 	case reflect.Uint8:
 		if typeName != "uint8" {
-			return encoderOfType(cfg, reflect.TypeOf((*uint8)(nil)).Elem())
+			return encoderOfType(cfg, prefix, reflect.TypeOf((*uint8)(nil)).Elem())
 		}
-		return &uint8Codec{}, nil
+		return &uint8Codec{}
 	case reflect.Uint16:
 		if typeName != "uint16" {
-			return encoderOfType(cfg, reflect.TypeOf((*uint16)(nil)).Elem())
+			return encoderOfType(cfg, prefix, reflect.TypeOf((*uint16)(nil)).Elem())
 		}
-		return &uint16Codec{}, nil
+		return &uint16Codec{}
 	case reflect.Uint32:
 		if typeName != "uint32" {
-			return encoderOfType(cfg, reflect.TypeOf((*uint32)(nil)).Elem())
+			return encoderOfType(cfg, prefix, reflect.TypeOf((*uint32)(nil)).Elem())
 		}
-		return &uint32Codec{}, nil
+		return &uint32Codec{}
 	case reflect.Uintptr:
 		if typeName != "uintptr" {
-			return encoderOfType(cfg, reflect.TypeOf((*uintptr)(nil)).Elem())
+			return encoderOfType(cfg, prefix, reflect.TypeOf((*uintptr)(nil)).Elem())
 		}
-		return &uintptrCodec{}, nil
+		return &uintptrCodec{}
 	case reflect.Uint64:
 		if typeName != "uint64" {
-			return encoderOfType(cfg, reflect.TypeOf((*uint64)(nil)).Elem())
+			return encoderOfType(cfg, prefix, reflect.TypeOf((*uint64)(nil)).Elem())
 		}
-		return &uint64Codec{}, nil
+		return &uint64Codec{}
 	case reflect.Float32:
 		if typeName != "float32" {
-			return encoderOfType(cfg, reflect.TypeOf((*float32)(nil)).Elem())
+			return encoderOfType(cfg, prefix, reflect.TypeOf((*float32)(nil)).Elem())
 		}
-		return &float32Codec{}, nil
+		return &float32Codec{}
 	case reflect.Float64:
 		if typeName != "float64" {
-			return encoderOfType(cfg, reflect.TypeOf((*float64)(nil)).Elem())
+			return encoderOfType(cfg, prefix, reflect.TypeOf((*float64)(nil)).Elem())
 		}
-		return &float64Codec{}, nil
+		return &float64Codec{}
 	case reflect.Bool:
 		if typeName != "bool" {
-			return encoderOfType(cfg, reflect.TypeOf((*bool)(nil)).Elem())
+			return encoderOfType(cfg, prefix, reflect.TypeOf((*bool)(nil)).Elem())
 		}
-		return &boolCodec{}, nil
+		return &boolCodec{}
 	case reflect.Interface:
 		if typ.NumMethod() == 0 {
-			return &emptyInterfaceCodec{}, nil
+			return &emptyInterfaceCodec{}
 		}
-		return &nonEmptyInterfaceCodec{}, nil
+		return &nonEmptyInterfaceCodec{}
 	case reflect.Struct:
-		return prefix(fmt.Sprintf("[%s]", typeName)).addToEncoder(encoderOfStruct(cfg, typ))
+		return encoderOfStruct(cfg, prefix, typ)
 	case reflect.Array:
-		return prefix("[array]").addToEncoder(encoderOfArray(cfg, typ))
+		return encoderOfArray(cfg, prefix, typ)
 	case reflect.Slice:
-		return prefix("[slice]").addToEncoder(encoderOfSlice(cfg, typ))
+		return encoderOfSlice(cfg, prefix, typ)
 	case reflect.Map:
-		return prefix("[map]").addToEncoder(encoderOfMap(cfg, typ))
+		return encoderOfMap(cfg, prefix, typ)
 	case reflect.Ptr:
-		return prefix("[optional]").addToEncoder(encoderOfOptional(cfg, typ))
+		return encoderOfOptional(cfg, prefix, typ)
 	default:
-		return nil, fmt.Errorf("unsupported type: %v", typ)
+		return &lazyErrorEncoder{err: fmt.Errorf("%s%s is unsupported type", prefix, typ.String())}
+	}
+}
+
+type placeholderEncoder struct {
+	cfg      *frozenConfig
+	cacheKey reflect.Type
+}
+
+func (encoder *placeholderEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
+	encoder.getRealEncoder().Encode(ptr, stream)
+}
+
+func (encoder *placeholderEncoder) EncodeInterface(val interface{}, stream *Stream) {
+	encoder.getRealEncoder().EncodeInterface(val, stream)
+}
+
+func (encoder *placeholderEncoder) IsEmpty(ptr unsafe.Pointer) bool {
+	return encoder.getRealEncoder().IsEmpty(ptr)
+}
+
+func (encoder *placeholderEncoder) getRealEncoder() ValEncoder {
+	for i := 0; i < 500; i++ {
+		realDecoder := encoder.cfg.getEncoderFromCache(encoder.cacheKey)
+		_, isPlaceholder := realDecoder.(*placeholderEncoder)
+		if isPlaceholder {
+			time.Sleep(10 * time.Millisecond)
+		} else {
+			return realDecoder
+		}
 	}
+	panic(fmt.Sprintf("real encoder not found for cache key: %v", encoder.cacheKey))
 }
 
-func decoderOfOptional(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
-	elemType := typ.Elem()
-	decoder, err := decoderOfType(cfg, elemType)
-	if err != nil {
-		return nil, err
+type placeholderDecoder struct {
+	cfg      *frozenConfig
+	cacheKey reflect.Type
+}
+
+func (decoder *placeholderDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
+	for i := 0; i < 500; i++ {
+		realDecoder := decoder.cfg.getDecoderFromCache(decoder.cacheKey)
+		_, isPlaceholder := realDecoder.(*placeholderDecoder)
+		if isPlaceholder {
+			time.Sleep(10 * time.Millisecond)
+		} else {
+			realDecoder.Decode(ptr, iter)
+			return
+		}
 	}
-	return &OptionalDecoder{elemType, decoder}, nil
+	panic(fmt.Sprintf("real decoder not found for cache key: %v", decoder.cacheKey))
 }
 
-func encoderOfOptional(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
-	elemType := typ.Elem()
-	elemEncoder, err := encoderOfType(cfg, elemType)
-	if err != nil {
-		return nil, err
+type lazyErrorDecoder struct {
+	err error
+}
+
+func (decoder *lazyErrorDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
+	if iter.WhatIsNext() != NilValue {
+		if iter.Error == nil {
+			iter.Error = decoder.err
+		}
+	} else {
+		iter.Skip()
 	}
-	encoder := &OptionalEncoder{elemEncoder}
-	if elemType.Kind() == reflect.Map {
-		encoder = &OptionalEncoder{encoder}
+}
+
+type lazyErrorEncoder struct {
+	err error
+}
+
+func (encoder *lazyErrorEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
+	if ptr == nil {
+		stream.WriteNil()
+	} else if stream.Error == nil {
+		stream.Error = encoder.err
 	}
-	return encoder, nil
 }
 
-func decoderOfMap(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
-	decoder, err := decoderOfType(cfg, typ.Elem())
-	if err != nil {
-		return nil, err
+func (encoder *lazyErrorEncoder) EncodeInterface(val interface{}, stream *Stream) {
+	if val == nil {
+		stream.WriteNil()
+	} else if stream.Error == nil {
+		stream.Error = encoder.err
 	}
-	mapInterface := reflect.New(typ).Interface()
-	return &mapDecoder{typ, typ.Key(), typ.Elem(), decoder, extractInterface(mapInterface)}, nil
+}
+
+func (encoder *lazyErrorEncoder) IsEmpty(ptr unsafe.Pointer) bool {
+	return false
 }
 
 func extractInterface(val interface{}) emptyInterface {
 	return *((*emptyInterface)(unsafe.Pointer(&val)))
 }
 
-func encoderOfMap(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
-	elemType := typ.Elem()
-	encoder, err := encoderOfType(cfg, elemType)
-	if err != nil {
-		return nil, err
-	}
-	mapInterface := reflect.New(typ).Elem().Interface()
-	if cfg.sortMapKeys {
-		return &sortKeysMapEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil
+// 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
 	}
-	return &mapEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}, nil
+	word unsafe.Pointer
 }

+ 6 - 12
feature_reflect_array.go

@@ -7,23 +7,17 @@ import (
 	"unsafe"
 )
 
-func decoderOfArray(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
-	decoder, err := decoderOfType(cfg, typ.Elem())
-	if err != nil {
-		return nil, err
-	}
-	return &arrayDecoder{typ, typ.Elem(), decoder}, nil
+func decoderOfArray(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
+	decoder := decoderOfType(cfg, prefix+"[array]->", typ.Elem())
+	return &arrayDecoder{typ, typ.Elem(), decoder}
 }
 
-func encoderOfArray(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
-	encoder, err := encoderOfType(cfg, typ.Elem())
-	if err != nil {
-		return nil, err
-	}
+func encoderOfArray(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
+	encoder := encoderOfType(cfg, prefix+"[array]->", typ.Elem())
 	if typ.Elem().Kind() == reflect.Map {
 		encoder = &OptionalEncoder{encoder}
 	}
-	return &arrayEncoder{typ, typ.Elem(), encoder}, nil
+	return &arrayEncoder{typ, typ.Elem(), encoder}
 }
 
 type arrayEncoder struct {

+ 6 - 20
feature_reflect_extension.go

@@ -240,7 +240,7 @@ func _getTypeEncoderFromExtension(cfg *frozenConfig, typ reflect.Type) ValEncode
 	return nil
 }
 
-func describeStruct(cfg *frozenConfig, typ reflect.Type) (*StructDescriptor, error) {
+func describeStruct(cfg *frozenConfig, prefix string, typ reflect.Type) *StructDescriptor {
 	embeddedBindings := []*Binding{}
 	bindings := []*Binding{}
 	for i := 0; i < typ.NumField(); i++ {
@@ -252,10 +252,7 @@ func describeStruct(cfg *frozenConfig, typ reflect.Type) (*StructDescriptor, err
 		}
 		if field.Anonymous && (tag == "" || tagParts[0] == "") {
 			if field.Type.Kind() == reflect.Struct {
-				structDescriptor, err := describeStruct(cfg, field.Type)
-				if err != nil {
-					return nil, err
-				}
+				structDescriptor := describeStruct(cfg, prefix, field.Type)
 				for _, binding := range structDescriptor.Fields {
 					binding.levels = append([]int{i}, binding.levels...)
 					omitempty := binding.Encoder.(*structFieldEncoder).omitempty
@@ -265,10 +262,7 @@ func describeStruct(cfg *frozenConfig, typ reflect.Type) (*StructDescriptor, err
 				}
 				continue
 			} else if field.Type.Kind() == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct {
-				structDescriptor, err := describeStruct(cfg, field.Type.Elem())
-				if err != nil {
-					return nil, err
-				}
+				structDescriptor := describeStruct(cfg, prefix, field.Type.Elem())
 				for _, binding := range structDescriptor.Fields {
 					binding.levels = append([]int{i}, binding.levels...)
 					omitempty := binding.Encoder.(*structFieldEncoder).omitempty
@@ -285,19 +279,11 @@ func describeStruct(cfg *frozenConfig, typ reflect.Type) (*StructDescriptor, err
 		fieldCacheKey := fmt.Sprintf("%s/%s", typ.String(), field.Name)
 		decoder := fieldDecoders[fieldCacheKey]
 		if decoder == nil {
-			var err error
-			decoder, err = decoderOfType(cfg, field.Type)
-			if len(fieldNames) > 0 && err != nil {
-				return nil, err
-			}
+			decoder = decoderOfType(cfg, prefix+typ.String()+"."+field.Name+"->", field.Type)
 		}
 		encoder := fieldEncoders[fieldCacheKey]
 		if encoder == nil {
-			var err error
-			encoder, err = encoderOfType(cfg, field.Type)
-			if len(fieldNames) > 0 && err != nil {
-				return nil, err
-			}
+			encoder = encoderOfType(cfg, prefix+typ.String()+"."+field.Name+"->", field.Type)
 			// map is stored as pointer in the struct,
 			// and treat nil or empty map as empty field
 			if encoder != nil && field.Type.Kind() == reflect.Map {
@@ -314,7 +300,7 @@ func describeStruct(cfg *frozenConfig, typ reflect.Type) (*StructDescriptor, err
 		binding.levels = []int{i}
 		bindings = append(bindings, binding)
 	}
-	return createStructDescriptor(cfg, typ, bindings, embeddedBindings), nil
+	return createStructDescriptor(cfg, typ, bindings, embeddedBindings)
 }
 func createStructDescriptor(cfg *frozenConfig, typ reflect.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor {
 	onePtrEmbedded := false

+ 16 - 0
feature_reflect_map.go

@@ -9,6 +9,22 @@ import (
 	"unsafe"
 )
 
+func decoderOfMap(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
+	decoder := decoderOfType(cfg, prefix+"[map]->", typ.Elem())
+	mapInterface := reflect.New(typ).Interface()
+	return &mapDecoder{typ, typ.Key(), typ.Elem(), decoder, extractInterface(mapInterface)}
+}
+
+func encoderOfMap(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
+	elemType := typ.Elem()
+	encoder := encoderOfType(cfg, prefix+"[map]->", elemType)
+	mapInterface := reflect.New(typ).Elem().Interface()
+	if cfg.sortMapKeys {
+		return &sortKeysMapEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}
+	}
+	return &mapEncoder{typ, elemType, encoder, *((*emptyInterface)(unsafe.Pointer(&mapInterface)))}
+}
+
 type mapDecoder struct {
 	mapType      reflect.Type
 	keyType      reflect.Type

+ 11 - 12
feature_reflect_object.go

@@ -8,17 +8,14 @@ import (
 	"unsafe"
 )
 
-func encoderOfStruct(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
+func encoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
 	type bindingTo struct {
 		binding *Binding
 		toName  string
 		ignored bool
 	}
 	orderedBindings := []*bindingTo{}
-	structDescriptor, err := describeStruct(cfg, typ)
-	if err != nil {
-		return nil, err
-	}
+	structDescriptor := describeStruct(cfg, prefix, typ)
 	for _, binding := range structDescriptor.Fields {
 		for _, toName := range binding.ToNames {
 			new := &bindingTo{
@@ -35,7 +32,7 @@ func encoderOfStruct(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
 		}
 	}
 	if len(orderedBindings) == 0 {
-		return &emptyStructEncoder{}, nil
+		return &emptyStructEncoder{}
 	}
 	finalOrderedFields := []structFieldTo{}
 	for _, bindingTo := range orderedBindings {
@@ -46,7 +43,8 @@ func encoderOfStruct(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
 			})
 		}
 	}
-	return &structEncoder{structDescriptor.onePtrEmbedded, structDescriptor.onePtrOptimization, finalOrderedFields}, nil
+	return &structEncoder{typ, structDescriptor.onePtrEmbedded,
+		structDescriptor.onePtrOptimization, finalOrderedFields}
 }
 
 func resolveConflictBinding(cfg *frozenConfig, old, new *Binding) (ignoreOld, ignoreNew bool) {
@@ -78,12 +76,9 @@ func resolveConflictBinding(cfg *frozenConfig, old, new *Binding) (ignoreOld, ig
 	}
 }
 
-func decoderOfStruct(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
+func decoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
 	bindings := map[string]*Binding{}
-	structDescriptor, err := describeStruct(cfg, typ)
-	if err != nil {
-		return nil, err
-	}
+	structDescriptor := describeStruct(cfg, prefix, typ)
 	for _, binding := range structDescriptor.Fields {
 		for _, fromName := range binding.FromNames {
 			old := bindings[fromName]
@@ -131,6 +126,7 @@ func (encoder *structFieldEncoder) IsEmpty(ptr unsafe.Pointer) bool {
 }
 
 type structEncoder struct {
+	typ                reflect.Type
 	onePtrEmbedded     bool
 	onePtrOptimization bool
 	fields             []structFieldTo
@@ -156,6 +152,9 @@ func (encoder *structEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
 		isNotFirst = true
 	}
 	stream.WriteObjectEnd()
+	if stream.Error != nil && stream.Error != io.EOF {
+		stream.Error = fmt.Errorf("%v.%s", encoder.typ, stream.Error.Error())
+	}
 }
 
 func (encoder *structEncoder) EncodeInterface(val interface{}, stream *Stream) {

+ 104 - 0
feature_reflect_optional.go

@@ -0,0 +1,104 @@
+package jsoniter
+
+import (
+	"reflect"
+	"unsafe"
+)
+
+func decoderOfOptional(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
+	elemType := typ.Elem()
+	decoder := decoderOfType(cfg, prefix, elemType)
+	return &OptionalDecoder{elemType, decoder}
+}
+
+func encoderOfOptional(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
+	elemType := typ.Elem()
+	elemEncoder := encoderOfType(cfg, prefix, elemType)
+	encoder := &OptionalEncoder{elemEncoder}
+	if elemType.Kind() == reflect.Map {
+		encoder = &OptionalEncoder{encoder}
+	}
+	return encoder
+}
+
+type OptionalDecoder struct {
+	ValueType    reflect.Type
+	ValueDecoder ValDecoder
+}
+
+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)
+			newPtr := extractInterface(value.Interface()).word
+			decoder.ValueDecoder.Decode(newPtr, iter)
+			*((*uintptr)(ptr)) = uintptr(newPtr)
+		} else {
+			//reuse existing instance
+			decoder.ValueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
+		}
+	}
+}
+
+type deferenceDecoder struct {
+	// only to deference a pointer
+	valueType    reflect.Type
+	valueDecoder ValDecoder
+}
+
+func (decoder *deferenceDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
+	if *((*unsafe.Pointer)(ptr)) == nil {
+		//pointer to null, we have to allocate memory to hold the value
+		value := reflect.New(decoder.valueType)
+		newPtr := extractInterface(value.Interface()).word
+		decoder.valueDecoder.Decode(newPtr, iter)
+		*((*uintptr)(ptr)) = uintptr(newPtr)
+	} else {
+		//reuse existing instance
+		decoder.valueDecoder.Decode(*((*unsafe.Pointer)(ptr)), iter)
+	}
+}
+
+type OptionalEncoder struct {
+	ValueEncoder ValEncoder
+}
+
+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 {
+	return *((*unsafe.Pointer)(ptr)) == nil
+}
+
+type optionalMapEncoder struct {
+	valueEncoder ValEncoder
+}
+
+func (encoder *optionalMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
+	if *((*unsafe.Pointer)(ptr)) == nil {
+		stream.WriteNil()
+	} else {
+		encoder.valueEncoder.Encode(*((*unsafe.Pointer)(ptr)), stream)
+	}
+}
+
+func (encoder *optionalMapEncoder) EncodeInterface(val interface{}, stream *Stream) {
+	WriteToStream(val, stream, encoder)
+}
+
+func (encoder *optionalMapEncoder) IsEmpty(ptr unsafe.Pointer) bool {
+	p := *((*unsafe.Pointer)(ptr))
+	return p == nil || encoder.valueEncoder.IsEmpty(p)
+}

+ 6 - 12
feature_reflect_slice.go

@@ -7,23 +7,17 @@ import (
 	"unsafe"
 )
 
-func decoderOfSlice(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
-	decoder, err := decoderOfType(cfg, typ.Elem())
-	if err != nil {
-		return nil, err
-	}
-	return &sliceDecoder{typ, typ.Elem(), decoder}, nil
+func decoderOfSlice(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder {
+	decoder := decoderOfType(cfg, prefix+"[slice]->", typ.Elem())
+	return &sliceDecoder{typ, typ.Elem(), decoder}
 }
 
-func encoderOfSlice(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
-	encoder, err := encoderOfType(cfg, typ.Elem())
-	if err != nil {
-		return nil, err
-	}
+func encoderOfSlice(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder {
+	encoder := encoderOfType(cfg, prefix+"[slice]->", typ.Elem())
 	if typ.Elem().Kind() == reflect.Map {
 		encoder = &OptionalEncoder{encoder}
 	}
-	return &sliceEncoder{typ, typ.Elem(), encoder}, nil
+	return &sliceEncoder{typ, typ.Elem(), encoder}
 }
 
 type sliceEncoder struct {

+ 79 - 47
feature_reflect_struct_decoder.go

@@ -8,22 +8,22 @@ import (
 	"unsafe"
 )
 
-func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder) (ValDecoder, error) {
+func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder) ValDecoder {
 	knownHash := map[int32]struct{}{
 		0: {},
 	}
 	switch len(fields) {
 	case 0:
-		return &skipObjectDecoder{typ}, nil
+		return &skipObjectDecoder{typ}
 	case 1:
 		for fieldName, fieldDecoder := range fields {
 			fieldHash := calcHash(fieldName)
 			_, known := knownHash[fieldHash]
 			if known {
-				return &generalStructDecoder{typ, fields}, nil
+				return &generalStructDecoder{typ, fields}
 			}
 			knownHash[fieldHash] = struct{}{}
-			return &oneFieldStructDecoder{typ, fieldHash, fieldDecoder}, nil
+			return &oneFieldStructDecoder{typ, fieldHash, fieldDecoder}
 		}
 	case 2:
 		var fieldHash1 int32
@@ -34,7 +34,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			fieldHash := calcHash(fieldName)
 			_, known := knownHash[fieldHash]
 			if known {
-				return &generalStructDecoder{typ, fields}, nil
+				return &generalStructDecoder{typ, fields}
 			}
 			knownHash[fieldHash] = struct{}{}
 			if fieldHash1 == 0 {
@@ -45,7 +45,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 				fieldDecoder2 = fieldDecoder
 			}
 		}
-		return &twoFieldsStructDecoder{typ, fieldHash1, fieldDecoder1, fieldHash2, fieldDecoder2}, nil
+		return &twoFieldsStructDecoder{typ, fieldHash1, fieldDecoder1, fieldHash2, fieldDecoder2}
 	case 3:
 		var fieldName1 int32
 		var fieldName2 int32
@@ -57,7 +57,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			fieldHash := calcHash(fieldName)
 			_, known := knownHash[fieldHash]
 			if known {
-				return &generalStructDecoder{typ, fields}, nil
+				return &generalStructDecoder{typ, fields}
 			}
 			knownHash[fieldHash] = struct{}{}
 			if fieldName1 == 0 {
@@ -72,7 +72,9 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			}
 		}
 		return &threeFieldsStructDecoder{typ,
-			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3}, nil
+			fieldName1, fieldDecoder1,
+			fieldName2, fieldDecoder2,
+			fieldName3, fieldDecoder3}
 	case 4:
 		var fieldName1 int32
 		var fieldName2 int32
@@ -86,7 +88,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			fieldHash := calcHash(fieldName)
 			_, known := knownHash[fieldHash]
 			if known {
-				return &generalStructDecoder{typ, fields}, nil
+				return &generalStructDecoder{typ, fields}
 			}
 			knownHash[fieldHash] = struct{}{}
 			if fieldName1 == 0 {
@@ -104,8 +106,10 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			}
 		}
 		return &fourFieldsStructDecoder{typ,
-			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
-			fieldName4, fieldDecoder4}, nil
+			fieldName1, fieldDecoder1,
+			fieldName2, fieldDecoder2,
+			fieldName3, fieldDecoder3,
+			fieldName4, fieldDecoder4}
 	case 5:
 		var fieldName1 int32
 		var fieldName2 int32
@@ -121,7 +125,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			fieldHash := calcHash(fieldName)
 			_, known := knownHash[fieldHash]
 			if known {
-				return &generalStructDecoder{typ, fields}, nil
+				return &generalStructDecoder{typ, fields}
 			}
 			knownHash[fieldHash] = struct{}{}
 			if fieldName1 == 0 {
@@ -142,8 +146,11 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			}
 		}
 		return &fiveFieldsStructDecoder{typ,
-			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
-			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5}, nil
+			fieldName1, fieldDecoder1,
+			fieldName2, fieldDecoder2,
+			fieldName3, fieldDecoder3,
+			fieldName4, fieldDecoder4,
+			fieldName5, fieldDecoder5}
 	case 6:
 		var fieldName1 int32
 		var fieldName2 int32
@@ -161,7 +168,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			fieldHash := calcHash(fieldName)
 			_, known := knownHash[fieldHash]
 			if known {
-				return &generalStructDecoder{typ, fields}, nil
+				return &generalStructDecoder{typ, fields}
 			}
 			knownHash[fieldHash] = struct{}{}
 			if fieldName1 == 0 {
@@ -185,8 +192,12 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			}
 		}
 		return &sixFieldsStructDecoder{typ,
-			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
-			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6}, nil
+			fieldName1, fieldDecoder1,
+			fieldName2, fieldDecoder2,
+			fieldName3, fieldDecoder3,
+			fieldName4, fieldDecoder4,
+			fieldName5, fieldDecoder5,
+			fieldName6, fieldDecoder6}
 	case 7:
 		var fieldName1 int32
 		var fieldName2 int32
@@ -206,7 +217,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			fieldHash := calcHash(fieldName)
 			_, known := knownHash[fieldHash]
 			if known {
-				return &generalStructDecoder{typ, fields}, nil
+				return &generalStructDecoder{typ, fields}
 			}
 			knownHash[fieldHash] = struct{}{}
 			if fieldName1 == 0 {
@@ -233,9 +244,13 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			}
 		}
 		return &sevenFieldsStructDecoder{typ,
-			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
-			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
-			fieldName7, fieldDecoder7}, nil
+			fieldName1, fieldDecoder1,
+			fieldName2, fieldDecoder2,
+			fieldName3, fieldDecoder3,
+			fieldName4, fieldDecoder4,
+			fieldName5, fieldDecoder5,
+			fieldName6, fieldDecoder6,
+			fieldName7, fieldDecoder7}
 	case 8:
 		var fieldName1 int32
 		var fieldName2 int32
@@ -257,7 +272,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			fieldHash := calcHash(fieldName)
 			_, known := knownHash[fieldHash]
 			if known {
-				return &generalStructDecoder{typ, fields}, nil
+				return &generalStructDecoder{typ, fields}
 			}
 			knownHash[fieldHash] = struct{}{}
 			if fieldName1 == 0 {
@@ -287,9 +302,14 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			}
 		}
 		return &eightFieldsStructDecoder{typ,
-			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
-			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
-			fieldName7, fieldDecoder7, fieldName8, fieldDecoder8}, nil
+			fieldName1, fieldDecoder1,
+			fieldName2, fieldDecoder2,
+			fieldName3, fieldDecoder3,
+			fieldName4, fieldDecoder4,
+			fieldName5, fieldDecoder5,
+			fieldName6, fieldDecoder6,
+			fieldName7, fieldDecoder7,
+			fieldName8, fieldDecoder8}
 	case 9:
 		var fieldName1 int32
 		var fieldName2 int32
@@ -313,7 +333,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			fieldHash := calcHash(fieldName)
 			_, known := knownHash[fieldHash]
 			if known {
-				return &generalStructDecoder{typ, fields}, nil
+				return &generalStructDecoder{typ, fields}
 			}
 			knownHash[fieldHash] = struct{}{}
 			if fieldName1 == 0 {
@@ -346,9 +366,15 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			}
 		}
 		return &nineFieldsStructDecoder{typ,
-			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
-			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
-			fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9}, nil
+			fieldName1, fieldDecoder1,
+			fieldName2, fieldDecoder2,
+			fieldName3, fieldDecoder3,
+			fieldName4, fieldDecoder4,
+			fieldName5, fieldDecoder5,
+			fieldName6, fieldDecoder6,
+			fieldName7, fieldDecoder7,
+			fieldName8, fieldDecoder8,
+			fieldName9, fieldDecoder9}
 	case 10:
 		var fieldName1 int32
 		var fieldName2 int32
@@ -374,7 +400,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			fieldHash := calcHash(fieldName)
 			_, known := knownHash[fieldHash]
 			if known {
-				return &generalStructDecoder{typ, fields}, nil
+				return &generalStructDecoder{typ, fields}
 			}
 			knownHash[fieldHash] = struct{}{}
 			if fieldName1 == 0 {
@@ -410,12 +436,18 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder
 			}
 		}
 		return &tenFieldsStructDecoder{typ,
-			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3,
-			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6,
-			fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9,
-			fieldName10, fieldDecoder10}, nil
-	}
-	return &generalStructDecoder{typ, fields}, nil
+			fieldName1, fieldDecoder1,
+			fieldName2, fieldDecoder2,
+			fieldName3, fieldDecoder3,
+			fieldName4, fieldDecoder4,
+			fieldName5, fieldDecoder5,
+			fieldName6, fieldDecoder6,
+			fieldName7, fieldDecoder7,
+			fieldName8, fieldDecoder8,
+			fieldName9, fieldDecoder9,
+			fieldName10, fieldDecoder10}
+	}
+	return &generalStructDecoder{typ, fields}
 }
 
 type generalStructDecoder struct {
@@ -464,7 +496,7 @@ func (decoder *generalStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator)
 		}
 	}
 	if iter.Error != nil && iter.Error != io.EOF {
-		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
+		iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
 	}
 }
 
@@ -502,7 +534,7 @@ func (decoder *oneFieldStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator)
 		}
 	}
 	if iter.Error != nil && iter.Error != io.EOF {
-		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
+		iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
 	}
 }
 
@@ -532,7 +564,7 @@ func (decoder *twoFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator
 		}
 	}
 	if iter.Error != nil && iter.Error != io.EOF {
-		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
+		iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
 	}
 }
 
@@ -566,7 +598,7 @@ func (decoder *threeFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterat
 		}
 	}
 	if iter.Error != nil && iter.Error != io.EOF {
-		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
+		iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
 	}
 }
 
@@ -604,7 +636,7 @@ func (decoder *fourFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterato
 		}
 	}
 	if iter.Error != nil && iter.Error != io.EOF {
-		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
+		iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
 	}
 }
 
@@ -646,7 +678,7 @@ func (decoder *fiveFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterato
 		}
 	}
 	if iter.Error != nil && iter.Error != io.EOF {
-		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
+		iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
 	}
 }
 
@@ -692,7 +724,7 @@ func (decoder *sixFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator
 		}
 	}
 	if iter.Error != nil && iter.Error != io.EOF {
-		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
+		iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
 	}
 }
 
@@ -742,7 +774,7 @@ func (decoder *sevenFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterat
 		}
 	}
 	if iter.Error != nil && iter.Error != io.EOF {
-		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
+		iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
 	}
 }
 
@@ -796,7 +828,7 @@ func (decoder *eightFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterat
 		}
 	}
 	if iter.Error != nil && iter.Error != io.EOF {
-		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
+		iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
 	}
 }
 
@@ -854,7 +886,7 @@ func (decoder *nineFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterato
 		}
 	}
 	if iter.Error != nil && iter.Error != io.EOF {
-		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
+		iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
 	}
 }
 
@@ -916,7 +948,7 @@ func (decoder *tenFieldsStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator
 		}
 	}
 	if iter.Error != nil && iter.Error != io.EOF {
-		iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error())
+		iter.Error = fmt.Errorf("%v.%s", decoder.typ, iter.Error.Error())
 	}
 }
 

+ 4 - 3
jsoniter_customize_test.go

@@ -109,12 +109,13 @@ func (extension *testExtension) UpdateStructDescriptor(structDescriptor *StructD
 
 func Test_customize_field_by_extension(t *testing.T) {
 	should := require.New(t)
-	RegisterExtension(&testExtension{})
+	cfg := Config{}.Froze()
+	cfg.RegisterExtension(&testExtension{})
 	obj := TestObject1{}
-	err := UnmarshalFromString(`{"field-1": 100}`, &obj)
+	err := cfg.UnmarshalFromString(`{"field-1": 100}`, &obj)
 	should.Nil(err)
 	should.Equal("100", obj.Field1)
-	str, err := MarshalToString(obj)
+	str, err := cfg.MarshalToString(obj)
 	should.Nil(err)
 	should.Equal(`{"field-1":100}`, str)
 }

+ 1 - 1
jsoniter_interface_test.go

@@ -20,7 +20,7 @@ func Test_write_empty_interface_via_placeholder(t *testing.T) {
 		cacheKey: reflect.TypeOf(m).Elem(),
 	}
 	stream := ConfigFastest.BorrowStream(nil)
-	encoderOfType(ConfigFastest.(*frozenConfig), reflect.TypeOf(m).Elem())
+	encoderOfType(ConfigFastest.(*frozenConfig), "", reflect.TypeOf(m).Elem())
 	encoder.EncodeInterface(inf, stream)
 	should.Equal(`"hello"`, string(stream.Buffer()))
 }

+ 37 - 0
jsoniter_invalid_test.go

@@ -147,3 +147,40 @@ func Test_nil_pointer(t *testing.T) {
 	err := Unmarshal(data, obj)
 	should.NotNil(err)
 }
+
+func Test_func_pointer_type(t *testing.T) {
+	type TestObject2 struct {
+		F func()
+	}
+	type TestObject1 struct {
+		Obj *TestObject2
+	}
+	t.Run("encode null is valid", func(t *testing.T) {
+		should := require.New(t)
+		output, err := json.Marshal(TestObject1{})
+		should.Nil(err)
+		should.Equal(`{"Obj":null}`, string(output))
+		output, err = Marshal(TestObject1{})
+		should.Nil(err)
+		should.Equal(`{"Obj":null}`, string(output))
+	})
+	t.Run("encode not null is invalid", func(t *testing.T) {
+		should := require.New(t)
+		_, err := json.Marshal(TestObject1{Obj: &TestObject2{}})
+		should.NotNil(err)
+		_, err = Marshal(TestObject1{Obj: &TestObject2{}})
+		should.NotNil(err)
+	})
+	t.Run("decode null is valid", func(t *testing.T) {
+		should := require.New(t)
+		var obj TestObject1
+		should.Nil(json.Unmarshal([]byte(`{"Obj":{"F": null}}`), &obj))
+		should.Nil(Unmarshal([]byte(`{"Obj":{"F": null}}`), &obj))
+	})
+	t.Run("decode not null is invalid", func(t *testing.T) {
+		should := require.New(t)
+		var obj TestObject1
+		should.NotNil(json.Unmarshal([]byte(`{"Obj":{"F": "hello"}}`), &obj))
+		should.NotNil(Unmarshal([]byte(`{"Obj":{"F": "hello"}}`), &obj))
+	})
+}