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 }