github.com/zerosnake0/jzon@v0.0.9-0.20230801092939-1b135cb83f7f/val_decoder_native_struct_small.go (about) 1 package jzon 2 3 import ( 4 "bytes" 5 "unsafe" 6 ) 7 8 type smallStructDecoderBuilder struct { 9 decoder *smallStructDecoder 10 fields []field 11 } 12 13 func newSmallStructDecoder(fields []field) *smallStructDecoderBuilder { 14 dfiList := make([]decoderFieldInfo, len(fields)) 15 for i := range fields { 16 dfiList[i].initFrom(&fields[i]) 17 } 18 return &smallStructDecoderBuilder{ 19 decoder: &smallStructDecoder{ 20 fields: dfiList, 21 }, 22 fields: fields, 23 } 24 } 25 26 func (builder *smallStructDecoderBuilder) build(cache decoderCache) { 27 for i := range builder.fields { 28 builder.decoder.fields[i].decoder = cache[rtypeOfType(builder.fields[i].ptrType)] 29 } 30 } 31 32 type smallStructDecoder struct { 33 fields []decoderFieldInfo 34 } 35 36 func (dec *smallStructDecoder) find(field []byte, caseSensitive bool) *decoderFieldInfo { 37 for i := range dec.fields { 38 ff := &dec.fields[i] 39 if bytes.Equal(ff.nameBytes, field) { 40 return ff 41 } 42 } 43 if caseSensitive { 44 return nil 45 } 46 for i := range dec.fields { 47 ff := &dec.fields[i] 48 if ff.equalFold(ff.nameBytes, field) { 49 return ff 50 } 51 } 52 return nil 53 } 54 55 func (dec *smallStructDecoder) Decode(ptr unsafe.Pointer, it *Iterator, _ *DecOpts) (err error) { 56 c, err := it.nextToken() 57 if err != nil { 58 return err 59 } 60 if c == 'n' { 61 it.head++ 62 err = it.expectBytes("ull") 63 return 64 } 65 if c != '{' { 66 return UnexpectedByteError{got: c, exp2: 'n', exp: '{'} 67 } 68 it.head++ 69 c, err = it.nextToken() 70 if err != nil { 71 return 72 } 73 if c == '}' { 74 it.head++ 75 return 76 } 77 if c != '"' { 78 return UnexpectedByteError{got: c, exp: '}', exp2: '"'} 79 } 80 it.head++ 81 for { 82 field, err := it.readObjectFieldAsSlice() 83 if err != nil { 84 return err 85 } 86 stField := dec.find(field, it.cfg.caseSensitive) 87 if stField != nil { 88 curPtr := add(ptr, stField.offsets[0].val, "struct field") 89 for _, offset := range stField.offsets[1:] { 90 subPtr := *(*unsafe.Pointer)(curPtr) 91 if subPtr == nil { 92 if offset.rtype == 0 { // the ptr field is not exported 93 return ErrNilEmbeddedPointer 94 } 95 subPtr = unsafe_New(offset.rtype) 96 *(*unsafe.Pointer)(curPtr) = subPtr 97 } 98 curPtr = add(subPtr, offset.val, "struct field") 99 } 100 opt := DecOpts{ 101 Quoted: stField.quoted, 102 } 103 if err = stField.decoder.Decode(curPtr, it, opt.noescape()); err != nil { 104 return err 105 } 106 } else { 107 if it.disallowUnknownFields { 108 return UnknownFieldError(field) 109 } 110 if err = it.Skip(); err != nil { 111 return err 112 } 113 } 114 c, err = it.nextToken() 115 if err != nil { 116 return err 117 } 118 switch c { 119 case '}': 120 it.head++ 121 return nil 122 case ',': 123 it.head++ 124 c, err = it.nextToken() 125 if err != nil { 126 return err 127 } 128 if c != '"' { 129 return UnexpectedByteError{got: c, exp: '"'} 130 } 131 it.head++ 132 default: 133 return UnexpectedByteError{got: c, exp: '}', exp2: ','} 134 } 135 } 136 }