-
Notifications
You must be signed in to change notification settings - Fork 8
/
array.go
105 lines (97 loc) · 2.01 KB
/
array.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
package sonnet
import (
"reflect"
"strconv"
"sync"
)
func compileArrayDecoder(typ reflect.Type) decoder {
length := typ.Len()
elm := typ.Elem()
fnc, ok := decs.get(elm)
rep := func() {
if !ok {
fnc = compileDecoder(elm)
decs.set(elm, fnc)
}
}
var once sync.Once
return func(head byte, val reflect.Value, dec *Decoder) error {
const ull = "ull"
if head == 'n' {
part, err := dec.readn(len(ull))
if err == nil && string(part) != ull {
err = dec.buildErrSyntax(head, ull, part)
}
return err
}
if head != '[' {
return dec.errUnmarshalType(head, val.Type())
}
err := dec.inc()
if err != nil {
return err
}
once.Do(rep)
val.SetZero()
for idx := 0; idx < length; idx++ {
dec.eatSpaces()
if dec.pos >= len(dec.buf) && !dec.fill() {
return dec.errSyntax("unexpected EOF reading a byte")
}
head = dec.buf[dec.pos]
dec.pos++
if head == ']' && idx == 0 {
dec.dep--
return nil
}
err = fnc(head, val.Index(idx), dec)
if err != nil {
return err
}
dec.eatSpaces()
if dec.pos >= len(dec.buf) && !dec.fill() {
return dec.errSyntax("unexpected EOF reading a byte")
}
head = dec.buf[dec.pos]
dec.pos++
if head == ']' {
dec.dep--
return nil
}
if head != ',' {
return dec.errSyntax("invalid character " + strconv.QuoteRune(rune(head)) + " after array element")
}
}
dec.dep--
return dec.skipArray(length != 0)
}
}
func compileArrayEncoder(typ reflect.Type) encoder {
length := typ.Len()
elm := typ.Elem()
fnc, ok := encs.get(elm)
rep := func() {
if !ok {
fnc = compileEncoder(elm, true)
encs.set(elm, fnc)
}
}
var once sync.Once
return func(dst []byte, val reflect.Value, enc *Encoder) ([]byte, error) {
once.Do(rep)
dst = append(dst, '[')
var mid bool
for idx := 0; idx < length; idx++ {
if mid {
dst = append(dst, ',')
}
var err error
dst, err = fnc(dst, val.Index(idx), enc)
if err != nil {
return nil, err
}
mid = true
}
return append(dst, ']'), nil
}
}