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