github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/vendor_skip/go.mongodb.org/mongo-driver/bson/marshal.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 bson
     8  
     9  import (
    10  	"bytes"
    11  	"encoding/json"
    12  
    13  	"go.mongodb.org/mongo-driver/bson/bsoncodec"
    14  	"go.mongodb.org/mongo-driver/bson/bsonrw"
    15  	"go.mongodb.org/mongo-driver/bson/bsontype"
    16  )
    17  
    18  const defaultDstCap = 256
    19  
    20  var bvwPool = bsonrw.NewBSONValueWriterPool()
    21  var extjPool = bsonrw.NewExtJSONValueWriterPool()
    22  
    23  // Marshaler is the interface implemented by types that can marshal themselves
    24  // into a valid BSON document.
    25  //
    26  // Implementations of Marshaler must return a full BSON document. To create
    27  // custom BSON marshaling behavior for individual values in a BSON document,
    28  // implement the ValueMarshaler interface instead.
    29  type Marshaler interface {
    30  	MarshalBSON() ([]byte, error)
    31  }
    32  
    33  // ValueMarshaler is the interface implemented by types that can marshal
    34  // themselves into a valid BSON value. The format of the returned bytes must
    35  // match the returned type.
    36  //
    37  // Implementations of ValueMarshaler must return an individual BSON value. To
    38  // create custom BSON marshaling behavior for an entire BSON document, implement
    39  // the Marshaler interface instead.
    40  type ValueMarshaler interface {
    41  	MarshalBSONValue() (bsontype.Type, []byte, error)
    42  }
    43  
    44  // Marshal returns the BSON encoding of val as a BSON document. If val is not a type that can be transformed into a
    45  // document, MarshalValue should be used instead.
    46  //
    47  // Marshal will use the default registry created by NewRegistry to recursively
    48  // marshal val into a []byte. Marshal will inspect struct tags and alter the
    49  // marshaling process accordingly.
    50  func Marshal(val interface{}) ([]byte, error) {
    51  	return MarshalWithRegistry(DefaultRegistry, val)
    52  }
    53  
    54  // MarshalAppend will encode val as a BSON document and append the bytes to dst. If dst is not large enough to hold the
    55  // bytes, it will be grown. If val is not a type that can be transformed into a document, MarshalValueAppend should be
    56  // used instead.
    57  //
    58  // Deprecated: Use [NewEncoder] and pass the dst byte slice (wrapped by a bytes.Buffer) into
    59  // [bsonrw.NewBSONValueWriter]:
    60  //
    61  //	buf := bytes.NewBuffer(dst)
    62  //	vw, err := bsonrw.NewBSONValueWriter(buf)
    63  //	if err != nil {
    64  //		panic(err)
    65  //	}
    66  //	enc, err := bson.NewEncoder(vw)
    67  //	if err != nil {
    68  //		panic(err)
    69  //	}
    70  //
    71  // See [Encoder] for more examples.
    72  func MarshalAppend(dst []byte, val interface{}) ([]byte, error) {
    73  	return MarshalAppendWithRegistry(DefaultRegistry, dst, val)
    74  }
    75  
    76  // MarshalWithRegistry returns the BSON encoding of val as a BSON document. If val is not a type that can be transformed
    77  // into a document, MarshalValueWithRegistry should be used instead.
    78  //
    79  // Deprecated: Use [NewEncoder] and specify the Registry by calling [Encoder.SetRegistry] instead:
    80  //
    81  //	buf := new(bytes.Buffer)
    82  //	vw, err := bsonrw.NewBSONValueWriter(buf)
    83  //	if err != nil {
    84  //		panic(err)
    85  //	}
    86  //	enc, err := bson.NewEncoder(vw)
    87  //	if err != nil {
    88  //		panic(err)
    89  //	}
    90  //	enc.SetRegistry(reg)
    91  //
    92  // See [Encoder] for more examples.
    93  func MarshalWithRegistry(r *bsoncodec.Registry, val interface{}) ([]byte, error) {
    94  	dst := make([]byte, 0)
    95  	return MarshalAppendWithRegistry(r, dst, val)
    96  }
    97  
    98  // MarshalWithContext returns the BSON encoding of val as a BSON document using EncodeContext ec. If val is not a type
    99  // that can be transformed into a document, MarshalValueWithContext should be used instead.
   100  //
   101  // Deprecated: Use [NewEncoder] and use the Encoder configuration methods to set the desired marshal
   102  // behavior instead:
   103  //
   104  //	buf := bytes.NewBuffer(dst)
   105  //	vw, err := bsonrw.NewBSONValueWriter(buf)
   106  //	if err != nil {
   107  //		panic(err)
   108  //	}
   109  //	enc, err := bson.NewEncoder(vw)
   110  //	if err != nil {
   111  //		panic(err)
   112  //	}
   113  //	enc.IntMinSize()
   114  //
   115  // See [Encoder] for more examples.
   116  func MarshalWithContext(ec bsoncodec.EncodeContext, val interface{}) ([]byte, error) {
   117  	dst := make([]byte, 0)
   118  	return MarshalAppendWithContext(ec, dst, val)
   119  }
   120  
   121  // MarshalAppendWithRegistry will encode val as a BSON document using Registry r and append the bytes to dst. If dst is
   122  // not large enough to hold the bytes, it will be grown. If val is not a type that can be transformed into a document,
   123  // MarshalValueAppendWithRegistry should be used instead.
   124  //
   125  // Deprecated: Use [NewEncoder], and pass the dst byte slice (wrapped by a bytes.Buffer) into
   126  // [bsonrw.NewBSONValueWriter], and specify the Registry by calling [Encoder.SetRegistry] instead:
   127  //
   128  //	buf := bytes.NewBuffer(dst)
   129  //	vw, err := bsonrw.NewBSONValueWriter(buf)
   130  //	if err != nil {
   131  //		panic(err)
   132  //	}
   133  //	enc, err := bson.NewEncoder(vw)
   134  //	if err != nil {
   135  //		panic(err)
   136  //	}
   137  //	enc.SetRegistry(reg)
   138  //
   139  // See [Encoder] for more examples.
   140  func MarshalAppendWithRegistry(r *bsoncodec.Registry, dst []byte, val interface{}) ([]byte, error) {
   141  	return MarshalAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val)
   142  }
   143  
   144  // MarshalAppendWithContext will encode val as a BSON document using Registry r and EncodeContext ec and append the
   145  // bytes to dst. If dst is not large enough to hold the bytes, it will be grown. If val is not a type that can be
   146  // transformed into a document, MarshalValueAppendWithContext should be used instead.
   147  //
   148  // Deprecated: Use [NewEncoder], pass the dst byte slice (wrapped by a bytes.Buffer) into
   149  // [bsonrw.NewBSONValueWriter], and use the Encoder configuration methods to set the desired marshal
   150  // behavior instead:
   151  //
   152  //	buf := bytes.NewBuffer(dst)
   153  //	vw, err := bsonrw.NewBSONValueWriter(buf)
   154  //	if err != nil {
   155  //		panic(err)
   156  //	}
   157  //	enc, err := bson.NewEncoder(vw)
   158  //	if err != nil {
   159  //		panic(err)
   160  //	}
   161  //	enc.IntMinSize()
   162  //
   163  // See [Encoder] for more examples.
   164  func MarshalAppendWithContext(ec bsoncodec.EncodeContext, dst []byte, val interface{}) ([]byte, error) {
   165  	sw := new(bsonrw.SliceWriter)
   166  	*sw = dst
   167  	vw := bvwPool.Get(sw)
   168  	defer bvwPool.Put(vw)
   169  
   170  	enc := encPool.Get().(*Encoder)
   171  	defer encPool.Put(enc)
   172  
   173  	err := enc.Reset(vw)
   174  	if err != nil {
   175  		return nil, err
   176  	}
   177  	err = enc.SetContext(ec)
   178  	if err != nil {
   179  		return nil, err
   180  	}
   181  
   182  	err = enc.Encode(val)
   183  	if err != nil {
   184  		return nil, err
   185  	}
   186  
   187  	return *sw, nil
   188  }
   189  
   190  // MarshalValue returns the BSON encoding of val.
   191  //
   192  // MarshalValue will use bson.DefaultRegistry to transform val into a BSON value. If val is a struct, this function will
   193  // inspect struct tags and alter the marshalling process accordingly.
   194  func MarshalValue(val interface{}) (bsontype.Type, []byte, error) {
   195  	return MarshalValueWithRegistry(DefaultRegistry, val)
   196  }
   197  
   198  // MarshalValueAppend will append the BSON encoding of val to dst. If dst is not large enough to hold the BSON encoding
   199  // of val, dst will be grown.
   200  //
   201  // Deprecated: Appending individual BSON elements to an existing slice will not be supported in Go
   202  // Driver 2.0.
   203  func MarshalValueAppend(dst []byte, val interface{}) (bsontype.Type, []byte, error) {
   204  	return MarshalValueAppendWithRegistry(DefaultRegistry, dst, val)
   205  }
   206  
   207  // MarshalValueWithRegistry returns the BSON encoding of val using Registry r.
   208  //
   209  // Deprecated: Using a custom registry to marshal individual BSON values will not be supported in Go
   210  // Driver 2.0.
   211  func MarshalValueWithRegistry(r *bsoncodec.Registry, val interface{}) (bsontype.Type, []byte, error) {
   212  	dst := make([]byte, 0)
   213  	return MarshalValueAppendWithRegistry(r, dst, val)
   214  }
   215  
   216  // MarshalValueWithContext returns the BSON encoding of val using EncodeContext ec.
   217  //
   218  // Deprecated: Using a custom EncodeContext to marshal individual BSON elements will not be
   219  // supported in Go Driver 2.0.
   220  func MarshalValueWithContext(ec bsoncodec.EncodeContext, val interface{}) (bsontype.Type, []byte, error) {
   221  	dst := make([]byte, 0)
   222  	return MarshalValueAppendWithContext(ec, dst, val)
   223  }
   224  
   225  // MarshalValueAppendWithRegistry will append the BSON encoding of val to dst using Registry r. If dst is not large
   226  // enough to hold the BSON encoding of val, dst will be grown.
   227  //
   228  // Deprecated: Appending individual BSON elements to an existing slice will not be supported in Go
   229  // Driver 2.0.
   230  func MarshalValueAppendWithRegistry(r *bsoncodec.Registry, dst []byte, val interface{}) (bsontype.Type, []byte, error) {
   231  	return MarshalValueAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val)
   232  }
   233  
   234  // MarshalValueAppendWithContext will append the BSON encoding of val to dst using EncodeContext ec. If dst is not large
   235  // enough to hold the BSON encoding of val, dst will be grown.
   236  //
   237  // Deprecated: Appending individual BSON elements to an existing slice will not be supported in Go
   238  // Driver 2.0.
   239  func MarshalValueAppendWithContext(ec bsoncodec.EncodeContext, dst []byte, val interface{}) (bsontype.Type, []byte, error) {
   240  	// get a ValueWriter configured to write to dst
   241  	sw := new(bsonrw.SliceWriter)
   242  	*sw = dst
   243  	vwFlusher := bvwPool.GetAtModeElement(sw)
   244  
   245  	// get an Encoder and encode the value
   246  	enc := encPool.Get().(*Encoder)
   247  	defer encPool.Put(enc)
   248  	if err := enc.Reset(vwFlusher); err != nil {
   249  		return 0, nil, err
   250  	}
   251  	if err := enc.SetContext(ec); err != nil {
   252  		return 0, nil, err
   253  	}
   254  	if err := enc.Encode(val); err != nil {
   255  		return 0, nil, err
   256  	}
   257  
   258  	// flush the bytes written because we cannot guarantee that a full document has been written
   259  	// after the flush, *sw will be in the format
   260  	// [value type, 0 (null byte to indicate end of empty element name), value bytes..]
   261  	if err := vwFlusher.Flush(); err != nil {
   262  		return 0, nil, err
   263  	}
   264  	buffer := *sw
   265  	return bsontype.Type(buffer[0]), buffer[2:], nil
   266  }
   267  
   268  // MarshalExtJSON returns the extended JSON encoding of val.
   269  func MarshalExtJSON(val interface{}, canonical, escapeHTML bool) ([]byte, error) {
   270  	return MarshalExtJSONWithRegistry(DefaultRegistry, val, canonical, escapeHTML)
   271  }
   272  
   273  // MarshalExtJSONAppend will append the extended JSON encoding of val to dst.
   274  // If dst is not large enough to hold the extended JSON encoding of val, dst
   275  // will be grown.
   276  //
   277  // Deprecated: Use [NewEncoder] and pass the dst byte slice (wrapped by a bytes.Buffer) into
   278  // [bsonrw.NewExtJSONValueWriter] instead:
   279  //
   280  //	buf := bytes.NewBuffer(dst)
   281  //	vw, err := bsonrw.NewExtJSONValueWriter(buf, true, false)
   282  //	if err != nil {
   283  //		panic(err)
   284  //	}
   285  //	enc, err := bson.NewEncoder(vw)
   286  //	if err != nil {
   287  //		panic(err)
   288  //	}
   289  //
   290  // See [Encoder] for more examples.
   291  func MarshalExtJSONAppend(dst []byte, val interface{}, canonical, escapeHTML bool) ([]byte, error) {
   292  	return MarshalExtJSONAppendWithRegistry(DefaultRegistry, dst, val, canonical, escapeHTML)
   293  }
   294  
   295  // MarshalExtJSONWithRegistry returns the extended JSON encoding of val using Registry r.
   296  //
   297  // Deprecated: Use [NewEncoder] and specify the Registry by calling [Encoder.SetRegistry] instead:
   298  //
   299  //	buf := new(bytes.Buffer)
   300  //	vw, err := bsonrw.NewBSONValueWriter(buf)
   301  //	if err != nil {
   302  //		panic(err)
   303  //	}
   304  //	enc, err := bson.NewEncoder(vw)
   305  //	if err != nil {
   306  //		panic(err)
   307  //	}
   308  //	enc.SetRegistry(reg)
   309  //
   310  // See [Encoder] for more examples.
   311  func MarshalExtJSONWithRegistry(r *bsoncodec.Registry, val interface{}, canonical, escapeHTML bool) ([]byte, error) {
   312  	dst := make([]byte, 0, defaultDstCap)
   313  	return MarshalExtJSONAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val, canonical, escapeHTML)
   314  }
   315  
   316  // MarshalExtJSONWithContext returns the extended JSON encoding of val using Registry r.
   317  //
   318  // Deprecated: Use [NewEncoder] and use the Encoder configuration methods to set the desired marshal
   319  // behavior instead:
   320  //
   321  //	buf := new(bytes.Buffer)
   322  //	vw, err := bsonrw.NewBSONValueWriter(buf)
   323  //	if err != nil {
   324  //		panic(err)
   325  //	}
   326  //	enc, err := bson.NewEncoder(vw)
   327  //	if err != nil {
   328  //		panic(err)
   329  //	}
   330  //	enc.IntMinSize()
   331  //
   332  // See [Encoder] for more examples.
   333  func MarshalExtJSONWithContext(ec bsoncodec.EncodeContext, val interface{}, canonical, escapeHTML bool) ([]byte, error) {
   334  	dst := make([]byte, 0, defaultDstCap)
   335  	return MarshalExtJSONAppendWithContext(ec, dst, val, canonical, escapeHTML)
   336  }
   337  
   338  // MarshalExtJSONAppendWithRegistry will append the extended JSON encoding of
   339  // val to dst using Registry r. If dst is not large enough to hold the BSON
   340  // encoding of val, dst will be grown.
   341  //
   342  // Deprecated: Use [NewEncoder], pass the dst byte slice (wrapped by a bytes.Buffer) into
   343  // [bsonrw.NewExtJSONValueWriter], and specify the Registry by calling [Encoder.SetRegistry]
   344  // instead:
   345  //
   346  //	buf := bytes.NewBuffer(dst)
   347  //	vw, err := bsonrw.NewExtJSONValueWriter(buf, true, false)
   348  //	if err != nil {
   349  //		panic(err)
   350  //	}
   351  //	enc, err := bson.NewEncoder(vw)
   352  //	if err != nil {
   353  //		panic(err)
   354  //	}
   355  //
   356  // See [Encoder] for more examples.
   357  func MarshalExtJSONAppendWithRegistry(r *bsoncodec.Registry, dst []byte, val interface{}, canonical, escapeHTML bool) ([]byte, error) {
   358  	return MarshalExtJSONAppendWithContext(bsoncodec.EncodeContext{Registry: r}, dst, val, canonical, escapeHTML)
   359  }
   360  
   361  // MarshalExtJSONAppendWithContext will append the extended JSON encoding of
   362  // val to dst using Registry r. If dst is not large enough to hold the BSON
   363  // encoding of val, dst will be grown.
   364  //
   365  // Deprecated: Use [NewEncoder], pass the dst byte slice (wrapped by a bytes.Buffer) into
   366  // [bsonrw.NewExtJSONValueWriter], and use the Encoder configuration methods to set the desired marshal
   367  // behavior instead:
   368  //
   369  //	buf := bytes.NewBuffer(dst)
   370  //	vw, err := bsonrw.NewExtJSONValueWriter(buf, true, false)
   371  //	if err != nil {
   372  //		panic(err)
   373  //	}
   374  //	enc, err := bson.NewEncoder(vw)
   375  //	if err != nil {
   376  //		panic(err)
   377  //	}
   378  //	enc.IntMinSize()
   379  //
   380  // See [Encoder] for more examples.
   381  func MarshalExtJSONAppendWithContext(ec bsoncodec.EncodeContext, dst []byte, val interface{}, canonical, escapeHTML bool) ([]byte, error) {
   382  	sw := new(bsonrw.SliceWriter)
   383  	*sw = dst
   384  	ejvw := extjPool.Get(sw, canonical, escapeHTML)
   385  	defer extjPool.Put(ejvw)
   386  
   387  	enc := encPool.Get().(*Encoder)
   388  	defer encPool.Put(enc)
   389  
   390  	err := enc.Reset(ejvw)
   391  	if err != nil {
   392  		return nil, err
   393  	}
   394  	err = enc.SetContext(ec)
   395  	if err != nil {
   396  		return nil, err
   397  	}
   398  
   399  	err = enc.Encode(val)
   400  	if err != nil {
   401  		return nil, err
   402  	}
   403  
   404  	return *sw, nil
   405  }
   406  
   407  // IndentExtJSON will prefix and indent the provided extended JSON src and append it to dst.
   408  func IndentExtJSON(dst *bytes.Buffer, src []byte, prefix, indent string) error {
   409  	return json.Indent(dst, src, prefix, indent)
   410  }
   411  
   412  // MarshalExtJSONIndent returns the extended JSON encoding of val with each line with prefixed
   413  // and indented.
   414  func MarshalExtJSONIndent(val interface{}, canonical, escapeHTML bool, prefix, indent string) ([]byte, error) {
   415  	marshaled, err := MarshalExtJSON(val, canonical, escapeHTML)
   416  	if err != nil {
   417  		return nil, err
   418  	}
   419  
   420  	var buf bytes.Buffer
   421  	err = IndentExtJSON(&buf, marshaled, prefix, indent)
   422  	if err != nil {
   423  		return nil, err
   424  	}
   425  
   426  	return buf.Bytes(), nil
   427  }