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