github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/jsoni/reflect_array.go (about) 1 package jsoni 2 3 import ( 4 "context" 5 "fmt" 6 "io" 7 "unsafe" 8 9 "github.com/modern-go/reflect2" 10 ) 11 12 func decoderOfArray(ctx *ctx, typ reflect2.Type) ValDecoder { 13 arrayType := typ.(*reflect2.UnsafeArrayType) 14 decoder := decoderOfType(ctx.append("[arrayElem]"), arrayType.Elem()) 15 return &arrayDecoder{arrayType, decoder} 16 } 17 18 func encoderOfArray(ctx *ctx, typ reflect2.Type) ValEncoder { 19 arrayType := typ.(*reflect2.UnsafeArrayType) 20 if arrayType.Len() == 0 { 21 return emptyArrayEncoder{} 22 } 23 encoder := encoderOfType(ctx.append("[arrayElem]"), arrayType.Elem()) 24 return &arrayEncoder{arrayType, encoder} 25 } 26 27 type emptyArrayEncoder struct{} 28 29 func (e emptyArrayEncoder) Encode(_ context.Context, _ unsafe.Pointer, stream *Stream) { 30 stream.WriteEmptyArray() 31 } 32 func (e emptyArrayEncoder) IsEmpty(context.Context, unsafe.Pointer, bool) bool { return true } 33 34 type arrayEncoder struct { 35 arrayType *reflect2.UnsafeArrayType 36 elemEncoder ValEncoder 37 } 38 39 func (e *arrayEncoder) Encode(ctx context.Context, ptr unsafe.Pointer, stream *Stream) { 40 stream.WriteArrayStart() 41 elemPtr := ptr 42 e.elemEncoder.Encode(ctx, elemPtr, stream) 43 for i := 1; i < e.arrayType.Len(); i++ { 44 stream.WriteMore() 45 elemPtr = e.arrayType.UnsafeGetIndex(ptr, i) 46 e.elemEncoder.Encode(ctx, elemPtr, stream) 47 } 48 stream.WriteArrayEnd() 49 if stream.Error != nil && stream.Error != io.EOF { 50 stream.Error = fmt.Errorf("%v: %s", e.arrayType, stream.Error.Error()) 51 } 52 } 53 54 func (e *arrayEncoder) IsEmpty(context.Context, unsafe.Pointer, bool) bool { return false } 55 56 type arrayDecoder struct { 57 arrayType *reflect2.UnsafeArrayType 58 elemDecoder ValDecoder 59 } 60 61 func (d *arrayDecoder) Decode(ctx context.Context, ptr unsafe.Pointer, iter *Iterator) { 62 d.doDecode(ctx, ptr, iter) 63 if iter.Error != nil && iter.Error != io.EOF { 64 iter.Error = fmt.Errorf("%v: %s", d.arrayType, iter.Error.Error()) 65 } 66 } 67 68 func (d *arrayDecoder) doDecode(ctx context.Context, ptr unsafe.Pointer, iter *Iterator) { 69 c := iter.nextToken() 70 arrayType := d.arrayType 71 if c == 'n' { 72 iter.skip3Bytes('u', 'l', 'l') 73 return 74 } 75 if c != '[' { 76 iter.ReportError("decode array", "expect [ or n, but found "+string([]byte{c})) 77 return 78 } 79 c = iter.nextToken() 80 if c == ']' { 81 return 82 } 83 iter.unreadByte() 84 elemPtr := arrayType.UnsafeGetIndex(ptr, 0) 85 d.elemDecoder.Decode(ctx, elemPtr, iter) 86 length := 1 87 for c = iter.nextToken(); c == ','; c = iter.nextToken() { 88 if length >= arrayType.Len() { 89 iter.Skip() 90 continue 91 } 92 idx := length 93 length += 1 94 elemPtr = arrayType.UnsafeGetIndex(ptr, idx) 95 d.elemDecoder.Decode(ctx, elemPtr, iter) 96 } 97 if c != ']' { 98 iter.ReportError("decode array", "expect ], but found "+string([]byte{c})) 99 return 100 } 101 }