You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

287 lines
12 KiB

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