github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/vendor_skip/go.mongodb.org/mongo-driver/bson/encoder.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 "errors" 11 "reflect" 12 "sync" 13 14 "go.mongodb.org/mongo-driver/bson/bsoncodec" 15 "go.mongodb.org/mongo-driver/bson/bsonrw" 16 ) 17 18 // This pool is used to keep the allocations of Encoders down. This is only used for the Marshal* 19 // methods and is not consumable from outside of this package. The Encoders retrieved from this pool 20 // must have both Reset and SetRegistry called on them. 21 var encPool = sync.Pool{ 22 New: func() interface{} { 23 return new(Encoder) 24 }, 25 } 26 27 // An Encoder writes a serialization format to an output stream. It writes to a bsonrw.ValueWriter 28 // as the destination of BSON data. 29 type Encoder struct { 30 ec bsoncodec.EncodeContext 31 vw bsonrw.ValueWriter 32 33 errorOnInlineDuplicates bool 34 intMinSize bool 35 stringifyMapKeysWithFmt bool 36 nilMapAsEmpty bool 37 nilSliceAsEmpty bool 38 nilByteSliceAsEmpty bool 39 omitZeroStruct bool 40 useJSONStructTags bool 41 } 42 43 // NewEncoder returns a new encoder that uses the DefaultRegistry to write to vw. 44 func NewEncoder(vw bsonrw.ValueWriter) (*Encoder, error) { 45 // TODO:(GODRIVER-2719): Remove error return value. 46 if vw == nil { 47 return nil, errors.New("cannot create a new Encoder with a nil ValueWriter") 48 } 49 50 return &Encoder{ 51 ec: bsoncodec.EncodeContext{Registry: DefaultRegistry}, 52 vw: vw, 53 }, nil 54 } 55 56 // NewEncoderWithContext returns a new encoder that uses EncodeContext ec to write to vw. 57 // 58 // Deprecated: Use [NewEncoder] and use the Encoder configuration methods to set the desired marshal 59 // behavior instead. 60 func NewEncoderWithContext(ec bsoncodec.EncodeContext, vw bsonrw.ValueWriter) (*Encoder, error) { 61 if ec.Registry == nil { 62 ec = bsoncodec.EncodeContext{Registry: DefaultRegistry} 63 } 64 if vw == nil { 65 return nil, errors.New("cannot create a new Encoder with a nil ValueWriter") 66 } 67 68 return &Encoder{ 69 ec: ec, 70 vw: vw, 71 }, nil 72 } 73 74 // Encode writes the BSON encoding of val to the stream. 75 // 76 // See [Marshal] for details about BSON marshaling behavior. 77 func (e *Encoder) Encode(val interface{}) error { 78 if marshaler, ok := val.(Marshaler); ok { 79 // TODO(skriptble): Should we have a MarshalAppender interface so that we can have []byte reuse? 80 buf, err := marshaler.MarshalBSON() 81 if err != nil { 82 return err 83 } 84 return bsonrw.Copier{}.CopyDocumentFromBytes(e.vw, buf) 85 } 86 87 encoder, err := e.ec.LookupEncoder(reflect.TypeOf(val)) 88 if err != nil { 89 return err 90 } 91 92 // Copy the configurations applied to the Encoder over to the EncodeContext, which actually 93 // communicates those configurations to the default ValueEncoders. 94 if e.errorOnInlineDuplicates { 95 e.ec.ErrorOnInlineDuplicates() 96 } 97 if e.intMinSize { 98 e.ec.MinSize = true 99 } 100 if e.stringifyMapKeysWithFmt { 101 e.ec.StringifyMapKeysWithFmt() 102 } 103 if e.nilMapAsEmpty { 104 e.ec.NilMapAsEmpty() 105 } 106 if e.nilSliceAsEmpty { 107 e.ec.NilSliceAsEmpty() 108 } 109 if e.nilByteSliceAsEmpty { 110 e.ec.NilByteSliceAsEmpty() 111 } 112 if e.omitZeroStruct { 113 e.ec.OmitZeroStruct() 114 } 115 if e.useJSONStructTags { 116 e.ec.UseJSONStructTags() 117 } 118 119 return encoder.EncodeValue(e.ec, e.vw, reflect.ValueOf(val)) 120 } 121 122 // Reset will reset the state of the Encoder, using the same *EncodeContext used in 123 // the original construction but using vw. 124 func (e *Encoder) Reset(vw bsonrw.ValueWriter) error { 125 // TODO:(GODRIVER-2719): Remove error return value. 126 e.vw = vw 127 return nil 128 } 129 130 // SetRegistry replaces the current registry of the Encoder with r. 131 func (e *Encoder) SetRegistry(r *bsoncodec.Registry) error { 132 // TODO:(GODRIVER-2719): Remove error return value. 133 e.ec.Registry = r 134 return nil 135 } 136 137 // SetContext replaces the current EncodeContext of the encoder with ec. 138 // 139 // Deprecated: Use the Encoder configuration methods set the desired marshal behavior instead. 140 func (e *Encoder) SetContext(ec bsoncodec.EncodeContext) error { 141 // TODO:(GODRIVER-2719): Remove error return value. 142 e.ec = ec 143 return nil 144 } 145 146 // ErrorOnInlineDuplicates causes the Encoder to return an error if there is a duplicate field in 147 // the marshaled BSON when the "inline" struct tag option is set. 148 func (e *Encoder) ErrorOnInlineDuplicates() { 149 e.errorOnInlineDuplicates = true 150 } 151 152 // IntMinSize causes the Encoder to marshal Go integer values (int, int8, int16, int32, int64, uint, 153 // uint8, uint16, uint32, or uint64) as the minimum BSON int size (either 32 or 64 bits) that can 154 // represent the integer value. 155 func (e *Encoder) IntMinSize() { 156 e.intMinSize = true 157 } 158 159 // StringifyMapKeysWithFmt causes the Encoder to convert Go map keys to BSON document field name 160 // strings using fmt.Sprint instead of the default string conversion logic. 161 func (e *Encoder) StringifyMapKeysWithFmt() { 162 e.stringifyMapKeysWithFmt = true 163 } 164 165 // NilMapAsEmpty causes the Encoder to marshal nil Go maps as empty BSON documents instead of BSON 166 // null. 167 func (e *Encoder) NilMapAsEmpty() { 168 e.nilMapAsEmpty = true 169 } 170 171 // NilSliceAsEmpty causes the Encoder to marshal nil Go slices as empty BSON arrays instead of BSON 172 // null. 173 func (e *Encoder) NilSliceAsEmpty() { 174 e.nilSliceAsEmpty = true 175 } 176 177 // NilByteSliceAsEmpty causes the Encoder to marshal nil Go byte slices as empty BSON binary values 178 // instead of BSON null. 179 func (e *Encoder) NilByteSliceAsEmpty() { 180 e.nilByteSliceAsEmpty = true 181 } 182 183 // TODO(GODRIVER-2820): Update the description to remove the note about only examining exported 184 // TODO struct fields once the logic is updated to also inspect private struct fields. 185 186 // OmitZeroStruct causes the Encoder to consider the zero value for a struct (e.g. MyStruct{}) 187 // as empty and omit it from the marshaled BSON when the "omitempty" struct tag option is set. 188 // 189 // Note that the Encoder only examines exported struct fields when determining if a struct is the 190 // zero value. It considers pointers to a zero struct value (e.g. &MyStruct{}) not empty. 191 func (e *Encoder) OmitZeroStruct() { 192 e.omitZeroStruct = true 193 } 194 195 // UseJSONStructTags causes the Encoder to fall back to using the "json" struct tag if a "bson" 196 // struct tag is not specified. 197 func (e *Encoder) UseJSONStructTags() { 198 e.useJSONStructTags = true 199 }