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  }