bson 4.15.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +4 -4
  4. data/Rakefile +5 -0
  5. data/ext/bson/bson-native.h +12 -4
  6. data/ext/bson/extconf.rb +8 -3
  7. data/ext/bson/init.c +11 -11
  8. data/ext/bson/read.c +21 -6
  9. data/ext/bson/util.c +168 -16
  10. data/ext/bson/write.c +30 -39
  11. data/lib/bson/active_support.rb +1 -0
  12. data/lib/bson/array.rb +57 -31
  13. data/lib/bson/big_decimal.rb +16 -6
  14. data/lib/bson/binary.rb +255 -128
  15. data/lib/bson/boolean.rb +1 -0
  16. data/lib/bson/code.rb +9 -11
  17. data/lib/bson/code_with_scope.rb +8 -10
  18. data/lib/bson/config.rb +1 -27
  19. data/lib/bson/date.rb +2 -1
  20. data/lib/bson/date_time.rb +2 -1
  21. data/lib/bson/db_pointer.rb +11 -12
  22. data/lib/bson/dbref.rb +11 -9
  23. data/lib/bson/decimal128/builder.rb +9 -8
  24. data/lib/bson/decimal128.rb +24 -110
  25. data/lib/bson/document.rb +1 -0
  26. data/lib/bson/environment.rb +1 -0
  27. data/lib/bson/error/bson_decode_error.rb +11 -0
  28. data/lib/bson/error/ext_json_parse_error.rb +11 -0
  29. data/lib/bson/error/illegal_key.rb +23 -0
  30. data/lib/bson/error/invalid_binary_type.rb +37 -0
  31. data/lib/bson/error/invalid_dbref_argument.rb +12 -0
  32. data/lib/bson/error/invalid_decimal128_argument.rb +25 -0
  33. data/lib/bson/error/invalid_decimal128_range.rb +27 -0
  34. data/lib/bson/error/invalid_decimal128_string.rb +26 -0
  35. data/lib/bson/error/invalid_key.rb +24 -0
  36. data/lib/bson/error/invalid_object_id.rb +11 -0
  37. data/lib/bson/error/invalid_regexp_pattern.rb +13 -0
  38. data/lib/bson/error/unrepresentable_precision.rb +19 -0
  39. data/lib/bson/error/unserializable_class.rb +13 -0
  40. data/lib/bson/error/unsupported_binary_subtype.rb +12 -0
  41. data/lib/bson/error/unsupported_type.rb +11 -0
  42. data/lib/bson/error.rb +16 -28
  43. data/lib/bson/ext_json.rb +1 -0
  44. data/lib/bson/false_class.rb +2 -1
  45. data/lib/bson/float.rb +2 -1
  46. data/lib/bson/hash.rb +127 -72
  47. data/lib/bson/int32.rb +16 -4
  48. data/lib/bson/int64.rb +16 -4
  49. data/lib/bson/integer.rb +3 -4
  50. data/lib/bson/json.rb +1 -0
  51. data/lib/bson/max_key.rb +7 -9
  52. data/lib/bson/min_key.rb +7 -9
  53. data/lib/bson/nil_class.rb +1 -0
  54. data/lib/bson/object.rb +5 -25
  55. data/lib/bson/object_id.rb +75 -121
  56. data/lib/bson/open_struct.rb +3 -2
  57. data/lib/bson/regexp.rb +35 -64
  58. data/lib/bson/registry.rb +2 -6
  59. data/lib/bson/specialized.rb +2 -1
  60. data/lib/bson/string.rb +4 -27
  61. data/lib/bson/symbol.rb +22 -19
  62. data/lib/bson/time.rb +2 -1
  63. data/lib/bson/time_with_zone.rb +13 -1
  64. data/lib/bson/timestamp.rb +2 -1
  65. data/lib/bson/true_class.rb +2 -1
  66. data/lib/bson/undefined.rb +14 -0
  67. data/lib/bson/version.rb +2 -1
  68. data/lib/bson.rb +3 -2
  69. data/spec/bson/array_spec.rb +19 -60
  70. data/spec/bson/big_decimal_spec.rb +16 -4
  71. data/spec/bson/binary_spec.rb +83 -74
  72. data/spec/bson/binary_uuid_spec.rb +1 -0
  73. data/spec/bson/boolean_spec.rb +1 -0
  74. data/spec/bson/byte_buffer_read_spec.rb +1 -0
  75. data/spec/bson/byte_buffer_spec.rb +1 -0
  76. data/spec/bson/byte_buffer_write_spec.rb +1 -0
  77. data/spec/bson/code_spec.rb +5 -3
  78. data/spec/bson/code_with_scope_spec.rb +5 -3
  79. data/spec/bson/config_spec.rb +1 -35
  80. data/spec/bson/date_spec.rb +1 -0
  81. data/spec/bson/date_time_spec.rb +1 -0
  82. data/spec/bson/dbref_legacy_spec.rb +20 -3
  83. data/spec/bson/dbref_spec.rb +9 -9
  84. data/spec/bson/decimal128_spec.rb +40 -20
  85. data/spec/bson/document_as_spec.rb +1 -0
  86. data/spec/bson/document_spec.rb +1 -1
  87. data/spec/bson/ext_json_parse_spec.rb +1 -0
  88. data/spec/bson/false_class_spec.rb +8 -0
  89. data/spec/bson/float_spec.rb +8 -3
  90. data/spec/bson/hash_as_spec.rb +1 -0
  91. data/spec/bson/hash_spec.rb +87 -75
  92. data/spec/bson/int32_spec.rb +21 -6
  93. data/spec/bson/int64_spec.rb +21 -6
  94. data/spec/bson/integer_spec.rb +45 -13
  95. data/spec/bson/json_spec.rb +1 -0
  96. data/spec/bson/max_key_spec.rb +5 -3
  97. data/spec/bson/min_key_spec.rb +5 -3
  98. data/spec/bson/nil_class_spec.rb +1 -0
  99. data/spec/bson/object_id_spec.rb +43 -4
  100. data/spec/bson/object_spec.rb +2 -1
  101. data/spec/bson/open_struct_spec.rb +14 -71
  102. data/spec/bson/raw_spec.rb +9 -15
  103. data/spec/bson/regexp_spec.rb +4 -3
  104. data/spec/bson/registry_spec.rb +2 -1
  105. data/spec/bson/string_spec.rb +13 -38
  106. data/spec/bson/symbol_raw_spec.rb +25 -0
  107. data/spec/bson/symbol_spec.rb +15 -18
  108. data/spec/bson/time_spec.rb +1 -0
  109. data/spec/bson/time_with_zone_spec.rb +1 -0
  110. data/spec/bson/timestamp_spec.rb +1 -0
  111. data/spec/bson/true_class_spec.rb +8 -0
  112. data/spec/bson/undefined_spec.rb +27 -0
  113. data/spec/bson_spec.rb +1 -0
  114. data/spec/runners/common_driver.rb +6 -5
  115. data/spec/runners/corpus.rb +6 -0
  116. data/spec/runners/corpus_legacy.rb +1 -0
  117. data/spec/shared/lib/mrss/constraints.rb +8 -16
  118. data/spec/shared/lib/mrss/docker_runner.rb +30 -3
  119. data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
  120. data/spec/shared/lib/mrss/event_subscriber.rb +15 -5
  121. data/spec/shared/lib/mrss/lite_constraints.rb +48 -1
  122. data/spec/shared/lib/mrss/server_version_registry.rb +16 -23
  123. data/spec/shared/lib/mrss/session_registry.rb +69 -0
  124. data/spec/shared/lib/mrss/session_registry_legacy.rb +60 -0
  125. data/spec/shared/lib/mrss/utils.rb +28 -6
  126. data/spec/shared/share/Dockerfile.erb +68 -85
  127. data/spec/shared/shlib/config.sh +27 -0
  128. data/spec/shared/shlib/server.sh +73 -24
  129. data/spec/shared/shlib/set_env.sh +39 -1
  130. data/spec/spec_helper.rb +1 -0
  131. data/spec/spec_tests/common_driver_spec.rb +9 -4
  132. data/spec/spec_tests/corpus_legacy_spec.rb +1 -0
  133. data/spec/spec_tests/corpus_spec.rb +13 -3
  134. data/spec/spec_tests/data/corpus/binary.json +5 -0
  135. data/spec/spec_tests/data/corpus/code.json +13 -13
  136. data/spec/spec_tests/data/corpus/decimal128-4.json +48 -0
  137. data/spec/spec_tests/data/corpus/decimal128-6.json +12 -0
  138. data/spec/spec_tests/data/corpus/decimal128-7.json +4 -0
  139. data/spec/spec_tests/data/corpus/document.json +20 -0
  140. data/spec/spec_tests/data/corpus/symbol.json +7 -7
  141. data/spec/spec_tests/data/corpus/top.json +18 -3
  142. data/spec/support/shared_examples.rb +28 -5
  143. data/spec/support/spec_config.rb +1 -0
  144. data/spec/support/utils.rb +49 -1
  145. data.tar.gz.sig +0 -0
  146. metadata +167 -144
  147. metadata.gz.sig +2 -1
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright (C) 2009-2020 MongoDB Inc.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,12 +14,7 @@
13
14
  # See the License for the specific language governing permissions and
14
15
  # limitations under the License.
15
16
 
16
- require "digest/md5"
17
- require "socket"
18
- require "thread"
19
-
20
17
  module BSON
21
-
22
18
  # Represents object_id data.
23
19
  #
24
20
  # @see http://bsonspec.org/#/specification
@@ -45,9 +41,10 @@ module BSON
45
41
  # @since 2.0.0
46
42
  def ==(other)
47
43
  return false unless other.is_a?(ObjectId)
44
+
48
45
  generate_data == other.send(:generate_data)
49
46
  end
50
- alias :eql? :==
47
+ alias eql? ==
51
48
 
52
49
  # Check case equality on the object id.
53
50
  #
@@ -60,32 +57,29 @@ module BSON
60
57
  #
61
58
  # @since 2.0.0
62
59
  def ===(other)
63
- return to_str === other.to_str if other.respond_to?(:to_str)
60
+ return to_str == other.to_str if other.respond_to?(:to_str)
61
+
64
62
  super
65
63
  end
66
64
 
67
- # Return the object id as a JSON hash representation.
65
+ # Return a string representation of the object id for use in
66
+ # application-level JSON serialization. This method is intentionally
67
+ # different from #as_extended_json.
68
68
  #
69
- # @example Get the object id as JSON.
69
+ # @example Get the object id as a JSON-serializable object.
70
70
  # object_id.as_json
71
71
  #
72
- # @return [ Hash ] The object id as a JSON hash.
73
- #
74
- # @since 2.0.0
75
- # @deprecated Use as_extended_json instead.
76
- def as_json(*args)
77
- as_extended_json
72
+ # @return [ String ] The object id as a string.
73
+ def as_json(*_)
74
+ to_s
78
75
  end
79
76
 
80
77
  # Converts this object to a representation directly serializable to
81
78
  # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
82
79
  #
83
- # @option opts [ nil | :relaxed | :legacy ] :mode Serialization mode
84
- # (default is canonical extended JSON)
85
- #
86
80
  # @return [ Hash ] The extended json representation.
87
- def as_extended_json(**options)
88
- { "$oid" => to_s }
81
+ def as_extended_json(**_)
82
+ { '$oid' => to_s }
89
83
  end
90
84
 
91
85
  # Compare this object id with another object for use in sorting.
@@ -113,9 +107,9 @@ module BSON
113
107
  #
114
108
  # @since 2.0.0
115
109
  def generation_time
116
- ::Time.at(generate_data.unpack1("N")).utc
110
+ ::Time.at(generate_data.unpack1('N')).utc
117
111
  end
118
- alias :to_time :generation_time
112
+ alias to_time generation_time
119
113
 
120
114
  # Get the hash value for the object id.
121
115
  #
@@ -138,7 +132,7 @@ module BSON
138
132
  #
139
133
  # @since 2.0.0
140
134
  def inspect
141
- "BSON::ObjectId('#{to_s}')"
135
+ "BSON::ObjectId('#{self}')"
142
136
  end
143
137
 
144
138
  # Dump the raw bson when calling Marshal.dump.
@@ -182,7 +176,7 @@ module BSON
182
176
  # @see http://bsonspec.org/#/specification
183
177
  #
184
178
  # @since 2.0.0
185
- def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
179
+ def to_bson(buffer = ByteBuffer.new)
186
180
  buffer.put_bytes(generate_data)
187
181
  end
188
182
 
@@ -197,12 +191,46 @@ module BSON
197
191
  def to_s
198
192
  generate_data.to_hex_string.force_encoding(UTF8)
199
193
  end
200
- alias :to_str :to_s
194
+ alias to_str to_s
201
195
 
202
- # Raised when trying to create an object id with invalid data.
196
+ # Extract the process-specific part of the object id. This is used only
197
+ # internally, for testing, and should not be used elsewhere.
203
198
  #
204
- # @since 2.0.0
205
- class Invalid < RuntimeError; end
199
+ # @return [ String ] The process portion of the id.
200
+ #
201
+ # @api private
202
+ def _process_part
203
+ to_s[8, 10]
204
+ end
205
+
206
+ # Extract the counter-specific part of the object id. This is used only
207
+ # internally, for testing, and should not be used elsewhere.
208
+ #
209
+ # @return [ String ] The counter portion of the id.
210
+ #
211
+ # @api private
212
+ def _counter_part
213
+ to_s[18, 6]
214
+ end
215
+
216
+ # Extended by native code (see init.c, util.c, GeneratorExtension.java)
217
+ #
218
+ # @api private
219
+ #
220
+ # rubocop:disable Lint/EmptyClass
221
+ class Generator
222
+ end
223
+ # rubocop:enable Lint/EmptyClass
224
+
225
+ # We keep one global generator for object ids.
226
+ @@generator = Generator.new
227
+
228
+ # Accessor for querying the generator directly; used in testing.
229
+ #
230
+ # @api private
231
+ def self._generator
232
+ @@generator
233
+ end
206
234
 
207
235
  private
208
236
 
@@ -213,7 +241,10 @@ module BSON
213
241
 
214
242
  def generate_data
215
243
  repair if defined?(@data)
244
+
245
+ # rubocop:disable Naming/MemoizedInstanceVariableName
216
246
  @raw_data ||= @@generator.next_object_id
247
+ # rubocop:enable Naming/MemoizedInstanceVariableName
217
248
  end
218
249
 
219
250
  def repair
@@ -222,20 +253,18 @@ module BSON
222
253
  end
223
254
 
224
255
  class << self
225
-
226
256
  # Deserialize the object id from raw BSON bytes.
227
257
  #
228
258
  # @example Get the object id from BSON.
229
259
  # ObjectId.from_bson(bson)
230
260
  #
231
261
  # @param [ ByteBuffer ] buffer The byte buffer.
232
- #
233
- # @option options [ nil | :bson ] :mode Decoding mode to use.
262
+ # @param [ Hash ] _ An optional hash of keyword arguments (unused).
234
263
  #
235
264
  # @return [ BSON::ObjectId ] The object id.
236
265
  #
237
266
  # @since 2.0.0
238
- def from_bson(buffer, **options)
267
+ def from_bson(buffer, **_)
239
268
  from_data(buffer.get_bytes(12))
240
269
  end
241
270
 
@@ -262,16 +291,15 @@ module BSON
262
291
  #
263
292
  # @param [ String ] string The string to create the id from.
264
293
  #
265
- # @raise [ BSON::ObjectId::Invalid ] If the provided string is invalid.
294
+ # @raise [ BSON::Error::InvalidObjectId ] If the provided string is invalid.
266
295
  #
267
296
  # @return [ BSON::ObjectId ] The new object id.
268
297
  #
269
298
  # @since 2.0.0
270
299
  def from_string(string)
271
- unless legal?(string)
272
- raise Invalid.new("'#{string}' is an invalid ObjectId.")
273
- end
274
- from_data([ string ].pack("H*"))
300
+ raise Error::InvalidObjectId, "'#{string}' is an invalid ObjectId." unless legal?(string)
301
+
302
+ from_data([ string ].pack('H*'))
275
303
  end
276
304
 
277
305
  # Create a new object id from a time.
@@ -292,7 +320,7 @@ module BSON
292
320
  #
293
321
  # @since 2.0.0
294
322
  def from_time(time, options = {})
295
- from_data(options[:unique] ? @@generator.next_object_id(time.to_i) : [ time.to_i ].pack("Nx8"))
323
+ from_data(options[:unique] ? @@generator.next_object_id(time.to_i) : [ time.to_i ].pack('Nx8'))
296
324
  end
297
325
 
298
326
  # Determine if the provided string is a legal object id.
@@ -306,7 +334,7 @@ module BSON
306
334
  #
307
335
  # @since 2.0.0
308
336
  def legal?(string)
309
- string.to_s =~ /\A[0-9a-f]{24}\z/i ? true : false
337
+ (string.to_s =~ /\A[0-9a-f]{24}\z/i) ? true : false
310
338
  end
311
339
 
312
340
  # Executes the provided block only if the size of the provided object is
@@ -317,100 +345,26 @@ module BSON
317
345
  #
318
346
  # @param [ String, Array ] object The object to repair.
319
347
  #
320
- # @raise [ Invalid ] If the array is not 12 elements.
348
+ # @raise [ BSON::Error::InvalidObjectId ] If the array is not 12 elements.
321
349
  #
322
350
  # @return [ String ] The result of the block.
323
351
  #
324
352
  # @since 2.0.0
325
353
  def repair(object)
326
- if object.size == 12
327
- block_given? ? yield(object) : object
328
- else
329
- raise Invalid.new("#{object.inspect} is not a valid object id.")
330
- end
331
- end
332
- end
354
+ raise Error::InvalidObjectId, "#{object.inspect} is not a valid object id." if object.size != 12
333
355
 
334
- # Inner class that encapsulates the behaviour of actually generating each
335
- # part of the ObjectId.
336
- #
337
- # @api private
338
- #
339
- # @since 2.0.0
340
- class Generator
341
-
342
- # @!attribute machine_id
343
- # @return [ String ] The unique machine id.
344
- # @since 2.0.0
345
- attr_reader :machine_id
346
-
347
- # Instantiate the new object id generator. Will set the machine id once
348
- # on the initial instantiation.
349
- #
350
- # @example Instantiate the generator.
351
- # BSON::ObjectId::Generator.new
352
- #
353
- # @since 2.0.0
354
- def initialize
355
- @counter = rand(0x1000000)
356
- @machine_id = Digest::MD5.digest(Socket.gethostname).unpack1("N")
357
- @mutex = Mutex.new
356
+ block_given? ? yield(object) : object
358
357
  end
359
358
 
360
- # Return object id data based on the current time, incrementing the
361
- # object id counter. Will use the provided time if not nil.
362
- #
363
- # @example Get the next object id data.
364
- # generator.next_object_id
365
- #
366
- # @param [ Time ] time The optional time to generate with.
367
- #
368
- # @return [ String ] The raw object id bytes.
359
+ # Returns an integer timestamp (seconds since the Epoch). Primarily used
360
+ # by the generator to produce object ids.
369
361
  #
370
- # @since 2.0.0
371
- def next_object_id(time = nil)
372
- @mutex.lock
373
- begin
374
- count = @counter = (@counter + 1) % 0xFFFFFF
375
- ensure
376
- @mutex.unlock rescue nil
377
- end
378
- generate(time || ::Time.new.to_i, count)
379
- end
380
-
381
- # Generate object id data for a given time using the provided counter.
382
- #
383
- # @example Generate the object id bytes.
384
- # generator.generate(time)
385
- #
386
- # @param [ Integer ] time The time since epoch in seconds.
387
- # @param [ Integer ] counter The optional counter.
388
- #
389
- # @return [ String ] The raw object id bytes.
390
- #
391
- # @since 2.0.0
392
- def generate(time, counter = 0)
393
- [ time, machine_id, process_id, counter << 8 ].pack("N NX lXX NX")
394
- end
395
-
396
- private
397
-
398
- if Environment.jruby?
399
- def process_id
400
- "#{Process.pid}#{Thread.current.object_id}".hash % 0xFFFF
401
- end
402
- else
403
- def process_id
404
- Process.pid % 0xFFFF
405
- end
362
+ # @return [ Integer ] the number of seconds since the Epoch.
363
+ def timestamp
364
+ ::Time.now.to_i
406
365
  end
407
366
  end
408
367
 
409
- # We keep one global generator for object ids.
410
- #
411
- # @since 2.0.0
412
- @@generator = Generator.new
413
-
414
368
  # Register this type when the module is loaded.
415
369
  #
416
370
  # @since 2.0.0
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # rubocop:todo all
2
3
  # Copyright (C) 2016-2020 MongoDB Inc.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -33,12 +34,12 @@ module BSON
33
34
  # @see http://bsonspec.org/#/specification
34
35
  #
35
36
  # @since 4.2.0
36
- def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
37
+ def to_bson(buffer = ByteBuffer.new)
37
38
  if Environment.ruby_1_9?
38
39
  marshal_dump.dup
39
40
  else
40
41
  to_h
41
- end.to_bson(buffer, validating_keys)
42
+ end.to_bson(buffer)
42
43
  end
43
44
 
44
45
  # The BSON type for OpenStruct objects is the Hash type of 0x03.
data/lib/bson/regexp.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Copyright (C) 2009-2020 MongoDB Inc.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,8 +14,8 @@
13
14
  # See the License for the specific language governing permissions and
14
15
  # limitations under the License.
15
16
 
17
+ # The top-level BSON module.
16
18
  module BSON
17
-
18
19
  # Injects behaviour for encoding and decoding regular expression values to
19
20
  # and from raw bytes as specified by the BSON spec.
20
21
  #
@@ -62,10 +63,8 @@ module BSON
62
63
  # regexp.as_json
63
64
  #
64
65
  # @return [ Hash ] The regexp as a JSON hash.
65
- #
66
- # @since 2.0.0
67
- def as_json(*args)
68
- { "$regex" => source, "$options" => bson_options }
66
+ def as_json(*)
67
+ { '$regex' => source, '$options' => bson_options }
69
68
  end
70
69
 
71
70
  # Get the regular expression as encoded BSON.
@@ -83,14 +82,11 @@ module BSON
83
82
  # and 'u' to make \w, \W, etc. match unicode.
84
83
  #
85
84
  # @param [ BSON::ByteBuffer ] buffer The byte buffer to append to.
86
- # @param [ true, false ] validating_keys
87
85
  #
88
86
  # @return [ BSON::ByteBuffer ] The buffer with the encoded object.
89
87
  #
90
88
  # @see http://bsonspec.org/#/specification
91
- #
92
- # @since 2.0.0
93
- def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
89
+ def to_bson(buffer = ByteBuffer.new)
94
90
  buffer.put_cstring(source)
95
91
  buffer.put_cstring(bson_options)
96
92
  end
@@ -103,30 +99,28 @@ module BSON
103
99
  end
104
100
 
105
101
  def bson_extended
106
- (options & ::Regexp::EXTENDED != 0) ? EXTENDED_VALUE : NO_VALUE
102
+ (options & ::Regexp::EXTENDED).zero? ? NO_VALUE : EXTENDED_VALUE
107
103
  end
108
104
 
109
105
  def bson_ignorecase
110
- (options & ::Regexp::IGNORECASE != 0) ? IGNORECASE_VALUE : NO_VALUE
106
+ (options & ::Regexp::IGNORECASE).zero? ? NO_VALUE : IGNORECASE_VALUE
111
107
  end
112
108
 
113
109
  def bson_dotall
114
110
  # Ruby Regexp's MULTILINE is equivalent to BSON's dotall value
115
- (options & ::Regexp::MULTILINE != 0) ? NEWLINE_VALUE : NO_VALUE
111
+ (options & ::Regexp::MULTILINE).zero? ? NO_VALUE : NEWLINE_VALUE
116
112
  end
117
113
 
118
114
  # Represents the raw values for the regular expression.
119
115
  #
120
116
  # @see https://jira.mongodb.org/browse/RUBY-698
121
- #
122
- # @since 3.0.0
123
117
  class Raw
124
118
  include JSON
125
119
 
126
120
  # @return [ String ] pattern The regex pattern.
127
121
  attr_reader :pattern
128
122
 
129
- # @return [ Integer ] options The options.
123
+ # @return [ String ] options The options.
130
124
  attr_reader :options
131
125
 
132
126
  # Compile the Regular expression into the native type.
@@ -135,10 +129,8 @@ module BSON
135
129
  # raw.compile
136
130
  #
137
131
  # @return [ ::Regexp ] The compiled regular expression.
138
- #
139
- # @since 3.0.0
140
132
  def compile
141
- @compiled ||= ::Regexp.new(pattern, options_to_int)
133
+ @compile ||= ::Regexp.new(pattern, options_to_int)
142
134
  end
143
135
 
144
136
  # Initialize the new raw regular expression.
@@ -147,13 +139,7 @@ module BSON
147
139
  # Raw.new(pattern, options)
148
140
  #
149
141
  # @param [ String ] pattern The regular expression pattern.
150
- # @param [ String, Integer ] options The options.
151
- #
152
- # @note The ability to specify options as an Integer is deprecated.
153
- # Please specify options as a String. The ability to pass options as
154
- # as Integer will be removed in version 5.0.0.
155
- #
156
- # @since 3.0.0
142
+ # @param [ String | Symbol ] options The options.
157
143
  def initialize(pattern, options = '')
158
144
  if pattern.include?(NULL_BYTE)
159
145
  raise Error::InvalidRegexpPattern, "Regexp pattern cannot contain a null byte: #{pattern}"
@@ -161,28 +147,22 @@ module BSON
161
147
  if options.to_s.include?(NULL_BYTE)
162
148
  raise Error::InvalidRegexpPattern, "Regexp options cannot contain a null byte: #{options}"
163
149
  end
164
- elsif !options.is_a?(Integer)
165
- raise ArgumentError, "Regexp options must be a String, Symbol, or Integer"
150
+ else
151
+ raise ArgumentError, 'Regexp options must be a String or Symbol'
166
152
  end
167
153
 
168
154
  @pattern = pattern
169
- @options = options
155
+ @options = options.to_s
170
156
  end
171
157
 
172
158
  # Allow automatic delegation of methods to the Regexp object
173
159
  # returned by +compile+.
174
160
  #
175
161
  # @param [ String] method The name of a method.
176
- #
177
- # @since 3.1.0
178
- def respond_to?(method, include_private = false)
179
- if defined?(@pattern)
180
- compile.respond_to?(method, include_private) || super
181
- else
182
- # YAML calls #respond_to? during deserialization, before the object
183
- # is initialized.
184
- super
185
- end
162
+ def respond_to_missing?(method, include_private = false)
163
+ # YAML calls #respond_to? during deserialization, before the object
164
+ # is initialized.
165
+ defined?(@pattern) && compile.respond_to?(method, include_private)
186
166
  end
187
167
 
188
168
  # Encode the Raw Regexp object to BSON.
@@ -200,15 +180,11 @@ module BSON
200
180
  # and 'u' to make \w, \W, etc. match unicode.
201
181
  #
202
182
  # @param [ BSON::ByteBuffer ] buffer The byte buffer to append to.
203
- # @param [ true, false ] validating_keys
204
183
  #
205
184
  # @return [ BSON::ByteBuffer ] The buffer with the encoded object.
206
185
  #
207
186
  # @see http://bsonspec.org/#/specification
208
- #
209
- # @since 4.2.0
210
- def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
211
- return compile.to_bson(buffer, validating_keys) if options.is_a?(Integer)
187
+ def to_bson(buffer = ByteBuffer.new)
212
188
  buffer.put_cstring(source)
213
189
  buffer.put_cstring(options.chars.sort.join)
214
190
  end
@@ -219,9 +195,7 @@ module BSON
219
195
  # raw_regexp.as_json
220
196
  #
221
197
  # @return [ Hash ] The raw regexp as a JSON hash.
222
- #
223
- # @since 4.2.0
224
- def as_json(*args)
198
+ def as_json(*)
225
199
  as_extended_json(mode: :legacy)
226
200
  end
227
201
 
@@ -234,9 +208,9 @@ module BSON
234
208
  # @return [ Hash ] The extended json representation.
235
209
  def as_extended_json(**opts)
236
210
  if opts[:mode] == :legacy
237
- { "$regex" => source, "$options" => options }
211
+ { '$regex' => source, '$options' => options }
238
212
  else
239
- {"$regularExpression" => {'pattern' => source, "options" => options}}
213
+ { '$regularExpression' => { 'pattern' => source, 'options' => options } }
240
214
  end
241
215
  end
242
216
 
@@ -248,24 +222,22 @@ module BSON
248
222
  # @param [ Object ] other The object to check against.
249
223
  #
250
224
  # @return [ true, false ] If the objects are equal.
251
- #
252
- # @since 4.2.0
253
225
  def ==(other)
254
226
  return false unless other.is_a?(::Regexp::Raw)
255
- pattern == other.pattern &&
256
- options == other.options
227
+
228
+ pattern == other.pattern && options == other.options
257
229
  end
258
- alias :eql? :==
230
+ alias eql? ==
259
231
 
260
232
  private
261
233
 
262
234
  def method_missing(method, *arguments)
263
235
  return super unless respond_to?(method)
236
+
264
237
  compile.send(method, *arguments)
265
238
  end
266
239
 
267
240
  def options_to_int
268
- return options if options.is_a?(Integer)
269
241
  opts = 0
270
242
  opts |= ::Regexp::IGNORECASE if options.include?(IGNORECASE_VALUE)
271
243
  opts |= ::Regexp::MULTILINE if options.include?(NEWLINE_VALUE)
@@ -274,10 +246,15 @@ module BSON
274
246
  end
275
247
  end
276
248
 
249
+ # Class-level methods to be added to the Regexp class.
277
250
  module ClassMethods
278
-
279
251
  # Deserialize the regular expression from BSON.
280
252
  #
253
+ # @note If the argument cannot be parsed, an exception will be raised
254
+ # and the argument will be left in an undefined state. The caller
255
+ # must explicitly call `rewind` on the buffer before trying to parse
256
+ # it again.
257
+ #
281
258
  # @param [ ByteBuffer ] buffer The byte buffer.
282
259
  #
283
260
  # @option opts [ nil | :bson ] :mode Decoding mode to use.
@@ -285,9 +262,7 @@ module BSON
285
262
  # @return [ Regexp ] The decoded regular expression.
286
263
  #
287
264
  # @see http://bsonspec.org/#/specification
288
- #
289
- # @since 2.0.0
290
- def from_bson(buffer, **opts)
265
+ def from_bson(buffer, **_)
291
266
  pattern = buffer.get_cstring
292
267
  options = buffer.get_cstring
293
268
  Raw.new(pattern, options)
@@ -295,14 +270,10 @@ module BSON
295
270
  end
296
271
 
297
272
  # Register this type when the module is loaded.
298
- #
299
- # @since 2.0.0
300
273
  Registry.register(BSON_TYPE, ::Regexp)
301
274
  end
302
275
 
303
276
  # Enrich the core Regexp class with this module.
304
- #
305
- # @since 2.0.0
306
- ::Regexp.send(:include, Regexp)
307
- ::Regexp.send(:extend, Regexp::ClassMethods)
277
+ ::Regexp.include Regexp
278
+ ::Regexp.extend Regexp::ClassMethods
308
279
  end
data/lib/bson/registry.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # rubocop:todo all
2
3
  # Copyright (C) 2009-2020 MongoDB Inc.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -64,11 +65,6 @@ module BSON
64
65
  define_type_reader(type)
65
66
  end
66
67
 
67
- # Raised when trying to get a type from the registry that doesn't exist.
68
- #
69
- # @since 4.1.0
70
- class UnsupportedType < RuntimeError; end
71
-
72
68
  private
73
69
 
74
70
  def define_type_reader(type)
@@ -81,7 +77,7 @@ module BSON
81
77
  message = "Detected unknown BSON type #{byte.inspect} "
82
78
  message += (field ? "for fieldname \"#{field}\". " : "in array. ")
83
79
  message +="Are you using the latest BSON version?"
84
- raise UnsupportedType.new(message)
80
+ raise Error::UnsupportedType.new(message)
85
81
  end
86
82
  end
87
83
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # rubocop:todo all
2
3
  # Copyright (C) 2009-2020 MongoDB Inc.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -46,7 +47,7 @@ module BSON
46
47
  # @return [ BSON::ByteBuffer ] The buffer with the encoded object.
47
48
  #
48
49
  # @since 2.0.0
49
- def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
50
+ def to_bson(buffer = ByteBuffer.new)
50
51
  buffer
51
52
  end
52
53