github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/vendor_skip/go.mongodb.org/mongo-driver/bson/decoder.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 "fmt" 12 "reflect" 13 "sync" 14 15 "go.mongodb.org/mongo-driver/bson/bsoncodec" 16 "go.mongodb.org/mongo-driver/bson/bsonrw" 17 ) 18 19 // ErrDecodeToNil is the error returned when trying to decode to a nil value 20 var ErrDecodeToNil = errors.New("cannot Decode to nil value") 21 22 // This pool is used to keep the allocations of Decoders down. This is only used for the Marshal* 23 // methods and is not consumable from outside of this package. The Decoders retrieved from this pool 24 // must have both Reset and SetRegistry called on them. 25 var decPool = sync.Pool{ 26 New: func() interface{} { 27 return new(Decoder) 28 }, 29 } 30 31 // A Decoder reads and decodes BSON documents from a stream. It reads from a bsonrw.ValueReader as 32 // the source of BSON data. 33 type Decoder struct { 34 dc bsoncodec.DecodeContext 35 vr bsonrw.ValueReader 36 37 // We persist defaultDocumentM and defaultDocumentD on the Decoder to prevent overwriting from 38 // (*Decoder).SetContext. 39 defaultDocumentM bool 40 defaultDocumentD bool 41 42 binaryAsSlice bool 43 useJSONStructTags bool 44 useLocalTimeZone bool 45 zeroMaps bool 46 zeroStructs bool 47 } 48 49 // NewDecoder returns a new decoder that uses the DefaultRegistry to read from vr. 50 func NewDecoder(vr bsonrw.ValueReader) (*Decoder, error) { 51 if vr == nil { 52 return nil, errors.New("cannot create a new Decoder with a nil ValueReader") 53 } 54 55 return &Decoder{ 56 dc: bsoncodec.DecodeContext{Registry: DefaultRegistry}, 57 vr: vr, 58 }, nil 59 } 60 61 // NewDecoderWithContext returns a new decoder that uses DecodeContext dc to read from vr. 62 // 63 // Deprecated: Use [NewDecoder] and use the Decoder configuration methods set the desired unmarshal 64 // behavior instead. 65 func NewDecoderWithContext(dc bsoncodec.DecodeContext, vr bsonrw.ValueReader) (*Decoder, error) { 66 if dc.Registry == nil { 67 dc.Registry = DefaultRegistry 68 } 69 if vr == nil { 70 return nil, errors.New("cannot create a new Decoder with a nil ValueReader") 71 } 72 73 return &Decoder{ 74 dc: dc, 75 vr: vr, 76 }, nil 77 } 78 79 // Decode reads the next BSON document from the stream and decodes it into the 80 // value pointed to by val. 81 // 82 // See [Unmarshal] for details about BSON unmarshaling behavior. 83 func (d *Decoder) Decode(val interface{}) error { 84 if unmarshaler, ok := val.(Unmarshaler); ok { 85 // TODO(skriptble): Reuse a []byte here and use the AppendDocumentBytes method. 86 buf, err := bsonrw.Copier{}.CopyDocumentToBytes(d.vr) 87 if err != nil { 88 return err 89 } 90 return unmarshaler.UnmarshalBSON(buf) 91 } 92 93 rval := reflect.ValueOf(val) 94 switch rval.Kind() { 95 case reflect.Ptr: 96 if rval.IsNil() { 97 return ErrDecodeToNil 98 } 99 rval = rval.Elem() 100 case reflect.Map: 101 if rval.IsNil() { 102 return ErrDecodeToNil 103 } 104 default: 105 return fmt.Errorf("argument to Decode must be a pointer or a map, but got %v", rval) 106 } 107 decoder, err := d.dc.LookupDecoder(rval.Type()) 108 if err != nil { 109 return err 110 } 111 112 if d.defaultDocumentM { 113 d.dc.DefaultDocumentM() 114 } 115 if d.defaultDocumentD { 116 d.dc.DefaultDocumentD() 117 } 118 if d.binaryAsSlice { 119 d.dc.BinaryAsSlice() 120 } 121 if d.useJSONStructTags { 122 d.dc.UseJSONStructTags() 123 } 124 if d.useLocalTimeZone { 125 d.dc.UseLocalTimeZone() 126 } 127 if d.zeroMaps { 128 d.dc.ZeroMaps() 129 } 130 if d.zeroStructs { 131 d.dc.ZeroStructs() 132 } 133 134 return decoder.DecodeValue(d.dc, d.vr, rval) 135 } 136 137 // Reset will reset the state of the decoder, using the same *DecodeContext used in 138 // the original construction but using vr for reading. 139 func (d *Decoder) Reset(vr bsonrw.ValueReader) error { 140 // TODO:(GODRIVER-2719): Remove error return value. 141 d.vr = vr 142 return nil 143 } 144 145 // SetRegistry replaces the current registry of the decoder with r. 146 func (d *Decoder) SetRegistry(r *bsoncodec.Registry) error { 147 // TODO:(GODRIVER-2719): Remove error return value. 148 d.dc.Registry = r 149 return nil 150 } 151 152 // SetContext replaces the current registry of the decoder with dc. 153 // 154 // Deprecated: Use the Decoder configuration methods to set the desired unmarshal behavior instead. 155 func (d *Decoder) SetContext(dc bsoncodec.DecodeContext) error { 156 // TODO:(GODRIVER-2719): Remove error return value. 157 d.dc = dc 158 return nil 159 } 160 161 // DefaultDocumentM causes the Decoder to always unmarshal documents into the primitive.M type. This 162 // behavior is restricted to data typed as "interface{}" or "map[string]interface{}". 163 func (d *Decoder) DefaultDocumentM() { 164 d.defaultDocumentM = true 165 } 166 167 // DefaultDocumentD causes the Decoder to always unmarshal documents into the primitive.D type. This 168 // behavior is restricted to data typed as "interface{}" or "map[string]interface{}". 169 func (d *Decoder) DefaultDocumentD() { 170 d.defaultDocumentD = true 171 } 172 173 // AllowTruncatingDoubles causes the Decoder to truncate the fractional part of BSON "double" values 174 // when attempting to unmarshal them into a Go integer (int, int8, int16, int32, or int64) struct 175 // field. The truncation logic does not apply to BSON "decimal128" values. 176 func (d *Decoder) AllowTruncatingDoubles() { 177 d.dc.Truncate = true 178 } 179 180 // BinaryAsSlice causes the Decoder to unmarshal BSON binary field values that are the "Generic" or 181 // "Old" BSON binary subtype as a Go byte slice instead of a primitive.Binary. 182 func (d *Decoder) BinaryAsSlice() { 183 d.binaryAsSlice = true 184 } 185 186 // UseJSONStructTags causes the Decoder to fall back to using the "json" struct tag if a "bson" 187 // struct tag is not specified. 188 func (d *Decoder) UseJSONStructTags() { 189 d.useJSONStructTags = true 190 } 191 192 // UseLocalTimeZone causes the Decoder to unmarshal time.Time values in the local timezone instead 193 // of the UTC timezone. 194 func (d *Decoder) UseLocalTimeZone() { 195 d.useLocalTimeZone = true 196 } 197 198 // ZeroMaps causes the Decoder to delete any existing values from Go maps in the destination value 199 // passed to Decode before unmarshaling BSON documents into them. 200 func (d *Decoder) ZeroMaps() { 201 d.zeroMaps = true 202 } 203 204 // ZeroStructs causes the Decoder to delete any existing values from Go structs in the destination 205 // value passed to Decode before unmarshaling BSON documents into them. 206 func (d *Decoder) ZeroStructs() { 207 d.zeroStructs = true 208 }