You've already forked json-iterator
							
							
				mirror of
				https://github.com/json-iterator/go.git
				synced 2025-10-31 00:07:40 +02:00 
			
		
		
		
	fix #207 delay unsupported type error reporting
This commit is contained in:
		
							
								
								
									
										1026
									
								
								feature_reflect.go
									
									
									
									
									
								
							
							
						
						
									
										1026
									
								
								feature_reflect.go
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -7,23 +7,17 @@ import ( | |||||||
| 	"unsafe" | 	"unsafe" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func decoderOfArray(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) { | func decoderOfArray(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder { | ||||||
| 	decoder, err := decoderOfType(cfg, typ.Elem()) | 	decoder := decoderOfType(cfg, prefix+"[array]->", typ.Elem()) | ||||||
| 	if err != nil { | 	return &arrayDecoder{typ, typ.Elem(), decoder} | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	return &arrayDecoder{typ, typ.Elem(), decoder}, nil |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func encoderOfArray(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) { | func encoderOfArray(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder { | ||||||
| 	encoder, err := encoderOfType(cfg, typ.Elem()) | 	encoder := encoderOfType(cfg, prefix+"[array]->", typ.Elem()) | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	if typ.Elem().Kind() == reflect.Map { | 	if typ.Elem().Kind() == reflect.Map { | ||||||
| 		encoder = &OptionalEncoder{encoder} | 		encoder = &OptionalEncoder{encoder} | ||||||
| 	} | 	} | ||||||
| 	return &arrayEncoder{typ, typ.Elem(), encoder}, nil | 	return &arrayEncoder{typ, typ.Elem(), encoder} | ||||||
| } | } | ||||||
|  |  | ||||||
| type arrayEncoder struct { | type arrayEncoder struct { | ||||||
|   | |||||||
| @@ -240,7 +240,7 @@ func _getTypeEncoderFromExtension(cfg *frozenConfig, typ reflect.Type) ValEncode | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func describeStruct(cfg *frozenConfig, typ reflect.Type) (*StructDescriptor, error) { | func describeStruct(cfg *frozenConfig, prefix string, typ reflect.Type) *StructDescriptor { | ||||||
| 	embeddedBindings := []*Binding{} | 	embeddedBindings := []*Binding{} | ||||||
| 	bindings := []*Binding{} | 	bindings := []*Binding{} | ||||||
| 	for i := 0; i < typ.NumField(); i++ { | 	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.Anonymous && (tag == "" || tagParts[0] == "") { | ||||||
| 			if field.Type.Kind() == reflect.Struct { | 			if field.Type.Kind() == reflect.Struct { | ||||||
| 				structDescriptor, err := describeStruct(cfg, field.Type) | 				structDescriptor := describeStruct(cfg, prefix, field.Type) | ||||||
| 				if err != nil { |  | ||||||
| 					return nil, err |  | ||||||
| 				} |  | ||||||
| 				for _, binding := range structDescriptor.Fields { | 				for _, binding := range structDescriptor.Fields { | ||||||
| 					binding.levels = append([]int{i}, binding.levels...) | 					binding.levels = append([]int{i}, binding.levels...) | ||||||
| 					omitempty := binding.Encoder.(*structFieldEncoder).omitempty | 					omitempty := binding.Encoder.(*structFieldEncoder).omitempty | ||||||
| @@ -265,10 +262,7 @@ func describeStruct(cfg *frozenConfig, typ reflect.Type) (*StructDescriptor, err | |||||||
| 				} | 				} | ||||||
| 				continue | 				continue | ||||||
| 			} else if field.Type.Kind() == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct { | 			} else if field.Type.Kind() == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct { | ||||||
| 				structDescriptor, err := describeStruct(cfg, field.Type.Elem()) | 				structDescriptor := describeStruct(cfg, prefix, field.Type.Elem()) | ||||||
| 				if err != nil { |  | ||||||
| 					return nil, err |  | ||||||
| 				} |  | ||||||
| 				for _, binding := range structDescriptor.Fields { | 				for _, binding := range structDescriptor.Fields { | ||||||
| 					binding.levels = append([]int{i}, binding.levels...) | 					binding.levels = append([]int{i}, binding.levels...) | ||||||
| 					omitempty := binding.Encoder.(*structFieldEncoder).omitempty | 					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) | 		fieldCacheKey := fmt.Sprintf("%s/%s", typ.String(), field.Name) | ||||||
| 		decoder := fieldDecoders[fieldCacheKey] | 		decoder := fieldDecoders[fieldCacheKey] | ||||||
| 		if decoder == nil { | 		if decoder == nil { | ||||||
| 			var err error | 			decoder = decoderOfType(cfg, prefix+typ.String()+"."+field.Name+"->", field.Type) | ||||||
| 			decoder, err = decoderOfType(cfg, field.Type) |  | ||||||
| 			if len(fieldNames) > 0 && err != nil { |  | ||||||
| 				return nil, err |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 		encoder := fieldEncoders[fieldCacheKey] | 		encoder := fieldEncoders[fieldCacheKey] | ||||||
| 		if encoder == nil { | 		if encoder == nil { | ||||||
| 			var err error | 			encoder = encoderOfType(cfg, prefix+typ.String()+"."+field.Name+"->", field.Type) | ||||||
| 			encoder, err = encoderOfType(cfg, field.Type) |  | ||||||
| 			if len(fieldNames) > 0 && err != nil { |  | ||||||
| 				return nil, err |  | ||||||
| 			} |  | ||||||
| 			// map is stored as pointer in the struct, | 			// map is stored as pointer in the struct, | ||||||
| 			// and treat nil or empty map as empty field | 			// and treat nil or empty map as empty field | ||||||
| 			if encoder != nil && field.Type.Kind() == reflect.Map { | 			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} | 		binding.levels = []int{i} | ||||||
| 		bindings = append(bindings, binding) | 		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 { | func createStructDescriptor(cfg *frozenConfig, typ reflect.Type, bindings []*Binding, embeddedBindings []*Binding) *StructDescriptor { | ||||||
| 	onePtrEmbedded := false | 	onePtrEmbedded := false | ||||||
|   | |||||||
| @@ -9,6 +9,22 @@ import ( | |||||||
| 	"unsafe" | 	"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 { | type mapDecoder struct { | ||||||
| 	mapType      reflect.Type | 	mapType      reflect.Type | ||||||
| 	keyType      reflect.Type | 	keyType      reflect.Type | ||||||
|   | |||||||
| @@ -8,17 +8,14 @@ import ( | |||||||
| 	"unsafe" | 	"unsafe" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func encoderOfStruct(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) { | func encoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder { | ||||||
| 	type bindingTo struct { | 	type bindingTo struct { | ||||||
| 		binding *Binding | 		binding *Binding | ||||||
| 		toName  string | 		toName  string | ||||||
| 		ignored bool | 		ignored bool | ||||||
| 	} | 	} | ||||||
| 	orderedBindings := []*bindingTo{} | 	orderedBindings := []*bindingTo{} | ||||||
| 	structDescriptor, err := describeStruct(cfg, typ) | 	structDescriptor := describeStruct(cfg, prefix, typ) | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	for _, binding := range structDescriptor.Fields { | 	for _, binding := range structDescriptor.Fields { | ||||||
| 		for _, toName := range binding.ToNames { | 		for _, toName := range binding.ToNames { | ||||||
| 			new := &bindingTo{ | 			new := &bindingTo{ | ||||||
| @@ -35,7 +32,7 @@ func encoderOfStruct(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if len(orderedBindings) == 0 { | 	if len(orderedBindings) == 0 { | ||||||
| 		return &emptyStructEncoder{}, nil | 		return &emptyStructEncoder{} | ||||||
| 	} | 	} | ||||||
| 	finalOrderedFields := []structFieldTo{} | 	finalOrderedFields := []structFieldTo{} | ||||||
| 	for _, bindingTo := range orderedBindings { | 	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) { | 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{} | 	bindings := map[string]*Binding{} | ||||||
| 	structDescriptor, err := describeStruct(cfg, typ) | 	structDescriptor := describeStruct(cfg, prefix, typ) | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	for _, binding := range structDescriptor.Fields { | 	for _, binding := range structDescriptor.Fields { | ||||||
| 		for _, fromName := range binding.FromNames { | 		for _, fromName := range binding.FromNames { | ||||||
| 			old := bindings[fromName] | 			old := bindings[fromName] | ||||||
| @@ -131,6 +126,7 @@ func (encoder *structFieldEncoder) IsEmpty(ptr unsafe.Pointer) bool { | |||||||
| } | } | ||||||
|  |  | ||||||
| type structEncoder struct { | type structEncoder struct { | ||||||
|  | 	typ                reflect.Type | ||||||
| 	onePtrEmbedded     bool | 	onePtrEmbedded     bool | ||||||
| 	onePtrOptimization bool | 	onePtrOptimization bool | ||||||
| 	fields             []structFieldTo | 	fields             []structFieldTo | ||||||
| @@ -156,6 +152,9 @@ func (encoder *structEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { | |||||||
| 		isNotFirst = true | 		isNotFirst = true | ||||||
| 	} | 	} | ||||||
| 	stream.WriteObjectEnd() | 	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) { | func (encoder *structEncoder) EncodeInterface(val interface{}, stream *Stream) { | ||||||
|   | |||||||
							
								
								
									
										104
									
								
								feature_reflect_optional.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								feature_reflect_optional.go
									
									
									
									
									
										Normal file
									
								
							| @@ -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) | ||||||
|  | } | ||||||
| @@ -7,23 +7,17 @@ import ( | |||||||
| 	"unsafe" | 	"unsafe" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func decoderOfSlice(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) { | func decoderOfSlice(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder { | ||||||
| 	decoder, err := decoderOfType(cfg, typ.Elem()) | 	decoder := decoderOfType(cfg, prefix+"[slice]->", typ.Elem()) | ||||||
| 	if err != nil { | 	return &sliceDecoder{typ, typ.Elem(), decoder} | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	return &sliceDecoder{typ, typ.Elem(), decoder}, nil |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func encoderOfSlice(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) { | func encoderOfSlice(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder { | ||||||
| 	encoder, err := encoderOfType(cfg, typ.Elem()) | 	encoder := encoderOfType(cfg, prefix+"[slice]->", typ.Elem()) | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	if typ.Elem().Kind() == reflect.Map { | 	if typ.Elem().Kind() == reflect.Map { | ||||||
| 		encoder = &OptionalEncoder{encoder} | 		encoder = &OptionalEncoder{encoder} | ||||||
| 	} | 	} | ||||||
| 	return &sliceEncoder{typ, typ.Elem(), encoder}, nil | 	return &sliceEncoder{typ, typ.Elem(), encoder} | ||||||
| } | } | ||||||
|  |  | ||||||
| type sliceEncoder struct { | type sliceEncoder struct { | ||||||
|   | |||||||
| @@ -8,22 +8,22 @@ import ( | |||||||
| 	"unsafe" | 	"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{}{ | 	knownHash := map[int32]struct{}{ | ||||||
| 		0: {}, | 		0: {}, | ||||||
| 	} | 	} | ||||||
| 	switch len(fields) { | 	switch len(fields) { | ||||||
| 	case 0: | 	case 0: | ||||||
| 		return &skipObjectDecoder{typ}, nil | 		return &skipObjectDecoder{typ} | ||||||
| 	case 1: | 	case 1: | ||||||
| 		for fieldName, fieldDecoder := range fields { | 		for fieldName, fieldDecoder := range fields { | ||||||
| 			fieldHash := calcHash(fieldName) | 			fieldHash := calcHash(fieldName) | ||||||
| 			_, known := knownHash[fieldHash] | 			_, known := knownHash[fieldHash] | ||||||
| 			if known { | 			if known { | ||||||
| 				return &generalStructDecoder{typ, fields}, nil | 				return &generalStructDecoder{typ, fields} | ||||||
| 			} | 			} | ||||||
| 			knownHash[fieldHash] = struct{}{} | 			knownHash[fieldHash] = struct{}{} | ||||||
| 			return &oneFieldStructDecoder{typ, fieldHash, fieldDecoder}, nil | 			return &oneFieldStructDecoder{typ, fieldHash, fieldDecoder} | ||||||
| 		} | 		} | ||||||
| 	case 2: | 	case 2: | ||||||
| 		var fieldHash1 int32 | 		var fieldHash1 int32 | ||||||
| @@ -34,7 +34,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			fieldHash := calcHash(fieldName) | 			fieldHash := calcHash(fieldName) | ||||||
| 			_, known := knownHash[fieldHash] | 			_, known := knownHash[fieldHash] | ||||||
| 			if known { | 			if known { | ||||||
| 				return &generalStructDecoder{typ, fields}, nil | 				return &generalStructDecoder{typ, fields} | ||||||
| 			} | 			} | ||||||
| 			knownHash[fieldHash] = struct{}{} | 			knownHash[fieldHash] = struct{}{} | ||||||
| 			if fieldHash1 == 0 { | 			if fieldHash1 == 0 { | ||||||
| @@ -45,7 +45,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 				fieldDecoder2 = fieldDecoder | 				fieldDecoder2 = fieldDecoder | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return &twoFieldsStructDecoder{typ, fieldHash1, fieldDecoder1, fieldHash2, fieldDecoder2}, nil | 		return &twoFieldsStructDecoder{typ, fieldHash1, fieldDecoder1, fieldHash2, fieldDecoder2} | ||||||
| 	case 3: | 	case 3: | ||||||
| 		var fieldName1 int32 | 		var fieldName1 int32 | ||||||
| 		var fieldName2 int32 | 		var fieldName2 int32 | ||||||
| @@ -57,7 +57,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			fieldHash := calcHash(fieldName) | 			fieldHash := calcHash(fieldName) | ||||||
| 			_, known := knownHash[fieldHash] | 			_, known := knownHash[fieldHash] | ||||||
| 			if known { | 			if known { | ||||||
| 				return &generalStructDecoder{typ, fields}, nil | 				return &generalStructDecoder{typ, fields} | ||||||
| 			} | 			} | ||||||
| 			knownHash[fieldHash] = struct{}{} | 			knownHash[fieldHash] = struct{}{} | ||||||
| 			if fieldName1 == 0 { | 			if fieldName1 == 0 { | ||||||
| @@ -72,7 +72,9 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return &threeFieldsStructDecoder{typ, | 		return &threeFieldsStructDecoder{typ, | ||||||
| 			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3}, nil | 			fieldName1, fieldDecoder1, | ||||||
|  | 			fieldName2, fieldDecoder2, | ||||||
|  | 			fieldName3, fieldDecoder3} | ||||||
| 	case 4: | 	case 4: | ||||||
| 		var fieldName1 int32 | 		var fieldName1 int32 | ||||||
| 		var fieldName2 int32 | 		var fieldName2 int32 | ||||||
| @@ -86,7 +88,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			fieldHash := calcHash(fieldName) | 			fieldHash := calcHash(fieldName) | ||||||
| 			_, known := knownHash[fieldHash] | 			_, known := knownHash[fieldHash] | ||||||
| 			if known { | 			if known { | ||||||
| 				return &generalStructDecoder{typ, fields}, nil | 				return &generalStructDecoder{typ, fields} | ||||||
| 			} | 			} | ||||||
| 			knownHash[fieldHash] = struct{}{} | 			knownHash[fieldHash] = struct{}{} | ||||||
| 			if fieldName1 == 0 { | 			if fieldName1 == 0 { | ||||||
| @@ -104,8 +106,10 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return &fourFieldsStructDecoder{typ, | 		return &fourFieldsStructDecoder{typ, | ||||||
| 			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, | 			fieldName1, fieldDecoder1, | ||||||
| 			fieldName4, fieldDecoder4}, nil | 			fieldName2, fieldDecoder2, | ||||||
|  | 			fieldName3, fieldDecoder3, | ||||||
|  | 			fieldName4, fieldDecoder4} | ||||||
| 	case 5: | 	case 5: | ||||||
| 		var fieldName1 int32 | 		var fieldName1 int32 | ||||||
| 		var fieldName2 int32 | 		var fieldName2 int32 | ||||||
| @@ -121,7 +125,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			fieldHash := calcHash(fieldName) | 			fieldHash := calcHash(fieldName) | ||||||
| 			_, known := knownHash[fieldHash] | 			_, known := knownHash[fieldHash] | ||||||
| 			if known { | 			if known { | ||||||
| 				return &generalStructDecoder{typ, fields}, nil | 				return &generalStructDecoder{typ, fields} | ||||||
| 			} | 			} | ||||||
| 			knownHash[fieldHash] = struct{}{} | 			knownHash[fieldHash] = struct{}{} | ||||||
| 			if fieldName1 == 0 { | 			if fieldName1 == 0 { | ||||||
| @@ -142,8 +146,11 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return &fiveFieldsStructDecoder{typ, | 		return &fiveFieldsStructDecoder{typ, | ||||||
| 			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, | 			fieldName1, fieldDecoder1, | ||||||
| 			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5}, nil | 			fieldName2, fieldDecoder2, | ||||||
|  | 			fieldName3, fieldDecoder3, | ||||||
|  | 			fieldName4, fieldDecoder4, | ||||||
|  | 			fieldName5, fieldDecoder5} | ||||||
| 	case 6: | 	case 6: | ||||||
| 		var fieldName1 int32 | 		var fieldName1 int32 | ||||||
| 		var fieldName2 int32 | 		var fieldName2 int32 | ||||||
| @@ -161,7 +168,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			fieldHash := calcHash(fieldName) | 			fieldHash := calcHash(fieldName) | ||||||
| 			_, known := knownHash[fieldHash] | 			_, known := knownHash[fieldHash] | ||||||
| 			if known { | 			if known { | ||||||
| 				return &generalStructDecoder{typ, fields}, nil | 				return &generalStructDecoder{typ, fields} | ||||||
| 			} | 			} | ||||||
| 			knownHash[fieldHash] = struct{}{} | 			knownHash[fieldHash] = struct{}{} | ||||||
| 			if fieldName1 == 0 { | 			if fieldName1 == 0 { | ||||||
| @@ -185,8 +192,12 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return &sixFieldsStructDecoder{typ, | 		return &sixFieldsStructDecoder{typ, | ||||||
| 			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, | 			fieldName1, fieldDecoder1, | ||||||
| 			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6}, nil | 			fieldName2, fieldDecoder2, | ||||||
|  | 			fieldName3, fieldDecoder3, | ||||||
|  | 			fieldName4, fieldDecoder4, | ||||||
|  | 			fieldName5, fieldDecoder5, | ||||||
|  | 			fieldName6, fieldDecoder6} | ||||||
| 	case 7: | 	case 7: | ||||||
| 		var fieldName1 int32 | 		var fieldName1 int32 | ||||||
| 		var fieldName2 int32 | 		var fieldName2 int32 | ||||||
| @@ -206,7 +217,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			fieldHash := calcHash(fieldName) | 			fieldHash := calcHash(fieldName) | ||||||
| 			_, known := knownHash[fieldHash] | 			_, known := knownHash[fieldHash] | ||||||
| 			if known { | 			if known { | ||||||
| 				return &generalStructDecoder{typ, fields}, nil | 				return &generalStructDecoder{typ, fields} | ||||||
| 			} | 			} | ||||||
| 			knownHash[fieldHash] = struct{}{} | 			knownHash[fieldHash] = struct{}{} | ||||||
| 			if fieldName1 == 0 { | 			if fieldName1 == 0 { | ||||||
| @@ -233,9 +244,13 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return &sevenFieldsStructDecoder{typ, | 		return &sevenFieldsStructDecoder{typ, | ||||||
| 			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, | 			fieldName1, fieldDecoder1, | ||||||
| 			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, | 			fieldName2, fieldDecoder2, | ||||||
| 			fieldName7, fieldDecoder7}, nil | 			fieldName3, fieldDecoder3, | ||||||
|  | 			fieldName4, fieldDecoder4, | ||||||
|  | 			fieldName5, fieldDecoder5, | ||||||
|  | 			fieldName6, fieldDecoder6, | ||||||
|  | 			fieldName7, fieldDecoder7} | ||||||
| 	case 8: | 	case 8: | ||||||
| 		var fieldName1 int32 | 		var fieldName1 int32 | ||||||
| 		var fieldName2 int32 | 		var fieldName2 int32 | ||||||
| @@ -257,7 +272,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			fieldHash := calcHash(fieldName) | 			fieldHash := calcHash(fieldName) | ||||||
| 			_, known := knownHash[fieldHash] | 			_, known := knownHash[fieldHash] | ||||||
| 			if known { | 			if known { | ||||||
| 				return &generalStructDecoder{typ, fields}, nil | 				return &generalStructDecoder{typ, fields} | ||||||
| 			} | 			} | ||||||
| 			knownHash[fieldHash] = struct{}{} | 			knownHash[fieldHash] = struct{}{} | ||||||
| 			if fieldName1 == 0 { | 			if fieldName1 == 0 { | ||||||
| @@ -287,9 +302,14 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return &eightFieldsStructDecoder{typ, | 		return &eightFieldsStructDecoder{typ, | ||||||
| 			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, | 			fieldName1, fieldDecoder1, | ||||||
| 			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, | 			fieldName2, fieldDecoder2, | ||||||
| 			fieldName7, fieldDecoder7, fieldName8, fieldDecoder8}, nil | 			fieldName3, fieldDecoder3, | ||||||
|  | 			fieldName4, fieldDecoder4, | ||||||
|  | 			fieldName5, fieldDecoder5, | ||||||
|  | 			fieldName6, fieldDecoder6, | ||||||
|  | 			fieldName7, fieldDecoder7, | ||||||
|  | 			fieldName8, fieldDecoder8} | ||||||
| 	case 9: | 	case 9: | ||||||
| 		var fieldName1 int32 | 		var fieldName1 int32 | ||||||
| 		var fieldName2 int32 | 		var fieldName2 int32 | ||||||
| @@ -313,7 +333,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			fieldHash := calcHash(fieldName) | 			fieldHash := calcHash(fieldName) | ||||||
| 			_, known := knownHash[fieldHash] | 			_, known := knownHash[fieldHash] | ||||||
| 			if known { | 			if known { | ||||||
| 				return &generalStructDecoder{typ, fields}, nil | 				return &generalStructDecoder{typ, fields} | ||||||
| 			} | 			} | ||||||
| 			knownHash[fieldHash] = struct{}{} | 			knownHash[fieldHash] = struct{}{} | ||||||
| 			if fieldName1 == 0 { | 			if fieldName1 == 0 { | ||||||
| @@ -346,9 +366,15 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return &nineFieldsStructDecoder{typ, | 		return &nineFieldsStructDecoder{typ, | ||||||
| 			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, | 			fieldName1, fieldDecoder1, | ||||||
| 			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, | 			fieldName2, fieldDecoder2, | ||||||
| 			fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9}, nil | 			fieldName3, fieldDecoder3, | ||||||
|  | 			fieldName4, fieldDecoder4, | ||||||
|  | 			fieldName5, fieldDecoder5, | ||||||
|  | 			fieldName6, fieldDecoder6, | ||||||
|  | 			fieldName7, fieldDecoder7, | ||||||
|  | 			fieldName8, fieldDecoder8, | ||||||
|  | 			fieldName9, fieldDecoder9} | ||||||
| 	case 10: | 	case 10: | ||||||
| 		var fieldName1 int32 | 		var fieldName1 int32 | ||||||
| 		var fieldName2 int32 | 		var fieldName2 int32 | ||||||
| @@ -374,7 +400,7 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			fieldHash := calcHash(fieldName) | 			fieldHash := calcHash(fieldName) | ||||||
| 			_, known := knownHash[fieldHash] | 			_, known := knownHash[fieldHash] | ||||||
| 			if known { | 			if known { | ||||||
| 				return &generalStructDecoder{typ, fields}, nil | 				return &generalStructDecoder{typ, fields} | ||||||
| 			} | 			} | ||||||
| 			knownHash[fieldHash] = struct{}{} | 			knownHash[fieldHash] = struct{}{} | ||||||
| 			if fieldName1 == 0 { | 			if fieldName1 == 0 { | ||||||
| @@ -410,12 +436,18 @@ func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		return &tenFieldsStructDecoder{typ, | 		return &tenFieldsStructDecoder{typ, | ||||||
| 			fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, | 			fieldName1, fieldDecoder1, | ||||||
| 			fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, | 			fieldName2, fieldDecoder2, | ||||||
| 			fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9, | 			fieldName3, fieldDecoder3, | ||||||
| 			fieldName10, fieldDecoder10}, nil | 			fieldName4, fieldDecoder4, | ||||||
|  | 			fieldName5, fieldDecoder5, | ||||||
|  | 			fieldName6, fieldDecoder6, | ||||||
|  | 			fieldName7, fieldDecoder7, | ||||||
|  | 			fieldName8, fieldDecoder8, | ||||||
|  | 			fieldName9, fieldDecoder9, | ||||||
|  | 			fieldName10, fieldDecoder10} | ||||||
| 	} | 	} | ||||||
| 	return &generalStructDecoder{typ, fields}, nil | 	return &generalStructDecoder{typ, fields} | ||||||
| } | } | ||||||
|  |  | ||||||
| type generalStructDecoder struct { | type generalStructDecoder struct { | ||||||
| @@ -464,7 +496,7 @@ func (decoder *generalStructDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if iter.Error != nil && iter.Error != io.EOF { | 	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 { | 	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 { | 	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 { | 	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 { | 	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 { | 	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 { | 	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 { | 	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 { | 	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 { | 	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 { | 	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()) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -109,12 +109,13 @@ func (extension *testExtension) UpdateStructDescriptor(structDescriptor *StructD | |||||||
|  |  | ||||||
| func Test_customize_field_by_extension(t *testing.T) { | func Test_customize_field_by_extension(t *testing.T) { | ||||||
| 	should := require.New(t) | 	should := require.New(t) | ||||||
| 	RegisterExtension(&testExtension{}) | 	cfg := Config{}.Froze() | ||||||
|  | 	cfg.RegisterExtension(&testExtension{}) | ||||||
| 	obj := TestObject1{} | 	obj := TestObject1{} | ||||||
| 	err := UnmarshalFromString(`{"field-1": 100}`, &obj) | 	err := cfg.UnmarshalFromString(`{"field-1": 100}`, &obj) | ||||||
| 	should.Nil(err) | 	should.Nil(err) | ||||||
| 	should.Equal("100", obj.Field1) | 	should.Equal("100", obj.Field1) | ||||||
| 	str, err := MarshalToString(obj) | 	str, err := cfg.MarshalToString(obj) | ||||||
| 	should.Nil(err) | 	should.Nil(err) | ||||||
| 	should.Equal(`{"field-1":100}`, str) | 	should.Equal(`{"field-1":100}`, str) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ func Test_write_empty_interface_via_placeholder(t *testing.T) { | |||||||
| 		cacheKey: reflect.TypeOf(m).Elem(), | 		cacheKey: reflect.TypeOf(m).Elem(), | ||||||
| 	} | 	} | ||||||
| 	stream := ConfigFastest.BorrowStream(nil) | 	stream := ConfigFastest.BorrowStream(nil) | ||||||
| 	encoderOfType(ConfigFastest.(*frozenConfig), reflect.TypeOf(m).Elem()) | 	encoderOfType(ConfigFastest.(*frozenConfig), "", reflect.TypeOf(m).Elem()) | ||||||
| 	encoder.EncodeInterface(inf, stream) | 	encoder.EncodeInterface(inf, stream) | ||||||
| 	should.Equal(`"hello"`, string(stream.Buffer())) | 	should.Equal(`"hello"`, string(stream.Buffer())) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -147,3 +147,40 @@ func Test_nil_pointer(t *testing.T) { | |||||||
| 	err := Unmarshal(data, obj) | 	err := Unmarshal(data, obj) | ||||||
| 	should.NotNil(err) | 	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)) | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user