| package jsoniter |
| |
| import ( |
| "fmt" |
| "github.com/modern-go/reflect2" |
| "io" |
| "unsafe" |
| ) |
| |
| func decoderOfArray(ctx *ctx, typ reflect2.Type) ValDecoder { |
| arrayType := typ.(*reflect2.UnsafeArrayType) |
| decoder := decoderOfType(ctx.append("[arrayElem]"), arrayType.Elem()) |
| return &arrayDecoder{arrayType, decoder} |
| } |
| |
| func encoderOfArray(ctx *ctx, typ reflect2.Type) ValEncoder { |
| arrayType := typ.(*reflect2.UnsafeArrayType) |
| if arrayType.Len() == 0 { |
| return emptyArrayEncoder{} |
| } |
| encoder := encoderOfType(ctx.append("[arrayElem]"), arrayType.Elem()) |
| return &arrayEncoder{arrayType, encoder} |
| } |
| |
| type emptyArrayEncoder struct{} |
| |
| func (encoder emptyArrayEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { |
| stream.WriteEmptyArray() |
| } |
| |
| func (encoder emptyArrayEncoder) IsEmpty(ptr unsafe.Pointer) bool { |
| return true |
| } |
| |
| type arrayEncoder struct { |
| arrayType *reflect2.UnsafeArrayType |
| elemEncoder ValEncoder |
| } |
| |
| func (encoder *arrayEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { |
| stream.WriteArrayStart() |
| elemPtr := unsafe.Pointer(ptr) |
| encoder.elemEncoder.Encode(elemPtr, stream) |
| for i := 1; i < encoder.arrayType.Len(); i++ { |
| stream.WriteMore() |
| elemPtr = encoder.arrayType.UnsafeGetIndex(ptr, i) |
| encoder.elemEncoder.Encode(elemPtr, stream) |
| } |
| stream.WriteArrayEnd() |
| if stream.Error != nil && stream.Error != io.EOF { |
| stream.Error = fmt.Errorf("%v: %s", encoder.arrayType, stream.Error.Error()) |
| } |
| } |
| |
| func (encoder *arrayEncoder) IsEmpty(ptr unsafe.Pointer) bool { |
| return false |
| } |
| |
| type arrayDecoder struct { |
| arrayType *reflect2.UnsafeArrayType |
| elemDecoder ValDecoder |
| } |
| |
| func (decoder *arrayDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { |
| decoder.doDecode(ptr, iter) |
| if iter.Error != nil && iter.Error != io.EOF { |
| iter.Error = fmt.Errorf("%v: %s", decoder.arrayType, iter.Error.Error()) |
| } |
| } |
| |
| func (decoder *arrayDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) { |
| c := iter.nextToken() |
| arrayType := decoder.arrayType |
| if c == 'n' { |
| iter.skipThreeBytes('u', 'l', 'l') |
| return |
| } |
| if c != '[' { |
| iter.ReportError("decode array", "expect [ or n, but found "+string([]byte{c})) |
| return |
| } |
| c = iter.nextToken() |
| if c == ']' { |
| return |
| } |
| iter.unreadByte() |
| elemPtr := arrayType.UnsafeGetIndex(ptr, 0) |
| decoder.elemDecoder.Decode(elemPtr, iter) |
| length := 1 |
| for c = iter.nextToken(); c == ','; c = iter.nextToken() { |
| if length >= arrayType.Len() { |
| iter.Skip() |
| continue |
| } |
| idx := length |
| length += 1 |
| elemPtr = arrayType.UnsafeGetIndex(ptr, idx) |
| decoder.elemDecoder.Decode(elemPtr, iter) |
| } |
| if c != ']' { |
| iter.ReportError("decode array", "expect ], but found "+string([]byte{c})) |
| return |
| } |
| } |