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  }