forked from francoispqt/gojay
-
Notifications
You must be signed in to change notification settings - Fork 0
/
decode_interface.go
130 lines (120 loc) · 2.84 KB
/
decode_interface.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package gojay
// TODO @afiune for now we are using the standard json unmarshaling but in
// the future it would be great to implement one here inside this repo
import "encoding/json"
// DecodeInterface reads the next JSON-encoded value from the decoder's input (io.Reader) and stores it in the value pointed to by i.
//
// i must be an interface poiter
func (dec *Decoder) DecodeInterface(i *interface{}) error {
if dec.isPooled == 1 {
panic(InvalidUsagePooledDecoderError("Invalid usage of pooled decoder"))
}
err := dec.decodeInterface(i)
return err
}
func (dec *Decoder) decodeInterface(i *interface{}) error {
start, end, err := dec.getObject()
if err != nil {
dec.cursor = start
return err
}
// if start & end are equal the object is a null, don't unmarshal
if start == end {
return nil
}
object := dec.data[start:end]
if err = json.Unmarshal(object, i); err != nil {
return err
}
dec.cursor = end
return nil
}
// @afiune Maybe return the type as well?
func (dec *Decoder) getObject() (start int, end int, err error) {
// start cursor
for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
switch dec.data[dec.cursor] {
case ' ', '\n', '\t', '\r', ',':
continue
// is null
case 'n':
dec.cursor++
err = dec.assertNull()
if err != nil {
return
}
// Set start & end to the same cursor to indicate the object
// is a null and should not be unmarshal
start = dec.cursor
end = dec.cursor
return
case 't':
start = dec.cursor
dec.cursor++
err = dec.assertTrue()
if err != nil {
return
}
end = dec.cursor
dec.cursor++
return
// is false
case 'f':
start = dec.cursor
dec.cursor++
err = dec.assertFalse()
if err != nil {
return
}
end = dec.cursor
dec.cursor++
return
// is an object
case '{':
start = dec.cursor
dec.cursor++
end, err = dec.skipObject()
dec.cursor = end
return
// is string
case '"':
start = dec.cursor
dec.cursor++
start, end, err = dec.getString()
start--
dec.cursor = end
return
// is array
case '[':
start = dec.cursor
dec.cursor++
end, err = dec.skipArray()
dec.cursor = end
return
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-':
start = dec.cursor
end, err = dec.skipNumber()
dec.cursor = end
return
default:
err = dec.raiseInvalidJSONErr(dec.cursor)
return
}
}
err = dec.raiseInvalidJSONErr(dec.cursor)
return
}
// Add Values functions
// AddInterface decodes the JSON value within an object or an array to a interface{}.
func (dec *Decoder) AddInterface(v *interface{}) error {
return dec.Interface(v)
}
// Interface decodes the JSON value within an object or an array to an interface{}.
func (dec *Decoder) Interface(value *interface{}) error {
err := dec.decodeInterface(value)
if err != nil {
return err
}
dec.called |= 1
return nil
}