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