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.
- checksums.yaml +5 -5
- data/README.md +106 -7
- data/Rakefile +86 -43
- data/ext/bson/{native-endian.h → bson-endian.h} +14 -107
- data/ext/bson/bson-native.h +135 -0
- data/ext/bson/bytebuf.c +133 -0
- data/ext/bson/endian.c +117 -0
- data/ext/bson/extconf.rb +8 -3
- data/ext/bson/init.c +364 -0
- data/ext/bson/libbson-utf8.c +230 -0
- data/ext/bson/read.c +470 -0
- data/ext/bson/util.c +250 -0
- data/ext/bson/write.c +675 -0
- data/lib/bson/active_support.rb +19 -0
- data/lib/bson/array.rb +97 -30
- data/lib/bson/big_decimal.rb +77 -0
- data/lib/bson/binary.rb +510 -70
- data/lib/bson/boolean.rb +15 -4
- data/lib/bson/code.rb +25 -12
- data/lib/bson/code_with_scope.rb +41 -15
- data/lib/bson/config.rb +3 -28
- data/lib/bson/date.rb +16 -4
- data/lib/bson/date_time.rb +6 -4
- data/lib/bson/db_pointer.rb +110 -0
- data/lib/bson/dbref.rb +154 -0
- data/lib/bson/decimal128/builder.rb +456 -0
- data/lib/bson/decimal128.rb +272 -0
- data/lib/bson/document.rb +177 -7
- data/lib/bson/environment.rb +17 -2
- data/lib/bson/error/bson_decode_error.rb +11 -0
- data/lib/bson/error/ext_json_parse_error.rb +11 -0
- data/lib/bson/error/illegal_key.rb +23 -0
- data/lib/bson/error/invalid_binary_type.rb +37 -0
- data/lib/bson/error/invalid_dbref_argument.rb +12 -0
- data/lib/bson/error/invalid_decimal128_argument.rb +25 -0
- data/lib/bson/error/invalid_decimal128_range.rb +27 -0
- data/lib/bson/error/invalid_decimal128_string.rb +26 -0
- data/lib/bson/error/invalid_key.rb +24 -0
- data/lib/bson/error/invalid_object_id.rb +11 -0
- data/lib/bson/error/invalid_regexp_pattern.rb +13 -0
- data/lib/bson/error/unrepresentable_precision.rb +19 -0
- data/lib/bson/error/unserializable_class.rb +13 -0
- data/lib/bson/error/unsupported_binary_subtype.rb +12 -0
- data/lib/bson/error/unsupported_type.rb +11 -0
- data/lib/bson/error.rb +22 -0
- data/lib/bson/ext_json.rb +389 -0
- data/lib/bson/false_class.rb +6 -4
- data/lib/bson/float.rb +43 -7
- data/lib/bson/hash.rb +152 -37
- data/lib/bson/int32.rb +104 -6
- data/lib/bson/int64.rb +111 -8
- data/lib/bson/integer.rb +43 -9
- data/lib/bson/json.rb +3 -1
- data/lib/bson/max_key.rb +21 -10
- data/lib/bson/min_key.rb +21 -10
- data/lib/bson/nil_class.rb +7 -3
- data/lib/bson/object.rb +25 -17
- data/lib/bson/object_id.rb +98 -113
- data/lib/bson/open_struct.rb +59 -0
- data/lib/bson/regexp.rb +129 -56
- data/lib/bson/registry.rb +7 -10
- data/lib/bson/specialized.rb +8 -4
- data/lib/bson/string.rb +12 -32
- data/lib/bson/symbol.rb +107 -11
- data/lib/bson/time.rb +68 -7
- data/lib/bson/time_with_zone.rb +67 -0
- data/lib/bson/timestamp.rb +50 -10
- data/lib/bson/true_class.rb +6 -4
- data/lib/bson/undefined.rb +28 -2
- data/lib/bson/vector.rb +44 -0
- data/lib/bson/version.rb +6 -14
- data/lib/bson.rb +22 -12
- data/spec/README.md +14 -0
- data/spec/bson/array_spec.rb +38 -62
- data/spec/bson/big_decimal_spec.rb +328 -0
- data/spec/bson/binary_spec.rb +199 -53
- data/spec/bson/binary_uuid_spec.rb +190 -0
- data/spec/bson/boolean_spec.rb +2 -1
- data/spec/bson/byte_buffer_read_spec.rb +198 -0
- data/spec/bson/byte_buffer_spec.rb +122 -381
- data/spec/bson/byte_buffer_write_spec.rb +855 -0
- data/spec/bson/code_spec.rb +6 -4
- data/spec/bson/code_with_scope_spec.rb +6 -4
- data/spec/bson/config_spec.rb +1 -35
- data/spec/bson/date_spec.rb +2 -1
- data/spec/bson/date_time_spec.rb +55 -1
- data/spec/bson/dbref_legacy_spec.rb +186 -0
- data/spec/bson/dbref_spec.rb +487 -0
- data/spec/bson/decimal128_spec.rb +1840 -0
- data/spec/bson/document_as_spec.rb +61 -0
- data/spec/bson/document_spec.rb +205 -32
- data/spec/bson/ext_json_parse_spec.rb +346 -0
- data/spec/bson/false_class_spec.rb +9 -1
- data/spec/bson/float_spec.rb +42 -1
- data/spec/bson/hash_as_spec.rb +58 -0
- data/spec/bson/hash_spec.rb +318 -66
- data/spec/bson/int32_spec.rb +248 -1
- data/spec/bson/int64_spec.rb +308 -1
- data/spec/bson/integer_spec.rb +61 -3
- data/spec/bson/json_spec.rb +2 -1
- data/spec/bson/max_key_spec.rb +6 -4
- data/spec/bson/min_key_spec.rb +6 -4
- data/spec/bson/nil_class_spec.rb +2 -1
- data/spec/bson/object_id_spec.rb +95 -5
- data/spec/bson/object_spec.rb +3 -2
- data/spec/bson/open_struct_spec.rb +87 -0
- data/spec/bson/raw_spec.rb +594 -0
- data/spec/bson/regexp_spec.rb +61 -8
- data/spec/bson/registry_spec.rb +3 -2
- data/spec/bson/string_spec.rb +26 -33
- data/spec/bson/symbol_raw_spec.rb +70 -0
- data/spec/bson/symbol_spec.rb +77 -20
- data/spec/bson/time_spec.rb +206 -2
- data/spec/bson/time_with_zone_spec.rb +69 -0
- data/spec/bson/timestamp_spec.rb +58 -2
- data/spec/bson/true_class_spec.rb +9 -1
- data/spec/bson/undefined_spec.rb +28 -1
- data/spec/bson/vector_spec.rb +33 -0
- data/spec/bson_spec.rb +2 -1
- data/spec/runners/binary_vector.rb +78 -0
- data/spec/runners/common_driver.rb +348 -0
- data/spec/runners/corpus.rb +191 -0
- data/spec/runners/corpus_legacy.rb +248 -0
- data/spec/shared/LICENSE +20 -0
- data/spec/shared/bin/get-mongodb-download-url +17 -0
- data/spec/shared/bin/s3-copy +45 -0
- data/spec/shared/bin/s3-upload +69 -0
- data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
- data/spec/shared/lib/mrss/cluster_config.rb +231 -0
- data/spec/shared/lib/mrss/constraints.rb +378 -0
- data/spec/shared/lib/mrss/docker_runner.rb +298 -0
- data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
- data/spec/shared/lib/mrss/event_subscriber.rb +210 -0
- data/spec/shared/lib/mrss/lite_constraints.rb +238 -0
- data/spec/shared/lib/mrss/release/candidate.rb +281 -0
- data/spec/shared/lib/mrss/release/product_data.rb +144 -0
- data/spec/shared/lib/mrss/server_version_registry.rb +113 -0
- data/spec/shared/lib/mrss/session_registry.rb +69 -0
- data/spec/shared/lib/mrss/session_registry_legacy.rb +60 -0
- data/spec/shared/lib/mrss/spec_organizer.rb +179 -0
- data/spec/shared/lib/mrss/utils.rb +37 -0
- data/spec/shared/lib/tasks/candidate.rake +64 -0
- data/spec/shared/share/Dockerfile.erb +251 -0
- data/spec/shared/share/haproxy-1.conf +16 -0
- data/spec/shared/share/haproxy-2.conf +17 -0
- data/spec/shared/shlib/config.sh +27 -0
- data/spec/shared/shlib/distro.sh +84 -0
- data/spec/shared/shlib/server.sh +423 -0
- data/spec/shared/shlib/set_env.sh +110 -0
- data/spec/spec_helper.rb +61 -1
- data/spec/spec_tests/binary_vector_spec.rb +82 -0
- data/spec/spec_tests/common_driver_spec.rb +84 -0
- data/spec/spec_tests/corpus_legacy_spec.rb +72 -0
- data/spec/spec_tests/corpus_spec.rb +134 -0
- data/spec/spec_tests/data/binary_vector/README.md +61 -0
- data/spec/spec_tests/data/binary_vector/float32.json +65 -0
- data/spec/spec_tests/data/binary_vector/int8.json +57 -0
- data/spec/spec_tests/data/binary_vector/packed_bit.json +83 -0
- data/spec/spec_tests/data/corpus/README.md +15 -0
- data/spec/spec_tests/data/corpus/array.json +49 -0
- data/spec/spec_tests/data/corpus/binary.json +153 -0
- data/spec/spec_tests/data/corpus/boolean.json +27 -0
- data/spec/spec_tests/data/corpus/code.json +67 -0
- data/spec/spec_tests/data/corpus/code_w_scope.json +78 -0
- data/spec/spec_tests/data/corpus/datetime.json +42 -0
- data/spec/spec_tests/data/corpus/dbpointer.json +56 -0
- data/spec/spec_tests/data/corpus/dbref.json +51 -0
- data/spec/spec_tests/data/corpus/decimal128-1.json +317 -0
- data/spec/spec_tests/data/corpus/decimal128-2.json +793 -0
- data/spec/spec_tests/data/corpus/decimal128-3.json +1771 -0
- data/spec/spec_tests/data/corpus/decimal128-4.json +165 -0
- data/spec/spec_tests/data/corpus/decimal128-5.json +402 -0
- data/spec/spec_tests/data/corpus/decimal128-6.json +131 -0
- data/spec/spec_tests/data/corpus/decimal128-7.json +327 -0
- data/spec/spec_tests/data/corpus/document.json +60 -0
- data/spec/spec_tests/data/corpus/double.json +87 -0
- data/spec/spec_tests/data/corpus/int32.json +43 -0
- data/spec/spec_tests/data/corpus/int64.json +43 -0
- data/spec/spec_tests/data/corpus/maxkey.json +12 -0
- data/spec/spec_tests/data/corpus/minkey.json +12 -0
- data/spec/spec_tests/data/corpus/multi-type-deprecated.json +15 -0
- data/spec/spec_tests/data/corpus/multi-type.json +11 -0
- data/spec/spec_tests/data/corpus/null.json +12 -0
- data/spec/spec_tests/data/corpus/oid.json +28 -0
- data/spec/spec_tests/data/corpus/regex.json +65 -0
- data/spec/spec_tests/data/corpus/string.json +72 -0
- data/spec/spec_tests/data/corpus/symbol.json +80 -0
- data/spec/spec_tests/data/corpus/timestamp.json +34 -0
- data/spec/spec_tests/data/corpus/top.json +262 -0
- data/spec/spec_tests/data/corpus/undefined.json +15 -0
- data/spec/spec_tests/data/corpus_legacy/array.json +49 -0
- data/spec/spec_tests/data/corpus_legacy/binary.json +69 -0
- data/spec/spec_tests/data/corpus_legacy/boolean.json +27 -0
- data/spec/spec_tests/data/corpus_legacy/code.json +67 -0
- data/spec/spec_tests/data/corpus_legacy/code_w_scope.json +78 -0
- data/spec/spec_tests/data/corpus_legacy/document.json +36 -0
- data/spec/spec_tests/data/corpus_legacy/double.json +69 -0
- data/spec/spec_tests/data/corpus_legacy/failures/datetime.json +31 -0
- data/spec/spec_tests/data/corpus_legacy/failures/dbpointer.json +42 -0
- data/spec/spec_tests/data/corpus_legacy/failures/int64.json +38 -0
- data/spec/spec_tests/data/corpus_legacy/failures/symbol.json +62 -0
- data/spec/spec_tests/data/corpus_legacy/int32.json +38 -0
- data/spec/spec_tests/data/corpus_legacy/maxkey.json +12 -0
- data/spec/spec_tests/data/corpus_legacy/minkey.json +12 -0
- data/spec/spec_tests/data/corpus_legacy/null.json +12 -0
- data/spec/spec_tests/data/corpus_legacy/oid.json +28 -0
- data/spec/spec_tests/data/corpus_legacy/regex.json +37 -0
- data/spec/spec_tests/data/corpus_legacy/string.json +67 -0
- data/spec/spec_tests/data/corpus_legacy/timestamp.json +18 -0
- data/spec/spec_tests/data/corpus_legacy/top.json +62 -0
- data/spec/spec_tests/data/corpus_legacy/undefined.json +13 -0
- data/spec/spec_tests/data/decimal128/decimal128-1.json +363 -0
- data/spec/spec_tests/data/decimal128/decimal128-2.json +793 -0
- data/spec/spec_tests/data/decimal128/decimal128-3.json +1771 -0
- data/spec/spec_tests/data/decimal128/decimal128-4.json +165 -0
- data/spec/spec_tests/data/decimal128/decimal128-5.json +402 -0
- data/spec/spec_tests/data/decimal128/decimal128-6.json +131 -0
- data/spec/spec_tests/data/decimal128/decimal128-7.json +327 -0
- data/spec/support/shared_examples.rb +32 -11
- data/spec/support/spec_config.rb +17 -0
- data/spec/support/utils.rb +58 -0
- metadata +284 -45
- checksums.yaml.gz.sig +0 -3
- data/ext/bson/native.c +0 -722
- data.tar.gz.sig +0 -0
- metadata.gz.sig +0 -0
data/lib/bson/hash.rb
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
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.
|
|
@@ -12,41 +14,32 @@
|
|
|
12
14
|
# See the License for the specific language governing permissions and
|
|
13
15
|
# limitations under the License.
|
|
14
16
|
|
|
17
|
+
# The top-level BSON module.
|
|
15
18
|
module BSON
|
|
16
|
-
|
|
17
19
|
# Injects behaviour for encoding and decoding hashes to
|
|
18
20
|
# and from raw bytes as specified by the BSON spec.
|
|
19
21
|
#
|
|
20
22
|
# @see http://bsonspec.org/#/specification
|
|
21
|
-
#
|
|
22
|
-
# @since 2.0.0
|
|
23
23
|
module Hash
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
#
|
|
27
|
-
# @since 2.0.0
|
|
28
|
-
BSON_TYPE = 3.chr.force_encoding(BINARY).freeze
|
|
24
|
+
# A hash, also called an embedded document, is type 0x03 in the BSON spec.
|
|
25
|
+
BSON_TYPE = ::String.new(3.chr, encoding: BINARY).freeze
|
|
29
26
|
|
|
30
27
|
# Get the hash as encoded BSON.
|
|
31
28
|
#
|
|
32
29
|
# @example Get the hash as encoded BSON.
|
|
33
30
|
# { "field" => "value" }.to_bson
|
|
34
31
|
#
|
|
35
|
-
# @return [
|
|
32
|
+
# @return [ BSON::ByteBuffer ] The buffer with the encoded object.
|
|
36
33
|
#
|
|
37
34
|
# @see http://bsonspec.org/#/specification
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
buffer
|
|
45
|
-
buffer.put_cstring(field.to_bson_key(validating_keys))
|
|
46
|
-
value.to_bson(buffer, 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.
|
|
38
|
+
if buffer.respond_to?(:put_hash)
|
|
39
|
+
buffer.put_hash(self)
|
|
40
|
+
else
|
|
41
|
+
serialize_to_buffer(buffer)
|
|
47
42
|
end
|
|
48
|
-
buffer.put_byte(NULL_BYTE)
|
|
49
|
-
buffer.replace_int32(position, buffer.length - position)
|
|
50
43
|
end
|
|
51
44
|
|
|
52
45
|
# Converts the hash to a normalized value in a BSON document.
|
|
@@ -54,44 +47,166 @@ module BSON
|
|
|
54
47
|
# @example Convert the hash to a normalized value.
|
|
55
48
|
# hash.to_bson_normalized_value
|
|
56
49
|
#
|
|
57
|
-
# @return [ BSON::Document ] The
|
|
58
|
-
#
|
|
59
|
-
# @since 3.0.0
|
|
50
|
+
# @return [ BSON::Document ] The normalized hash.
|
|
60
51
|
def to_bson_normalized_value
|
|
61
52
|
Document.new(self)
|
|
62
53
|
end
|
|
63
54
|
|
|
64
|
-
|
|
55
|
+
# Converts this object to a representation directly serializable to
|
|
56
|
+
# Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json/extended-json.md).
|
|
57
|
+
#
|
|
58
|
+
# This method recursively invokes +as_extended_json+ with the provided
|
|
59
|
+
# options on each hash value.
|
|
60
|
+
#
|
|
61
|
+
# @option opts [ nil | :relaxed | :legacy ] :mode Serialization mode
|
|
62
|
+
# (default is canonical extended JSON)
|
|
63
|
+
#
|
|
64
|
+
# @return [ Hash ] This hash converted to extended json representation.
|
|
65
|
+
def as_extended_json(**options)
|
|
66
|
+
transform_values { |value| value.as_extended_json(**options) }
|
|
67
|
+
end
|
|
68
|
+
|
|
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
|
|
65
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
|
|
120
|
+
|
|
121
|
+
# The methods to augment the Hash class with (class-level methods).
|
|
122
|
+
module ClassMethods
|
|
66
123
|
# Deserialize the hash from BSON.
|
|
67
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
|
+
#
|
|
68
130
|
# @param [ ByteBuffer ] buffer The byte buffer.
|
|
69
131
|
#
|
|
70
|
-
# @
|
|
132
|
+
# @option options [ nil | :bson ] :mode Decoding mode to use.
|
|
133
|
+
#
|
|
134
|
+
# @return [ Hash ] The decoded hash.
|
|
71
135
|
#
|
|
72
136
|
# @see http://bsonspec.org/#/specification
|
|
137
|
+
def from_bson(buffer, **options)
|
|
138
|
+
if buffer.respond_to?(:get_hash)
|
|
139
|
+
buffer.get_hash(**options)
|
|
140
|
+
else
|
|
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.
|
|
73
151
|
#
|
|
74
|
-
# @
|
|
75
|
-
|
|
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)
|
|
76
170
|
hash = Document.allocate
|
|
77
|
-
|
|
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)
|
|
78
190
|
while (type = buffer.get_byte) != NULL_BYTE
|
|
79
191
|
field = buffer.get_cstring
|
|
80
|
-
|
|
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)
|
|
81
201
|
end
|
|
82
|
-
hash
|
|
83
202
|
end
|
|
84
203
|
end
|
|
85
204
|
|
|
86
205
|
# Register this type when the module is loaded.
|
|
87
|
-
#
|
|
88
|
-
# @since 2.0.0
|
|
89
206
|
Registry.register(BSON_TYPE, ::Hash)
|
|
90
207
|
end
|
|
91
208
|
|
|
92
209
|
# Enrich the core Hash class with this module.
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
::Hash.send(:include, Hash)
|
|
96
|
-
::Hash.send(:extend, Hash::ClassMethods)
|
|
210
|
+
::Hash.include Hash
|
|
211
|
+
::Hash.extend Hash::ClassMethods
|
|
97
212
|
end
|
data/lib/bson/int32.rb
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
#
|
|
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.
|
|
@@ -14,18 +16,18 @@
|
|
|
14
16
|
|
|
15
17
|
module BSON
|
|
16
18
|
|
|
17
|
-
# Represents
|
|
18
|
-
# specification.
|
|
19
|
+
# Represents int32 type.
|
|
19
20
|
#
|
|
20
21
|
# @see http://bsonspec.org/#/specification
|
|
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
|
#
|
|
27
29
|
# @since 2.0.0
|
|
28
|
-
BSON_TYPE = 16.chr
|
|
30
|
+
BSON_TYPE = ::String.new(16.chr, encoding: BINARY).freeze
|
|
29
31
|
|
|
30
32
|
# The number of bytes constant.
|
|
31
33
|
#
|
|
@@ -35,21 +37,117 @@ module BSON
|
|
|
35
37
|
# Constant for the int 32 pack directive.
|
|
36
38
|
#
|
|
37
39
|
# @since 2.0.0
|
|
38
|
-
PACK = "l<"
|
|
40
|
+
PACK = "l<"
|
|
39
41
|
|
|
40
42
|
# Deserialize an Integer from BSON.
|
|
41
43
|
#
|
|
42
44
|
# @param [ ByteBuffer ] buffer The byte buffer.
|
|
43
45
|
#
|
|
46
|
+
# @option options [ nil | :bson ] :mode Decoding mode to use.
|
|
47
|
+
#
|
|
44
48
|
# @return [ Integer ] The decoded Integer.
|
|
45
49
|
#
|
|
46
50
|
# @see http://bsonspec.org/#/specification
|
|
47
51
|
#
|
|
48
52
|
# @since 2.0.0
|
|
49
|
-
def self.from_bson(buffer)
|
|
53
|
+
def self.from_bson(buffer, **options)
|
|
50
54
|
buffer.get_int32
|
|
51
55
|
end
|
|
52
56
|
|
|
57
|
+
# Instantiate a BSON Int32.
|
|
58
|
+
#
|
|
59
|
+
# @param [ Integer ] value The 32-bit integer.
|
|
60
|
+
#
|
|
61
|
+
# @see http://bsonspec.org/#/specification
|
|
62
|
+
#
|
|
63
|
+
# @since 4.2.0
|
|
64
|
+
def initialize(value)
|
|
65
|
+
if value.is_a?(self.class)
|
|
66
|
+
@value = value.value
|
|
67
|
+
return
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
unless value.bson_int32?
|
|
71
|
+
raise RangeError.new("#{value} cannot be stored in 32 bits")
|
|
72
|
+
end
|
|
73
|
+
@value = value.freeze
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Returns the value of this Int32.
|
|
77
|
+
#
|
|
78
|
+
# @return [ Integer ] The integer value.
|
|
79
|
+
attr_reader :value
|
|
80
|
+
|
|
81
|
+
# Append the integer as encoded BSON to a ByteBuffer.
|
|
82
|
+
#
|
|
83
|
+
# @example Encoded the integer and append to a ByteBuffer.
|
|
84
|
+
# int32.to_bson
|
|
85
|
+
#
|
|
86
|
+
# @return [ BSON::ByteBuffer ] The buffer with the encoded integer.
|
|
87
|
+
#
|
|
88
|
+
# @see http://bsonspec.org/#/specification
|
|
89
|
+
#
|
|
90
|
+
# @since 4.2.0
|
|
91
|
+
def to_bson(buffer = ByteBuffer.new)
|
|
92
|
+
buffer.put_int32(value)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Convert the integer to a BSON string key.
|
|
96
|
+
#
|
|
97
|
+
# @example Convert the integer to a BSON key string.
|
|
98
|
+
# int.to_bson_key
|
|
99
|
+
#
|
|
100
|
+
# @return [ String ] The string key.
|
|
101
|
+
#
|
|
102
|
+
# @since 4.2.0
|
|
103
|
+
def to_bson_key
|
|
104
|
+
value
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Check equality of the int32 with another object.
|
|
108
|
+
#
|
|
109
|
+
# @param [ Object ] other The object to check against.
|
|
110
|
+
#
|
|
111
|
+
# @return [ true, false ] If the objects are equal.
|
|
112
|
+
#
|
|
113
|
+
# @since 4.4.0
|
|
114
|
+
def ==(other)
|
|
115
|
+
return false unless other.is_a?(Int32)
|
|
116
|
+
value == other.value
|
|
117
|
+
end
|
|
118
|
+
alias :eql? :==
|
|
119
|
+
alias :=== :==
|
|
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
|
+
|
|
133
|
+
# Converts this object to a representation directly serializable to
|
|
134
|
+
# Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json/extended-json.md).
|
|
135
|
+
#
|
|
136
|
+
# This method returns the integer value if relaxed representation is
|
|
137
|
+
# requested, otherwise a $numberInt hash.
|
|
138
|
+
#
|
|
139
|
+
# @option opts [ nil | :relaxed | :legacy ] :mode Serialization mode
|
|
140
|
+
# (default is canonical extended JSON)
|
|
141
|
+
#
|
|
142
|
+
# @return [ Hash | Integer ] The extended json representation.
|
|
143
|
+
def as_extended_json(**options)
|
|
144
|
+
if options[:mode] == :relaxed || options[:mode] == :legacy
|
|
145
|
+
value
|
|
146
|
+
else
|
|
147
|
+
{'$numberInt' => value.to_s}
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
53
151
|
# Register this type when the module is loaded.
|
|
54
152
|
#
|
|
55
153
|
# @since 2.0.0
|
data/lib/bson/int64.rb
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
#
|
|
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.
|
|
@@ -14,35 +16,136 @@
|
|
|
14
16
|
|
|
15
17
|
module BSON
|
|
16
18
|
|
|
17
|
-
# Represents
|
|
18
|
-
# specification.
|
|
19
|
+
# Represents int64 type.
|
|
19
20
|
#
|
|
20
21
|
# @see http://bsonspec.org/#/specification
|
|
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
|
#
|
|
27
29
|
# @since 2.0.0
|
|
28
|
-
BSON_TYPE = 18.chr
|
|
30
|
+
BSON_TYPE = ::String.new(18.chr, encoding: BINARY).freeze
|
|
29
31
|
|
|
30
32
|
# Constant for the int 64 pack directive.
|
|
31
33
|
#
|
|
32
34
|
# @since 2.0.0
|
|
33
|
-
PACK = "q<"
|
|
35
|
+
PACK = "q<"
|
|
34
36
|
|
|
35
37
|
# Deserialize an Integer from BSON.
|
|
36
38
|
#
|
|
37
39
|
# @param [ ByteBuffer ] buffer The byte buffer.
|
|
38
40
|
#
|
|
39
|
-
# @
|
|
41
|
+
# @option options [ nil | :bson ] :mode Decoding mode to use.
|
|
42
|
+
#
|
|
43
|
+
# @return [ Integer | BSON::Int64 ] The decoded Integer.
|
|
40
44
|
#
|
|
41
45
|
# @see http://bsonspec.org/#/specification
|
|
42
46
|
#
|
|
43
47
|
# @since 2.0.0
|
|
44
|
-
def self.from_bson(buffer)
|
|
45
|
-
buffer.get_int64
|
|
48
|
+
def self.from_bson(buffer, **options)
|
|
49
|
+
value = buffer.get_int64
|
|
50
|
+
if options[:mode] == :bson
|
|
51
|
+
new(value)
|
|
52
|
+
else
|
|
53
|
+
value
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Instantiate a BSON Int64.
|
|
58
|
+
#
|
|
59
|
+
# @param [ Integer ] value The 64-bit integer.
|
|
60
|
+
#
|
|
61
|
+
# @see http://bsonspec.org/#/specification
|
|
62
|
+
#
|
|
63
|
+
# @since 4.2.0
|
|
64
|
+
def initialize(value)
|
|
65
|
+
if value.is_a?(self.class)
|
|
66
|
+
@value = value.value
|
|
67
|
+
return
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
unless value.bson_int64?
|
|
71
|
+
raise RangeError.new("#{value} cannot be stored in 64 bits")
|
|
72
|
+
end
|
|
73
|
+
@value = value.freeze
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Returns the value of this Int64.
|
|
77
|
+
#
|
|
78
|
+
# @return [ Integer ] The integer value.
|
|
79
|
+
attr_reader :value
|
|
80
|
+
|
|
81
|
+
# Append the integer as encoded BSON to a ByteBuffer.
|
|
82
|
+
#
|
|
83
|
+
# @example Encoded the integer and append to a ByteBuffer.
|
|
84
|
+
# int64.to_bson
|
|
85
|
+
#
|
|
86
|
+
# @return [ BSON::ByteBuffer ] The buffer with the encoded integer.
|
|
87
|
+
#
|
|
88
|
+
# @see http://bsonspec.org/#/specification
|
|
89
|
+
#
|
|
90
|
+
# @since 4.2.0
|
|
91
|
+
def to_bson(buffer = ByteBuffer.new)
|
|
92
|
+
buffer.put_int64(value)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Convert the integer to a BSON string key.
|
|
96
|
+
#
|
|
97
|
+
# @example Convert the integer to a BSON key string.
|
|
98
|
+
# int.to_bson_key
|
|
99
|
+
#
|
|
100
|
+
# @return [ String ] The string key.
|
|
101
|
+
#
|
|
102
|
+
# @since 4.2.0
|
|
103
|
+
def to_bson_key
|
|
104
|
+
value
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Check equality of the int64 with another object.
|
|
108
|
+
#
|
|
109
|
+
# @param [ Object ] other The object to check against.
|
|
110
|
+
#
|
|
111
|
+
# @return [ true, false ] If the objects are equal.
|
|
112
|
+
#
|
|
113
|
+
# @since 4.4.0
|
|
114
|
+
def ==(other)
|
|
115
|
+
return false unless other.is_a?(Int64)
|
|
116
|
+
value == other.value
|
|
117
|
+
end
|
|
118
|
+
alias :eql? :==
|
|
119
|
+
alias :=== :==
|
|
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
|
+
|
|
133
|
+
# Converts this object to a representation directly serializable to
|
|
134
|
+
# Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json/extended-json.md).
|
|
135
|
+
#
|
|
136
|
+
# This method returns the integer value if relaxed representation is
|
|
137
|
+
# requested, otherwise a $numberLong hash.
|
|
138
|
+
#
|
|
139
|
+
# @option opts [ nil | :relaxed | :legacy ] :mode Serialization mode
|
|
140
|
+
# (default is canonical extended JSON)
|
|
141
|
+
#
|
|
142
|
+
# @return [ Hash | Integer ] The extended json representation.
|
|
143
|
+
def as_extended_json(**options)
|
|
144
|
+
if options[:mode] == :relaxed || options[:mode] == :legacy
|
|
145
|
+
value
|
|
146
|
+
else
|
|
147
|
+
{'$numberLong' => value.to_s}
|
|
148
|
+
end
|
|
46
149
|
end
|
|
47
150
|
|
|
48
151
|
# Register this type when the module is loaded.
|
data/lib/bson/integer.rb
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
#
|
|
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.
|
|
@@ -45,13 +47,13 @@ module BSON
|
|
|
45
47
|
# The BSON index size.
|
|
46
48
|
#
|
|
47
49
|
# @since 2.0.0
|
|
48
|
-
BSON_INDEX_SIZE = 1024
|
|
50
|
+
BSON_INDEX_SIZE = 1024
|
|
49
51
|
|
|
50
52
|
# A hash of index values for array optimization.
|
|
51
53
|
#
|
|
52
54
|
# @since 2.0.0
|
|
53
55
|
BSON_ARRAY_INDEXES = ::Array.new(BSON_INDEX_SIZE) do |i|
|
|
54
|
-
(i.to_s.
|
|
56
|
+
(i.to_s.b << NULL_BYTE).freeze
|
|
55
57
|
end.freeze
|
|
56
58
|
|
|
57
59
|
# Is this integer a valid BSON 32 bit value?
|
|
@@ -98,12 +100,12 @@ module BSON
|
|
|
98
100
|
# @example Get the integer as encoded BSON.
|
|
99
101
|
# 1024.to_bson
|
|
100
102
|
#
|
|
101
|
-
# @return [
|
|
103
|
+
# @return [ BSON::ByteBuffer ] The buffer with the encoded object.
|
|
102
104
|
#
|
|
103
105
|
# @see http://bsonspec.org/#/specification
|
|
104
106
|
#
|
|
105
107
|
# @since 2.0.0
|
|
106
|
-
def to_bson(buffer = ByteBuffer.new
|
|
108
|
+
def to_bson(buffer = ByteBuffer.new)
|
|
107
109
|
if bson_int32?
|
|
108
110
|
buffer.put_int32(self)
|
|
109
111
|
elsif bson_int64?
|
|
@@ -150,13 +152,45 @@ module BSON
|
|
|
150
152
|
# @example Convert the integer to a BSON key string.
|
|
151
153
|
# 1.to_bson_key
|
|
152
154
|
#
|
|
153
|
-
# @param [ true, false ] validating_keys If BSON should validate the key.
|
|
154
|
-
#
|
|
155
155
|
# @return [ String ] The string key.
|
|
156
156
|
#
|
|
157
157
|
# @since 2.0.0
|
|
158
|
-
def to_bson_key
|
|
159
|
-
|
|
158
|
+
def to_bson_key
|
|
159
|
+
self
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# Converts this object to a representation directly serializable to
|
|
163
|
+
# Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json/extended-json.md).
|
|
164
|
+
#
|
|
165
|
+
# This method returns the integer itself if relaxed representation is
|
|
166
|
+
# requested, otherwise a $numberInt hash if the value fits in 32 bits
|
|
167
|
+
# and a $numberLong otherwise. Regardless of which representation is
|
|
168
|
+
# requested, a value that does not fit in 64 bits raises RangeError.
|
|
169
|
+
#
|
|
170
|
+
# @option opts [ nil | :relaxed | :legacy ] :mode Serialization mode
|
|
171
|
+
# (default is canonical extended JSON)
|
|
172
|
+
#
|
|
173
|
+
# @return [ Hash | Integer ] The extended json representation.
|
|
174
|
+
def as_extended_json(**options)
|
|
175
|
+
# The behavior of native integers' serialization to extended json is
|
|
176
|
+
# not specified. Following our bson serialization logic in this file,
|
|
177
|
+
# produce explicit $numberInt or $numberLong, choosing $numberInt if
|
|
178
|
+
# the integer fits in 32 bits. In Ruby integers can be arbitrarily
|
|
179
|
+
# big; integers that do not fit into 64 bits raise an error as we do not
|
|
180
|
+
# want to silently perform an effective type conversion of integer ->
|
|
181
|
+
# decimal.
|
|
182
|
+
|
|
183
|
+
unless bson_int64?
|
|
184
|
+
raise RangeError, "Integer #{self} is too big to be represented as a MongoDB integer"
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
if options[:mode] == :relaxed || options[:mode] == :legacy
|
|
188
|
+
self
|
|
189
|
+
elsif bson_int32?
|
|
190
|
+
{'$numberInt' => to_s}
|
|
191
|
+
else
|
|
192
|
+
{'$numberLong' => to_s}
|
|
193
|
+
end
|
|
160
194
|
end
|
|
161
195
|
|
|
162
196
|
private
|
data/lib/bson/json.rb
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
#
|
|
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.
|