1package 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}
326