1package decoder
2
3import (
4	"unsafe"
5
6	"github.com/goccy/go-json/internal/errors"
7	"github.com/goccy/go-json/internal/runtime"
8)
9
10type arrayDecoder struct {
11	elemType     *runtime.Type
12	size         uintptr
13	valueDecoder Decoder
14	alen         int
15	structName   string
16	fieldName    string
17	zeroValue    unsafe.Pointer
18}
19
20func newArrayDecoder(dec Decoder, elemType *runtime.Type, alen int, structName, fieldName string) *arrayDecoder {
21	zeroValue := *(*unsafe.Pointer)(unsafe_New(elemType))
22	return &arrayDecoder{
23		valueDecoder: dec,
24		elemType:     elemType,
25		size:         elemType.Size(),
26		alen:         alen,
27		structName:   structName,
28		fieldName:    fieldName,
29		zeroValue:    zeroValue,
30	}
31}
32
33func (d *arrayDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
34	depth++
35	if depth > maxDecodeNestingDepth {
36		return errors.ErrExceededMaxDepth(s.char(), s.cursor)
37	}
38
39	for {
40		switch s.char() {
41		case ' ', '\n', '\t', '\r':
42		case 'n':
43			if err := nullBytes(s); err != nil {
44				return err
45			}
46			return nil
47		case '[':
48			idx := 0
49			s.cursor++
50			if s.skipWhiteSpace() == ']' {
51				for idx < d.alen {
52					*(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
53					idx++
54				}
55				s.cursor++
56				return nil
57			}
58			for {
59				if idx < d.alen {
60					if err := d.valueDecoder.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size)); err != nil {
61						return err
62					}
63				} else {
64					if err := s.skipValue(depth); err != nil {
65						return err
66					}
67				}
68				idx++
69				switch s.skipWhiteSpace() {
70				case ']':
71					for idx < d.alen {
72						*(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
73						idx++
74					}
75					s.cursor++
76					return nil
77				case ',':
78					s.cursor++
79					continue
80				case nul:
81					if s.read() {
82						s.cursor++
83						continue
84					}
85					goto ERROR
86				default:
87					goto ERROR
88				}
89			}
90		case nul:
91			if s.read() {
92				continue
93			}
94			goto ERROR
95		default:
96			goto ERROR
97		}
98		s.cursor++
99	}
100ERROR:
101	return errors.ErrUnexpectedEndOfJSON("array", s.totalOffset())
102}
103
104func (d *arrayDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
105	buf := ctx.Buf
106	depth++
107	if depth > maxDecodeNestingDepth {
108		return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
109	}
110
111	for {
112		switch buf[cursor] {
113		case ' ', '\n', '\t', '\r':
114			cursor++
115			continue
116		case 'n':
117			if err := validateNull(buf, cursor); err != nil {
118				return 0, err
119			}
120			cursor += 4
121			return cursor, nil
122		case '[':
123			idx := 0
124			cursor++
125			cursor = skipWhiteSpace(buf, cursor)
126			if buf[cursor] == ']' {
127				for idx < d.alen {
128					*(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
129					idx++
130				}
131				cursor++
132				return cursor, nil
133			}
134			for {
135				if idx < d.alen {
136					c, err := d.valueDecoder.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size))
137					if err != nil {
138						return 0, err
139					}
140					cursor = c
141				} else {
142					c, err := skipValue(buf, cursor, depth)
143					if err != nil {
144						return 0, err
145					}
146					cursor = c
147				}
148				idx++
149				cursor = skipWhiteSpace(buf, cursor)
150				switch buf[cursor] {
151				case ']':
152					for idx < d.alen {
153						*(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
154						idx++
155					}
156					cursor++
157					return cursor, nil
158				case ',':
159					cursor++
160					continue
161				default:
162					return 0, errors.ErrInvalidCharacter(buf[cursor], "array", cursor)
163				}
164			}
165		default:
166			return 0, errors.ErrUnexpectedEndOfJSON("array", cursor)
167		}
168	}
169}
170