1package jsoniter
2
3import (
4	"fmt"
5	"io"
6	"reflect"
7	"unsafe"
8)
9
10func decoderOfArray(cfg *frozenConfig, typ reflect.Type) (ValDecoder, error) {
11	decoder, err := decoderOfType(cfg, typ.Elem())
12	if err != nil {
13		return nil, err
14	}
15	return &arrayDecoder{typ, typ.Elem(), decoder}, nil
16}
17
18func encoderOfArray(cfg *frozenConfig, typ reflect.Type) (ValEncoder, error) {
19	encoder, err := encoderOfType(cfg, typ.Elem())
20	if err != nil {
21		return nil, err
22	}
23	if typ.Elem().Kind() == reflect.Map {
24		encoder = &optionalEncoder{encoder}
25	}
26	return &arrayEncoder{typ, typ.Elem(), encoder}, nil
27}
28
29type arrayEncoder struct {
30	arrayType   reflect.Type
31	elemType    reflect.Type
32	elemEncoder ValEncoder
33}
34
35func (encoder *arrayEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
36	stream.WriteArrayStart()
37	elemPtr := unsafe.Pointer(ptr)
38	encoder.elemEncoder.Encode(elemPtr, stream)
39	for i := 1; i < encoder.arrayType.Len(); i++ {
40		stream.WriteMore()
41		elemPtr = unsafe.Pointer(uintptr(elemPtr) + encoder.elemType.Size())
42		encoder.elemEncoder.Encode(unsafe.Pointer(elemPtr), stream)
43	}
44	stream.WriteArrayEnd()
45	if stream.Error != nil && stream.Error != io.EOF {
46		stream.Error = fmt.Errorf("%v: %s", encoder.arrayType, stream.Error.Error())
47	}
48}
49
50func (encoder *arrayEncoder) EncodeInterface(val interface{}, stream *Stream) {
51	// special optimization for interface{}
52	e := (*emptyInterface)(unsafe.Pointer(&val))
53	if e.word == nil {
54		stream.WriteArrayStart()
55		stream.WriteNil()
56		stream.WriteArrayEnd()
57		return
58	}
59	elemType := encoder.arrayType.Elem()
60	if encoder.arrayType.Len() == 1 && (elemType.Kind() == reflect.Ptr || elemType.Kind() == reflect.Map) {
61		ptr := uintptr(e.word)
62		e.word = unsafe.Pointer(&ptr)
63	}
64	if reflect.TypeOf(val).Kind() == reflect.Ptr {
65		encoder.Encode(unsafe.Pointer(&e.word), stream)
66	} else {
67		encoder.Encode(e.word, stream)
68	}
69}
70
71func (encoder *arrayEncoder) IsEmpty(ptr unsafe.Pointer) bool {
72	return false
73}
74
75type arrayDecoder struct {
76	arrayType   reflect.Type
77	elemType    reflect.Type
78	elemDecoder ValDecoder
79}
80
81func (decoder *arrayDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) {
82	decoder.doDecode(ptr, iter)
83	if iter.Error != nil && iter.Error != io.EOF {
84		iter.Error = fmt.Errorf("%v: %s", decoder.arrayType, iter.Error.Error())
85	}
86}
87
88func (decoder *arrayDecoder) doDecode(ptr unsafe.Pointer, iter *Iterator) {
89	offset := uintptr(0)
90	iter.ReadArrayCB(func(iter *Iterator) bool {
91		if offset < decoder.arrayType.Size() {
92			decoder.elemDecoder.Decode(unsafe.Pointer(uintptr(ptr)+offset), iter)
93			offset += decoder.elemType.Size()
94		} else {
95			iter.Skip()
96		}
97		return true
98	})
99}
100