raw_value.go raw

   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