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

     1  package jsoni
     2  
     3  import (
     4  	"context"
     5  	"reflect"
     6  	"unsafe"
     7  
     8  	"github.com/modern-go/reflect2"
     9  )
    10  
    11  type dynamicEncoder struct {
    12  	valType reflect2.Type
    13  }
    14  
    15  func (e *dynamicEncoder) Encode(ctx context.Context, ptr unsafe.Pointer, stream *Stream) {
    16  	obj := e.valType.UnsafeIndirect(ptr)
    17  	stream.WriteVal(ctx, obj)
    18  }
    19  
    20  func (e *dynamicEncoder) IsEmpty(_ context.Context, ptr unsafe.Pointer, checkZero bool) bool {
    21  	obj := e.valType.UnsafeIndirect(ptr)
    22  	return reflect2.IsNil(obj) || checkZero && reflect.ValueOf(obj).IsZero()
    23  }
    24  
    25  type efaceDecoder struct{}
    26  
    27  func (d *efaceDecoder) Decode(ctx context.Context, ptr unsafe.Pointer, iter *Iterator) {
    28  	pObj := (*interface{})(ptr)
    29  	obj := *pObj
    30  	if obj == nil {
    31  		*pObj = iter.Read(ctx)
    32  		return
    33  	}
    34  	typ := reflect2.TypeOf(obj)
    35  	if typ.Kind() != reflect.Ptr {
    36  		*pObj = iter.Read(ctx)
    37  		return
    38  	}
    39  	ptrType := typ.(*reflect2.UnsafePtrType)
    40  	ptrElemType := ptrType.Elem()
    41  	if iter.WhatIsNext() == NilValue {
    42  		if ptrElemType.Kind() != reflect.Ptr {
    43  			iter.skip4Bytes('n', 'u', 'l', 'l')
    44  			*pObj = nil
    45  			return
    46  		}
    47  	}
    48  	if reflect2.IsNil(obj) {
    49  		obj := ptrElemType.New()
    50  		iter.ReadVal(ctx, obj)
    51  		*pObj = obj
    52  		return
    53  	}
    54  	iter.ReadVal(ctx, obj)
    55  }
    56  
    57  type ifaceDecoder struct {
    58  	valType *reflect2.UnsafeIFaceType
    59  }
    60  
    61  func (d *ifaceDecoder) Decode(ctx context.Context, ptr unsafe.Pointer, iter *Iterator) {
    62  	if iter.ReadNil() {
    63  		d.valType.UnsafeSet(ptr, d.valType.UnsafeNew())
    64  		return
    65  	}
    66  	obj := d.valType.UnsafeIndirect(ptr)
    67  	if reflect2.IsNil(obj) {
    68  		iter.ReportError("decode non empty interface", "can not unmarshal into nil")
    69  		return
    70  	}
    71  	iter.ReadVal(ctx, obj)
    72  }