1
2
3
4
5
6
7 package bsonrw
8
9 import (
10 "errors"
11 "fmt"
12 "io"
13 "math"
14 "strconv"
15 "strings"
16 "sync"
17
18 "go.mongodb.org/mongo-driver/bson/bsontype"
19 "go.mongodb.org/mongo-driver/bson/primitive"
20 "go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
21 )
22
23 var _ ValueWriter = (*valueWriter)(nil)
24
25 var vwPool = sync.Pool{
26 New: func() interface{} {
27 return new(valueWriter)
28 },
29 }
30
31 func putValueWriter(vw *valueWriter) {
32 if vw != nil {
33 vw.w = nil
34 vwPool.Put(vw)
35 }
36 }
37
38
39
40
41 type BSONValueWriterPool struct {
42 pool sync.Pool
43 }
44
45
46
47
48 func NewBSONValueWriterPool() *BSONValueWriterPool {
49 return &BSONValueWriterPool{
50 pool: sync.Pool{
51 New: func() interface{} {
52 return new(valueWriter)
53 },
54 },
55 }
56 }
57
58
59
60
61 func (bvwp *BSONValueWriterPool) Get(w io.Writer) ValueWriter {
62 vw := bvwp.pool.Get().(*valueWriter)
63
64
65 vw.reset(vw.buf)
66 vw.buf = vw.buf[:0]
67 vw.w = w
68 return vw
69 }
70
71
72
73
74 func (bvwp *BSONValueWriterPool) GetAtModeElement(w io.Writer) ValueWriterFlusher {
75 vw := bvwp.Get(w).(*valueWriter)
76 vw.push(mElement)
77 return vw
78 }
79
80
81
82
83
84 func (bvwp *BSONValueWriterPool) Put(vw ValueWriter) (ok bool) {
85 bvw, ok := vw.(*valueWriter)
86 if !ok {
87 return false
88 }
89
90 bvwp.pool.Put(bvw)
91 return true
92 }
93
94
95
96 var maxSize = math.MaxInt32
97
98 var errNilWriter = errors.New("cannot create a ValueWriter from a nil io.Writer")
99
100 type errMaxDocumentSizeExceeded struct {
101 size int64
102 }
103
104 func (mdse errMaxDocumentSizeExceeded) Error() string {
105 return fmt.Sprintf("document size (%d) is larger than the max int32", mdse.size)
106 }
107
108 type vwMode int
109
110 const (
111 _ vwMode = iota
112 vwTopLevel
113 vwDocument
114 vwArray
115 vwValue
116 vwElement
117 vwCodeWithScope
118 )
119
120 func (vm vwMode) String() string {
121 var str string
122
123 switch vm {
124 case vwTopLevel:
125 str = "TopLevel"
126 case vwDocument:
127 str = "DocumentMode"
128 case vwArray:
129 str = "ArrayMode"
130 case vwValue:
131 str = "ValueMode"
132 case vwElement:
133 str = "ElementMode"
134 case vwCodeWithScope:
135 str = "CodeWithScopeMode"
136 default:
137 str = "UnknownMode"
138 }
139
140 return str
141 }
142
143 type vwState struct {
144 mode mode
145 key string
146 arrkey int
147 start int32
148 }
149
150 type valueWriter struct {
151 w io.Writer
152 buf []byte
153
154 stack []vwState
155 frame int64
156 }
157
158 func (vw *valueWriter) advanceFrame() {
159 vw.frame++
160 if vw.frame >= int64(len(vw.stack)) {
161 vw.stack = append(vw.stack, vwState{})
162 }
163 }
164
165 func (vw *valueWriter) push(m mode) {
166 vw.advanceFrame()
167
168
169 vw.stack[vw.frame] = vwState{mode: m}
170
171 switch m {
172 case mDocument, mArray, mCodeWithScope:
173 vw.reserveLength()
174 }
175 }
176
177 func (vw *valueWriter) reserveLength() {
178 vw.stack[vw.frame].start = int32(len(vw.buf))
179 vw.buf = append(vw.buf, 0x00, 0x00, 0x00, 0x00)
180 }
181
182 func (vw *valueWriter) pop() {
183 switch vw.stack[vw.frame].mode {
184 case mElement, mValue:
185 vw.frame--
186 case mDocument, mArray, mCodeWithScope:
187 vw.frame -= 2
188 }
189 }
190
191
192
193
194
195 func NewBSONValueWriter(w io.Writer) (ValueWriter, error) {
196 if w == nil {
197 return nil, errNilWriter
198 }
199 return newValueWriter(w), nil
200 }
201
202 func newValueWriter(w io.Writer) *valueWriter {
203 vw := new(valueWriter)
204 stack := make([]vwState, 1, 5)
205 stack[0] = vwState{mode: mTopLevel}
206 vw.w = w
207 vw.stack = stack
208
209 return vw
210 }
211
212
213 func newValueWriterFromSlice(buf []byte) *valueWriter {
214 vw := new(valueWriter)
215 stack := make([]vwState, 1, 5)
216 stack[0] = vwState{mode: mTopLevel}
217 vw.stack = stack
218 vw.buf = buf
219
220 return vw
221 }
222
223 func (vw *valueWriter) reset(buf []byte) {
224 if vw.stack == nil {
225 vw.stack = make([]vwState, 1, 5)
226 }
227 vw.stack = vw.stack[:1]
228 vw.stack[0] = vwState{mode: mTopLevel}
229 vw.buf = buf
230 vw.frame = 0
231 vw.w = nil
232 }
233
234 func (vw *valueWriter) invalidTransitionError(destination mode, name string, modes []mode) error {
235 te := TransitionError{
236 name: name,
237 current: vw.stack[vw.frame].mode,
238 destination: destination,
239 modes: modes,
240 action: "write",
241 }
242 if vw.frame != 0 {
243 te.parent = vw.stack[vw.frame-1].mode
244 }
245 return te
246 }
247
248 func (vw *valueWriter) writeElementHeader(t bsontype.Type, destination mode, callerName string, addmodes ...mode) error {
249 frame := &vw.stack[vw.frame]
250 switch frame.mode {
251 case mElement:
252 key := frame.key
253 if !isValidCString(key) {
254 return errors.New("BSON element key cannot contain null bytes")
255 }
256 vw.appendHeader(t, key)
257 case mValue:
258 vw.appendIntHeader(t, frame.arrkey)
259 default:
260 modes := []mode{mElement, mValue}
261 if addmodes != nil {
262 modes = append(modes, addmodes...)
263 }
264 return vw.invalidTransitionError(destination, callerName, modes)
265 }
266
267 return nil
268 }
269
270 func (vw *valueWriter) WriteValueBytes(t bsontype.Type, b []byte) error {
271 if err := vw.writeElementHeader(t, mode(0), "WriteValueBytes"); err != nil {
272 return err
273 }
274 vw.buf = append(vw.buf, b...)
275 vw.pop()
276 return nil
277 }
278
279 func (vw *valueWriter) WriteArray() (ArrayWriter, error) {
280 if err := vw.writeElementHeader(bsontype.Array, mArray, "WriteArray"); err != nil {
281 return nil, err
282 }
283
284 vw.push(mArray)
285
286 return vw, nil
287 }
288
289 func (vw *valueWriter) WriteBinary(b []byte) error {
290 return vw.WriteBinaryWithSubtype(b, 0x00)
291 }
292
293 func (vw *valueWriter) WriteBinaryWithSubtype(b []byte, btype byte) error {
294 if err := vw.writeElementHeader(bsontype.Binary, mode(0), "WriteBinaryWithSubtype"); err != nil {
295 return err
296 }
297
298 vw.buf = bsoncore.AppendBinary(vw.buf, btype, b)
299 vw.pop()
300 return nil
301 }
302
303 func (vw *valueWriter) WriteBoolean(b bool) error {
304 if err := vw.writeElementHeader(bsontype.Boolean, mode(0), "WriteBoolean"); err != nil {
305 return err
306 }
307
308 vw.buf = bsoncore.AppendBoolean(vw.buf, b)
309 vw.pop()
310 return nil
311 }
312
313 func (vw *valueWriter) WriteCodeWithScope(code string) (DocumentWriter, error) {
314 if err := vw.writeElementHeader(bsontype.CodeWithScope, mCodeWithScope, "WriteCodeWithScope"); err != nil {
315 return nil, err
316 }
317
318
319
320
321
322 vw.push(mCodeWithScope)
323 vw.buf = bsoncore.AppendString(vw.buf, code)
324 vw.push(mSpacer)
325 vw.push(mDocument)
326
327 return vw, nil
328 }
329
330 func (vw *valueWriter) WriteDBPointer(ns string, oid primitive.ObjectID) error {
331 if err := vw.writeElementHeader(bsontype.DBPointer, mode(0), "WriteDBPointer"); err != nil {
332 return err
333 }
334
335 vw.buf = bsoncore.AppendDBPointer(vw.buf, ns, oid)
336 vw.pop()
337 return nil
338 }
339
340 func (vw *valueWriter) WriteDateTime(dt int64) error {
341 if err := vw.writeElementHeader(bsontype.DateTime, mode(0), "WriteDateTime"); err != nil {
342 return err
343 }
344
345 vw.buf = bsoncore.AppendDateTime(vw.buf, dt)
346 vw.pop()
347 return nil
348 }
349
350 func (vw *valueWriter) WriteDecimal128(d128 primitive.Decimal128) error {
351 if err := vw.writeElementHeader(bsontype.Decimal128, mode(0), "WriteDecimal128"); err != nil {
352 return err
353 }
354
355 vw.buf = bsoncore.AppendDecimal128(vw.buf, d128)
356 vw.pop()
357 return nil
358 }
359
360 func (vw *valueWriter) WriteDouble(f float64) error {
361 if err := vw.writeElementHeader(bsontype.Double, mode(0), "WriteDouble"); err != nil {
362 return err
363 }
364
365 vw.buf = bsoncore.AppendDouble(vw.buf, f)
366 vw.pop()
367 return nil
368 }
369
370 func (vw *valueWriter) WriteInt32(i32 int32) error {
371 if err := vw.writeElementHeader(bsontype.Int32, mode(0), "WriteInt32"); err != nil {
372 return err
373 }
374
375 vw.buf = bsoncore.AppendInt32(vw.buf, i32)
376 vw.pop()
377 return nil
378 }
379
380 func (vw *valueWriter) WriteInt64(i64 int64) error {
381 if err := vw.writeElementHeader(bsontype.Int64, mode(0), "WriteInt64"); err != nil {
382 return err
383 }
384
385 vw.buf = bsoncore.AppendInt64(vw.buf, i64)
386 vw.pop()
387 return nil
388 }
389
390 func (vw *valueWriter) WriteJavascript(code string) error {
391 if err := vw.writeElementHeader(bsontype.JavaScript, mode(0), "WriteJavascript"); err != nil {
392 return err
393 }
394
395 vw.buf = bsoncore.AppendJavaScript(vw.buf, code)
396 vw.pop()
397 return nil
398 }
399
400 func (vw *valueWriter) WriteMaxKey() error {
401 if err := vw.writeElementHeader(bsontype.MaxKey, mode(0), "WriteMaxKey"); err != nil {
402 return err
403 }
404
405 vw.pop()
406 return nil
407 }
408
409 func (vw *valueWriter) WriteMinKey() error {
410 if err := vw.writeElementHeader(bsontype.MinKey, mode(0), "WriteMinKey"); err != nil {
411 return err
412 }
413
414 vw.pop()
415 return nil
416 }
417
418 func (vw *valueWriter) WriteNull() error {
419 if err := vw.writeElementHeader(bsontype.Null, mode(0), "WriteNull"); err != nil {
420 return err
421 }
422
423 vw.pop()
424 return nil
425 }
426
427 func (vw *valueWriter) WriteObjectID(oid primitive.ObjectID) error {
428 if err := vw.writeElementHeader(bsontype.ObjectID, mode(0), "WriteObjectID"); err != nil {
429 return err
430 }
431
432 vw.buf = bsoncore.AppendObjectID(vw.buf, oid)
433 vw.pop()
434 return nil
435 }
436
437 func (vw *valueWriter) WriteRegex(pattern string, options string) error {
438 if !isValidCString(pattern) || !isValidCString(options) {
439 return errors.New("BSON regex values cannot contain null bytes")
440 }
441 if err := vw.writeElementHeader(bsontype.Regex, mode(0), "WriteRegex"); err != nil {
442 return err
443 }
444
445 vw.buf = bsoncore.AppendRegex(vw.buf, pattern, sortStringAlphebeticAscending(options))
446 vw.pop()
447 return nil
448 }
449
450 func (vw *valueWriter) WriteString(s string) error {
451 if err := vw.writeElementHeader(bsontype.String, mode(0), "WriteString"); err != nil {
452 return err
453 }
454
455 vw.buf = bsoncore.AppendString(vw.buf, s)
456 vw.pop()
457 return nil
458 }
459
460 func (vw *valueWriter) WriteDocument() (DocumentWriter, error) {
461 if vw.stack[vw.frame].mode == mTopLevel {
462 vw.reserveLength()
463 return vw, nil
464 }
465 if err := vw.writeElementHeader(bsontype.EmbeddedDocument, mDocument, "WriteDocument", mTopLevel); err != nil {
466 return nil, err
467 }
468
469 vw.push(mDocument)
470 return vw, nil
471 }
472
473 func (vw *valueWriter) WriteSymbol(symbol string) error {
474 if err := vw.writeElementHeader(bsontype.Symbol, mode(0), "WriteSymbol"); err != nil {
475 return err
476 }
477
478 vw.buf = bsoncore.AppendSymbol(vw.buf, symbol)
479 vw.pop()
480 return nil
481 }
482
483 func (vw *valueWriter) WriteTimestamp(t uint32, i uint32) error {
484 if err := vw.writeElementHeader(bsontype.Timestamp, mode(0), "WriteTimestamp"); err != nil {
485 return err
486 }
487
488 vw.buf = bsoncore.AppendTimestamp(vw.buf, t, i)
489 vw.pop()
490 return nil
491 }
492
493 func (vw *valueWriter) WriteUndefined() error {
494 if err := vw.writeElementHeader(bsontype.Undefined, mode(0), "WriteUndefined"); err != nil {
495 return err
496 }
497
498 vw.pop()
499 return nil
500 }
501
502 func (vw *valueWriter) WriteDocumentElement(key string) (ValueWriter, error) {
503 switch vw.stack[vw.frame].mode {
504 case mTopLevel, mDocument:
505 default:
506 return nil, vw.invalidTransitionError(mElement, "WriteDocumentElement", []mode{mTopLevel, mDocument})
507 }
508
509 vw.push(mElement)
510 vw.stack[vw.frame].key = key
511
512 return vw, nil
513 }
514
515 func (vw *valueWriter) WriteDocumentEnd() error {
516 switch vw.stack[vw.frame].mode {
517 case mTopLevel, mDocument:
518 default:
519 return fmt.Errorf("incorrect mode to end document: %s", vw.stack[vw.frame].mode)
520 }
521
522 vw.buf = append(vw.buf, 0x00)
523
524 err := vw.writeLength()
525 if err != nil {
526 return err
527 }
528
529 if vw.stack[vw.frame].mode == mTopLevel {
530 if err = vw.Flush(); err != nil {
531 return err
532 }
533 }
534
535 vw.pop()
536
537 if vw.stack[vw.frame].mode == mCodeWithScope {
538
539
540 _ = vw.writeLength()
541 vw.pop()
542 }
543 return nil
544 }
545
546 func (vw *valueWriter) Flush() error {
547 if vw.w == nil {
548 return nil
549 }
550
551 if _, err := vw.w.Write(vw.buf); err != nil {
552 return err
553 }
554
555 vw.buf = vw.buf[:0]
556 return nil
557 }
558
559 func (vw *valueWriter) WriteArrayElement() (ValueWriter, error) {
560 if vw.stack[vw.frame].mode != mArray {
561 return nil, vw.invalidTransitionError(mValue, "WriteArrayElement", []mode{mArray})
562 }
563
564 arrkey := vw.stack[vw.frame].arrkey
565 vw.stack[vw.frame].arrkey++
566
567 vw.push(mValue)
568 vw.stack[vw.frame].arrkey = arrkey
569
570 return vw, nil
571 }
572
573 func (vw *valueWriter) WriteArrayEnd() error {
574 if vw.stack[vw.frame].mode != mArray {
575 return fmt.Errorf("incorrect mode to end array: %s", vw.stack[vw.frame].mode)
576 }
577
578 vw.buf = append(vw.buf, 0x00)
579
580 err := vw.writeLength()
581 if err != nil {
582 return err
583 }
584
585 vw.pop()
586 return nil
587 }
588
589
590
591
592
593
594
595 func (vw *valueWriter) writeLength() error {
596 length := len(vw.buf)
597 if length > maxSize {
598 return errMaxDocumentSizeExceeded{size: int64(len(vw.buf))}
599 }
600 frame := &vw.stack[vw.frame]
601 length = length - int(frame.start)
602 start := frame.start
603
604 _ = vw.buf[start+3]
605 vw.buf[start+0] = byte(length)
606 vw.buf[start+1] = byte(length >> 8)
607 vw.buf[start+2] = byte(length >> 16)
608 vw.buf[start+3] = byte(length >> 24)
609 return nil
610 }
611
612 func isValidCString(cs string) bool {
613
614
615
616
617
618
619
620
621
622
623 return strings.IndexByte(cs, 0) == -1
624 }
625
626
627
628
629
630 func (vw *valueWriter) appendHeader(t bsontype.Type, key string) {
631 vw.buf = bsoncore.AppendType(vw.buf, t)
632 vw.buf = append(vw.buf, key...)
633 vw.buf = append(vw.buf, 0x00)
634 }
635
636 func (vw *valueWriter) appendIntHeader(t bsontype.Type, key int) {
637 vw.buf = bsoncore.AppendType(vw.buf, t)
638 vw.buf = strconv.AppendInt(vw.buf, int64(key), 10)
639 vw.buf = append(vw.buf, 0x00)
640 }
641
View as plain text