1// Copyright (C) MongoDB, Inc. 2014-present.
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may
4// not use this file except in compliance with the License. You may obtain
5// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6
7package json
8
9import (
10	"fmt"
11	"gopkg.in/mgo.v2/bson"
12	"reflect"
13)
14
15// Represents base-64 encoded binary data
16type BinData struct {
17	Type   byte
18	Base64 string
19}
20
21// Represents the number of milliseconds since the Unix epoch.
22type Date int64
23
24type ISODate string
25
26type ObjectId string
27
28// Represents a reference to another document.
29type DBRef struct {
30	Collection string
31	Id         interface{}
32	Database   string // optional
33}
34
35// Refers to a document in some namespace by wrapping a string containing the namespace
36// and the objectId in which the _id of the document is contained
37type DBPointer struct {
38	Namespace string
39	Id        bson.ObjectId
40}
41
42// Represents the literal MinKey.
43type MinKey struct{}
44
45// Represents the literal MaxKey.
46type MaxKey struct{}
47
48// Represents a signed 32-bit integer.
49type NumberInt int32
50
51// Represents a signed 64-bit integer.
52type NumberLong int64
53
54// Represents a signed 64-bit float.
55type NumberFloat float64
56
57type Decimal128 struct {
58	bson.Decimal128
59}
60
61// Represents a regular expression.
62type RegExp struct {
63	Pattern string
64	Options string
65}
66
67// Represents a timestamp value.
68type Timestamp struct {
69	Seconds   uint32
70	Increment uint32
71}
72
73type JavaScript struct {
74	Code  string
75	Scope interface{}
76}
77
78type Float float64
79
80// Represents the literal undefined.
81type Undefined struct{}
82
83var (
84	// primitive types
85	byteType   = reflect.TypeOf(byte(0))
86	stringType = reflect.TypeOf(string(""))
87	uint32Type = reflect.TypeOf(uint32(0))
88
89	// object types
90	binDataType     = reflect.TypeOf(BinData{})
91	dateType        = reflect.TypeOf(Date(0))
92	isoDateType     = reflect.TypeOf(ISODate(""))
93	dbRefType       = reflect.TypeOf(DBRef{})
94	dbPointerType   = reflect.TypeOf(DBPointer{})
95	maxKeyType      = reflect.TypeOf(MaxKey{})
96	minKeyType      = reflect.TypeOf(MinKey{})
97	numberIntType   = reflect.TypeOf(NumberInt(0))
98	numberLongType  = reflect.TypeOf(NumberLong(0))
99	numberFloatType = reflect.TypeOf(NumberFloat(0))
100	objectIdType    = reflect.TypeOf(ObjectId(""))
101	regexpType      = reflect.TypeOf(RegExp{})
102	timestampType   = reflect.TypeOf(Timestamp{})
103	undefinedType   = reflect.TypeOf(Undefined{})
104	orderedBSONType = reflect.TypeOf(bson.D{})
105	interfaceType   = reflect.TypeOf((*interface{})(nil))
106)
107
108func (d Date) isFormatable() bool {
109	return int64(d) < int64(32535215999000)
110}
111
112func stateBeginExtendedValue(s *scanner, c int) int {
113	switch c {
114	case 'u': // beginning of undefined
115		s.step = stateU
116	case 'B': // beginning of BinData or Boolean
117		s.step = stateB
118	case 'D': // beginning of Date
119		s.step = stateD
120	case 'I': // beginning of Infinity or ISODate
121		s.step = stateI
122	case 'M': // beginning of MinKey or MaxKey
123		s.step = stateM
124	case 'N': // beginning of NaN or NumberXX
125		s.step = stateUpperN
126	case 'O': // beginning of ObjectId
127		s.step = stateO
128	case 'R': // beginning of RegExp
129		s.step = stateR
130	case 'T': // beginning of Timestamp
131		s.step = stateUpperT
132	case '/': // beginning of /foo/i
133		s.step = stateInRegexpPattern
134	default:
135		return s.error(c, "looking for beginning of value")
136	}
137
138	return scanBeginLiteral
139}
140
141// stateB is the state after reading `B`.
142func stateB(s *scanner, c int) int {
143	if c == 'i' {
144		s.step = stateBi
145		return scanContinue
146	}
147	if c == 'o' {
148		s.step = stateBo
149		return scanContinue
150	}
151	return s.error(c, "in literal BinData or Boolean (expecting 'i' or 'o')")
152}
153
154// stateUpperN is the state after reading `N`.
155func stateUpperN(s *scanner, c int) int {
156	if c == 'a' {
157		s.step = stateUpperNa
158		return scanContinue
159	}
160	if c == 'u' {
161		s.step = stateUpperNu
162		return scanContinue
163	}
164	return s.error(c, "in literal NaN or Number (expecting 'a' or 'u')")
165}
166
167// stateM is the state after reading `M`.
168func stateM(s *scanner, c int) int {
169	if c == 'a' {
170		s.step = stateUpperMa
171		return scanContinue
172	}
173	if c == 'i' {
174		s.step = stateUpperMi
175		return scanContinue
176	}
177	return s.error(c, "in literal MaxKey or MinKey (expecting 'a' or 'i')")
178}
179
180// stateD is the state after reading `D`.
181func stateD(s *scanner, c int) int {
182	switch c {
183	case 'a':
184		s.step = stateDa
185	case 'B':
186		s.step = stateDB
187	case 'b':
188		s.step = stateDb
189	default:
190		return s.error(c, "in literal Date or DBRef (expecting 'a' or 'B')")
191	}
192	return scanContinue
193}
194
195// stateDB is the state after reading `DB`.
196func stateDB(s *scanner, c int) int {
197	if c == 'R' {
198		s.step = stateDBR
199		return scanContinue
200	}
201	if c == 'P' {
202		s.step = stateDBP
203		return scanContinue
204	}
205	return s.error(c, "in state DB (expecting 'R or P')")
206}
207
208// stateI is the state after reading `I`.
209func stateI(s *scanner, c int) int {
210	switch c {
211	case 'n':
212		s.step = stateIn
213	case 'S':
214		s.step = stateIS
215	default:
216		return s.error(c, "in literal Infinity or ISO (expecting 'n' or 'S')")
217	}
218	return scanContinue
219}
220
221// Decodes a literal stored in item into v.
222func (d *decodeState) storeExtendedLiteral(item []byte, v reflect.Value, fromQuoted bool) bool {
223	switch c := item[0]; c {
224	case 'n':
225		d.storeNewLiteral(v, fromQuoted)
226
227	case 'u': // undefined
228		switch kind := v.Kind(); kind {
229		case reflect.Interface:
230			v.Set(reflect.ValueOf(Undefined{}))
231		default:
232			d.error(fmt.Errorf("cannot store %v value into %v type", undefinedType, kind))
233		}
234
235	case 'B': // BinData or Boolean
236		switch item[1] {
237		case 'i': // BinData
238			d.storeBinData(v)
239		case 'o': // Boolean
240			d.storeBoolean(v)
241		}
242	case 'D': // Date, DBRef, DBPointer, Dbpointer,or Dbref
243		switch item[1] {
244		case 'a': // Date
245			d.storeDate(v)
246		case 'b': // Dbref
247			d.storeDBRef(v)
248		case 'B': // DBRef or DBPointer
249			switch item[2] {
250			case 'R': //DBRef
251				d.storeDBRef(v)
252			case 'P': //DBPointer
253				d.storeDBPointer(v)
254			}
255		}
256	case 'I':
257		switch item[1] {
258		case 'S': // ISODate
259			d.storeISODate(v)
260		}
261
262	case 'M': // MinKey or MaxKey
263		switch item[1] {
264		case 'i': // MinKey
265			switch kind := v.Kind(); kind {
266			case reflect.Interface:
267				v.Set(reflect.ValueOf(MinKey{}))
268			default:
269				d.error(fmt.Errorf("cannot store %v value into %v type", minKeyType, kind))
270			}
271		case 'a': // MaxKey
272			switch kind := v.Kind(); kind {
273			case reflect.Interface:
274				v.Set(reflect.ValueOf(MaxKey{}))
275			default:
276				d.error(fmt.Errorf("cannot store %v value into %v type", maxKeyType, kind))
277			}
278		}
279
280	case 'O': // ObjectId
281		d.storeObjectId(v)
282
283	case 'N': // NumberInt or NumberLong
284		switch item[6] {
285		case 'I': // NumberInt
286			d.storeNumberInt(v)
287		case 'L': // NumberLong
288			d.storeNumberLong(v)
289		}
290
291	case 'R': // RegExp constructor
292		d.storeRegexp(v)
293
294	case 'T': // Timestamp
295		d.storeTimestamp(v)
296
297	case '/': // regular expression literal
298		op := d.scanWhile(scanSkipSpace)
299		if op != scanRegexpPattern {
300			d.error(fmt.Errorf("expected beginning of regular expression pattern"))
301		}
302
303		pattern, options, err := d.regexp()
304		if err != nil {
305			d.error(err)
306		}
307		switch kind := v.Kind(); kind {
308		case reflect.Interface:
309			v.Set(reflect.ValueOf(RegExp{pattern, options}))
310		default:
311			d.error(fmt.Errorf("cannot store %v value into %v type", regexpType, kind))
312		}
313
314	default:
315		return false
316	}
317
318	return true
319}
320
321// Returns a literal from the underlying byte data.
322func (d *decodeState) getExtendedLiteral(item []byte) (interface{}, bool) {
323	switch c := item[0]; c {
324	case 'n':
325		return d.getNewLiteral(), true
326
327	case 'u': // undefined
328		return Undefined{}, true
329
330	case 'B': // BinData or Boolean
331		switch item[1] {
332		case 'i': // BinData
333			return d.getBinData(), true
334		case 'o': // Boolean
335			return d.getBoolean(), true
336		}
337
338	case 'D': // Date, DBRef, or Dbref
339		switch item[1] {
340		case 'a': // Date
341			return d.getDate(), true
342		case 'b': // Dbref
343			return d.getDBRef(), true
344		case 'B': // DBRef or DBPointer
345			switch item[2] {
346			case 'R': // DBRef
347				return d.getDBRef(), true
348			case 'P': // DBPointer
349				return d.getDBPointer(), true
350			}
351		}
352
353	case 'M': // MinKey or MaxKey
354		switch item[1] {
355		case 'i': // MinKey
356			return MinKey{}, true
357		case 'a': // MaxKey
358			return MaxKey{}, true
359		}
360
361	case 'O': // ObjectId
362		return d.getObjectId(), true
363
364	case 'N': // NumberInt or NumberLong
365		switch item[6] {
366		case 'I': // NumberInt
367			return d.getNumberInt(), true
368		case 'L': // NumberLong
369			return d.getNumberLong(), true
370		}
371
372	case 'R': // RegExp constructor
373		return d.getRegexp(), true
374
375	case 'T': // Timestamp
376		return d.getTimestamp(), true
377
378	case 'I': // ISO Date
379		switch item[1] {
380		case 'S': // ISODate
381			return d.getDate(), true
382		}
383
384	case '/': // regular expression literal
385		op := d.scanWhile(scanSkipSpace)
386		if op != scanRegexpPattern {
387			d.error(fmt.Errorf("expected beginning of regular expression pattern"))
388		}
389
390		pattern, options, err := d.regexp()
391		if err != nil {
392			d.error(err)
393		}
394		return RegExp{pattern, options}, true
395	}
396
397	return nil, false
398}
399