raw_value.go 13 KB

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