/
decoder_array_slice.go
113 lines (107 loc) · 2.04 KB
/
decoder_array_slice.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package decoder
import (
"encoding/base64"
"encoding/json"
"reflect"
)
func (d *Decoder) decodeSlice(v reflect.Value, elemDecoder DecoderFn) error {
d.SkipWhitespace()
c := d.char()
switch c {
case '[':
case 'n':
err := d.ScanNull()
if err != nil {
return err
}
v.SetZero()
return nil
default:
return d.Error("[Blaze decodeSlice()] invalid char, expected '[' or 'null'")
}
d.depth++
if d.depth > MAX_DEPTH {
return d.Error("[Blaze decodeSlice()] maximum depth reached")
}
size, err := d.ScanArray()
if err != nil {
return err
}
if size == 0 {
return nil
}
cap := v.Cap()
if cap < size {
v.Grow(size - cap)
}
v.SetLen(size)
i := -1
d.pos = d.start + 1
for {
d.SkipWhitespace()
c := d.char()
switch c {
case ',':
i++
d.pos++
d.SkipWhitespace()
err := elemDecoder(d, v.Index(i))
if err != nil {
return err
}
case ']':
d.pos++
d.depth--
return nil
case TERMINATION_CHAR:
return d.Error("[Blaze decodeSlice()] unexpected end of input, expected ']'")
default:
i++
err := elemDecoder(d, v.Index(i))
if err != nil {
return err
}
}
}
}
func newSliceDecoder(t reflect.Type) DecoderFn {
if t.Elem() == reflect.TypeFor[byte]() {
if t == reflect.TypeFor[json.RawMessage]() {
return decodeRawMessage
}
return decodeBytes
}
elemDecoder := newDecoderFn(t.Elem(), true)
return func(d *Decoder, v reflect.Value) error {
return d.decodeSlice(v, elemDecoder)
}
}
func decodeBytes(d *Decoder, v reflect.Value) error {
d.SkipWhitespace()
d.start = d.pos
if d.char() != '"' {
return d.Error("[Blaze decodeBytes()] expected '\"'")
}
d.pos++
b, err := d.unquoteString()
if err != nil {
return err
}
res := make([]byte, base64.StdEncoding.DecodedLen(len(b)))
n, err := base64.StdEncoding.Decode(res, b)
if err != nil {
return err
}
v.SetBytes(res[:n])
return nil
}
func decodeRawMessage(d *Decoder, v reflect.Value) error {
d.SkipWhitespace()
start := d.pos
err := d.Skip()
if err != nil {
return err
}
v.SetBytes(d.Buf[start:d.pos])
return nil
}