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  }