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 "errors"
12 "fmt"
13 "reflect"
14 "time"
15 16 "go.mongodb.org/mongo-driver/bson/bsoncodec"
17 "go.mongodb.org/mongo-driver/bson/bsonrw"
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 // ErrNilContext is returned when the provided DecodeContext is nil.
24 var ErrNilContext = errors.New("DecodeContext cannot be nil")
25 26 // ErrNilRegistry is returned when the provided registry is nil.
27 var ErrNilRegistry = errors.New("Registry cannot be nil")
28 29 // RawValue is a raw encoded BSON value. It can be used to delay BSON value decoding or precompute
30 // BSON encoded value. Type is the BSON type of the value and Value is the raw encoded BSON value.
31 //
32 // A RawValue must be an individual BSON value. Use the Raw type for full BSON documents.
33 type RawValue struct {
34 Type bsontype.Type
35 Value []byte
36 37 r *bsoncodec.Registry
38 }
39 40 // IsZero reports whether the RawValue is zero, i.e. no data is present on
41 // the RawValue. It returns true if Type is 0 and Value is empty or nil.
42 func (rv RawValue) IsZero() bool {
43 return rv.Type == 0x00 && len(rv.Value) == 0
44 }
45 46 // Unmarshal deserializes BSON into the provided val. If RawValue cannot be unmarshaled into val, an
47 // error is returned. This method will use the registry used to create the RawValue, if the RawValue
48 // was created from partial BSON processing, or it will use the default registry. Users wishing to
49 // specify the registry to use should use UnmarshalWithRegistry.
50 func (rv RawValue) Unmarshal(val interface{}) error {
51 reg := rv.r
52 if reg == nil {
53 reg = DefaultRegistry
54 }
55 return rv.UnmarshalWithRegistry(reg, val)
56 }
57 58 // Equal compares rv and rv2 and returns true if they are equal.
59 func (rv RawValue) Equal(rv2 RawValue) bool {
60 if rv.Type != rv2.Type {
61 return false
62 }
63 64 if !bytes.Equal(rv.Value, rv2.Value) {
65 return false
66 }
67 68 return true
69 }
70 71 // UnmarshalWithRegistry performs the same unmarshalling as Unmarshal but uses the provided registry
72 // instead of the one attached or the default registry.
73 func (rv RawValue) UnmarshalWithRegistry(r *bsoncodec.Registry, val interface{}) error {
74 if r == nil {
75 return ErrNilRegistry
76 }
77 78 vr := bsonrw.NewBSONValueReader(rv.Type, rv.Value)
79 rval := reflect.ValueOf(val)
80 if rval.Kind() != reflect.Ptr {
81 return fmt.Errorf("argument to Unmarshal* must be a pointer to a type, but got %v", rval)
82 }
83 rval = rval.Elem()
84 dec, err := r.LookupDecoder(rval.Type())
85 if err != nil {
86 return err
87 }
88 return dec.DecodeValue(bsoncodec.DecodeContext{Registry: r}, vr, rval)
89 }
90 91 // UnmarshalWithContext performs the same unmarshalling as Unmarshal but uses the provided DecodeContext
92 // instead of the one attached or the default registry.
93 func (rv RawValue) UnmarshalWithContext(dc *bsoncodec.DecodeContext, val interface{}) error {
94 if dc == nil {
95 return ErrNilContext
96 }
97 98 vr := bsonrw.NewBSONValueReader(rv.Type, rv.Value)
99 rval := reflect.ValueOf(val)
100 if rval.Kind() != reflect.Ptr {
101 return fmt.Errorf("argument to Unmarshal* must be a pointer to a type, but got %v", rval)
102 }
103 rval = rval.Elem()
104 dec, err := dc.LookupDecoder(rval.Type())
105 if err != nil {
106 return err
107 }
108 return dec.DecodeValue(*dc, vr, rval)
109 }
110 111 func convertFromCoreValue(v bsoncore.Value) RawValue { return RawValue{Type: v.Type, Value: v.Data} }
112 func convertToCoreValue(v RawValue) bsoncore.Value {
113 return bsoncore.Value{Type: v.Type, Data: v.Value}
114 }
115 116 // Validate ensures the value is a valid BSON value.
117 func (rv RawValue) Validate() error { return convertToCoreValue(rv).Validate() }
118 119 // IsNumber returns true if the type of v is a numeric BSON type.
120 func (rv RawValue) IsNumber() bool { return convertToCoreValue(rv).IsNumber() }
121 122 // String implements the fmt.String interface. This method will return values in extended JSON
123 // format. If the value is not valid, this returns an empty string
124 func (rv RawValue) String() string { return convertToCoreValue(rv).String() }
125 126 // DebugString outputs a human readable version of Document. It will attempt to stringify the
127 // valid components of the document even if the entire document is not valid.
128 func (rv RawValue) DebugString() string { return convertToCoreValue(rv).DebugString() }
129 130 // Double returns the float64 value for this element.
131 // It panics if e's BSON type is not bsontype.Double.
132 func (rv RawValue) Double() float64 { return convertToCoreValue(rv).Double() }
133 134 // DoubleOK is the same as Double, but returns a boolean instead of panicking.
135 func (rv RawValue) DoubleOK() (float64, bool) { return convertToCoreValue(rv).DoubleOK() }
136 137 // StringValue returns the string value for this element.
138 // It panics if e's BSON type is not bsontype.String.
139 //
140 // NOTE: This method is called StringValue to avoid a collision with the String method which
141 // implements the fmt.Stringer interface.
142 func (rv RawValue) StringValue() string { return convertToCoreValue(rv).StringValue() }
143 144 // StringValueOK is the same as StringValue, but returns a boolean instead of
145 // panicking.
146 func (rv RawValue) StringValueOK() (string, bool) { return convertToCoreValue(rv).StringValueOK() }
147 148 // Document returns the BSON document the Value represents as a Document. It panics if the
149 // value is a BSON type other than document.
150 func (rv RawValue) Document() Raw { return Raw(convertToCoreValue(rv).Document()) }
151 152 // DocumentOK is the same as Document, except it returns a boolean
153 // instead of panicking.
154 func (rv RawValue) DocumentOK() (Raw, bool) {
155 doc, ok := convertToCoreValue(rv).DocumentOK()
156 return Raw(doc), ok
157 }
158 159 // Array returns the BSON array the Value represents as an Array. It panics if the
160 // value is a BSON type other than array.
161 func (rv RawValue) Array() Raw { return Raw(convertToCoreValue(rv).Array()) }
162 163 // ArrayOK is the same as Array, except it returns a boolean instead
164 // of panicking.
165 func (rv RawValue) ArrayOK() (Raw, bool) {
166 doc, ok := convertToCoreValue(rv).ArrayOK()
167 return Raw(doc), ok
168 }
169 170 // Binary returns the BSON binary value the Value represents. It panics if the value is a BSON type
171 // other than binary.
172 func (rv RawValue) Binary() (subtype byte, data []byte) { return convertToCoreValue(rv).Binary() }
173 174 // BinaryOK is the same as Binary, except it returns a boolean instead of
175 // panicking.
176 func (rv RawValue) BinaryOK() (subtype byte, data []byte, ok bool) {
177 return convertToCoreValue(rv).BinaryOK()
178 }
179 180 // ObjectID returns the BSON objectid value the Value represents. It panics if the value is a BSON
181 // type other than objectid.
182 func (rv RawValue) ObjectID() primitive.ObjectID { return convertToCoreValue(rv).ObjectID() }
183 184 // ObjectIDOK is the same as ObjectID, except it returns a boolean instead of
185 // panicking.
186 func (rv RawValue) ObjectIDOK() (primitive.ObjectID, bool) {
187 return convertToCoreValue(rv).ObjectIDOK()
188 }
189 190 // Boolean returns the boolean value the Value represents. It panics if the
191 // value is a BSON type other than boolean.
192 func (rv RawValue) Boolean() bool { return convertToCoreValue(rv).Boolean() }
193 194 // BooleanOK is the same as Boolean, except it returns a boolean instead of
195 // panicking.
196 func (rv RawValue) BooleanOK() (bool, bool) { return convertToCoreValue(rv).BooleanOK() }
197 198 // DateTime returns the BSON datetime value the Value represents as a
199 // unix timestamp. It panics if the value is a BSON type other than datetime.
200 func (rv RawValue) DateTime() int64 { return convertToCoreValue(rv).DateTime() }
201 202 // DateTimeOK is the same as DateTime, except it returns a boolean instead of
203 // panicking.
204 func (rv RawValue) DateTimeOK() (int64, bool) { return convertToCoreValue(rv).DateTimeOK() }
205 206 // Time returns the BSON datetime value the Value represents. It panics if the value is a BSON
207 // type other than datetime.
208 func (rv RawValue) Time() time.Time { return convertToCoreValue(rv).Time() }
209 210 // TimeOK is the same as Time, except it returns a boolean instead of
211 // panicking.
212 func (rv RawValue) TimeOK() (time.Time, bool) { return convertToCoreValue(rv).TimeOK() }
213 214 // Regex returns the BSON regex value the Value represents. It panics if the value is a BSON
215 // type other than regex.
216 func (rv RawValue) Regex() (pattern, options string) { return convertToCoreValue(rv).Regex() }
217 218 // RegexOK is the same as Regex, except it returns a boolean instead of
219 // panicking.
220 func (rv RawValue) RegexOK() (pattern, options string, ok bool) {
221 return convertToCoreValue(rv).RegexOK()
222 }
223 224 // DBPointer returns the BSON dbpointer value the Value represents. It panics if the value is a BSON
225 // type other than DBPointer.
226 func (rv RawValue) DBPointer() (string, primitive.ObjectID) {
227 return convertToCoreValue(rv).DBPointer()
228 }
229 230 // DBPointerOK is the same as DBPoitner, except that it returns a boolean
231 // instead of panicking.
232 func (rv RawValue) DBPointerOK() (string, primitive.ObjectID, bool) {
233 return convertToCoreValue(rv).DBPointerOK()
234 }
235 236 // JavaScript returns the BSON JavaScript code value the Value represents. It panics if the value is
237 // a BSON type other than JavaScript code.
238 func (rv RawValue) JavaScript() string { return convertToCoreValue(rv).JavaScript() }
239 240 // JavaScriptOK is the same as Javascript, excepti that it returns a boolean
241 // instead of panicking.
242 func (rv RawValue) JavaScriptOK() (string, bool) { return convertToCoreValue(rv).JavaScriptOK() }
243 244 // Symbol returns the BSON symbol value the Value represents. It panics if the value is a BSON
245 // type other than symbol.
246 func (rv RawValue) Symbol() string { return convertToCoreValue(rv).Symbol() }
247 248 // SymbolOK is the same as Symbol, excepti that it returns a boolean
249 // instead of panicking.
250 func (rv RawValue) SymbolOK() (string, bool) { return convertToCoreValue(rv).SymbolOK() }
251 252 // CodeWithScope returns the BSON JavaScript code with scope the Value represents.
253 // It panics if the value is a BSON type other than JavaScript code with scope.
254 func (rv RawValue) CodeWithScope() (string, Raw) {
255 code, scope := convertToCoreValue(rv).CodeWithScope()
256 return code, Raw(scope)
257 }
258 259 // CodeWithScopeOK is the same as CodeWithScope, except that it returns a boolean instead of
260 // panicking.
261 func (rv RawValue) CodeWithScopeOK() (string, Raw, bool) {
262 code, scope, ok := convertToCoreValue(rv).CodeWithScopeOK()
263 return code, Raw(scope), ok
264 }
265 266 // Int32 returns the int32 the Value represents. It panics if the value is a BSON type other than
267 // int32.
268 func (rv RawValue) Int32() int32 { return convertToCoreValue(rv).Int32() }
269 270 // Int32OK is the same as Int32, except that it returns a boolean instead of
271 // panicking.
272 func (rv RawValue) Int32OK() (int32, bool) { return convertToCoreValue(rv).Int32OK() }
273 274 // AsInt32 returns a BSON number as an int32. If the BSON type is not a numeric one, this method
275 // will panic.
276 //
277 // Deprecated: Use AsInt64 instead. If an int32 is required, convert the returned value to an int32
278 // and perform any required overflow/underflow checking.
279 func (rv RawValue) AsInt32() int32 { return convertToCoreValue(rv).AsInt32() }
280 281 // AsInt32OK is the same as AsInt32, except that it returns a boolean instead of
282 // panicking.
283 //
284 // Deprecated: Use AsInt64OK instead. If an int32 is required, convert the returned value to an
285 // int32 and perform any required overflow/underflow checking.
286 func (rv RawValue) AsInt32OK() (int32, bool) { return convertToCoreValue(rv).AsInt32OK() }
287 288 // Timestamp returns the BSON timestamp value the Value represents. It panics if the value is a
289 // BSON type other than timestamp.
290 func (rv RawValue) Timestamp() (t, i uint32) { return convertToCoreValue(rv).Timestamp() }
291 292 // TimestampOK is the same as Timestamp, except that it returns a boolean
293 // instead of panicking.
294 func (rv RawValue) TimestampOK() (t, i uint32, ok bool) { return convertToCoreValue(rv).TimestampOK() }
295 296 // Int64 returns the int64 the Value represents. It panics if the value is a BSON type other than
297 // int64.
298 func (rv RawValue) Int64() int64 { return convertToCoreValue(rv).Int64() }
299 300 // Int64OK is the same as Int64, except that it returns a boolean instead of
301 // panicking.
302 func (rv RawValue) Int64OK() (int64, bool) { return convertToCoreValue(rv).Int64OK() }
303 304 // AsInt64 returns a BSON number as an int64. If the BSON type is not a numeric one, this method
305 // will panic.
306 func (rv RawValue) AsInt64() int64 { return convertToCoreValue(rv).AsInt64() }
307 308 // AsInt64OK is the same as AsInt64, except that it returns a boolean instead of
309 // panicking.
310 func (rv RawValue) AsInt64OK() (int64, bool) { return convertToCoreValue(rv).AsInt64OK() }
311 312 // Decimal128 returns the decimal the Value represents. It panics if the value is a BSON type other than
313 // decimal.
314 func (rv RawValue) Decimal128() primitive.Decimal128 { return convertToCoreValue(rv).Decimal128() }
315 316 // Decimal128OK is the same as Decimal128, except that it returns a boolean
317 // instead of panicking.
318 func (rv RawValue) Decimal128OK() (primitive.Decimal128, bool) {
319 return convertToCoreValue(rv).Decimal128OK()
320 }
321