extjson_reader.go raw
1 // Copyright (C) MongoDB, Inc. 2017-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
7 package bsonrw
8
9 import (
10 "fmt"
11 "io"
12 "sync"
13
14 "go.mongodb.org/mongo-driver/bson/bsontype"
15 "go.mongodb.org/mongo-driver/bson/primitive"
16 )
17
18 // ExtJSONValueReaderPool is a pool for ValueReaders that read ExtJSON.
19 //
20 // Deprecated: ExtJSONValueReaderPool will not be supported in Go Driver 2.0.
21 type ExtJSONValueReaderPool struct {
22 pool sync.Pool
23 }
24
25 // NewExtJSONValueReaderPool instantiates a new ExtJSONValueReaderPool.
26 //
27 // Deprecated: ExtJSONValueReaderPool will not be supported in Go Driver 2.0.
28 func NewExtJSONValueReaderPool() *ExtJSONValueReaderPool {
29 return &ExtJSONValueReaderPool{
30 pool: sync.Pool{
31 New: func() interface{} {
32 return new(extJSONValueReader)
33 },
34 },
35 }
36 }
37
38 // Get retrieves a ValueReader from the pool and uses src as the underlying ExtJSON.
39 //
40 // Deprecated: ExtJSONValueReaderPool will not be supported in Go Driver 2.0.
41 func (bvrp *ExtJSONValueReaderPool) Get(r io.Reader, canonical bool) (ValueReader, error) {
42 vr := bvrp.pool.Get().(*extJSONValueReader)
43 return vr.reset(r, canonical)
44 }
45
46 // Put inserts a ValueReader into the pool. If the ValueReader is not a ExtJSON ValueReader nothing
47 // is inserted into the pool and ok will be false.
48 //
49 // Deprecated: ExtJSONValueReaderPool will not be supported in Go Driver 2.0.
50 func (bvrp *ExtJSONValueReaderPool) Put(vr ValueReader) (ok bool) {
51 bvr, ok := vr.(*extJSONValueReader)
52 if !ok {
53 return false
54 }
55
56 bvr, _ = bvr.reset(nil, false)
57 bvrp.pool.Put(bvr)
58 return true
59 }
60
61 type ejvrState struct {
62 mode mode
63 vType bsontype.Type
64 depth int
65 }
66
67 // extJSONValueReader is for reading extended JSON.
68 type extJSONValueReader struct {
69 p *extJSONParser
70
71 stack []ejvrState
72 frame int
73 }
74
75 // NewExtJSONValueReader creates a new ValueReader from a given io.Reader
76 // It will interpret the JSON of r as canonical or relaxed according to the
77 // given canonical flag
78 func NewExtJSONValueReader(r io.Reader, canonical bool) (ValueReader, error) {
79 return newExtJSONValueReader(r, canonical)
80 }
81
82 func newExtJSONValueReader(r io.Reader, canonical bool) (*extJSONValueReader, error) {
83 ejvr := new(extJSONValueReader)
84 return ejvr.reset(r, canonical)
85 }
86
87 func (ejvr *extJSONValueReader) reset(r io.Reader, canonical bool) (*extJSONValueReader, error) {
88 p := newExtJSONParser(r, canonical)
89 typ, err := p.peekType()
90
91 if err != nil {
92 return nil, ErrInvalidJSON
93 }
94
95 var m mode
96 switch typ {
97 case bsontype.EmbeddedDocument:
98 m = mTopLevel
99 case bsontype.Array:
100 m = mArray
101 default:
102 m = mValue
103 }
104
105 stack := make([]ejvrState, 1, 5)
106 stack[0] = ejvrState{
107 mode: m,
108 vType: typ,
109 }
110 return &extJSONValueReader{
111 p: p,
112 stack: stack,
113 }, nil
114 }
115
116 func (ejvr *extJSONValueReader) advanceFrame() {
117 if ejvr.frame+1 >= len(ejvr.stack) { // We need to grow the stack
118 length := len(ejvr.stack)
119 if length+1 >= cap(ejvr.stack) {
120 // double it
121 buf := make([]ejvrState, 2*cap(ejvr.stack)+1)
122 copy(buf, ejvr.stack)
123 ejvr.stack = buf
124 }
125 ejvr.stack = ejvr.stack[:length+1]
126 }
127 ejvr.frame++
128
129 // Clean the stack
130 ejvr.stack[ejvr.frame].mode = 0
131 ejvr.stack[ejvr.frame].vType = 0
132 ejvr.stack[ejvr.frame].depth = 0
133 }
134
135 func (ejvr *extJSONValueReader) pushDocument() {
136 ejvr.advanceFrame()
137
138 ejvr.stack[ejvr.frame].mode = mDocument
139 ejvr.stack[ejvr.frame].depth = ejvr.p.depth
140 }
141
142 func (ejvr *extJSONValueReader) pushCodeWithScope() {
143 ejvr.advanceFrame()
144
145 ejvr.stack[ejvr.frame].mode = mCodeWithScope
146 }
147
148 func (ejvr *extJSONValueReader) pushArray() {
149 ejvr.advanceFrame()
150
151 ejvr.stack[ejvr.frame].mode = mArray
152 }
153
154 func (ejvr *extJSONValueReader) push(m mode, t bsontype.Type) {
155 ejvr.advanceFrame()
156
157 ejvr.stack[ejvr.frame].mode = m
158 ejvr.stack[ejvr.frame].vType = t
159 }
160
161 func (ejvr *extJSONValueReader) pop() {
162 switch ejvr.stack[ejvr.frame].mode {
163 case mElement, mValue:
164 ejvr.frame--
165 case mDocument, mArray, mCodeWithScope:
166 ejvr.frame -= 2 // we pop twice to jump over the vrElement: vrDocument -> vrElement -> vrDocument/TopLevel/etc...
167 }
168 }
169
170 func (ejvr *extJSONValueReader) skipObject() {
171 // read entire object until depth returns to 0 (last ending } or ] seen)
172 depth := 1
173 for depth > 0 {
174 ejvr.p.advanceState()
175
176 // If object is empty, raise depth and continue. When emptyObject is true, the
177 // parser has already read both the opening and closing brackets of an empty
178 // object ("{}"), so the next valid token will be part of the parent document,
179 // not part of the nested document.
180 //
181 // If there is a comma, there are remaining fields, emptyObject must be set back
182 // to false, and comma must be skipped with advanceState().
183 if ejvr.p.emptyObject {
184 if ejvr.p.s == jpsSawComma {
185 ejvr.p.emptyObject = false
186 ejvr.p.advanceState()
187 }
188 depth--
189 continue
190 }
191
192 switch ejvr.p.s {
193 case jpsSawBeginObject, jpsSawBeginArray:
194 depth++
195 case jpsSawEndObject, jpsSawEndArray:
196 depth--
197 }
198 }
199 }
200
201 func (ejvr *extJSONValueReader) invalidTransitionErr(destination mode, name string, modes []mode) error {
202 te := TransitionError{
203 name: name,
204 current: ejvr.stack[ejvr.frame].mode,
205 destination: destination,
206 modes: modes,
207 action: "read",
208 }
209 if ejvr.frame != 0 {
210 te.parent = ejvr.stack[ejvr.frame-1].mode
211 }
212 return te
213 }
214
215 func (ejvr *extJSONValueReader) typeError(t bsontype.Type) error {
216 return fmt.Errorf("positioned on %s, but attempted to read %s", ejvr.stack[ejvr.frame].vType, t)
217 }
218
219 func (ejvr *extJSONValueReader) ensureElementValue(t bsontype.Type, destination mode, callerName string, addModes ...mode) error {
220 switch ejvr.stack[ejvr.frame].mode {
221 case mElement, mValue:
222 if ejvr.stack[ejvr.frame].vType != t {
223 return ejvr.typeError(t)
224 }
225 default:
226 modes := []mode{mElement, mValue}
227 if addModes != nil {
228 modes = append(modes, addModes...)
229 }
230 return ejvr.invalidTransitionErr(destination, callerName, modes)
231 }
232
233 return nil
234 }
235
236 func (ejvr *extJSONValueReader) Type() bsontype.Type {
237 return ejvr.stack[ejvr.frame].vType
238 }
239
240 func (ejvr *extJSONValueReader) Skip() error {
241 switch ejvr.stack[ejvr.frame].mode {
242 case mElement, mValue:
243 default:
244 return ejvr.invalidTransitionErr(0, "Skip", []mode{mElement, mValue})
245 }
246
247 defer ejvr.pop()
248
249 t := ejvr.stack[ejvr.frame].vType
250 switch t {
251 case bsontype.Array, bsontype.EmbeddedDocument, bsontype.CodeWithScope:
252 // read entire array, doc or CodeWithScope
253 ejvr.skipObject()
254 default:
255 _, err := ejvr.p.readValue(t)
256 if err != nil {
257 return err
258 }
259 }
260
261 return nil
262 }
263
264 func (ejvr *extJSONValueReader) ReadArray() (ArrayReader, error) {
265 switch ejvr.stack[ejvr.frame].mode {
266 case mTopLevel: // allow reading array from top level
267 case mArray:
268 return ejvr, nil
269 default:
270 if err := ejvr.ensureElementValue(bsontype.Array, mArray, "ReadArray", mTopLevel, mArray); err != nil {
271 return nil, err
272 }
273 }
274
275 ejvr.pushArray()
276
277 return ejvr, nil
278 }
279
280 func (ejvr *extJSONValueReader) ReadBinary() (b []byte, btype byte, err error) {
281 if err := ejvr.ensureElementValue(bsontype.Binary, 0, "ReadBinary"); err != nil {
282 return nil, 0, err
283 }
284
285 v, err := ejvr.p.readValue(bsontype.Binary)
286 if err != nil {
287 return nil, 0, err
288 }
289
290 b, btype, err = v.parseBinary()
291
292 ejvr.pop()
293 return b, btype, err
294 }
295
296 func (ejvr *extJSONValueReader) ReadBoolean() (bool, error) {
297 if err := ejvr.ensureElementValue(bsontype.Boolean, 0, "ReadBoolean"); err != nil {
298 return false, err
299 }
300
301 v, err := ejvr.p.readValue(bsontype.Boolean)
302 if err != nil {
303 return false, err
304 }
305
306 if v.t != bsontype.Boolean {
307 return false, fmt.Errorf("expected type bool, but got type %s", v.t)
308 }
309
310 ejvr.pop()
311 return v.v.(bool), nil
312 }
313
314 func (ejvr *extJSONValueReader) ReadDocument() (DocumentReader, error) {
315 switch ejvr.stack[ejvr.frame].mode {
316 case mTopLevel:
317 return ejvr, nil
318 case mElement, mValue:
319 if ejvr.stack[ejvr.frame].vType != bsontype.EmbeddedDocument {
320 return nil, ejvr.typeError(bsontype.EmbeddedDocument)
321 }
322
323 ejvr.pushDocument()
324 return ejvr, nil
325 default:
326 return nil, ejvr.invalidTransitionErr(mDocument, "ReadDocument", []mode{mTopLevel, mElement, mValue})
327 }
328 }
329
330 func (ejvr *extJSONValueReader) ReadCodeWithScope() (code string, dr DocumentReader, err error) {
331 if err = ejvr.ensureElementValue(bsontype.CodeWithScope, 0, "ReadCodeWithScope"); err != nil {
332 return "", nil, err
333 }
334
335 v, err := ejvr.p.readValue(bsontype.CodeWithScope)
336 if err != nil {
337 return "", nil, err
338 }
339
340 code, err = v.parseJavascript()
341
342 ejvr.pushCodeWithScope()
343 return code, ejvr, err
344 }
345
346 func (ejvr *extJSONValueReader) ReadDBPointer() (ns string, oid primitive.ObjectID, err error) {
347 if err = ejvr.ensureElementValue(bsontype.DBPointer, 0, "ReadDBPointer"); err != nil {
348 return "", primitive.NilObjectID, err
349 }
350
351 v, err := ejvr.p.readValue(bsontype.DBPointer)
352 if err != nil {
353 return "", primitive.NilObjectID, err
354 }
355
356 ns, oid, err = v.parseDBPointer()
357
358 ejvr.pop()
359 return ns, oid, err
360 }
361
362 func (ejvr *extJSONValueReader) ReadDateTime() (int64, error) {
363 if err := ejvr.ensureElementValue(bsontype.DateTime, 0, "ReadDateTime"); err != nil {
364 return 0, err
365 }
366
367 v, err := ejvr.p.readValue(bsontype.DateTime)
368 if err != nil {
369 return 0, err
370 }
371
372 d, err := v.parseDateTime()
373
374 ejvr.pop()
375 return d, err
376 }
377
378 func (ejvr *extJSONValueReader) ReadDecimal128() (primitive.Decimal128, error) {
379 if err := ejvr.ensureElementValue(bsontype.Decimal128, 0, "ReadDecimal128"); err != nil {
380 return primitive.Decimal128{}, err
381 }
382
383 v, err := ejvr.p.readValue(bsontype.Decimal128)
384 if err != nil {
385 return primitive.Decimal128{}, err
386 }
387
388 d, err := v.parseDecimal128()
389
390 ejvr.pop()
391 return d, err
392 }
393
394 func (ejvr *extJSONValueReader) ReadDouble() (float64, error) {
395 if err := ejvr.ensureElementValue(bsontype.Double, 0, "ReadDouble"); err != nil {
396 return 0, err
397 }
398
399 v, err := ejvr.p.readValue(bsontype.Double)
400 if err != nil {
401 return 0, err
402 }
403
404 d, err := v.parseDouble()
405
406 ejvr.pop()
407 return d, err
408 }
409
410 func (ejvr *extJSONValueReader) ReadInt32() (int32, error) {
411 if err := ejvr.ensureElementValue(bsontype.Int32, 0, "ReadInt32"); err != nil {
412 return 0, err
413 }
414
415 v, err := ejvr.p.readValue(bsontype.Int32)
416 if err != nil {
417 return 0, err
418 }
419
420 i, err := v.parseInt32()
421
422 ejvr.pop()
423 return i, err
424 }
425
426 func (ejvr *extJSONValueReader) ReadInt64() (int64, error) {
427 if err := ejvr.ensureElementValue(bsontype.Int64, 0, "ReadInt64"); err != nil {
428 return 0, err
429 }
430
431 v, err := ejvr.p.readValue(bsontype.Int64)
432 if err != nil {
433 return 0, err
434 }
435
436 i, err := v.parseInt64()
437
438 ejvr.pop()
439 return i, err
440 }
441
442 func (ejvr *extJSONValueReader) ReadJavascript() (code string, err error) {
443 if err = ejvr.ensureElementValue(bsontype.JavaScript, 0, "ReadJavascript"); err != nil {
444 return "", err
445 }
446
447 v, err := ejvr.p.readValue(bsontype.JavaScript)
448 if err != nil {
449 return "", err
450 }
451
452 code, err = v.parseJavascript()
453
454 ejvr.pop()
455 return code, err
456 }
457
458 func (ejvr *extJSONValueReader) ReadMaxKey() error {
459 if err := ejvr.ensureElementValue(bsontype.MaxKey, 0, "ReadMaxKey"); err != nil {
460 return err
461 }
462
463 v, err := ejvr.p.readValue(bsontype.MaxKey)
464 if err != nil {
465 return err
466 }
467
468 err = v.parseMinMaxKey("max")
469
470 ejvr.pop()
471 return err
472 }
473
474 func (ejvr *extJSONValueReader) ReadMinKey() error {
475 if err := ejvr.ensureElementValue(bsontype.MinKey, 0, "ReadMinKey"); err != nil {
476 return err
477 }
478
479 v, err := ejvr.p.readValue(bsontype.MinKey)
480 if err != nil {
481 return err
482 }
483
484 err = v.parseMinMaxKey("min")
485
486 ejvr.pop()
487 return err
488 }
489
490 func (ejvr *extJSONValueReader) ReadNull() error {
491 if err := ejvr.ensureElementValue(bsontype.Null, 0, "ReadNull"); err != nil {
492 return err
493 }
494
495 v, err := ejvr.p.readValue(bsontype.Null)
496 if err != nil {
497 return err
498 }
499
500 if v.t != bsontype.Null {
501 return fmt.Errorf("expected type null but got type %s", v.t)
502 }
503
504 ejvr.pop()
505 return nil
506 }
507
508 func (ejvr *extJSONValueReader) ReadObjectID() (primitive.ObjectID, error) {
509 if err := ejvr.ensureElementValue(bsontype.ObjectID, 0, "ReadObjectID"); err != nil {
510 return primitive.ObjectID{}, err
511 }
512
513 v, err := ejvr.p.readValue(bsontype.ObjectID)
514 if err != nil {
515 return primitive.ObjectID{}, err
516 }
517
518 oid, err := v.parseObjectID()
519
520 ejvr.pop()
521 return oid, err
522 }
523
524 func (ejvr *extJSONValueReader) ReadRegex() (pattern string, options string, err error) {
525 if err = ejvr.ensureElementValue(bsontype.Regex, 0, "ReadRegex"); err != nil {
526 return "", "", err
527 }
528
529 v, err := ejvr.p.readValue(bsontype.Regex)
530 if err != nil {
531 return "", "", err
532 }
533
534 pattern, options, err = v.parseRegex()
535
536 ejvr.pop()
537 return pattern, options, err
538 }
539
540 func (ejvr *extJSONValueReader) ReadString() (string, error) {
541 if err := ejvr.ensureElementValue(bsontype.String, 0, "ReadString"); err != nil {
542 return "", err
543 }
544
545 v, err := ejvr.p.readValue(bsontype.String)
546 if err != nil {
547 return "", err
548 }
549
550 if v.t != bsontype.String {
551 return "", fmt.Errorf("expected type string but got type %s", v.t)
552 }
553
554 ejvr.pop()
555 return v.v.(string), nil
556 }
557
558 func (ejvr *extJSONValueReader) ReadSymbol() (symbol string, err error) {
559 if err = ejvr.ensureElementValue(bsontype.Symbol, 0, "ReadSymbol"); err != nil {
560 return "", err
561 }
562
563 v, err := ejvr.p.readValue(bsontype.Symbol)
564 if err != nil {
565 return "", err
566 }
567
568 symbol, err = v.parseSymbol()
569
570 ejvr.pop()
571 return symbol, err
572 }
573
574 func (ejvr *extJSONValueReader) ReadTimestamp() (t uint32, i uint32, err error) {
575 if err = ejvr.ensureElementValue(bsontype.Timestamp, 0, "ReadTimestamp"); err != nil {
576 return 0, 0, err
577 }
578
579 v, err := ejvr.p.readValue(bsontype.Timestamp)
580 if err != nil {
581 return 0, 0, err
582 }
583
584 t, i, err = v.parseTimestamp()
585
586 ejvr.pop()
587 return t, i, err
588 }
589
590 func (ejvr *extJSONValueReader) ReadUndefined() error {
591 if err := ejvr.ensureElementValue(bsontype.Undefined, 0, "ReadUndefined"); err != nil {
592 return err
593 }
594
595 v, err := ejvr.p.readValue(bsontype.Undefined)
596 if err != nil {
597 return err
598 }
599
600 err = v.parseUndefined()
601
602 ejvr.pop()
603 return err
604 }
605
606 func (ejvr *extJSONValueReader) ReadElement() (string, ValueReader, error) {
607 switch ejvr.stack[ejvr.frame].mode {
608 case mTopLevel, mDocument, mCodeWithScope:
609 default:
610 return "", nil, ejvr.invalidTransitionErr(mElement, "ReadElement", []mode{mTopLevel, mDocument, mCodeWithScope})
611 }
612
613 name, t, err := ejvr.p.readKey()
614
615 if err != nil {
616 if err == ErrEOD {
617 if ejvr.stack[ejvr.frame].mode == mCodeWithScope {
618 _, err := ejvr.p.peekType()
619 if err != nil {
620 return "", nil, err
621 }
622 }
623
624 ejvr.pop()
625 }
626
627 return "", nil, err
628 }
629
630 ejvr.push(mElement, t)
631 return name, ejvr, nil
632 }
633
634 func (ejvr *extJSONValueReader) ReadValue() (ValueReader, error) {
635 switch ejvr.stack[ejvr.frame].mode {
636 case mArray:
637 default:
638 return nil, ejvr.invalidTransitionErr(mValue, "ReadValue", []mode{mArray})
639 }
640
641 t, err := ejvr.p.peekType()
642 if err != nil {
643 if err == ErrEOA {
644 ejvr.pop()
645 }
646
647 return nil, err
648 }
649
650 ejvr.push(mValue, t)
651 return ejvr, nil
652 }
653