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