blob: f6b8aeab0a12dd61faf85156fd8dea10c96a8c9c [file] [log] [blame]
Zack Williamse940c7a2019-08-21 14:25:39 -07001package jsoniter
2
3import (
4 "errors"
5 "fmt"
6 "github.com/modern-go/reflect2"
7 "io"
8 "reflect"
9 "strconv"
10 "unsafe"
11)
12
13// Any generic object representation.
14// The lazy json implementation holds []byte and parse lazily.
15type Any interface {
16 LastError() error
17 ValueType() ValueType
18 MustBeValid() Any
19 ToBool() bool
20 ToInt() int
21 ToInt32() int32
22 ToInt64() int64
23 ToUint() uint
24 ToUint32() uint32
25 ToUint64() uint64
26 ToFloat32() float32
27 ToFloat64() float64
28 ToString() string
29 ToVal(val interface{})
30 Get(path ...interface{}) Any
31 Size() int
32 Keys() []string
33 GetInterface() interface{}
34 WriteTo(stream *Stream)
35}
36
37type baseAny struct{}
38
39func (any *baseAny) Get(path ...interface{}) Any {
40 return &invalidAny{baseAny{}, fmt.Errorf("GetIndex %v from simple value", path)}
41}
42
43func (any *baseAny) Size() int {
44 return 0
45}
46
47func (any *baseAny) Keys() []string {
48 return []string{}
49}
50
51func (any *baseAny) ToVal(obj interface{}) {
52 panic("not implemented")
53}
54
55// WrapInt32 turn int32 into Any interface
56func WrapInt32(val int32) Any {
57 return &int32Any{baseAny{}, val}
58}
59
60// WrapInt64 turn int64 into Any interface
61func WrapInt64(val int64) Any {
62 return &int64Any{baseAny{}, val}
63}
64
65// WrapUint32 turn uint32 into Any interface
66func WrapUint32(val uint32) Any {
67 return &uint32Any{baseAny{}, val}
68}
69
70// WrapUint64 turn uint64 into Any interface
71func WrapUint64(val uint64) Any {
72 return &uint64Any{baseAny{}, val}
73}
74
75// WrapFloat64 turn float64 into Any interface
76func WrapFloat64(val float64) Any {
77 return &floatAny{baseAny{}, val}
78}
79
80// WrapString turn string into Any interface
81func WrapString(val string) Any {
82 return &stringAny{baseAny{}, val}
83}
84
85// Wrap turn a go object into Any interface
86func Wrap(val interface{}) Any {
87 if val == nil {
88 return &nilAny{}
89 }
90 asAny, isAny := val.(Any)
91 if isAny {
92 return asAny
93 }
94 typ := reflect2.TypeOf(val)
95 switch typ.Kind() {
96 case reflect.Slice:
97 return wrapArray(val)
98 case reflect.Struct:
99 return wrapStruct(val)
100 case reflect.Map:
101 return wrapMap(val)
102 case reflect.String:
103 return WrapString(val.(string))
104 case reflect.Int:
105 if strconv.IntSize == 32 {
106 return WrapInt32(int32(val.(int)))
107 }
108 return WrapInt64(int64(val.(int)))
109 case reflect.Int8:
110 return WrapInt32(int32(val.(int8)))
111 case reflect.Int16:
112 return WrapInt32(int32(val.(int16)))
113 case reflect.Int32:
114 return WrapInt32(val.(int32))
115 case reflect.Int64:
116 return WrapInt64(val.(int64))
117 case reflect.Uint:
118 if strconv.IntSize == 32 {
119 return WrapUint32(uint32(val.(uint)))
120 }
121 return WrapUint64(uint64(val.(uint)))
122 case reflect.Uintptr:
123 if ptrSize == 32 {
124 return WrapUint32(uint32(val.(uintptr)))
125 }
126 return WrapUint64(uint64(val.(uintptr)))
127 case reflect.Uint8:
128 return WrapUint32(uint32(val.(uint8)))
129 case reflect.Uint16:
130 return WrapUint32(uint32(val.(uint16)))
131 case reflect.Uint32:
132 return WrapUint32(uint32(val.(uint32)))
133 case reflect.Uint64:
134 return WrapUint64(val.(uint64))
135 case reflect.Float32:
136 return WrapFloat64(float64(val.(float32)))
137 case reflect.Float64:
138 return WrapFloat64(val.(float64))
139 case reflect.Bool:
140 if val.(bool) == true {
141 return &trueAny{}
142 }
143 return &falseAny{}
144 }
145 return &invalidAny{baseAny{}, fmt.Errorf("unsupported type: %v", typ)}
146}
147
148// ReadAny read next JSON element as an Any object. It is a better json.RawMessage.
149func (iter *Iterator) ReadAny() Any {
150 return iter.readAny()
151}
152
153func (iter *Iterator) readAny() Any {
154 c := iter.nextToken()
155 switch c {
156 case '"':
157 iter.unreadByte()
158 return &stringAny{baseAny{}, iter.ReadString()}
159 case 'n':
160 iter.skipThreeBytes('u', 'l', 'l') // null
161 return &nilAny{}
162 case 't':
163 iter.skipThreeBytes('r', 'u', 'e') // true
164 return &trueAny{}
165 case 'f':
166 iter.skipFourBytes('a', 'l', 's', 'e') // false
167 return &falseAny{}
168 case '{':
169 return iter.readObjectAny()
170 case '[':
171 return iter.readArrayAny()
172 case '-':
173 return iter.readNumberAny(false)
174 case 0:
175 return &invalidAny{baseAny{}, errors.New("input is empty")}
176 default:
177 return iter.readNumberAny(true)
178 }
179}
180
181func (iter *Iterator) readNumberAny(positive bool) Any {
182 iter.startCapture(iter.head - 1)
183 iter.skipNumber()
184 lazyBuf := iter.stopCapture()
185 return &numberLazyAny{baseAny{}, iter.cfg, lazyBuf, nil}
186}
187
188func (iter *Iterator) readObjectAny() Any {
189 iter.startCapture(iter.head - 1)
190 iter.skipObject()
191 lazyBuf := iter.stopCapture()
192 return &objectLazyAny{baseAny{}, iter.cfg, lazyBuf, nil}
193}
194
195func (iter *Iterator) readArrayAny() Any {
196 iter.startCapture(iter.head - 1)
197 iter.skipArray()
198 lazyBuf := iter.stopCapture()
199 return &arrayLazyAny{baseAny{}, iter.cfg, lazyBuf, nil}
200}
201
202func locateObjectField(iter *Iterator, target string) []byte {
203 var found []byte
204 iter.ReadObjectCB(func(iter *Iterator, field string) bool {
205 if field == target {
206 found = iter.SkipAndReturnBytes()
207 return false
208 }
209 iter.Skip()
210 return true
211 })
212 return found
213}
214
215func locateArrayElement(iter *Iterator, target int) []byte {
216 var found []byte
217 n := 0
218 iter.ReadArrayCB(func(iter *Iterator) bool {
219 if n == target {
220 found = iter.SkipAndReturnBytes()
221 return false
222 }
223 iter.Skip()
224 n++
225 return true
226 })
227 return found
228}
229
230func locatePath(iter *Iterator, path []interface{}) Any {
231 for i, pathKeyObj := range path {
232 switch pathKey := pathKeyObj.(type) {
233 case string:
234 valueBytes := locateObjectField(iter, pathKey)
235 if valueBytes == nil {
236 return newInvalidAny(path[i:])
237 }
238 iter.ResetBytes(valueBytes)
239 case int:
240 valueBytes := locateArrayElement(iter, pathKey)
241 if valueBytes == nil {
242 return newInvalidAny(path[i:])
243 }
244 iter.ResetBytes(valueBytes)
245 case int32:
246 if '*' == pathKey {
247 return iter.readAny().Get(path[i:]...)
248 }
249 return newInvalidAny(path[i:])
250 default:
251 return newInvalidAny(path[i:])
252 }
253 }
254 if iter.Error != nil && iter.Error != io.EOF {
255 return &invalidAny{baseAny{}, iter.Error}
256 }
257 return iter.readAny()
258}
259
260var anyType = reflect2.TypeOfPtr((*Any)(nil)).Elem()
261
262func createDecoderOfAny(ctx *ctx, typ reflect2.Type) ValDecoder {
263 if typ == anyType {
264 return &directAnyCodec{}
265 }
266 if typ.Implements(anyType) {
267 return &anyCodec{
268 valType: typ,
269 }
270 }
271 return nil
272}
273
274func createEncoderOfAny(ctx *ctx, typ reflect2.Type) ValEncoder {
275 if typ == anyType {
276 return &directAnyCodec{}
277 }
278 if typ.Implements(anyType) {
279 return &anyCodec{
280 valType: typ,
281 }
282 }
283 return nil
284}
285
286type anyCodec struct {
287 valType reflect2.Type
288}
289
290func (codec *anyCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
291 panic("not implemented")
292}
293
294func (codec *anyCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
295 obj := codec.valType.UnsafeIndirect(ptr)
296 any := obj.(Any)
297 any.WriteTo(stream)
298}
299
300func (codec *anyCodec) IsEmpty(ptr unsafe.Pointer) bool {
301 obj := codec.valType.UnsafeIndirect(ptr)
302 any := obj.(Any)
303 return any.Size() == 0
304}
305
306type directAnyCodec struct {
307}
308
309func (codec *directAnyCodec) Decode(ptr unsafe.Pointer, iter *Iterator) {
310 *(*Any)(ptr) = iter.readAny()
311}
312
313func (codec *directAnyCodec) Encode(ptr unsafe.Pointer, stream *Stream) {
314 any := *(*Any)(ptr)
315 if any == nil {
316 stream.WriteNil()
317 return
318 }
319 any.WriteTo(stream)
320}
321
322func (codec *directAnyCodec) IsEmpty(ptr unsafe.Pointer) bool {
323 any := *(*Any)(ptr)
324 return any.Size() == 0
325}