bson 4.15.0 → 5.0.2

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 (153) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +94 -10
  3. data/Rakefile +68 -39
  4. data/ext/bson/bson-native.h +12 -4
  5. data/ext/bson/extconf.rb +8 -3
  6. data/ext/bson/init.c +11 -11
  7. data/ext/bson/read.c +39 -9
  8. data/ext/bson/util.c +171 -16
  9. data/ext/bson/write.c +34 -39
  10. data/lib/bson/active_support.rb +1 -0
  11. data/lib/bson/array.rb +58 -32
  12. data/lib/bson/big_decimal.rb +16 -6
  13. data/lib/bson/binary.rb +271 -129
  14. data/lib/bson/boolean.rb +1 -0
  15. data/lib/bson/code.rb +10 -12
  16. data/lib/bson/code_with_scope.rb +9 -11
  17. data/lib/bson/config.rb +1 -27
  18. data/lib/bson/date.rb +2 -1
  19. data/lib/bson/date_time.rb +2 -1
  20. data/lib/bson/db_pointer.rb +12 -13
  21. data/lib/bson/dbref.rb +11 -9
  22. data/lib/bson/decimal128/builder.rb +10 -9
  23. data/lib/bson/decimal128.rb +25 -111
  24. data/lib/bson/document.rb +1 -0
  25. data/lib/bson/environment.rb +1 -0
  26. data/lib/bson/error/bson_decode_error.rb +11 -0
  27. data/lib/bson/error/ext_json_parse_error.rb +11 -0
  28. data/lib/bson/error/illegal_key.rb +23 -0
  29. data/lib/bson/error/invalid_binary_type.rb +37 -0
  30. data/lib/bson/error/invalid_dbref_argument.rb +12 -0
  31. data/lib/bson/error/invalid_decimal128_argument.rb +25 -0
  32. data/lib/bson/error/invalid_decimal128_range.rb +27 -0
  33. data/lib/bson/error/invalid_decimal128_string.rb +26 -0
  34. data/lib/bson/error/invalid_key.rb +24 -0
  35. data/lib/bson/error/invalid_object_id.rb +11 -0
  36. data/lib/bson/error/invalid_regexp_pattern.rb +13 -0
  37. data/lib/bson/error/unrepresentable_precision.rb +19 -0
  38. data/lib/bson/error/unserializable_class.rb +13 -0
  39. data/lib/bson/error/unsupported_binary_subtype.rb +12 -0
  40. data/lib/bson/error/unsupported_type.rb +11 -0
  41. data/lib/bson/error.rb +16 -28
  42. data/lib/bson/ext_json.rb +2 -1
  43. data/lib/bson/false_class.rb +2 -1
  44. data/lib/bson/float.rb +3 -2
  45. data/lib/bson/hash.rb +128 -73
  46. data/lib/bson/int32.rb +17 -5
  47. data/lib/bson/int64.rb +17 -5
  48. data/lib/bson/integer.rb +4 -5
  49. data/lib/bson/json.rb +1 -0
  50. data/lib/bson/max_key.rb +8 -10
  51. data/lib/bson/min_key.rb +8 -10
  52. data/lib/bson/nil_class.rb +1 -0
  53. data/lib/bson/object.rb +7 -27
  54. data/lib/bson/object_id.rb +84 -120
  55. data/lib/bson/open_struct.rb +3 -2
  56. data/lib/bson/regexp.rb +36 -65
  57. data/lib/bson/registry.rb +2 -6
  58. data/lib/bson/specialized.rb +2 -1
  59. data/lib/bson/string.rb +4 -27
  60. data/lib/bson/symbol.rb +23 -20
  61. data/lib/bson/time.rb +3 -2
  62. data/lib/bson/time_with_zone.rb +13 -1
  63. data/lib/bson/timestamp.rb +3 -2
  64. data/lib/bson/true_class.rb +2 -1
  65. data/lib/bson/undefined.rb +15 -1
  66. data/lib/bson/version.rb +3 -1
  67. data/lib/bson.rb +3 -2
  68. data/spec/bson/array_spec.rb +19 -60
  69. data/spec/bson/big_decimal_spec.rb +16 -4
  70. data/spec/bson/binary_spec.rb +129 -81
  71. data/spec/bson/binary_uuid_spec.rb +1 -0
  72. data/spec/bson/boolean_spec.rb +1 -0
  73. data/spec/bson/byte_buffer_read_spec.rb +1 -0
  74. data/spec/bson/byte_buffer_spec.rb +1 -0
  75. data/spec/bson/byte_buffer_write_spec.rb +1 -0
  76. data/spec/bson/code_spec.rb +5 -3
  77. data/spec/bson/code_with_scope_spec.rb +5 -3
  78. data/spec/bson/config_spec.rb +1 -35
  79. data/spec/bson/date_spec.rb +1 -0
  80. data/spec/bson/date_time_spec.rb +1 -0
  81. data/spec/bson/dbref_legacy_spec.rb +20 -3
  82. data/spec/bson/dbref_spec.rb +9 -9
  83. data/spec/bson/decimal128_spec.rb +40 -20
  84. data/spec/bson/document_as_spec.rb +1 -0
  85. data/spec/bson/document_spec.rb +1 -1
  86. data/spec/bson/ext_json_parse_spec.rb +1 -0
  87. data/spec/bson/false_class_spec.rb +8 -0
  88. data/spec/bson/float_spec.rb +8 -3
  89. data/spec/bson/hash_as_spec.rb +1 -0
  90. data/spec/bson/hash_spec.rb +87 -75
  91. data/spec/bson/int32_spec.rb +21 -6
  92. data/spec/bson/int64_spec.rb +21 -6
  93. data/spec/bson/integer_spec.rb +45 -13
  94. data/spec/bson/json_spec.rb +1 -0
  95. data/spec/bson/max_key_spec.rb +5 -3
  96. data/spec/bson/min_key_spec.rb +5 -3
  97. data/spec/bson/nil_class_spec.rb +1 -0
  98. data/spec/bson/object_id_spec.rb +57 -4
  99. data/spec/bson/object_spec.rb +2 -1
  100. data/spec/bson/open_struct_spec.rb +14 -71
  101. data/spec/bson/raw_spec.rb +9 -15
  102. data/spec/bson/regexp_spec.rb +4 -3
  103. data/spec/bson/registry_spec.rb +2 -1
  104. data/spec/bson/string_spec.rb +13 -38
  105. data/spec/bson/symbol_raw_spec.rb +25 -0
  106. data/spec/bson/symbol_spec.rb +15 -18
  107. data/spec/bson/time_spec.rb +1 -0
  108. data/spec/bson/time_with_zone_spec.rb +1 -0
  109. data/spec/bson/timestamp_spec.rb +1 -0
  110. data/spec/bson/true_class_spec.rb +8 -0
  111. data/spec/bson/undefined_spec.rb +27 -0
  112. data/spec/bson_spec.rb +1 -0
  113. data/spec/runners/common_driver.rb +6 -5
  114. data/spec/runners/corpus.rb +6 -0
  115. data/spec/runners/corpus_legacy.rb +1 -0
  116. data/spec/spec_helper.rb +1 -0
  117. data/spec/spec_tests/common_driver_spec.rb +9 -4
  118. data/spec/spec_tests/corpus_legacy_spec.rb +1 -0
  119. data/spec/spec_tests/corpus_spec.rb +13 -3
  120. data/spec/spec_tests/data/corpus/binary.json +5 -0
  121. data/spec/spec_tests/data/corpus/code.json +13 -13
  122. data/spec/spec_tests/data/corpus/decimal128-4.json +48 -0
  123. data/spec/spec_tests/data/corpus/decimal128-6.json +12 -0
  124. data/spec/spec_tests/data/corpus/decimal128-7.json +4 -0
  125. data/spec/spec_tests/data/corpus/document.json +20 -0
  126. data/spec/spec_tests/data/corpus/symbol.json +7 -7
  127. data/spec/spec_tests/data/corpus/top.json +18 -3
  128. data/spec/support/shared_examples.rb +28 -5
  129. data/spec/support/spec_config.rb +1 -0
  130. data/spec/support/utils.rb +49 -1
  131. metadata +114 -164
  132. checksums.yaml.gz.sig +0 -0
  133. data/spec/shared/LICENSE +0 -20
  134. data/spec/shared/bin/get-mongodb-download-url +0 -17
  135. data/spec/shared/bin/s3-copy +0 -45
  136. data/spec/shared/bin/s3-upload +0 -69
  137. data/spec/shared/lib/mrss/child_process_helper.rb +0 -80
  138. data/spec/shared/lib/mrss/cluster_config.rb +0 -231
  139. data/spec/shared/lib/mrss/constraints.rb +0 -386
  140. data/spec/shared/lib/mrss/docker_runner.rb +0 -271
  141. data/spec/shared/lib/mrss/event_subscriber.rb +0 -200
  142. data/spec/shared/lib/mrss/lite_constraints.rb +0 -191
  143. data/spec/shared/lib/mrss/server_version_registry.rb +0 -120
  144. data/spec/shared/lib/mrss/spec_organizer.rb +0 -179
  145. data/spec/shared/lib/mrss/utils.rb +0 -15
  146. data/spec/shared/share/Dockerfile.erb +0 -338
  147. data/spec/shared/share/haproxy-1.conf +0 -16
  148. data/spec/shared/share/haproxy-2.conf +0 -17
  149. data/spec/shared/shlib/distro.sh +0 -74
  150. data/spec/shared/shlib/server.sh +0 -367
  151. data/spec/shared/shlib/set_env.sh +0 -131
  152. data.tar.gz.sig +0 -0
  153. metadata.gz.sig +0 -1
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ # rubocop:todo all
3
+
4
+ module BSON
5
+ class Error
6
+
7
+ # Raised when trying to create a Decimal128 from a string with
8
+ # an invalid format.
9
+ class InvalidDecimal128String < Error
10
+
11
+ # The custom error message for this error.
12
+ MESSAGE = 'Invalid string format for creating a Decimal128 object.'
13
+
14
+ # Get the custom error message for the exception.
15
+ #
16
+ # @example Get the message.
17
+ # error.message
18
+ #
19
+ # @return [ String ] The error message.
20
+ def message
21
+ MESSAGE
22
+ end
23
+ end
24
+ end
25
+ end
26
+
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+ # rubocop:todo all
3
+
4
+ module BSON
5
+ class Error
6
+
7
+ # Raised when trying to serialize an object into a key.
8
+ class InvalidKey < Error
9
+
10
+ # Instantiate the exception.
11
+ #
12
+ # @example Instantiate the exception.
13
+ # BSON::Object::InvalidKey.new(object)
14
+ #
15
+ # @param [ Object ] object The object that was meant for the key.
16
+ #
17
+ # @api private
18
+ def initialize(object)
19
+ super("#{object.class} instances are not allowed as keys in a BSON document.")
20
+ end
21
+ end
22
+ end
23
+ end
24
+
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+ # rubocop:todo all
3
+
4
+ module BSON
5
+ class Error
6
+
7
+ # Raised when trying to create an object id with invalid data.
8
+ class InvalidObjectId < Error; end
9
+ end
10
+ end
11
+
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+ # rubocop:todo all
3
+
4
+ module BSON
5
+ class Error
6
+
7
+ # Exception raised when there is an invalid argument passed into the
8
+ # constructor of regexp object. This includes when the argument contains
9
+ # a null byte.
10
+ class InvalidRegexpPattern < Error
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+ # rubocop:todo all
3
+
4
+ module BSON
5
+ class Error
6
+
7
+ # Raised when the significand provided is outside the valid range.
8
+ class UnrepresentablePrecision < Error
9
+
10
+ # Get the custom error message for the exception.
11
+ #
12
+ # @return [ String ] The error message.
13
+ def message
14
+ 'The value contains too much precision for Decimal128 representation'
15
+ end
16
+ end
17
+ end
18
+ end
19
+
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+ # rubocop:todo all
3
+
4
+ module BSON
5
+ class Error
6
+
7
+ # Exception raised when serializing an Array or Hash to BSON and an
8
+ # array or hash element is of a class that does not define how to serialize
9
+ # itself to BSON.
10
+ class UnserializableClass < Error
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ # rubocop:todo all
3
+
4
+ module BSON
5
+ class Error
6
+
7
+ # Exception raised when decoding BSON and the data contains an
8
+ # unsupported binary subtype.
9
+ class UnsupportedBinarySubtype < Error
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+ # rubocop:todo all
3
+
4
+ module BSON
5
+ class Error
6
+
7
+ # Raised when trying to get a type from the registry that doesn't exist.
8
+ class UnsupportedType < Error; end
9
+ end
10
+ end
11
+
data/lib/bson/error.rb CHANGED
@@ -1,34 +1,22 @@
1
1
  # frozen_string_literal: true
2
+ # rubocop:todo all
2
3
  module BSON
3
4
  # Base exception class for all BSON-related errors.
4
- #
5
- # @note Many existing exceptions raised by bson-ruby do not derive from
6
- # this base class. This will change in the next major version (5.0).
7
5
  class Error < StandardError
8
-
9
- # Exception raised when Extended JSON parsing fails.
10
- class ExtJSONParseError < Error
11
- end
12
-
13
- # Exception raised when decoding BSON and the data contains an
14
- # unsupported binary subtype.
15
- class UnsupportedBinarySubtype < Error
16
- end
17
-
18
- # Exception raised when BSON decoding fails.
19
- class BSONDecodeError < Error
20
- end
21
-
22
- # Exception raised when serializing an Array or Hash to BSON and an
23
- # array or hash element is of a class that does not define how to serialize
24
- # itself to BSON.
25
- class UnserializableClass < Error
26
- end
27
-
28
- # Exception raised when there is an invalid argument passed into the
29
- # constructor of regexp object. This includes when the argument contains
30
- # a null byte.
31
- class InvalidRegexpPattern < Error
32
- end
33
6
  end
34
7
  end
8
+
9
+ require 'bson/error/bson_decode_error'
10
+ require 'bson/error/ext_json_parse_error'
11
+ require 'bson/error/invalid_binary_type'
12
+ require 'bson/error/invalid_dbref_argument'
13
+ require 'bson/error/invalid_decimal128_argument'
14
+ require 'bson/error/invalid_decimal128_range'
15
+ require 'bson/error/invalid_decimal128_string'
16
+ require 'bson/error/invalid_key'
17
+ require 'bson/error/invalid_object_id'
18
+ require 'bson/error/invalid_regexp_pattern'
19
+ require 'bson/error/unrepresentable_precision'
20
+ require 'bson/error/unserializable_class'
21
+ require 'bson/error/unsupported_binary_subtype'
22
+ require 'bson/error/unsupported_type'
data/lib/bson/ext_json.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # rubocop:todo all
2
3
  # Copyright (C) 2019-2020 MongoDB Inc.
3
4
  #
4
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,7 +19,7 @@ require 'json'
18
19
  module BSON
19
20
 
20
21
  # This module contains methods for parsing Extended JSON 2.0.
21
- # https://github.com/mongodb/specifications/blob/master/source/extended-json.rst
22
+ # https://github.com/mongodb/specifications/blob/master/source/extended-json/extended-json.md
22
23
  module ExtJSON
23
24
 
24
25
  # Parses JSON in a string into a Ruby object tree.
@@ -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");
@@ -50,7 +51,7 @@ module BSON
50
51
  # @see http://bsonspec.org/#/specification
51
52
  #
52
53
  # @since 2.0.0
53
- def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
54
+ def to_bson(buffer = ByteBuffer.new)
54
55
  buffer.put_byte(FALSE_BYTE)
55
56
  end
56
57
  end
data/lib/bson/float.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");
@@ -43,12 +44,12 @@ module BSON
43
44
  # @see http://bsonspec.org/#/specification
44
45
  #
45
46
  # @since 2.0.0
46
- def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
47
+ def to_bson(buffer = ByteBuffer.new)
47
48
  buffer.put_double(self)
48
49
  end
49
50
 
50
51
  # Converts this object to a representation directly serializable to
51
- # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
52
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json/extended-json.md).
52
53
  #
53
54
  # This method returns the float itself if relaxed representation is
54
55
  # requested and the value is finite, otherwise a $numberDouble hash.
data/lib/bson/hash.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,19 +14,14 @@
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 hashes to
19
20
  # and from raw bytes as specified by the BSON spec.
20
21
  #
21
22
  # @see http://bsonspec.org/#/specification
22
- #
23
- # @since 2.0.0
24
23
  module Hash
25
-
26
24
  # A hash, also called an embedded document, is type 0x03 in the BSON spec.
27
- #
28
- # @since 2.0.0
29
25
  BSON_TYPE = ::String.new(3.chr, encoding: BINARY).freeze
30
26
 
31
27
  # Get the hash as encoded BSON.
@@ -36,33 +32,13 @@ module BSON
36
32
  # @return [ BSON::ByteBuffer ] The buffer with the encoded object.
37
33
  #
38
34
  # @see http://bsonspec.org/#/specification
39
- #
40
- # @since 2.0.0
41
- def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
35
+ def to_bson(buffer = ByteBuffer.new)
36
+ # If the native buffer version has an optimized version, we'll call
37
+ # it directly. Otherwise, we'll serialize the hash the hard way.
42
38
  if buffer.respond_to?(:put_hash)
43
- buffer.put_hash(self, validating_keys)
39
+ buffer.put_hash(self)
44
40
  else
45
- position = buffer.length
46
- buffer.put_int32(0)
47
- each do |field, value|
48
- unless value.respond_to?(:bson_type)
49
- raise Error::UnserializableClass, "Hash value for key '#{field}' does not define its BSON serialized type: #{value}"
50
- end
51
- buffer.put_byte(value.bson_type)
52
- key = field.to_bson_key(validating_keys)
53
- begin
54
- buffer.put_cstring(key)
55
- rescue ArgumentError => e
56
- raise ArgumentError, "Error serializing key #{key}: #{e.class}: #{e}"
57
- rescue EncodingError => e
58
- # Note this may convert exception class from a subclass of
59
- # EncodingError to EncodingError itself
60
- raise EncodingError, "Error serializing key #{key}: #{e.class}: #{e}"
61
- end
62
- value.to_bson(buffer, validating_keys)
63
- end
64
- buffer.put_byte(NULL_BYTE)
65
- buffer.replace_int32(position, buffer.length - position)
41
+ serialize_to_buffer(buffer)
66
42
  end
67
43
  end
68
44
 
@@ -72,14 +48,12 @@ module BSON
72
48
  # hash.to_bson_normalized_value
73
49
  #
74
50
  # @return [ BSON::Document ] The normalized hash.
75
- #
76
- # @since 3.0.0
77
51
  def to_bson_normalized_value
78
52
  Document.new(self)
79
53
  end
80
54
 
81
55
  # Converts this object to a representation directly serializable to
82
- # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
56
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json/extended-json.md).
83
57
  #
84
58
  # This method recursively invokes +as_extended_json+ with the provided
85
59
  # options on each hash value.
@@ -92,10 +66,67 @@ module BSON
92
66
  transform_values { |value| value.as_extended_json(**options) }
93
67
  end
94
68
 
95
- module ClassMethods
69
+ private
70
+
71
+ # Serialize this hash instance to the given buffer.
72
+ #
73
+ # @param [ ByteBuf ] buffer The buffer to receive the serialized hash.
74
+ def serialize_to_buffer(buffer)
75
+ position = buffer.length
76
+ buffer.put_int32(0)
77
+ serialize_key_value_pairs(buffer)
78
+ buffer.put_byte(NULL_BYTE)
79
+ buffer.replace_int32(position, buffer.length - position)
80
+ end
81
+
82
+ # Serialize the key/value pairs in this hash instance to the given
83
+ # buffer.
84
+ #
85
+ # @param [ ByteBuf ] buffer The buffer to received the serialized
86
+ # key/value pairs.
87
+ #
88
+ # @raise [ Error::UnserializableClass ] if a value cannot be serialized
89
+ def serialize_key_value_pairs(buffer)
90
+ each do |field, value|
91
+ unless value.respond_to?(:bson_type)
92
+ raise Error::UnserializableClass,
93
+ "Hash value for key '#{field}' does not define its BSON serialized type: #{value}"
94
+ end
95
+
96
+ buffer.put_byte(value.bson_type)
97
+ key = field.to_bson_key
98
+ serialize_key(buffer, key)
99
+ value.to_bson(buffer)
100
+ end
101
+ end
102
+
103
+ # Serialize the key/value pairs in this hash instance to the given
104
+ # buffer.
105
+ #
106
+ # @param [ ByteBuf ] buffer The buffer to received the serialized
107
+ # key/value pairs.
108
+ #
109
+ # @raise [ ArgumentError ] if the string cannot be serialized
110
+ # @raise [ EncodingError ] if the string is not a valid encoding
111
+ def serialize_key(buffer, key)
112
+ buffer.put_cstring(key)
113
+ rescue ArgumentError => e
114
+ raise ArgumentError, "Error serializing key #{key}: #{e.class}: #{e}"
115
+ rescue EncodingError => e
116
+ # Note this may convert exception class from a subclass of
117
+ # EncodingError to EncodingError itself
118
+ raise EncodingError, "Error serializing key #{key}: #{e.class}: #{e}"
119
+ end
96
120
 
121
+ # The methods to augment the Hash class with (class-level methods).
122
+ module ClassMethods
97
123
  # Deserialize the hash from BSON.
98
124
  #
125
+ # @note If the argument cannot be parsed, an exception will be raised
126
+ # and the argument will be left in an undefined state. The caller
127
+ # must explicitly call `rewind` on the buffer before trying to parse
128
+ # it again.
129
+ #
99
130
  # @param [ ByteBuffer ] buffer The byte buffer.
100
131
  #
101
132
  # @option options [ nil | :bson ] :mode Decoding mode to use.
@@ -103,55 +134,79 @@ module BSON
103
134
  # @return [ Hash ] The decoded hash.
104
135
  #
105
136
  # @see http://bsonspec.org/#/specification
106
- #
107
- # @since 2.0.0
108
137
  def from_bson(buffer, **options)
109
138
  if buffer.respond_to?(:get_hash)
110
139
  buffer.get_hash(**options)
111
140
  else
112
- hash = Document.allocate
113
- start_position = buffer.read_position
114
- expected_byte_size = buffer.get_int32
115
- while (type = buffer.get_byte) != NULL_BYTE
116
- field = buffer.get_cstring
117
- cls = BSON::Registry.get(type, field)
118
- value = if options.empty?
119
- # Compatibility with the older Ruby driver versions which define
120
- # a DBRef class with from_bson accepting a single argument.
121
- cls.from_bson(buffer)
122
- else
123
- cls.from_bson(buffer, **options)
124
- end
125
- hash.store(field, value)
126
- end
127
- actual_byte_size = buffer.read_position - start_position
128
- if actual_byte_size != expected_byte_size
129
- raise Error::BSONDecodeError, "Expected hash to take #{expected_byte_size} bytes but it took #{actual_byte_size} bytes"
130
- end
131
-
132
- if hash['$ref'] && hash['$id']
133
- # We're doing implicit decoding here. If the document is an invalid
134
- # dbref, we should decode it as a BSON::Document.
135
- begin
136
- hash = DBRef.new(hash)
137
- rescue ArgumentError
138
- end
139
- end
140
-
141
- hash
141
+ hash = parse_hash_from_buffer(buffer, **options)
142
+ maybe_dbref(hash)
143
+ end
144
+ end
145
+
146
+ private
147
+
148
+ # If the hash looks like a DBRef, try and decode it as such. If
149
+ # is turns out to be invalid--or if it doesn't look like a DBRef
150
+ # to begin with--return the hash itself.
151
+ #
152
+ # @param [ Hash ] hash the hash to try and decode
153
+ #
154
+ # @return [ DBRef | Hash ] the result of decoding the hash
155
+ def maybe_dbref(hash)
156
+ return DBRef.new(hash) if hash['$ref'] && hash['$id']
157
+
158
+ hash
159
+ rescue Error::InvalidDBRefArgument
160
+ hash
161
+ end
162
+
163
+ # Given a byte buffer, extract and return a hash from it.
164
+ #
165
+ # @param [ ByteBuf ] buffer the buffer to read data from
166
+ # @param [ Hash ] options the keyword arguments
167
+ #
168
+ # @return [ Hash ] the hash parsed from the buffer
169
+ def parse_hash_from_buffer(buffer, **options)
170
+ hash = Document.allocate
171
+ start_position = buffer.read_position
172
+ expected_byte_size = buffer.get_int32
173
+
174
+ parse_hash_contents(hash, buffer, **options)
175
+
176
+ actual_byte_size = buffer.read_position - start_position
177
+ return hash unless actual_byte_size != expected_byte_size
178
+
179
+ raise Error::BSONDecodeError,
180
+ "Expected hash to take #{expected_byte_size} bytes but it took #{actual_byte_size} bytes"
181
+ end
182
+
183
+ # Given an empty hash and a byte buffer, parse the key/value pairs from
184
+ # the buffer and populate the hash with them.
185
+ #
186
+ # @param [ Hash ] hash the hash to populate
187
+ # @param [ ByteBuf ] buffer the buffer to read data from
188
+ # @param [ Hash ] options the keyword arguments
189
+ def parse_hash_contents(hash, buffer, **options)
190
+ while (type = buffer.get_byte) != NULL_BYTE
191
+ field = buffer.get_cstring
192
+ cls = BSON::Registry.get(type, field)
193
+ value = if options.empty?
194
+ # Compatibility with the older Ruby driver versions which define
195
+ # a DBRef class with from_bson accepting a single argument.
196
+ cls.from_bson(buffer)
197
+ else
198
+ cls.from_bson(buffer, **options)
199
+ end
200
+ hash.store(field, value)
142
201
  end
143
202
  end
144
203
  end
145
204
 
146
205
  # Register this type when the module is loaded.
147
- #
148
- # @since 2.0.0
149
206
  Registry.register(BSON_TYPE, ::Hash)
150
207
  end
151
208
 
152
209
  # Enrich the core Hash class with this module.
153
- #
154
- # @since 2.0.0
155
- ::Hash.send(:include, Hash)
156
- ::Hash.send(:extend, Hash::ClassMethods)
210
+ ::Hash.include Hash
211
+ ::Hash.extend Hash::ClassMethods
157
212
  end
data/lib/bson/int32.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");
@@ -21,6 +22,7 @@ module BSON
21
22
  #
22
23
  # @since 2.0.0
23
24
  class Int32
25
+ include JSON
24
26
 
25
27
  # A boolean is type 0x08 in the BSON spec.
26
28
  #
@@ -86,7 +88,7 @@ module BSON
86
88
  # @see http://bsonspec.org/#/specification
87
89
  #
88
90
  # @since 4.2.0
89
- def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
91
+ def to_bson(buffer = ByteBuffer.new)
90
92
  buffer.put_int32(value)
91
93
  end
92
94
 
@@ -95,12 +97,10 @@ module BSON
95
97
  # @example Convert the integer to a BSON key string.
96
98
  # int.to_bson_key
97
99
  #
98
- # @param [ true, false ] validating_keys If BSON should validate the key.
99
- #
100
100
  # @return [ String ] The string key.
101
101
  #
102
102
  # @since 4.2.0
103
- def to_bson_key(validating_keys = Config.validating_keys?)
103
+ def to_bson_key
104
104
  value
105
105
  end
106
106
 
@@ -118,8 +118,20 @@ module BSON
118
118
  alias :eql? :==
119
119
  alias :=== :==
120
120
 
121
+ # Return a string representation of the Int32 for use in
122
+ # application-level JSON serialization. This method is intentionally
123
+ # different from #as_extended_json.
124
+ #
125
+ # @example Get the Int32 as a JSON-serializable object.
126
+ # int32.as_json
127
+ #
128
+ # @return [ Integer ] The Int32 as an Integer.
129
+ def as_json(**options)
130
+ value
131
+ end
132
+
121
133
  # Converts this object to a representation directly serializable to
122
- # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
134
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json/extended-json.md).
123
135
  #
124
136
  # This method returns the integer value if relaxed representation is
125
137
  # requested, otherwise a $numberInt hash.
data/lib/bson/int64.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");
@@ -21,6 +22,7 @@ module BSON
21
22
  #
22
23
  # @since 2.0.0
23
24
  class Int64
25
+ include JSON
24
26
 
25
27
  # A boolean is type 0x08 in the BSON spec.
26
28
  #
@@ -86,7 +88,7 @@ module BSON
86
88
  # @see http://bsonspec.org/#/specification
87
89
  #
88
90
  # @since 4.2.0
89
- def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
91
+ def to_bson(buffer = ByteBuffer.new)
90
92
  buffer.put_int64(value)
91
93
  end
92
94
 
@@ -95,12 +97,10 @@ module BSON
95
97
  # @example Convert the integer to a BSON key string.
96
98
  # int.to_bson_key
97
99
  #
98
- # @param [ true, false ] validating_keys If BSON should validate the key.
99
- #
100
100
  # @return [ String ] The string key.
101
101
  #
102
102
  # @since 4.2.0
103
- def to_bson_key(validating_keys = Config.validating_keys?)
103
+ def to_bson_key
104
104
  value
105
105
  end
106
106
 
@@ -118,8 +118,20 @@ module BSON
118
118
  alias :eql? :==
119
119
  alias :=== :==
120
120
 
121
+ # Return a string representation of the Int64 for use in
122
+ # application-level JSON serialization. This method is intentionally
123
+ # different from #as_extended_json.
124
+ #
125
+ # @example Get the Int64 as a JSON-serializable object.
126
+ # int64.as_json
127
+ #
128
+ # @return [ Integer ] The Int64 as an Integer.
129
+ def as_json(**options)
130
+ value
131
+ end
132
+
121
133
  # Converts this object to a representation directly serializable to
122
- # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
134
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json/extended-json.md).
123
135
  #
124
136
  # This method returns the integer value if relaxed representation is
125
137
  # requested, otherwise a $numberLong hash.
data/lib/bson/integer.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");
@@ -104,7 +105,7 @@ module BSON
104
105
  # @see http://bsonspec.org/#/specification
105
106
  #
106
107
  # @since 2.0.0
107
- def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
108
+ def to_bson(buffer = ByteBuffer.new)
108
109
  if bson_int32?
109
110
  buffer.put_int32(self)
110
111
  elsif bson_int64?
@@ -151,17 +152,15 @@ module BSON
151
152
  # @example Convert the integer to a BSON key string.
152
153
  # 1.to_bson_key
153
154
  #
154
- # @param [ true, false ] validating_keys If BSON should validate the key.
155
- #
156
155
  # @return [ String ] The string key.
157
156
  #
158
157
  # @since 2.0.0
159
- def to_bson_key(validating_keys = Config.validating_keys?)
158
+ def to_bson_key
160
159
  self
161
160
  end
162
161
 
163
162
  # Converts this object to a representation directly serializable to
164
- # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
163
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json/extended-json.md).
165
164
  #
166
165
  # This method returns the integer itself if relaxed representation is
167
166
  # requested, otherwise a $numberInt hash if the value fits in 32 bits
data/lib/bson/json.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");