github.com/zerosnake0/jzon@v0.0.9-0.20230801092939-1b135cb83f7f/val_decoder_native_struct.go (about)

     1  package jzon
     2  
     3  import (
     4  	"unsafe"
     5  )
     6  
     7  type structDecoderBuilder struct {
     8  	decoder *structDecoder
     9  	fields  structFields
    10  }
    11  
    12  func newStructDecoder(fields structFields) *structDecoderBuilder {
    13  	return &structDecoderBuilder{
    14  		decoder: &structDecoder{},
    15  		fields:  fields,
    16  	}
    17  }
    18  
    19  func (builder *structDecoderBuilder) build(cache decoderCache) {
    20  	builder.decoder.fields.init(len(builder.fields))
    21  	for i := range builder.fields {
    22  		fi := &builder.fields[i]
    23  		fiPtrRType := rtypeOfType(fi.ptrType)
    24  		builder.decoder.fields.add(fi, cache[fiPtrRType])
    25  	}
    26  }
    27  
    28  type decoderFieldInfo struct {
    29  	offsets   []offset
    30  	nameBytes []byte                 // []byte(name)
    31  	equalFold func(s, t []byte) bool // bytes.EqualFold or equivalent
    32  	quoted    bool
    33  	decoder   ValDecoder
    34  }
    35  
    36  func (dfi *decoderFieldInfo) initFrom(f *field) {
    37  	dfi.offsets = f.offsets
    38  	dfi.nameBytes = f.nameBytes
    39  	dfi.equalFold = f.equalFold
    40  	dfi.quoted = f.quoted
    41  }
    42  
    43  type decoderFields struct {
    44  	list           []decoderFieldInfo
    45  	nameIndex      map[string]int
    46  	nameIndexUpper map[string]int
    47  }
    48  
    49  func (df *decoderFields) init(size int) {
    50  	df.list = make([]decoderFieldInfo, 0, size)
    51  	df.nameIndex = make(map[string]int, size)
    52  	df.nameIndexUpper = make(map[string]int, size)
    53  }
    54  
    55  func (df *decoderFields) add(f *field, dec ValDecoder) {
    56  	df.nameIndex[f.name] = len(df.list)
    57  	nameUpper := string(f.nameBytesUpper)
    58  	if _, ok := df.nameIndexUpper[nameUpper]; !ok {
    59  		df.nameIndexUpper[nameUpper] = len(df.list)
    60  	}
    61  	var dfi decoderFieldInfo
    62  	dfi.initFrom(f)
    63  	dfi.decoder = dec
    64  	df.list = append(df.list, dfi)
    65  }
    66  
    67  // key and buf
    68  func (df *decoderFields) find(key, buf []byte, caseSensitive bool) (*decoderFieldInfo, []byte) {
    69  	if i, ok := df.nameIndex[localByteToString(key)]; ok {
    70  		return &df.list[i], buf
    71  	}
    72  	if caseSensitive {
    73  		return nil, buf
    74  	}
    75  	l := len(buf)
    76  	// TODO: compare performance
    77  	if true {
    78  		// use the same buffer
    79  		upper := toUpper(key, buf)
    80  		i, ok := df.nameIndexUpper[localByteToString(upper[l:])]
    81  		if ok {
    82  			return &df.list[i], upper
    83  		}
    84  		return nil, upper
    85  	}
    86  	for i := range df.list {
    87  		ff := &df.list[i]
    88  		if ff.equalFold(ff.nameBytes, key) {
    89  			return ff, buf
    90  		}
    91  	}
    92  	return nil, buf
    93  }
    94  
    95  type structDecoder struct {
    96  	fields decoderFields
    97  }
    98  
    99  func (dec *structDecoder) Decode(ptr unsafe.Pointer, it *Iterator, _ *DecOpts) (err error) {
   100  	c, err := it.nextToken()
   101  	if err != nil {
   102  		return err
   103  	}
   104  	if c == 'n' {
   105  		it.head++
   106  		err = it.expectBytes("ull")
   107  		return
   108  	}
   109  	if c != '{' {
   110  		return UnexpectedByteError{got: c, exp2: 'n', exp: '{'}
   111  	}
   112  	it.head++
   113  	c, err = it.nextToken()
   114  	if err != nil {
   115  		return
   116  	}
   117  	if c == '}' {
   118  		it.head++
   119  		return
   120  	}
   121  	if c != '"' {
   122  		return UnexpectedByteError{got: c, exp: '}', exp2: '"'}
   123  	}
   124  	it.head++
   125  	for {
   126  		field, err := it.readObjectFieldAsSlice()
   127  		if err != nil {
   128  			return err
   129  		}
   130  		stField, fieldOut := dec.fields.find(field, field, it.cfg.caseSensitive)
   131  		it.tmpBuffer = fieldOut
   132  		if stField != nil {
   133  			curPtr := add(ptr, stField.offsets[0].val, "struct field")
   134  			for _, offset := range stField.offsets[1:] {
   135  				subPtr := *(*unsafe.Pointer)(curPtr)
   136  				if subPtr == nil {
   137  					if offset.rtype == 0 { // the ptr field is not exported
   138  						return ErrNilEmbeddedPointer
   139  					}
   140  					subPtr = unsafe_New(offset.rtype)
   141  					*(*unsafe.Pointer)(curPtr) = subPtr
   142  				}
   143  				curPtr = add(subPtr, offset.val, "struct field")
   144  			}
   145  			opt := DecOpts{
   146  				Quoted: stField.quoted,
   147  			}
   148  			if err = stField.decoder.Decode(curPtr, it, opt.noescape()); err != nil {
   149  				return err
   150  			}
   151  		} else {
   152  			if it.disallowUnknownFields {
   153  				return UnknownFieldError(field)
   154  			}
   155  			if err = it.Skip(); err != nil {
   156  				return err
   157  			}
   158  		}
   159  		c, err = it.nextToken()
   160  		if err != nil {
   161  			return err
   162  		}
   163  		switch c {
   164  		case '}':
   165  			it.head++
   166  			return nil
   167  		case ',':
   168  			it.head++
   169  			c, err = it.nextToken()
   170  			if err != nil {
   171  				return err
   172  			}
   173  			if c != '"' {
   174  				return UnexpectedByteError{got: c, exp: '"'}
   175  			}
   176  			it.head++
   177  		default:
   178  			return UnexpectedByteError{got: c, exp: '}', exp2: ','}
   179  		}
   180  	}
   181  }