bson 4.1.1 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +106 -7
  3. data/Rakefile +86 -43
  4. data/ext/bson/{native-endian.h → bson-endian.h} +14 -107
  5. data/ext/bson/bson-native.h +135 -0
  6. data/ext/bson/bytebuf.c +133 -0
  7. data/ext/bson/endian.c +117 -0
  8. data/ext/bson/extconf.rb +8 -3
  9. data/ext/bson/init.c +364 -0
  10. data/ext/bson/libbson-utf8.c +230 -0
  11. data/ext/bson/read.c +470 -0
  12. data/ext/bson/util.c +250 -0
  13. data/ext/bson/write.c +675 -0
  14. data/lib/bson/active_support.rb +19 -0
  15. data/lib/bson/array.rb +97 -30
  16. data/lib/bson/big_decimal.rb +77 -0
  17. data/lib/bson/binary.rb +510 -70
  18. data/lib/bson/boolean.rb +15 -4
  19. data/lib/bson/code.rb +25 -12
  20. data/lib/bson/code_with_scope.rb +41 -15
  21. data/lib/bson/config.rb +3 -28
  22. data/lib/bson/date.rb +16 -4
  23. data/lib/bson/date_time.rb +6 -4
  24. data/lib/bson/db_pointer.rb +110 -0
  25. data/lib/bson/dbref.rb +154 -0
  26. data/lib/bson/decimal128/builder.rb +456 -0
  27. data/lib/bson/decimal128.rb +272 -0
  28. data/lib/bson/document.rb +177 -7
  29. data/lib/bson/environment.rb +17 -2
  30. data/lib/bson/error/bson_decode_error.rb +11 -0
  31. data/lib/bson/error/ext_json_parse_error.rb +11 -0
  32. data/lib/bson/error/illegal_key.rb +23 -0
  33. data/lib/bson/error/invalid_binary_type.rb +37 -0
  34. data/lib/bson/error/invalid_dbref_argument.rb +12 -0
  35. data/lib/bson/error/invalid_decimal128_argument.rb +25 -0
  36. data/lib/bson/error/invalid_decimal128_range.rb +27 -0
  37. data/lib/bson/error/invalid_decimal128_string.rb +26 -0
  38. data/lib/bson/error/invalid_key.rb +24 -0
  39. data/lib/bson/error/invalid_object_id.rb +11 -0
  40. data/lib/bson/error/invalid_regexp_pattern.rb +13 -0
  41. data/lib/bson/error/unrepresentable_precision.rb +19 -0
  42. data/lib/bson/error/unserializable_class.rb +13 -0
  43. data/lib/bson/error/unsupported_binary_subtype.rb +12 -0
  44. data/lib/bson/error/unsupported_type.rb +11 -0
  45. data/lib/bson/error.rb +22 -0
  46. data/lib/bson/ext_json.rb +389 -0
  47. data/lib/bson/false_class.rb +6 -4
  48. data/lib/bson/float.rb +43 -7
  49. data/lib/bson/hash.rb +152 -37
  50. data/lib/bson/int32.rb +104 -6
  51. data/lib/bson/int64.rb +111 -8
  52. data/lib/bson/integer.rb +43 -9
  53. data/lib/bson/json.rb +3 -1
  54. data/lib/bson/max_key.rb +21 -10
  55. data/lib/bson/min_key.rb +21 -10
  56. data/lib/bson/nil_class.rb +7 -3
  57. data/lib/bson/object.rb +25 -17
  58. data/lib/bson/object_id.rb +98 -113
  59. data/lib/bson/open_struct.rb +59 -0
  60. data/lib/bson/regexp.rb +129 -56
  61. data/lib/bson/registry.rb +7 -10
  62. data/lib/bson/specialized.rb +8 -4
  63. data/lib/bson/string.rb +12 -32
  64. data/lib/bson/symbol.rb +107 -11
  65. data/lib/bson/time.rb +68 -7
  66. data/lib/bson/time_with_zone.rb +67 -0
  67. data/lib/bson/timestamp.rb +50 -10
  68. data/lib/bson/true_class.rb +6 -4
  69. data/lib/bson/undefined.rb +28 -2
  70. data/lib/bson/vector.rb +44 -0
  71. data/lib/bson/version.rb +6 -14
  72. data/lib/bson.rb +22 -12
  73. data/spec/README.md +14 -0
  74. data/spec/bson/array_spec.rb +38 -62
  75. data/spec/bson/big_decimal_spec.rb +328 -0
  76. data/spec/bson/binary_spec.rb +199 -53
  77. data/spec/bson/binary_uuid_spec.rb +190 -0
  78. data/spec/bson/boolean_spec.rb +2 -1
  79. data/spec/bson/byte_buffer_read_spec.rb +198 -0
  80. data/spec/bson/byte_buffer_spec.rb +122 -381
  81. data/spec/bson/byte_buffer_write_spec.rb +855 -0
  82. data/spec/bson/code_spec.rb +6 -4
  83. data/spec/bson/code_with_scope_spec.rb +6 -4
  84. data/spec/bson/config_spec.rb +1 -35
  85. data/spec/bson/date_spec.rb +2 -1
  86. data/spec/bson/date_time_spec.rb +55 -1
  87. data/spec/bson/dbref_legacy_spec.rb +186 -0
  88. data/spec/bson/dbref_spec.rb +487 -0
  89. data/spec/bson/decimal128_spec.rb +1840 -0
  90. data/spec/bson/document_as_spec.rb +61 -0
  91. data/spec/bson/document_spec.rb +205 -32
  92. data/spec/bson/ext_json_parse_spec.rb +346 -0
  93. data/spec/bson/false_class_spec.rb +9 -1
  94. data/spec/bson/float_spec.rb +42 -1
  95. data/spec/bson/hash_as_spec.rb +58 -0
  96. data/spec/bson/hash_spec.rb +318 -66
  97. data/spec/bson/int32_spec.rb +248 -1
  98. data/spec/bson/int64_spec.rb +308 -1
  99. data/spec/bson/integer_spec.rb +61 -3
  100. data/spec/bson/json_spec.rb +2 -1
  101. data/spec/bson/max_key_spec.rb +6 -4
  102. data/spec/bson/min_key_spec.rb +6 -4
  103. data/spec/bson/nil_class_spec.rb +2 -1
  104. data/spec/bson/object_id_spec.rb +95 -5
  105. data/spec/bson/object_spec.rb +3 -2
  106. data/spec/bson/open_struct_spec.rb +87 -0
  107. data/spec/bson/raw_spec.rb +594 -0
  108. data/spec/bson/regexp_spec.rb +61 -8
  109. data/spec/bson/registry_spec.rb +3 -2
  110. data/spec/bson/string_spec.rb +26 -33
  111. data/spec/bson/symbol_raw_spec.rb +70 -0
  112. data/spec/bson/symbol_spec.rb +77 -20
  113. data/spec/bson/time_spec.rb +206 -2
  114. data/spec/bson/time_with_zone_spec.rb +69 -0
  115. data/spec/bson/timestamp_spec.rb +58 -2
  116. data/spec/bson/true_class_spec.rb +9 -1
  117. data/spec/bson/undefined_spec.rb +28 -1
  118. data/spec/bson/vector_spec.rb +33 -0
  119. data/spec/bson_spec.rb +2 -1
  120. data/spec/runners/binary_vector.rb +78 -0
  121. data/spec/runners/common_driver.rb +348 -0
  122. data/spec/runners/corpus.rb +191 -0
  123. data/spec/runners/corpus_legacy.rb +248 -0
  124. data/spec/shared/LICENSE +20 -0
  125. data/spec/shared/bin/get-mongodb-download-url +17 -0
  126. data/spec/shared/bin/s3-copy +45 -0
  127. data/spec/shared/bin/s3-upload +69 -0
  128. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  129. data/spec/shared/lib/mrss/cluster_config.rb +231 -0
  130. data/spec/shared/lib/mrss/constraints.rb +378 -0
  131. data/spec/shared/lib/mrss/docker_runner.rb +298 -0
  132. data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
  133. data/spec/shared/lib/mrss/event_subscriber.rb +210 -0
  134. data/spec/shared/lib/mrss/lite_constraints.rb +238 -0
  135. data/spec/shared/lib/mrss/release/candidate.rb +281 -0
  136. data/spec/shared/lib/mrss/release/product_data.rb +144 -0
  137. data/spec/shared/lib/mrss/server_version_registry.rb +113 -0
  138. data/spec/shared/lib/mrss/session_registry.rb +69 -0
  139. data/spec/shared/lib/mrss/session_registry_legacy.rb +60 -0
  140. data/spec/shared/lib/mrss/spec_organizer.rb +179 -0
  141. data/spec/shared/lib/mrss/utils.rb +37 -0
  142. data/spec/shared/lib/tasks/candidate.rake +64 -0
  143. data/spec/shared/share/Dockerfile.erb +251 -0
  144. data/spec/shared/share/haproxy-1.conf +16 -0
  145. data/spec/shared/share/haproxy-2.conf +17 -0
  146. data/spec/shared/shlib/config.sh +27 -0
  147. data/spec/shared/shlib/distro.sh +84 -0
  148. data/spec/shared/shlib/server.sh +423 -0
  149. data/spec/shared/shlib/set_env.sh +110 -0
  150. data/spec/spec_helper.rb +61 -1
  151. data/spec/spec_tests/binary_vector_spec.rb +82 -0
  152. data/spec/spec_tests/common_driver_spec.rb +84 -0
  153. data/spec/spec_tests/corpus_legacy_spec.rb +72 -0
  154. data/spec/spec_tests/corpus_spec.rb +134 -0
  155. data/spec/spec_tests/data/binary_vector/README.md +61 -0
  156. data/spec/spec_tests/data/binary_vector/float32.json +65 -0
  157. data/spec/spec_tests/data/binary_vector/int8.json +57 -0
  158. data/spec/spec_tests/data/binary_vector/packed_bit.json +83 -0
  159. data/spec/spec_tests/data/corpus/README.md +15 -0
  160. data/spec/spec_tests/data/corpus/array.json +49 -0
  161. data/spec/spec_tests/data/corpus/binary.json +153 -0
  162. data/spec/spec_tests/data/corpus/boolean.json +27 -0
  163. data/spec/spec_tests/data/corpus/code.json +67 -0
  164. data/spec/spec_tests/data/corpus/code_w_scope.json +78 -0
  165. data/spec/spec_tests/data/corpus/datetime.json +42 -0
  166. data/spec/spec_tests/data/corpus/dbpointer.json +56 -0
  167. data/spec/spec_tests/data/corpus/dbref.json +51 -0
  168. data/spec/spec_tests/data/corpus/decimal128-1.json +317 -0
  169. data/spec/spec_tests/data/corpus/decimal128-2.json +793 -0
  170. data/spec/spec_tests/data/corpus/decimal128-3.json +1771 -0
  171. data/spec/spec_tests/data/corpus/decimal128-4.json +165 -0
  172. data/spec/spec_tests/data/corpus/decimal128-5.json +402 -0
  173. data/spec/spec_tests/data/corpus/decimal128-6.json +131 -0
  174. data/spec/spec_tests/data/corpus/decimal128-7.json +327 -0
  175. data/spec/spec_tests/data/corpus/document.json +60 -0
  176. data/spec/spec_tests/data/corpus/double.json +87 -0
  177. data/spec/spec_tests/data/corpus/int32.json +43 -0
  178. data/spec/spec_tests/data/corpus/int64.json +43 -0
  179. data/spec/spec_tests/data/corpus/maxkey.json +12 -0
  180. data/spec/spec_tests/data/corpus/minkey.json +12 -0
  181. data/spec/spec_tests/data/corpus/multi-type-deprecated.json +15 -0
  182. data/spec/spec_tests/data/corpus/multi-type.json +11 -0
  183. data/spec/spec_tests/data/corpus/null.json +12 -0
  184. data/spec/spec_tests/data/corpus/oid.json +28 -0
  185. data/spec/spec_tests/data/corpus/regex.json +65 -0
  186. data/spec/spec_tests/data/corpus/string.json +72 -0
  187. data/spec/spec_tests/data/corpus/symbol.json +80 -0
  188. data/spec/spec_tests/data/corpus/timestamp.json +34 -0
  189. data/spec/spec_tests/data/corpus/top.json +262 -0
  190. data/spec/spec_tests/data/corpus/undefined.json +15 -0
  191. data/spec/spec_tests/data/corpus_legacy/array.json +49 -0
  192. data/spec/spec_tests/data/corpus_legacy/binary.json +69 -0
  193. data/spec/spec_tests/data/corpus_legacy/boolean.json +27 -0
  194. data/spec/spec_tests/data/corpus_legacy/code.json +67 -0
  195. data/spec/spec_tests/data/corpus_legacy/code_w_scope.json +78 -0
  196. data/spec/spec_tests/data/corpus_legacy/document.json +36 -0
  197. data/spec/spec_tests/data/corpus_legacy/double.json +69 -0
  198. data/spec/spec_tests/data/corpus_legacy/failures/datetime.json +31 -0
  199. data/spec/spec_tests/data/corpus_legacy/failures/dbpointer.json +42 -0
  200. data/spec/spec_tests/data/corpus_legacy/failures/int64.json +38 -0
  201. data/spec/spec_tests/data/corpus_legacy/failures/symbol.json +62 -0
  202. data/spec/spec_tests/data/corpus_legacy/int32.json +38 -0
  203. data/spec/spec_tests/data/corpus_legacy/maxkey.json +12 -0
  204. data/spec/spec_tests/data/corpus_legacy/minkey.json +12 -0
  205. data/spec/spec_tests/data/corpus_legacy/null.json +12 -0
  206. data/spec/spec_tests/data/corpus_legacy/oid.json +28 -0
  207. data/spec/spec_tests/data/corpus_legacy/regex.json +37 -0
  208. data/spec/spec_tests/data/corpus_legacy/string.json +67 -0
  209. data/spec/spec_tests/data/corpus_legacy/timestamp.json +18 -0
  210. data/spec/spec_tests/data/corpus_legacy/top.json +62 -0
  211. data/spec/spec_tests/data/corpus_legacy/undefined.json +13 -0
  212. data/spec/spec_tests/data/decimal128/decimal128-1.json +363 -0
  213. data/spec/spec_tests/data/decimal128/decimal128-2.json +793 -0
  214. data/spec/spec_tests/data/decimal128/decimal128-3.json +1771 -0
  215. data/spec/spec_tests/data/decimal128/decimal128-4.json +165 -0
  216. data/spec/spec_tests/data/decimal128/decimal128-5.json +402 -0
  217. data/spec/spec_tests/data/decimal128/decimal128-6.json +131 -0
  218. data/spec/spec_tests/data/decimal128/decimal128-7.json +327 -0
  219. data/spec/support/shared_examples.rb +32 -11
  220. data/spec/support/spec_config.rb +17 -0
  221. data/spec/support/utils.rb +58 -0
  222. metadata +284 -45
  223. checksums.yaml.gz.sig +0 -3
  224. data/ext/bson/native.c +0 -722
  225. data.tar.gz.sig +0 -0
  226. metadata.gz.sig +0 -0
data/lib/bson/boolean.rb CHANGED
@@ -1,4 +1,6 @@
1
- # Copyright (C) 2009-2014 MongoDB Inc.
1
+ # frozen_string_literal: true
2
+ # rubocop:todo all
3
+ # Copyright (C) 2009-2020 MongoDB Inc.
2
4
  #
3
5
  # Licensed under the Apache License, Version 2.0 (the "License");
4
6
  # you may not use this file except in compliance with the License.
@@ -25,19 +27,28 @@ module BSON
25
27
  # A boolean is type 0x08 in the BSON spec.
26
28
  #
27
29
  # @since 2.0.0
28
- BSON_TYPE = 8.chr.force_encoding(BINARY).freeze
30
+ BSON_TYPE = ::String.new(8.chr, encoding: BINARY).freeze
29
31
 
30
32
  # Deserialize a boolean from BSON.
31
33
  #
32
34
  # @param [ ByteBuffer ] buffer The byte buffer.
33
35
  #
36
+ # @option options [ nil | :bson ] :mode Decoding mode to use.
37
+ #
34
38
  # @return [ TrueClass, FalseClass ] The decoded boolean.
35
39
  #
36
40
  # @see http://bsonspec.org/#/specification
37
41
  #
38
42
  # @since 2.0.0
39
- def self.from_bson(buffer)
40
- buffer.get_byte == TrueClass::TRUE_BYTE
43
+ def self.from_bson(buffer, **options)
44
+ case v = buffer.get_byte
45
+ when TrueClass::TRUE_BYTE
46
+ true
47
+ when FalseClass::FALSE_BYTE
48
+ false
49
+ else
50
+ raise Error::BSONDecodeError, "Invalid boolean byte value: #{v}"
51
+ end
41
52
  end
42
53
 
43
54
  # Register this type when the module is loaded.
data/lib/bson/code.rb CHANGED
@@ -1,4 +1,6 @@
1
- # Copyright (C) 2009-2014 MongoDB Inc.
1
+ # frozen_string_literal: true
2
+ # rubocop:todo all
3
+ # Copyright (C) 2009-2020 MongoDB Inc.
2
4
  #
3
5
  # Licensed under the Apache License, Version 2.0 (the "License");
4
6
  # you may not use this file except in compliance with the License.
@@ -25,7 +27,7 @@ module BSON
25
27
  # A code is type 0x0D in the BSON spec.
26
28
  #
27
29
  # @since 2.0.0
28
- BSON_TYPE = 13.chr.force_encoding(BINARY).freeze
30
+ BSON_TYPE = ::String.new(13.chr, encoding: BINARY).freeze
29
31
 
30
32
  # @!attribute javascript
31
33
  # @return [ String ] The javascript code.
@@ -47,15 +49,24 @@ module BSON
47
49
  javascript == other.javascript
48
50
  end
49
51
 
50
- # Get the code as JSON hash data.
51
- #
52
- # @example Get the code as a JSON hash.
53
- # code.as_json
52
+ # Return a representation of the object for use in
53
+ # application-level JSON serialization. Since BSON::Code
54
+ # is used exclusively in BSON-related contexts, this
55
+ # method returns the canonical Extended JSON representation.
56
+ #
57
+ # @return [ Hash ] The extended json representation.
58
+ def as_json(*_args)
59
+ as_extended_json
60
+ end
61
+
62
+ # Converts this object to a representation directly serializable to
63
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json/extended-json.md).
54
64
  #
55
- # @return [ Hash ] The code as a JSON hash.
65
+ # @option opts [ nil | :relaxed | :legacy ] :mode Serialization mode
66
+ # (default is canonical extended JSON)
56
67
  #
57
- # @since 2.0.0
58
- def as_json(*args)
68
+ # @return [ Hash ] The extended json representation.
69
+ def as_extended_json(**_options)
59
70
  { "$code" => javascript }
60
71
  end
61
72
 
@@ -76,12 +87,12 @@ module BSON
76
87
  # @example Encode the code.
77
88
  # code.to_bson
78
89
  #
79
- # @return [ String ] The encoded string.
90
+ # @return [ BSON::ByteBuffer ] The buffer with the encoded object.
80
91
  #
81
92
  # @see http://bsonspec.org/#/specification
82
93
  #
83
94
  # @since 2.0.0
84
- def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
95
+ def to_bson(buffer = ByteBuffer.new)
85
96
  buffer.put_string(javascript) # @todo: was formerly to_bson_string
86
97
  end
87
98
 
@@ -89,12 +100,14 @@ module BSON
89
100
  #
90
101
  # @param [ ByteBuffer ] buffer The byte buffer.
91
102
  #
103
+ # @option options [ nil | :bson ] :mode Decoding mode to use.
104
+ #
92
105
  # @return [ TrueClass, FalseClass ] The decoded code.
93
106
  #
94
107
  # @see http://bsonspec.org/#/specification
95
108
  #
96
109
  # @since 2.0.0
97
- def self.from_bson(buffer)
110
+ def self.from_bson(buffer, **options)
98
111
  new(buffer.get_string)
99
112
  end
100
113
 
@@ -1,4 +1,6 @@
1
- # Copyright (C) 2009-2014 MongoDB Inc.
1
+ # frozen_string_literal: true
2
+ # rubocop:todo all
3
+ # Copyright (C) 2009-2020 MongoDB Inc.
2
4
  #
3
5
  # Licensed under the Apache License, Version 2.0 (the "License");
4
6
  # you may not use this file except in compliance with the License.
@@ -26,7 +28,7 @@ module BSON
26
28
  # A code with scope is type 0x0F in the BSON spec.
27
29
  #
28
30
  # @since 2.0.0
29
- BSON_TYPE = 15.chr.force_encoding(BINARY).freeze
31
+ BSON_TYPE = ::String.new(15.chr, encoding: BINARY).freeze
30
32
 
31
33
  # @!attribute javascript
32
34
  # @return [ String ] The javascript code.
@@ -51,16 +53,25 @@ module BSON
51
53
  javascript == other.javascript && scope == other.scope
52
54
  end
53
55
 
54
- # Get the code with scope as JSON hash data.
55
- #
56
- # @example Get the code with scope as a JSON hash.
57
- # code_with_scope.as_json
56
+ # Return a representation of the object for use in
57
+ # application-level JSON serialization. Since BSON::CodeWithScope
58
+ # is used exclusively in BSON-related contexts, this
59
+ # method returns the canonical Extended JSON representation.
60
+ #
61
+ # @return [ Hash ] The extended json representation.
62
+ def as_json(*_args)
63
+ as_extended_json
64
+ end
65
+
66
+ # Converts this object to a representation directly serializable to
67
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json/extended-json.md).
58
68
  #
59
- # @return [ Hash ] The code with scope as a JSON hash.
69
+ # @option opts [ nil | :relaxed | :legacy ] :mode Serialization mode
70
+ # (default is canonical extended JSON)
60
71
  #
61
- # @since 2.0.0
62
- def as_json(*args)
63
- { "$code" => javascript, "$scope" => scope }
72
+ # @return [ Hash ] The extended json representation.
73
+ def as_extended_json(**options)
74
+ { "$code" => javascript, "$scope" => scope.as_extended_json(**options) }
64
75
  end
65
76
 
66
77
  # Instantiate the new code with scope.
@@ -82,12 +93,12 @@ module BSON
82
93
  # @example Encode the code with scope.
83
94
  # code_with_scope.to_bson
84
95
  #
85
- # @return [ String ] The encoded string.
96
+ # @return [ BSON::ByteBuffer ] The buffer with the encoded object.
86
97
  #
87
98
  # @see http://bsonspec.org/#/specification
88
99
  #
89
100
  # @since 2.0.0
90
- def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
101
+ def to_bson(buffer = ByteBuffer.new)
91
102
  position = buffer.length
92
103
  buffer.put_int32(0)
93
104
  buffer.put_string(javascript)
@@ -99,14 +110,29 @@ module BSON
99
110
  #
100
111
  # @param [ ByteBuffer ] buffer The byte buffer.
101
112
  #
113
+ # @option options [ nil | :bson ] :mode Decoding mode to use.
114
+ #
102
115
  # @return [ TrueClass, FalseClass ] The decoded code with scope.
103
116
  #
104
117
  # @see http://bsonspec.org/#/specification
105
118
  #
106
119
  # @since 2.0.0
107
- def self.from_bson(buffer)
108
- buffer.get_int32 # Throw away the total length.
109
- new(buffer.get_string, ::Hash.from_bson(buffer))
120
+ def self.from_bson(buffer, **options)
121
+ # Code with scope has a length (?) field which is not needed for
122
+ # decoding, but spec tests want this field validated.
123
+ start_position = buffer.read_position
124
+ length = buffer.get_int32
125
+ javascript = buffer.get_string
126
+ scope = if options.empty?
127
+ ::Hash.from_bson(buffer)
128
+ else
129
+ ::Hash.from_bson(buffer, **options)
130
+ end
131
+ read_bytes = buffer.read_position - start_position
132
+ if read_bytes != length
133
+ raise Error::BSONDecodeError, "CodeWithScope invalid: claimed length #{length}, actual length #{read_bytes}"
134
+ end
135
+ new(javascript, scope)
110
136
  end
111
137
 
112
138
  # Register this type when the module is loaded.
data/lib/bson/config.rb CHANGED
@@ -1,4 +1,6 @@
1
- # Copyright (C) 2016 MongoDB Inc.
1
+ # frozen_string_literal: true
2
+ # rubocop:todo all
3
+ # Copyright (C) 2016-2020 MongoDB Inc.
2
4
  #
3
5
  # Licensed under the Apache License, Version 2.0 (the "License");
4
6
  # you may not use this file except in compliance with the License.
@@ -20,32 +22,5 @@ module BSON
20
22
  module Config
21
23
  extend self
22
24
 
23
- # Set the configuration option for BSON to validate keys or not.
24
- #
25
- # @example Set the config option.
26
- # BSON::Config.validating_keys = true
27
- #
28
- # @param [ true, false ] value The value to set.
29
- #
30
- # @return [ true, false ] The value.
31
- #
32
- # @since 4.1.0
33
- def validating_keys=(value)
34
- @validating_keys = value
35
- end
36
-
37
- # Returns true if BSON will validate the document keys on serialization to
38
- # determine if they contain invalid MongoDB values. Invalid keys start with
39
- # '$' or contain a '.' in them.
40
- #
41
- # @example Is BSON validating keys?
42
- # BSON::Config.validating_keys?
43
- #
44
- # @return [ true, false ] If BSON is validating keys?
45
- #
46
- # @since 4.1.0
47
- def validating_keys?
48
- !!@validating_keys
49
- end
50
25
  end
51
26
  end
data/lib/bson/date.rb CHANGED
@@ -1,4 +1,6 @@
1
- # Copyright (C) 2009-2014 MongoDB Inc.
1
+ # frozen_string_literal: true
2
+ # rubocop:todo all
3
+ # Copyright (C) 2009-2020 MongoDB Inc.
2
4
  #
3
5
  # Licensed under the Apache License, Version 2.0 (the "License");
4
6
  # you may not use this file except in compliance with the License.
@@ -16,6 +18,16 @@ require 'date'
16
18
 
17
19
  module BSON
18
20
 
21
+ # Julian day of Date 1970-01-01 - UNIX timestamp reference.
22
+ #
23
+ # @api private
24
+ DATE_REFERENCE = ::Date.new(1970, 1, 1).jd
25
+
26
+ # Number of miliseconds in a day.
27
+ #
28
+ # @api private
29
+ MILLISECONDS_IN_DAY = 60 * 60 * 24 * 1_000
30
+
19
31
  # Injects behaviour for encoding date values to raw bytes as specified by
20
32
  # the BSON spec for time.
21
33
  #
@@ -29,13 +41,13 @@ module BSON
29
41
  # @example Get the date as encoded BSON.
30
42
  # Date.new(2012, 1, 1).to_bson
31
43
  #
32
- # @return [ String ] The encoded string.
44
+ # @return [ BSON::ByteBuffer ] The buffer with the encoded object.
33
45
  #
34
46
  # @see http://bsonspec.org/#/specification
35
47
  #
36
48
  # @since 2.1.0
37
- def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
38
- ::Time.utc(year, month, day).to_bson(buffer)
49
+ def to_bson(buffer = ByteBuffer.new)
50
+ buffer.put_int64((jd - DATE_REFERENCE) * MILLISECONDS_IN_DAY)
39
51
  end
40
52
 
41
53
  # Get the BSON type for the date.
@@ -1,4 +1,6 @@
1
- # Copyright (C) 2009-2014 MongoDB Inc.
1
+ # frozen_string_literal: true
2
+ # rubocop:todo all
3
+ # Copyright (C) 2009-2020 MongoDB Inc.
2
4
  #
3
5
  # Licensed under the Apache License, Version 2.0 (the "License");
4
6
  # you may not use this file except in compliance with the License.
@@ -29,13 +31,13 @@ module BSON
29
31
  # @example Get the date time as encoded BSON.
30
32
  # DateTime.new(2012, 1, 1, 0, 0, 0).to_bson
31
33
  #
32
- # @return [ String ] The encoded string.
34
+ # @return [ BSON::ByteBuffer ] The buffer with the encoded object.
33
35
  #
34
36
  # @see http://bsonspec.org/#/specification
35
37
  #
36
38
  # @since 2.1.0
37
- def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
38
- to_time.to_bson(buffer)
39
+ def to_bson(buffer = ByteBuffer.new)
40
+ gregorian.to_time.to_bson(buffer)
39
41
  end
40
42
  end
41
43
 
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+ # rubocop:todo all
3
+ # Copyright (C) 2020 MongoDB Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ module BSON
18
+
19
+ # Injects behaviour for encoding and decoding DBPointer values to and from
20
+ # raw bytes as specified by the BSON spec.
21
+ #
22
+ # @see http://bsonspec.org/#/specification
23
+ class DbPointer
24
+ include JSON
25
+
26
+ # A DBPointer is type 0x0C in the BSON spec.
27
+ BSON_TYPE = ::String.new(0x0C.chr, encoding: BINARY).freeze
28
+
29
+ # Create a new DBPointer object.
30
+ #
31
+ # @param [ String ] ref The database collection name.
32
+ # @param [ BSON::ObjectId ] id The DBPointer id.
33
+ def initialize(ref, id)
34
+ @ref = ref
35
+ @id = id
36
+ end
37
+
38
+ # Return the collection name.
39
+ #
40
+ # @return [ String ] The database collection name.
41
+ attr_reader :ref
42
+
43
+ # Return the DbPointer's id.
44
+ #
45
+ # @return [ BSON::ObjectId ] The id of the DbPointer instance
46
+ attr_reader :id
47
+
48
+ # Determine if this DBPointer object is equal to another object.
49
+ #
50
+ # @param [ Object ] other The object to compare against.
51
+ #
52
+ # @return [ true | false ] If the objects are equal
53
+ def ==(other)
54
+ return false unless other.is_a?(DbPointer)
55
+ ref == other.ref && id == other.id
56
+ end
57
+
58
+ # Return a representation of the object for use in
59
+ # application-level JSON serialization. Since BSON::DbPointer
60
+ # is used exclusively in BSON-related contexts, this
61
+ # method returns the canonical Extended JSON representation.
62
+ #
63
+ # @return [ Hash ] The extended json representation.
64
+ def as_json(*_args)
65
+ as_extended_json
66
+ end
67
+
68
+ # Converts this object to a representation directly serializable to
69
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json/extended-json.md).
70
+ #
71
+ # @return [ Hash ] The extended json representation.
72
+ def as_extended_json(**_options)
73
+ { '$dbPointer' => { "$ref" => ref, '$id' => id.as_extended_json } }
74
+ end
75
+
76
+ # Encode the DBPointer.
77
+ #
78
+ # @return [ BSON::ByteBuffer ] The buffer with the encoded object.
79
+ #
80
+ # @see http://bsonspec.org/#/specification
81
+ def to_bson(buffer = ByteBuffer.new)
82
+ buffer.put_string(ref)
83
+ id.to_bson(buffer)
84
+ buffer
85
+ end
86
+
87
+ # Deserialize a DBPointer from BSON.
88
+ #
89
+ # @param [ ByteBuffer ] buffer The byte buffer.
90
+ # @param [ Hash ] options
91
+ #
92
+ # @option options [ nil | :bson ] :mode Decoding mode to use.
93
+ #
94
+ # @return [ BSON::DbPointer ] The decoded DBPointer.
95
+ #
96
+ # @see http://bsonspec.org/#/specification
97
+ def self.from_bson(buffer, **options)
98
+ ref = buffer.get_string
99
+ id = if options.empty?
100
+ ObjectId.from_bson(buffer)
101
+ else
102
+ ObjectId.from_bson(buffer, **options)
103
+ end
104
+ new(ref, id)
105
+ end
106
+
107
+ # Register this type when the module is loaded.
108
+ Registry.register(BSON_TYPE, self)
109
+ end
110
+ end
data/lib/bson/dbref.rb ADDED
@@ -0,0 +1,154 @@
1
+ # frozen_string_literal: true
2
+ # rubocop:todo all
3
+
4
+ # Copyright (C) 2015-2021 MongoDB Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the 'License');
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an 'AS IS' BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ module BSON
19
+
20
+ # Represents a DBRef document in the database.
21
+ class DBRef < Document
22
+ include JSON
23
+
24
+ # The constant for the collection reference field.
25
+ #
26
+ # @deprecated
27
+ COLLECTION = '$ref'.freeze
28
+
29
+ # The constant for the id field.
30
+ #
31
+ # @deprecated
32
+ ID = '$id'.freeze
33
+
34
+ # The constant for the database field.
35
+ #
36
+ # @deprecated
37
+ DATABASE = '$db'.freeze
38
+
39
+ # @return [ String ] collection The collection name.
40
+ def collection
41
+ self['$ref']
42
+ end
43
+
44
+ # @return [ BSON::ObjectId ] id The referenced document id.
45
+ def id
46
+ self['$id']
47
+ end
48
+
49
+ # @return [ String ] database The database name.
50
+ def database
51
+ self['$db']
52
+ end
53
+
54
+ # Get the DBRef as a JSON document
55
+ #
56
+ # @example Get the DBRef as a JSON hash.
57
+ # dbref.as_json
58
+ #
59
+ # @return [ Hash ] The max key as a JSON hash.
60
+ def as_json(*args)
61
+ {}.update(self)
62
+ end
63
+
64
+ # Instantiate a new DBRef.
65
+ #
66
+ # @example Create the DBRef - hash API.
67
+ # BSON::DBRef.new({'$ref' => 'users', '$id' => id, '$db' => 'database'})
68
+ #
69
+ # @example Create the DBRef - legacy API.
70
+ # BSON::DBRef.new('users', id, 'database')
71
+ #
72
+ # @param [ Hash | String ] hash_or_collection The DBRef hash, when using
73
+ # the hash API. It must contain $ref and $id. When using the legacy API,
74
+ # this parameter must be a String containing the collection name.
75
+ # @param [ Object ] id The object id, when using the legacy API.
76
+ # @param [ String ] database The database name, when using the legacy API.
77
+ #
78
+ # @raise [ BSON::Error::InvalidDBRefArgument ] if giving invalid arguments
79
+ # to the constructor.
80
+ def initialize(hash_or_collection, id = nil, database = nil)
81
+ if hash_or_collection.is_a?(Hash)
82
+ hash = hash_or_collection
83
+
84
+ unless id.nil? && database.nil?
85
+ raise Error::InvalidDBRefArgument, 'When using the hash API, DBRef constructor accepts only one argument'
86
+ end
87
+ else
88
+ warn("BSON::DBRef constructor called with the legacy API - please use the hash API instead")
89
+
90
+ if id.nil?
91
+ raise Error::InvalidDBRefArgument, 'When using the legacy constructor API, id must be provided'
92
+ end
93
+
94
+ hash = {
95
+ :$ref => hash_or_collection,
96
+ :$id => id,
97
+ :$db => database,
98
+ }
99
+ end
100
+
101
+ hash = reorder_fields(hash)
102
+ %w($ref $id).each do |key|
103
+ unless hash[key]
104
+ raise Error::InvalidDBRefArgument, "DBRef must have #{key}: #{hash}"
105
+ end
106
+ end
107
+
108
+ unless hash['$ref'].is_a?(String)
109
+ raise Error::InvalidDBRefArgument, "The value for key $ref must be a string, got: #{hash['$ref']}"
110
+ end
111
+
112
+ if db = hash['$db']
113
+ unless db.is_a?(String)
114
+ raise Error::InvalidDBRefArgument, "The value for key $db must be a string, got: #{hash['$db']}"
115
+ end
116
+ end
117
+
118
+ super(hash)
119
+ end
120
+
121
+ # Converts the DBRef to raw BSON.
122
+ #
123
+ # @example Convert the DBRef to raw BSON.
124
+ # dbref.to_bson
125
+ #
126
+ # @param [ BSON::ByteBuffer ] buffer The encoded BSON buffer to append to.
127
+ #
128
+ # @return [ BSON::ByteBuffer ] The buffer with the encoded object.
129
+ def to_bson(buffer = ByteBuffer.new)
130
+ as_json.to_bson(buffer)
131
+ end
132
+
133
+ private
134
+
135
+ # Reorder the fields of the given Hash to have $ref first, $id second,
136
+ # and $db third. The rest of the fields in the hash can come in any
137
+ # order after that.
138
+ #
139
+ # @param [ Hash ] hash The input hash. Must be a valid dbref.
140
+ #
141
+ # @return [ Hash ] The hash with it's fields reordered.
142
+ def reorder_fields(hash)
143
+ hash = BSON::Document.new(hash)
144
+ reordered = {}
145
+ reordered['$ref'] = hash.delete('$ref')
146
+ reordered['$id'] = hash.delete('$id')
147
+ if db = hash.delete('$db')
148
+ reordered['$db'] = db
149
+ end
150
+
151
+ reordered.update(hash)
152
+ end
153
+ end
154
+ end