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 }