github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/jsoni/reflect_struct_decoder.go (about)

     1  package jsoni
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io"
     7  	"strings"
     8  	"unsafe"
     9  
    10  	"github.com/modern-go/reflect2"
    11  )
    12  
    13  func decoderOfStruct(ctx *ctx, typ reflect2.Type) ValDecoder {
    14  	bindings := map[string]*Binding{}
    15  	structDescriptor := describeStruct(ctx, typ)
    16  	for _, binding := range structDescriptor.Fields {
    17  		for _, fromName := range binding.FromNames {
    18  			old := bindings[fromName]
    19  			if old == nil {
    20  				bindings[fromName] = binding
    21  				continue
    22  			}
    23  			ignoreOld, ignoreNew := resolveConflictBinding(ctx.frozenConfig, old, binding)
    24  			if ignoreOld {
    25  				delete(bindings, fromName)
    26  			}
    27  			if !ignoreNew {
    28  				bindings[fromName] = binding
    29  			}
    30  		}
    31  	}
    32  	fields := map[string]*structFieldDecoder{}
    33  	for k, binding := range bindings {
    34  		fields[k] = binding.Decoder.(*structFieldDecoder)
    35  	}
    36  
    37  	if !ctx.caseSensitive() {
    38  		for k, b := range bindings {
    39  			if _, found := fields[strings.ToLower(k)]; !found {
    40  				fields[strings.ToLower(k)] = b.Decoder.(*structFieldDecoder)
    41  			}
    42  		}
    43  	}
    44  
    45  	return createStructDecoder(ctx, typ, fields)
    46  }
    47  
    48  func createStructDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structFieldDecoder) ValDecoder {
    49  	if ctx.disallowUnknownFields {
    50  		return &generalStructDecoder{typ: typ, fields: fields, disallowUnknownFields: true}
    51  	}
    52  
    53  	if l := len(fields); l == 0 {
    54  		return &skipObjectDecoder{}
    55  	} else if l <= 10 {
    56  		return createDecoder(ctx, typ, fields)
    57  	} else {
    58  		return &generalStructDecoder{typ: typ, fields: fields}
    59  	}
    60  }
    61  
    62  func createDecoder(ctx *ctx, typ reflect2.Type, fields map[string]*structFieldDecoder) ValDecoder {
    63  	knownHash := map[int64]struct{}{0: {}}
    64  	hashDecoders := make(map[int64]*structFieldDecoder)
    65  	for fieldName, fieldDecoder := range fields {
    66  		fieldHash := calcHash(fieldName, ctx.caseSensitive())
    67  		if _, known := knownHash[fieldHash]; known {
    68  			return &generalStructDecoder{typ: typ, fields: fields}
    69  		}
    70  		knownHash[fieldHash] = struct{}{}
    71  		hashDecoders[fieldHash] = fieldDecoder
    72  	}
    73  	return &fieldsStructDecoder{typ: typ, HashDecoders: hashDecoders}
    74  }
    75  
    76  type generalStructDecoder struct {
    77  	typ                   reflect2.Type
    78  	fields                map[string]*structFieldDecoder
    79  	disallowUnknownFields bool
    80  }
    81  
    82  func (d *generalStructDecoder) Decode(ctx context.Context, ptr unsafe.Pointer, iter *Iterator) {
    83  	if !iter.readObjectStart() || !iter.incrementDepth() {
    84  		return
    85  	}
    86  	var c byte
    87  	for c = ','; c == ','; c = iter.nextToken() {
    88  		d.decodeOneField(ctx, ptr, iter)
    89  	}
    90  	if iter.Error != nil && iter.Error != io.EOF && len(d.typ.Type1().Name()) != 0 {
    91  		iter.Error = fmt.Errorf("%v.%s", d.typ, iter.Error.Error())
    92  	}
    93  	if c != '}' {
    94  		iter.ReportError("struct Decode", `expect }, but found `+string([]byte{c}))
    95  	}
    96  	iter.decrementDepth()
    97  }
    98  
    99  func (d *generalStructDecoder) decodeOneField(ctx context.Context, ptr unsafe.Pointer, iter *Iterator) {
   100  	var field string
   101  	var fieldDecoder *structFieldDecoder
   102  	if iter.cfg.objectFieldMustBeSimpleString {
   103  		fieldBytes := iter.ReadStringAsSlice()
   104  		field = *(*string)(unsafe.Pointer(&fieldBytes))
   105  		fieldDecoder = d.fields[field]
   106  		if fieldDecoder == nil && !iter.cfg.caseSensitive {
   107  			fieldDecoder = d.fields[strings.ToLower(field)]
   108  		}
   109  	} else {
   110  		field = iter.ReadString()
   111  		fieldDecoder = d.fields[field]
   112  		if fieldDecoder == nil && !iter.cfg.caseSensitive {
   113  			fieldDecoder = d.fields[strings.ToLower(field)]
   114  		}
   115  	}
   116  	if fieldDecoder == nil {
   117  		if d.disallowUnknownFields {
   118  			msg := "found unknown field: " + field
   119  			iter.ReportError("ReadObject", msg)
   120  		}
   121  		if c := iter.nextToken(); c != ':' {
   122  			iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
   123  		}
   124  		iter.Skip()
   125  		return
   126  	}
   127  	if c := iter.nextToken(); c != ':' {
   128  		iter.ReportError("ReadObject", "expect : after object field, but found "+string([]byte{c}))
   129  	}
   130  	fieldDecoder.Decode(ctx, ptr, iter)
   131  }
   132  
   133  type skipObjectDecoder struct{}
   134  
   135  func (d *skipObjectDecoder) Decode(_ context.Context, _ unsafe.Pointer, iter *Iterator) {
   136  	valueType := iter.WhatIsNext()
   137  	if valueType != ObjectValue && valueType != NilValue {
   138  		iter.ReportError("skipObjectDecoder", "expect object or null")
   139  		return
   140  	}
   141  	iter.Skip()
   142  }
   143  
   144  type fieldsStructDecoder struct {
   145  	typ          reflect2.Type
   146  	HashDecoders map[int64]*structFieldDecoder
   147  }
   148  
   149  func (d *fieldsStructDecoder) Decode(ctx context.Context, ptr unsafe.Pointer, iter *Iterator) {
   150  	if !iter.readObjectStart() || !iter.incrementDepth() {
   151  		return
   152  	}
   153  	for {
   154  		fieldHash := iter.readFieldHash()
   155  		if decoder, ok := d.HashDecoders[fieldHash]; ok {
   156  			decoder.Decode(ctx, ptr, iter)
   157  		} else {
   158  			iter.Skip()
   159  		}
   160  
   161  		if iter.isObjectEnd() {
   162  			break
   163  		}
   164  	}
   165  	if iter.Error != nil && iter.Error != io.EOF && len(d.typ.Type1().Name()) != 0 {
   166  		iter.Error = fmt.Errorf("%v.%s", d.typ, iter.Error.Error())
   167  	}
   168  	iter.decrementDepth()
   169  }
   170  
   171  type structFieldDecoder struct {
   172  	field        reflect2.StructField
   173  	fieldDecoder ValDecoder
   174  }
   175  
   176  func (d *structFieldDecoder) Decode(ctx context.Context, ptr unsafe.Pointer, iter *Iterator) {
   177  	fieldPtr := d.field.UnsafeGet(ptr)
   178  	d.fieldDecoder.Decode(ctx, fieldPtr, iter)
   179  	if iter.Error != nil && iter.Error != io.EOF {
   180  		iter.Error = fmt.Errorf("%s: %s", d.field.Name(), iter.Error.Error())
   181  	}
   182  }
   183  
   184  type stringModeStringDecoder struct {
   185  	elemDecoder ValDecoder
   186  	cfg         *frozenConfig
   187  }
   188  
   189  func (d *stringModeStringDecoder) Decode(ctx context.Context, ptr unsafe.Pointer, iter *Iterator) {
   190  	d.elemDecoder.Decode(ctx, ptr, iter)
   191  	str := *((*string)(ptr))
   192  	tempIter := d.cfg.BorrowIterator([]byte(str))
   193  	defer d.cfg.ReturnIterator(tempIter)
   194  	*((*string)(ptr)) = tempIter.ReadString()
   195  }
   196  
   197  type stringModeNumberDecoder struct {
   198  	decoder ValDecoder
   199  }
   200  
   201  func (d *stringModeNumberDecoder) Decode(ctx context.Context, ptr unsafe.Pointer, iter *Iterator) {
   202  	if iter.WhatIsNext() == NilValue {
   203  		d.decoder.Decode(ctx, ptr, iter)
   204  		return
   205  	}
   206  
   207  	if c := iter.nextToken(); c != '"' {
   208  		iter.ReportError("stringModeNumberDecoder", `expect ", but found `+string([]byte{c}))
   209  		return
   210  	}
   211  	d.decoder.Decode(ctx, ptr, iter)
   212  	if iter.Error != nil {
   213  		return
   214  	}
   215  	if c := iter.readByte(); c != '"' {
   216  		iter.ReportError("stringModeNumberDecoder", `expect ", but found `+string([]byte{c}))
   217  		return
   218  	}
   219  }
   220  
   221  type stringModeNumberCompatibleDecoder struct {
   222  	decoder ValDecoder
   223  }
   224  
   225  func (d *stringModeNumberCompatibleDecoder) Decode(ctx context.Context, ptr unsafe.Pointer, iter *Iterator) {
   226  	if iter.WhatIsNext() == NilValue {
   227  		d.decoder.Decode(ctx, ptr, iter)
   228  		return
   229  	}
   230  
   231  	isString := iter.nextToken() == '"'
   232  	if !isString {
   233  		iter.unreadByte()
   234  	}
   235  	d.decoder.Decode(ctx, ptr, iter)
   236  	if iter.Error != nil {
   237  		return
   238  	}
   239  
   240  	if isString {
   241  		if c := iter.readByte(); c != '"' {
   242  			iter.ReportError("stringModeNumberCompatibleDecoder", `expect ", but found `+string([]byte{c}))
   243  			return
   244  		}
   245  	}
   246  }