package jsoniter import ( "fmt" "io" "reflect" "strings" "unicode" "unsafe" ) func encoderOfStruct(typ reflect.Type) (Encoder, error) { structEncoder_ := &structEncoder{} fields := map[string]*structFieldEncoder{} for _, field := range listStructFields(typ) { fieldEncoderKey := fmt.Sprintf("%s/%s", typ.String(), field.Name) var extensionProvidedFieldNames []string for _, extension := range extensions { alternativeFieldNames, fun, _ := extension(typ, field) if alternativeFieldNames != nil { extensionProvidedFieldNames = alternativeFieldNames } if fun != nil { fieldEncoders[fieldEncoderKey] = &funcEncoder{fun} } } tagParts := strings.Split(field.Tag.Get("json"), ",") // if fieldNames set by extension, use theirs, otherwise try tags fieldNames := calcFieldNames(field.Name, tagParts[0], extensionProvidedFieldNames) omitempty := false for _, tagPart := range tagParts { if tagPart == "omitempty" { omitempty = true } } encoder := fieldEncoders[fieldEncoderKey] var err error if encoder == nil && len(fieldNames) > 0 { encoder, err = encoderOfType(field.Type) if err != nil { return prefix(fmt.Sprintf("{%s}", field.Name)).addToEncoder(encoder, err) } // map is stored as pointer in the struct if field.Type.Kind() == reflect.Map { encoder = &optionalEncoder{encoder} } } for _, fieldName := range fieldNames { fields[fieldName] = &structFieldEncoder{field, fieldName, encoder, omitempty} } } if len(fields) == 0 { return &emptyStructEncoder{}, nil } for _, field := range fields { structEncoder_.fields = append(structEncoder_.fields, field) } return structEncoder_, nil } func listStructFields(typ reflect.Type) []*reflect.StructField { fields := []*reflect.StructField{} for i := 0; i < typ.NumField(); i++ { field := typ.Field(i) if field.Anonymous { fields = append(fields, listStructFields(field.Type)...) } else { fields = append(fields, &field) } } return fields } func decoderOfStruct(typ reflect.Type) (Decoder, error) { fields := map[string]*structFieldDecoder{} for i := 0; i < typ.NumField(); i++ { field := typ.Field(i) fieldDecoderKey := fmt.Sprintf("%s/%s", typ.String(), field.Name) var extensionProviedFieldNames []string for _, extension := range extensions { alternativeFieldNames, _, fun := extension(typ, &field) if alternativeFieldNames != nil { extensionProviedFieldNames = alternativeFieldNames } if fun != nil { fieldDecoders[fieldDecoderKey] = &funcDecoder{fun} } } decoder := fieldDecoders[fieldDecoderKey] tagParts := strings.Split(field.Tag.Get("json"), ",") fieldNames := calcFieldNames(field.Name, tagParts[0], extensionProviedFieldNames) if decoder == nil && len(fieldNames) > 0 { var err error decoder, err = decoderOfType(field.Type) if err != nil { return prefix(fmt.Sprintf("{%s}", field.Name)).addToDecoder(decoder, err) } } if len(tagParts) > 1 && tagParts[1] == "string" { decoder = &stringNumberDecoder{decoder} } for _, fieldName := range fieldNames { fields[fieldName] = &structFieldDecoder{&field, decoder} } } return createStructDecoder(typ, fields) } func calcFieldNames(originalFieldName string, tagProvidedFieldName string, extensionProvidedFieldNames []string) []string { // tag => extension => exported? => original isNotExported := unicode.IsLower(rune(originalFieldName[0])) var fieldNames []string /// tagParts[0] always present, even if no tags switch tagProvidedFieldName { case "": if extensionProvidedFieldNames != nil { fieldNames = extensionProvidedFieldNames } else { if isNotExported { fieldNames = []string{} } else { fieldNames = []string{originalFieldName} } } case "-": fieldNames = []string{} default: fieldNames = []string{tagProvidedFieldName} } return fieldNames } func EnableUnexportedStructFieldsSupport() { RegisterExtension(func(type_ reflect.Type, field *reflect.StructField) ([]string, EncoderFunc, DecoderFunc) { return []string{field.Name}, nil, nil }) } func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder) (Decoder, error) { knownHash := map[int32]struct{}{ 0: {}, } switch len(fields) { case 0: return &skipDecoder{typ}, nil case 1: for fieldName, fieldDecoder := range fields { fieldHash := calcHash(fieldName) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields}, nil } else { knownHash[fieldHash] = struct{}{} } return &oneFieldStructDecoder{typ, fieldHash, fieldDecoder}, nil } case 2: var fieldHash1 int32 var fieldHash2 int32 var fieldDecoder1 *structFieldDecoder var fieldDecoder2 *structFieldDecoder for fieldName, fieldDecoder := range fields { fieldHash := calcHash(fieldName) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields}, nil } else { knownHash[fieldHash] = struct{}{} } if fieldHash1 == 0 { fieldHash1 = fieldHash fieldDecoder1 = fieldDecoder } else { fieldHash2 = fieldHash fieldDecoder2 = fieldDecoder } } return &twoFieldsStructDecoder{typ, fieldHash1, fieldDecoder1, fieldHash2, fieldDecoder2}, nil case 3: var fieldName1 int32 var fieldName2 int32 var fieldName3 int32 var fieldDecoder1 *structFieldDecoder var fieldDecoder2 *structFieldDecoder var fieldDecoder3 *structFieldDecoder for fieldName, fieldDecoder := range fields { fieldHash := calcHash(fieldName) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields}, nil } else { knownHash[fieldHash] = struct{}{} } if fieldName1 == 0 { fieldName1 = fieldHash fieldDecoder1 = fieldDecoder } else if fieldName2 == 0 { fieldName2 = fieldHash fieldDecoder2 = fieldDecoder } else { fieldName3 = fieldHash fieldDecoder3 = fieldDecoder } } return &threeFieldsStructDecoder{typ, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3}, nil case 4: var fieldName1 int32 var fieldName2 int32 var fieldName3 int32 var fieldName4 int32 var fieldDecoder1 *structFieldDecoder var fieldDecoder2 *structFieldDecoder var fieldDecoder3 *structFieldDecoder var fieldDecoder4 *structFieldDecoder for fieldName, fieldDecoder := range fields { fieldHash := calcHash(fieldName) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields}, nil } else { knownHash[fieldHash] = struct{}{} } if fieldName1 == 0 { fieldName1 = fieldHash fieldDecoder1 = fieldDecoder } else if fieldName2 == 0 { fieldName2 = fieldHash fieldDecoder2 = fieldDecoder } else if fieldName3 == 0 { fieldName3 = fieldHash fieldDecoder3 = fieldDecoder } else { fieldName4 = fieldHash fieldDecoder4 = fieldDecoder } } return &fourFieldsStructDecoder{typ, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName4, fieldDecoder4}, nil case 5: var fieldName1 int32 var fieldName2 int32 var fieldName3 int32 var fieldName4 int32 var fieldName5 int32 var fieldDecoder1 *structFieldDecoder var fieldDecoder2 *structFieldDecoder var fieldDecoder3 *structFieldDecoder var fieldDecoder4 *structFieldDecoder var fieldDecoder5 *structFieldDecoder for fieldName, fieldDecoder := range fields { fieldHash := calcHash(fieldName) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields}, nil } else { knownHash[fieldHash] = struct{}{} } if fieldName1 == 0 { fieldName1 = fieldHash fieldDecoder1 = fieldDecoder } else if fieldName2 == 0 { fieldName2 = fieldHash fieldDecoder2 = fieldDecoder } else if fieldName3 == 0 { fieldName3 = fieldHash fieldDecoder3 = fieldDecoder } else if fieldName4 == 0 { fieldName4 = fieldHash fieldDecoder4 = fieldDecoder } else { fieldName5 = fieldHash fieldDecoder5 = fieldDecoder } } return &fiveFieldsStructDecoder{typ, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName4, fieldDecoder4, fieldName5, fieldDecoder5}, nil case 6: var fieldName1 int32 var fieldName2 int32 var fieldName3 int32 var fieldName4 int32 var fieldName5 int32 var fieldName6 int32 var fieldDecoder1 *structFieldDecoder var fieldDecoder2 *structFieldDecoder var fieldDecoder3 *structFieldDecoder var fieldDecoder4 *structFieldDecoder var fieldDecoder5 *structFieldDecoder var fieldDecoder6 *structFieldDecoder for fieldName, fieldDecoder := range fields { fieldHash := calcHash(fieldName) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields}, nil } else { knownHash[fieldHash] = struct{}{} } if fieldName1 == 0 { fieldName1 = fieldHash fieldDecoder1 = fieldDecoder } else if fieldName2 == 0 { fieldName2 = fieldHash fieldDecoder2 = fieldDecoder } else if fieldName3 == 0 { fieldName3 = fieldHash fieldDecoder3 = fieldDecoder } else if fieldName4 == 0 { fieldName4 = fieldHash fieldDecoder4 = fieldDecoder } else if fieldName5 == 0 { fieldName5 = fieldHash fieldDecoder5 = fieldDecoder } else { fieldName6 = fieldHash fieldDecoder6 = fieldDecoder } } return &sixFieldsStructDecoder{typ, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6}, nil case 7: var fieldName1 int32 var fieldName2 int32 var fieldName3 int32 var fieldName4 int32 var fieldName5 int32 var fieldName6 int32 var fieldName7 int32 var fieldDecoder1 *structFieldDecoder var fieldDecoder2 *structFieldDecoder var fieldDecoder3 *structFieldDecoder var fieldDecoder4 *structFieldDecoder var fieldDecoder5 *structFieldDecoder var fieldDecoder6 *structFieldDecoder var fieldDecoder7 *structFieldDecoder for fieldName, fieldDecoder := range fields { fieldHash := calcHash(fieldName) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields}, nil } else { knownHash[fieldHash] = struct{}{} } if fieldName1 == 0 { fieldName1 = fieldHash fieldDecoder1 = fieldDecoder } else if fieldName2 == 0 { fieldName2 = fieldHash fieldDecoder2 = fieldDecoder } else if fieldName3 == 0 { fieldName3 = fieldHash fieldDecoder3 = fieldDecoder } else if fieldName4 == 0 { fieldName4 = fieldHash fieldDecoder4 = fieldDecoder } else if fieldName5 == 0 { fieldName5 = fieldHash fieldDecoder5 = fieldDecoder } else if fieldName6 == 0 { fieldName6 = fieldHash fieldDecoder6 = fieldDecoder } else { fieldName7 = fieldHash fieldDecoder7 = fieldDecoder } } return &sevenFieldsStructDecoder{typ, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, fieldName7, fieldDecoder7}, nil case 8: var fieldName1 int32 var fieldName2 int32 var fieldName3 int32 var fieldName4 int32 var fieldName5 int32 var fieldName6 int32 var fieldName7 int32 var fieldName8 int32 var fieldDecoder1 *structFieldDecoder var fieldDecoder2 *structFieldDecoder var fieldDecoder3 *structFieldDecoder var fieldDecoder4 *structFieldDecoder var fieldDecoder5 *structFieldDecoder var fieldDecoder6 *structFieldDecoder var fieldDecoder7 *structFieldDecoder var fieldDecoder8 *structFieldDecoder for fieldName, fieldDecoder := range fields { fieldHash := calcHash(fieldName) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields}, nil } else { knownHash[fieldHash] = struct{}{} } if fieldName1 == 0 { fieldName1 = fieldHash fieldDecoder1 = fieldDecoder } else if fieldName2 == 0 { fieldName2 = fieldHash fieldDecoder2 = fieldDecoder } else if fieldName3 == 0 { fieldName3 = fieldHash fieldDecoder3 = fieldDecoder } else if fieldName4 == 0 { fieldName4 = fieldHash fieldDecoder4 = fieldDecoder } else if fieldName5 == 0 { fieldName5 = fieldHash fieldDecoder5 = fieldDecoder } else if fieldName6 == 0 { fieldName6 = fieldHash fieldDecoder6 = fieldDecoder } else if fieldName7 == 0 { fieldName7 = fieldHash fieldDecoder7 = fieldDecoder } else { fieldName8 = fieldHash fieldDecoder8 = fieldDecoder } } return &eightFieldsStructDecoder{typ, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, fieldName7, fieldDecoder7, fieldName8, fieldDecoder8}, nil case 9: var fieldName1 int32 var fieldName2 int32 var fieldName3 int32 var fieldName4 int32 var fieldName5 int32 var fieldName6 int32 var fieldName7 int32 var fieldName8 int32 var fieldName9 int32 var fieldDecoder1 *structFieldDecoder var fieldDecoder2 *structFieldDecoder var fieldDecoder3 *structFieldDecoder var fieldDecoder4 *structFieldDecoder var fieldDecoder5 *structFieldDecoder var fieldDecoder6 *structFieldDecoder var fieldDecoder7 *structFieldDecoder var fieldDecoder8 *structFieldDecoder var fieldDecoder9 *structFieldDecoder for fieldName, fieldDecoder := range fields { fieldHash := calcHash(fieldName) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields}, nil } else { knownHash[fieldHash] = struct{}{} } if fieldName1 == 0 { fieldName1 = fieldHash fieldDecoder1 = fieldDecoder } else if fieldName2 == 0 { fieldName2 = fieldHash fieldDecoder2 = fieldDecoder } else if fieldName3 == 0 { fieldName3 = fieldHash fieldDecoder3 = fieldDecoder } else if fieldName4 == 0 { fieldName4 = fieldHash fieldDecoder4 = fieldDecoder } else if fieldName5 == 0 { fieldName5 = fieldHash fieldDecoder5 = fieldDecoder } else if fieldName6 == 0 { fieldName6 = fieldHash fieldDecoder6 = fieldDecoder } else if fieldName7 == 0 { fieldName7 = fieldHash fieldDecoder7 = fieldDecoder } else if fieldName8 == 0 { fieldName8 = fieldHash fieldDecoder8 = fieldDecoder } else { fieldName9 = fieldHash fieldDecoder9 = fieldDecoder } } return &nineFieldsStructDecoder{typ, fieldName1, fieldDecoder1, fieldName2, fieldDecoder2, fieldName3, fieldDecoder3, fieldName4, fieldDecoder4, fieldName5, fieldDecoder5, fieldName6, fieldDecoder6, fieldName7, fieldDecoder7, fieldName8, fieldDecoder8, fieldName9, fieldDecoder9}, nil case 10: var fieldName1 int32 var fieldName2 int32 var fieldName3 int32 var fieldName4 int32 var fieldName5 int32 var fieldName6 int32 var fieldName7 int32 var fieldName8 int32 var fieldName9 int32 var fieldName10 int32 var fieldDecoder1 *structFieldDecoder var fieldDecoder2 *structFieldDecoder var fieldDecoder3 *structFieldDecoder var fieldDecoder4 *structFieldDecoder var fieldDecoder5 *structFieldDecoder var fieldDecoder6 *structFieldDecoder var fieldDecoder7 *structFieldDecoder var fieldDecoder8 *structFieldDecoder var fieldDecoder9 *structFieldDecoder var fieldDecoder10 *structFieldDecoder for fieldName, fieldDecoder := range fields { fieldHash := calcHash(fieldName) _, known := knownHash[fieldHash] if known { return &generalStructDecoder{typ, fields}, nil } else { knownHash[fieldHash] = struct{}{} } if fieldName1 == 0 { fieldName1 = fieldHash fieldDecoder1 = fieldDecoder } else if fieldName2 == 0 { fieldName2 = fieldHash fieldDecoder2 = fieldDecoder } else if fieldName3 == 0 { fieldName3 = fieldHash fieldDecoder3 = fieldDecoder } else if fieldName4 == 0 { fieldName4 = fieldHash fieldDecoder4 = fieldDecoder } else if fieldName5 == 0 { fieldName5 = fieldHash fieldDecoder5 = fieldDecoder } else if fieldName6 == 0 { fieldName6 = fieldHash fieldDecoder6 = fieldDecoder } else if fieldName7 == 0 { fieldName7 = fieldHash fieldDecoder7 = fieldDecoder } else if fieldName8 == 0 { fieldName8 = fieldHash fieldDecoder8 = fieldDecoder } else if fieldName9 == 0 { fieldName9 = fieldHash fieldDecoder9 = fieldDecoder } else { fieldName10 = fieldHash fieldDecoder10 = fieldDecoder } } 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 } type generalStructDecoder struct { typ reflect.Type fields map[string]*structFieldDecoder } func (decoder *generalStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.readObjectStart() { return } fieldBytes := iter.readObjectFieldAsBytes() field := *(*string)(unsafe.Pointer(&fieldBytes)) fieldDecoder := decoder.fields[field] if fieldDecoder == nil { iter.Skip() } else { fieldDecoder.decode(ptr, iter) } for iter.nextToken() == ',' { fieldBytes = iter.readObjectFieldAsBytes() field = *(*string)(unsafe.Pointer(&fieldBytes)) fieldDecoder = decoder.fields[field] if fieldDecoder == nil { iter.Skip() } else { fieldDecoder.decode(ptr, iter) } } if iter.Error != nil && iter.Error != io.EOF { iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) } } type skipDecoder struct { typ reflect.Type } func (decoder *skipDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { iter.Skip() if iter.Error != nil && iter.Error != io.EOF { iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) } } type oneFieldStructDecoder struct { typ reflect.Type fieldHash int32 fieldDecoder *structFieldDecoder } func (decoder *oneFieldStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.readObjectStart() { return } for { if iter.readFieldHash() == decoder.fieldHash { decoder.fieldDecoder.decode(ptr, iter) } else { iter.Skip() } if iter.nextToken() != ',' { break } } if iter.Error != nil && iter.Error != io.EOF { iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) } } type twoFieldsStructDecoder struct { typ reflect.Type fieldHash1 int32 fieldDecoder1 *structFieldDecoder fieldHash2 int32 fieldDecoder2 *structFieldDecoder } func (decoder *twoFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.readObjectStart() { return } for { switch iter.readFieldHash() { case decoder.fieldHash1: decoder.fieldDecoder1.decode(ptr, iter) case decoder.fieldHash2: decoder.fieldDecoder2.decode(ptr, iter) default: iter.Skip() } if iter.nextToken() != ',' { break } } if iter.Error != nil && iter.Error != io.EOF { iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) } } type threeFieldsStructDecoder struct { typ reflect.Type fieldHash1 int32 fieldDecoder1 *structFieldDecoder fieldHash2 int32 fieldDecoder2 *structFieldDecoder fieldHash3 int32 fieldDecoder3 *structFieldDecoder } func (decoder *threeFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.readObjectStart() { return } for { switch iter.readFieldHash() { case decoder.fieldHash1: decoder.fieldDecoder1.decode(ptr, iter) case decoder.fieldHash2: decoder.fieldDecoder2.decode(ptr, iter) case decoder.fieldHash3: decoder.fieldDecoder3.decode(ptr, iter) default: iter.Skip() } if iter.nextToken() != ',' { break } } if iter.Error != nil && iter.Error != io.EOF { iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) } } type fourFieldsStructDecoder struct { typ reflect.Type fieldHash1 int32 fieldDecoder1 *structFieldDecoder fieldHash2 int32 fieldDecoder2 *structFieldDecoder fieldHash3 int32 fieldDecoder3 *structFieldDecoder fieldHash4 int32 fieldDecoder4 *structFieldDecoder } func (decoder *fourFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.readObjectStart() { return } for { switch iter.readFieldHash() { case decoder.fieldHash1: decoder.fieldDecoder1.decode(ptr, iter) case decoder.fieldHash2: decoder.fieldDecoder2.decode(ptr, iter) case decoder.fieldHash3: decoder.fieldDecoder3.decode(ptr, iter) case decoder.fieldHash4: decoder.fieldDecoder4.decode(ptr, iter) default: iter.Skip() } if iter.nextToken() != ',' { break } } if iter.Error != nil && iter.Error != io.EOF { iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) } } type fiveFieldsStructDecoder struct { typ reflect.Type fieldHash1 int32 fieldDecoder1 *structFieldDecoder fieldHash2 int32 fieldDecoder2 *structFieldDecoder fieldHash3 int32 fieldDecoder3 *structFieldDecoder fieldHash4 int32 fieldDecoder4 *structFieldDecoder fieldHash5 int32 fieldDecoder5 *structFieldDecoder } func (decoder *fiveFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.readObjectStart() { return } for { switch iter.readFieldHash() { case decoder.fieldHash1: decoder.fieldDecoder1.decode(ptr, iter) case decoder.fieldHash2: decoder.fieldDecoder2.decode(ptr, iter) case decoder.fieldHash3: decoder.fieldDecoder3.decode(ptr, iter) case decoder.fieldHash4: decoder.fieldDecoder4.decode(ptr, iter) case decoder.fieldHash5: decoder.fieldDecoder5.decode(ptr, iter) default: iter.Skip() } if iter.nextToken() != ',' { break } } if iter.Error != nil && iter.Error != io.EOF { iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) } } type sixFieldsStructDecoder struct { typ reflect.Type fieldHash1 int32 fieldDecoder1 *structFieldDecoder fieldHash2 int32 fieldDecoder2 *structFieldDecoder fieldHash3 int32 fieldDecoder3 *structFieldDecoder fieldHash4 int32 fieldDecoder4 *structFieldDecoder fieldHash5 int32 fieldDecoder5 *structFieldDecoder fieldHash6 int32 fieldDecoder6 *structFieldDecoder } func (decoder *sixFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.readObjectStart() { return } for { switch iter.readFieldHash() { case decoder.fieldHash1: decoder.fieldDecoder1.decode(ptr, iter) case decoder.fieldHash2: decoder.fieldDecoder2.decode(ptr, iter) case decoder.fieldHash3: decoder.fieldDecoder3.decode(ptr, iter) case decoder.fieldHash4: decoder.fieldDecoder4.decode(ptr, iter) case decoder.fieldHash5: decoder.fieldDecoder5.decode(ptr, iter) case decoder.fieldHash6: decoder.fieldDecoder6.decode(ptr, iter) default: iter.Skip() } if iter.nextToken() != ',' { break } } if iter.Error != nil && iter.Error != io.EOF { iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) } } type sevenFieldsStructDecoder struct { typ reflect.Type fieldHash1 int32 fieldDecoder1 *structFieldDecoder fieldHash2 int32 fieldDecoder2 *structFieldDecoder fieldHash3 int32 fieldDecoder3 *structFieldDecoder fieldHash4 int32 fieldDecoder4 *structFieldDecoder fieldHash5 int32 fieldDecoder5 *structFieldDecoder fieldHash6 int32 fieldDecoder6 *structFieldDecoder fieldHash7 int32 fieldDecoder7 *structFieldDecoder } func (decoder *sevenFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.readObjectStart() { return } for { switch iter.readFieldHash() { case decoder.fieldHash1: decoder.fieldDecoder1.decode(ptr, iter) case decoder.fieldHash2: decoder.fieldDecoder2.decode(ptr, iter) case decoder.fieldHash3: decoder.fieldDecoder3.decode(ptr, iter) case decoder.fieldHash4: decoder.fieldDecoder4.decode(ptr, iter) case decoder.fieldHash5: decoder.fieldDecoder5.decode(ptr, iter) case decoder.fieldHash6: decoder.fieldDecoder6.decode(ptr, iter) case decoder.fieldHash7: decoder.fieldDecoder7.decode(ptr, iter) default: iter.Skip() } if iter.nextToken() != ',' { break } } if iter.Error != nil && iter.Error != io.EOF { iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) } } type eightFieldsStructDecoder struct { typ reflect.Type fieldHash1 int32 fieldDecoder1 *structFieldDecoder fieldHash2 int32 fieldDecoder2 *structFieldDecoder fieldHash3 int32 fieldDecoder3 *structFieldDecoder fieldHash4 int32 fieldDecoder4 *structFieldDecoder fieldHash5 int32 fieldDecoder5 *structFieldDecoder fieldHash6 int32 fieldDecoder6 *structFieldDecoder fieldHash7 int32 fieldDecoder7 *structFieldDecoder fieldHash8 int32 fieldDecoder8 *structFieldDecoder } func (decoder *eightFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.readObjectStart() { return } for { switch iter.readFieldHash() { case decoder.fieldHash1: decoder.fieldDecoder1.decode(ptr, iter) case decoder.fieldHash2: decoder.fieldDecoder2.decode(ptr, iter) case decoder.fieldHash3: decoder.fieldDecoder3.decode(ptr, iter) case decoder.fieldHash4: decoder.fieldDecoder4.decode(ptr, iter) case decoder.fieldHash5: decoder.fieldDecoder5.decode(ptr, iter) case decoder.fieldHash6: decoder.fieldDecoder6.decode(ptr, iter) case decoder.fieldHash7: decoder.fieldDecoder7.decode(ptr, iter) case decoder.fieldHash8: decoder.fieldDecoder8.decode(ptr, iter) default: iter.Skip() } if iter.nextToken() != ',' { break } } if iter.Error != nil && iter.Error != io.EOF { iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) } } type nineFieldsStructDecoder struct { typ reflect.Type fieldHash1 int32 fieldDecoder1 *structFieldDecoder fieldHash2 int32 fieldDecoder2 *structFieldDecoder fieldHash3 int32 fieldDecoder3 *structFieldDecoder fieldHash4 int32 fieldDecoder4 *structFieldDecoder fieldHash5 int32 fieldDecoder5 *structFieldDecoder fieldHash6 int32 fieldDecoder6 *structFieldDecoder fieldHash7 int32 fieldDecoder7 *structFieldDecoder fieldHash8 int32 fieldDecoder8 *structFieldDecoder fieldHash9 int32 fieldDecoder9 *structFieldDecoder } func (decoder *nineFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.readObjectStart() { return } for { switch iter.readFieldHash() { case decoder.fieldHash1: decoder.fieldDecoder1.decode(ptr, iter) case decoder.fieldHash2: decoder.fieldDecoder2.decode(ptr, iter) case decoder.fieldHash3: decoder.fieldDecoder3.decode(ptr, iter) case decoder.fieldHash4: decoder.fieldDecoder4.decode(ptr, iter) case decoder.fieldHash5: decoder.fieldDecoder5.decode(ptr, iter) case decoder.fieldHash6: decoder.fieldDecoder6.decode(ptr, iter) case decoder.fieldHash7: decoder.fieldDecoder7.decode(ptr, iter) case decoder.fieldHash8: decoder.fieldDecoder8.decode(ptr, iter) case decoder.fieldHash9: decoder.fieldDecoder9.decode(ptr, iter) default: iter.Skip() } if iter.nextToken() != ',' { break } } if iter.Error != nil && iter.Error != io.EOF { iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) } } type tenFieldsStructDecoder struct { typ reflect.Type fieldHash1 int32 fieldDecoder1 *structFieldDecoder fieldHash2 int32 fieldDecoder2 *structFieldDecoder fieldHash3 int32 fieldDecoder3 *structFieldDecoder fieldHash4 int32 fieldDecoder4 *structFieldDecoder fieldHash5 int32 fieldDecoder5 *structFieldDecoder fieldHash6 int32 fieldDecoder6 *structFieldDecoder fieldHash7 int32 fieldDecoder7 *structFieldDecoder fieldHash8 int32 fieldDecoder8 *structFieldDecoder fieldHash9 int32 fieldDecoder9 *structFieldDecoder fieldHash10 int32 fieldDecoder10 *structFieldDecoder } func (decoder *tenFieldsStructDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { if !iter.readObjectStart() { return } for { switch iter.readFieldHash() { case decoder.fieldHash1: decoder.fieldDecoder1.decode(ptr, iter) case decoder.fieldHash2: decoder.fieldDecoder2.decode(ptr, iter) case decoder.fieldHash3: decoder.fieldDecoder3.decode(ptr, iter) case decoder.fieldHash4: decoder.fieldDecoder4.decode(ptr, iter) case decoder.fieldHash5: decoder.fieldDecoder5.decode(ptr, iter) case decoder.fieldHash6: decoder.fieldDecoder6.decode(ptr, iter) case decoder.fieldHash7: decoder.fieldDecoder7.decode(ptr, iter) case decoder.fieldHash8: decoder.fieldDecoder8.decode(ptr, iter) case decoder.fieldHash9: decoder.fieldDecoder9.decode(ptr, iter) case decoder.fieldHash10: decoder.fieldDecoder10.decode(ptr, iter) default: iter.Skip() } if iter.nextToken() != ',' { break } } if iter.Error != nil && iter.Error != io.EOF { iter.Error = fmt.Errorf("%v: %s", decoder.typ, iter.Error.Error()) } } type structFieldDecoder struct { field *reflect.StructField fieldDecoder Decoder } func (decoder *structFieldDecoder) decode(ptr unsafe.Pointer, iter *Iterator) { fieldPtr := uintptr(ptr) + decoder.field.Offset decoder.fieldDecoder.decode(unsafe.Pointer(fieldPtr), iter) if iter.Error != nil && iter.Error != io.EOF { iter.Error = fmt.Errorf("%s: %s", decoder.field.Name, iter.Error.Error()) } } type structFieldEncoder struct { field *reflect.StructField fieldName string fieldEncoder Encoder omitempty bool } func (encoder *structFieldEncoder) encode(ptr unsafe.Pointer, stream *Stream) { fieldPtr := uintptr(ptr) + encoder.field.Offset stream.WriteObjectField(encoder.fieldName) encoder.fieldEncoder.encode(unsafe.Pointer(fieldPtr), stream) if stream.Error != nil && stream.Error != io.EOF { stream.Error = fmt.Errorf("%s: %s", encoder.field.Name, stream.Error.Error()) } } func (encoder *structFieldEncoder) encodeInterface(val interface{}, stream *Stream) { writeToStream(val, stream, encoder) } func (encoder *structFieldEncoder) isEmpty(ptr unsafe.Pointer) bool { fieldPtr := uintptr(ptr) + encoder.field.Offset return encoder.fieldEncoder.isEmpty(unsafe.Pointer(fieldPtr)) } type structEncoder struct { fields []*structFieldEncoder } func (encoder *structEncoder) encode(ptr unsafe.Pointer, stream *Stream) { stream.WriteObjectStart() isNotFirst := false for _, field := range encoder.fields { if field.omitempty && field.isEmpty(ptr) { continue } if isNotFirst { stream.WriteMore() } field.encode(ptr, stream) isNotFirst = true } stream.WriteObjectEnd() } func (encoder *structEncoder) encodeInterface(val interface{}, stream *Stream) { var encoderToUse Encoder encoderToUse = encoder if len(encoder.fields) == 1 { firstEncoder := encoder.fields[0].fieldEncoder firstEncoderName := reflect.TypeOf(firstEncoder).String() // interface{} has inline optimization for this case if firstEncoderName == "*jsoniter.optionalEncoder" { encoderToUse = &structEncoder{ fields: []*structFieldEncoder{{ field: encoder.fields[0].field, fieldName: encoder.fields[0].fieldName, fieldEncoder: firstEncoder.(*optionalEncoder).valueEncoder, omitempty: encoder.fields[0].omitempty, }}, } } } writeToStream(val, stream, encoderToUse) } func (encoder *structEncoder) isEmpty(ptr unsafe.Pointer) bool { for _, field := range encoder.fields { if !field.isEmpty(ptr) { return false } } return true } type emptyStructEncoder struct { } func (encoder *emptyStructEncoder) encode(ptr unsafe.Pointer, stream *Stream) { stream.WriteEmptyObject() } func (encoder *emptyStructEncoder) encodeInterface(val interface{}, stream *Stream) { writeToStream(val, stream, encoder) } func (encoder *emptyStructEncoder) isEmpty(ptr unsafe.Pointer) bool { return true }