bson 4.2.2 → 4.12.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/README.md +25 -7
- data/Rakefile +16 -9
- data/ext/bson/{native-endian.h → bson-endian.h} +5 -99
- data/ext/bson/bson-native.h +125 -0
- data/ext/bson/bytebuf.c +133 -0
- data/ext/bson/endian.c +117 -0
- data/ext/bson/init.c +355 -0
- data/ext/bson/libbson-utf8.c +230 -0
- data/ext/bson/read.c +411 -0
- data/ext/bson/util.c +95 -0
- data/ext/bson/write.c +680 -0
- data/lib/bson.rb +6 -3
- data/lib/bson/active_support.rb +17 -0
- data/lib/bson/array.rb +57 -17
- data/lib/bson/binary.rb +185 -13
- data/lib/bson/boolean.rb +12 -3
- data/lib/bson/code.rb +16 -2
- data/lib/bson/code_with_scope.rb +32 -5
- data/lib/bson/config.rb +1 -1
- data/lib/bson/date.rb +12 -2
- data/lib/bson/date_time.rb +2 -2
- data/lib/bson/db_pointer.rb +110 -0
- data/lib/bson/decimal128.rb +17 -3
- data/lib/bson/decimal128/builder.rb +1 -1
- data/lib/bson/document.rb +152 -5
- data/lib/bson/environment.rb +2 -1
- data/lib/bson/error.rb +27 -0
- data/lib/bson/ext_json.rb +383 -0
- data/lib/bson/false_class.rb +1 -1
- data/lib/bson/float.rb +48 -2
- data/lib/bson/hash.rb +68 -17
- data/lib/bson/int32.rb +52 -13
- data/lib/bson/int64.rb +59 -15
- data/lib/bson/integer.rb +36 -2
- data/lib/bson/json.rb +1 -1
- data/lib/bson/max_key.rb +13 -1
- data/lib/bson/min_key.rb +13 -1
- data/lib/bson/nil_class.rb +4 -2
- data/lib/bson/object.rb +28 -1
- data/lib/bson/object_id.rb +16 -2
- data/lib/bson/open_struct.rb +1 -1
- data/lib/bson/regexp.rb +27 -4
- data/lib/bson/registry.rb +3 -3
- data/lib/bson/specialized.rb +4 -2
- data/lib/bson/string.rb +5 -3
- data/lib/bson/symbol.rb +99 -7
- data/lib/bson/time.rb +63 -4
- data/lib/bson/time_with_zone.rb +54 -0
- data/lib/bson/timestamp.rb +44 -6
- data/lib/bson/true_class.rb +1 -1
- data/lib/bson/undefined.rb +12 -1
- data/lib/bson/version.rb +2 -2
- data/spec/bson/array_spec.rb +18 -1
- data/spec/bson/binary_spec.rb +100 -3
- data/spec/bson/binary_uuid_spec.rb +189 -0
- data/spec/bson/boolean_spec.rb +1 -1
- data/spec/bson/byte_buffer_read_spec.rb +197 -0
- data/spec/bson/byte_buffer_spec.rb +121 -381
- data/spec/bson/byte_buffer_write_spec.rb +854 -0
- data/spec/bson/code_spec.rb +1 -1
- data/spec/bson/code_with_scope_spec.rb +1 -1
- data/spec/bson/date_spec.rb +1 -1
- data/spec/bson/date_time_spec.rb +54 -1
- data/spec/bson/decimal128_spec.rb +35 -35
- data/spec/bson/document_as_spec.rb +46 -0
- data/spec/bson/document_spec.rb +197 -30
- data/spec/bson/ext_json_parse_spec.rb +308 -0
- data/spec/bson/false_class_spec.rb +1 -1
- data/spec/bson/float_spec.rb +37 -1
- data/spec/bson/hash_as_spec.rb +57 -0
- data/spec/bson/hash_spec.rb +209 -1
- data/spec/bson/int32_spec.rb +180 -6
- data/spec/bson/int64_spec.rb +199 -6
- data/spec/bson/integer_spec.rb +29 -3
- data/spec/bson/json_spec.rb +1 -1
- data/spec/bson/max_key_spec.rb +1 -1
- data/spec/bson/min_key_spec.rb +1 -1
- data/spec/bson/nil_class_spec.rb +1 -1
- data/spec/bson/object_id_spec.rb +1 -1
- data/spec/bson/object_spec.rb +1 -1
- data/spec/bson/open_struct_spec.rb +1 -1
- data/spec/bson/raw_spec.rb +34 -2
- data/spec/bson/regexp_spec.rb +1 -1
- data/spec/bson/registry_spec.rb +1 -1
- data/spec/bson/string_spec.rb +19 -1
- data/spec/bson/symbol_raw_spec.rb +45 -0
- data/spec/bson/symbol_spec.rb +63 -3
- data/spec/bson/time_spec.rb +205 -2
- data/spec/bson/time_with_zone_spec.rb +68 -0
- data/spec/bson/timestamp_spec.rb +56 -1
- data/spec/bson/true_class_spec.rb +1 -1
- data/spec/bson/undefined_spec.rb +1 -1
- data/spec/bson_spec.rb +1 -1
- data/spec/{support → runners}/common_driver.rb +1 -1
- data/spec/runners/corpus.rb +185 -0
- data/spec/{support/corpus.rb → runners/corpus_legacy.rb} +41 -59
- data/spec/spec_helper.rb +40 -3
- data/spec/{bson/driver_bson_spec.rb → spec_tests/common_driver_spec.rb} +1 -0
- data/spec/{bson/corpus_spec.rb → spec_tests/corpus_legacy_spec.rb} +10 -7
- data/spec/spec_tests/corpus_spec.rb +124 -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 +113 -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 +31 -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 +117 -0
- data/spec/spec_tests/data/corpus/decimal128-5.json +402 -0
- data/spec/spec_tests/data/corpus/decimal128-6.json +119 -0
- data/spec/spec_tests/data/corpus/decimal128-7.json +323 -0
- data/spec/spec_tests/data/corpus/document.json +36 -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 +236 -0
- data/spec/spec_tests/data/corpus/undefined.json +15 -0
- data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/array.json +8 -2
- data/spec/{support/corpus-tests/failures → spec_tests/data/corpus_legacy}/binary.json +0 -0
- data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/boolean.json +0 -0
- data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/code.json +1 -1
- data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/code_w_scope.json +1 -1
- data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/document.json +1 -1
- data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/double.json +1 -1
- data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/failures/datetime.json +0 -0
- data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/failures/dbpointer.json +0 -0
- data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/failures/int64.json +0 -0
- data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/failures/symbol.json +0 -0
- data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/int32.json +1 -1
- data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/maxkey.json +1 -1
- data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/minkey.json +1 -1
- data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/null.json +1 -1
- data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/oid.json +0 -0
- data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/regex.json +1 -1
- data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/string.json +0 -0
- data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/timestamp.json +1 -1
- data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/top.json +0 -0
- data/spec/{support/corpus-tests/failures → spec_tests/data/corpus_legacy}/undefined.json +0 -0
- data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-1.json +0 -0
- data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-2.json +0 -0
- data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-3.json +0 -0
- data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-4.json +0 -0
- data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-5.json +0 -0
- data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-6.json +0 -0
- data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-7.json +0 -0
- data/spec/support/shared_examples.rb +3 -5
- data/spec/support/spec_config.rb +16 -0
- data/spec/support/utils.rb +10 -0
- metadata +227 -124
- metadata.gz.sig +0 -0
- data/ext/bson/bson_native.c +0 -762
data/lib/bson.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2009-
|
1
|
+
# Copyright (C) 2009-2020 MongoDB Inc.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -57,6 +57,7 @@ module BSON
|
|
57
57
|
end
|
58
58
|
|
59
59
|
require "bson/config"
|
60
|
+
require "bson/error"
|
60
61
|
require "bson/registry"
|
61
62
|
require "bson/specialized"
|
62
63
|
require "bson/json"
|
@@ -70,8 +71,10 @@ require "bson/code"
|
|
70
71
|
require "bson/code_with_scope"
|
71
72
|
require "bson/date"
|
72
73
|
require "bson/date_time"
|
74
|
+
require "bson/db_pointer"
|
73
75
|
require "bson/decimal128"
|
74
76
|
require "bson/document"
|
77
|
+
require "bson/ext_json"
|
75
78
|
require "bson/false_class"
|
76
79
|
require "bson/float"
|
77
80
|
require "bson/hash"
|
@@ -101,7 +104,7 @@ begin
|
|
101
104
|
else
|
102
105
|
require "bson_native"
|
103
106
|
end
|
104
|
-
rescue LoadError
|
105
|
-
$stderr.puts("Failed to load the necessary extensions.")
|
107
|
+
rescue LoadError => e
|
108
|
+
$stderr.puts("Failed to load the necessary extensions: #{e.class}: #{e}")
|
106
109
|
raise
|
107
110
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Copyright (C) 2018-2020 MongoDB Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
# Require this file if using BSON with ActiveSupport.
|
16
|
+
|
17
|
+
require "bson/time_with_zone"
|
data/lib/bson/array.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2009-
|
1
|
+
# Copyright (C) 2009-2020 MongoDB Inc.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -41,15 +41,22 @@ module BSON
|
|
41
41
|
#
|
42
42
|
# @since 2.0.0
|
43
43
|
def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
buffer.
|
48
|
-
buffer.
|
49
|
-
value
|
44
|
+
if buffer.respond_to?(:put_array)
|
45
|
+
buffer.put_array(self, validating_keys)
|
46
|
+
else
|
47
|
+
position = buffer.length
|
48
|
+
buffer.put_int32(0)
|
49
|
+
each_with_index do |value, index|
|
50
|
+
unless value.respond_to?(:bson_type)
|
51
|
+
raise Error::UnserializableClass, "Array element at position #{index} does not define its BSON serialized type: #{value}"
|
52
|
+
end
|
53
|
+
buffer.put_byte(value.bson_type)
|
54
|
+
buffer.put_cstring(index.to_s)
|
55
|
+
value.to_bson(buffer, validating_keys)
|
56
|
+
end
|
57
|
+
buffer.put_byte(NULL_BYTE)
|
58
|
+
buffer.replace_int32(position, buffer.length - position)
|
50
59
|
end
|
51
|
-
buffer.put_byte(NULL_BYTE)
|
52
|
-
buffer.replace_int32(position, buffer.length - position)
|
53
60
|
end
|
54
61
|
|
55
62
|
# Convert the array to an object id. This will only work for arrays of size
|
@@ -60,7 +67,7 @@ module BSON
|
|
60
67
|
#
|
61
68
|
# @note This is used for repairing legacy bson data.
|
62
69
|
#
|
63
|
-
# @raise [
|
70
|
+
# @raise [ BSON::ObjectId::Invalid ] If the array is not 12 elements.
|
64
71
|
#
|
65
72
|
# @return [ String ] The raw object id bytes.
|
66
73
|
#
|
@@ -81,25 +88,58 @@ module BSON
|
|
81
88
|
map { |value| value.to_bson_normalized_value }
|
82
89
|
end
|
83
90
|
|
91
|
+
# Converts this object to a representation directly serializable to
|
92
|
+
# Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
|
93
|
+
#
|
94
|
+
# This method recursively invokes +as_extended_json+ with the provided
|
95
|
+
# options on each array element.
|
96
|
+
#
|
97
|
+
# @option opts [ nil | :relaxed | :legacy ] :mode Serialization mode
|
98
|
+
# (default is canonical extended JSON)
|
99
|
+
#
|
100
|
+
# @return [ Array ] This array converted to extended json representation.
|
101
|
+
def as_extended_json(**options)
|
102
|
+
map do |item|
|
103
|
+
item.as_extended_json(**options)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
84
107
|
module ClassMethods
|
85
108
|
|
86
109
|
# Deserialize the array from BSON.
|
87
110
|
#
|
88
111
|
# @param [ ByteBuffer ] buffer The byte buffer.
|
89
112
|
#
|
113
|
+
# @option options [ nil | :bson ] :mode Decoding mode to use.
|
114
|
+
#
|
90
115
|
# @return [ Array ] The decoded array.
|
91
116
|
#
|
92
117
|
# @see http://bsonspec.org/#/specification
|
93
118
|
#
|
94
119
|
# @since 2.0.0
|
95
|
-
def from_bson(buffer)
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
120
|
+
def from_bson(buffer, **options)
|
121
|
+
if buffer.respond_to?(:get_array)
|
122
|
+
buffer.get_array(**options)
|
123
|
+
else
|
124
|
+
array = new
|
125
|
+
start_position = buffer.read_position
|
126
|
+
expected_byte_size = buffer.get_int32
|
127
|
+
while (type = buffer.get_byte) != NULL_BYTE
|
128
|
+
buffer.get_cstring
|
129
|
+
cls = BSON::Registry.get(type)
|
130
|
+
value = if options.empty?
|
131
|
+
cls.from_bson(buffer)
|
132
|
+
else
|
133
|
+
cls.from_bson(buffer, **options)
|
134
|
+
end
|
135
|
+
array << value
|
136
|
+
end
|
137
|
+
actual_byte_size = buffer.read_position - start_position
|
138
|
+
if actual_byte_size != expected_byte_size
|
139
|
+
raise Error::BSONDecodeError, "Expected array to take #{expected_byte_size} bytes but it took #{actual_byte_size} bytes"
|
140
|
+
end
|
141
|
+
array
|
101
142
|
end
|
102
|
-
array
|
103
143
|
end
|
104
144
|
end
|
105
145
|
|
data/lib/bson/binary.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2009-
|
1
|
+
# Copyright (C) 2009-2020 MongoDB Inc.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -31,6 +31,12 @@ module BSON
|
|
31
31
|
|
32
32
|
# The mappings of subtypes to their single byte identifiers.
|
33
33
|
#
|
34
|
+
# @note subtype 6 (ciphertext) is used for the Client-Side Encryption
|
35
|
+
# feature. Data represented by this subtype is often encrypted, but
|
36
|
+
# may also be plaintext. All instances of this subtype necessary for
|
37
|
+
# Client-Side Encryption will be created internally by the Ruby driver.
|
38
|
+
# An application should not create new BSON::Binary objects of this subtype.
|
39
|
+
#
|
34
40
|
# @since 2.0.0
|
35
41
|
SUBTYPES = {
|
36
42
|
:generic => 0.chr,
|
@@ -39,6 +45,7 @@ module BSON
|
|
39
45
|
:uuid_old => 3.chr,
|
40
46
|
:uuid => 4.chr,
|
41
47
|
:md5 => 5.chr,
|
48
|
+
:ciphertext => 6.chr,
|
42
49
|
:user => 128.chr
|
43
50
|
}.freeze
|
44
51
|
|
@@ -47,13 +54,17 @@ module BSON
|
|
47
54
|
# @since 2.0.0
|
48
55
|
TYPES = SUBTYPES.invert.freeze
|
49
56
|
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
|
56
|
-
|
57
|
+
# @return [ String ] The raw binary data.
|
58
|
+
#
|
59
|
+
# The string is always stored in BINARY encoding.
|
60
|
+
#
|
61
|
+
# @since 2.0.0
|
62
|
+
attr_reader :data
|
63
|
+
|
64
|
+
# @return [ Symbol ] The binary type.
|
65
|
+
#
|
66
|
+
# @since 2.0.0
|
67
|
+
attr_reader :type
|
57
68
|
|
58
69
|
# Determine if this binary object is equal to another object.
|
59
70
|
#
|
@@ -90,21 +101,61 @@ module BSON
|
|
90
101
|
# @return [ Hash ] The binary as a JSON hash.
|
91
102
|
#
|
92
103
|
# @since 2.0.0
|
104
|
+
# @deprecated Use as_extended_json instead.
|
93
105
|
def as_json(*args)
|
94
|
-
|
106
|
+
as_extended_json
|
107
|
+
end
|
108
|
+
|
109
|
+
# Converts this object to a representation directly serializable to
|
110
|
+
# Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
|
111
|
+
#
|
112
|
+
# @option opts [ nil | :relaxed | :legacy ] :mode Serialization mode
|
113
|
+
# (default is canonical extended JSON)
|
114
|
+
#
|
115
|
+
# @return [ Hash ] The extended json representation.
|
116
|
+
def as_extended_json(**options)
|
117
|
+
subtype = SUBTYPES[type].each_byte.map { |c| c.to_s(16) }.join
|
118
|
+
if subtype.length == 1
|
119
|
+
subtype = "0#{subtype}"
|
120
|
+
end
|
121
|
+
|
122
|
+
value = Base64.encode64(data).strip
|
123
|
+
|
124
|
+
if options[:mode] == :legacy
|
125
|
+
{ "$binary" => value, "$type" => subtype }
|
126
|
+
else
|
127
|
+
{ "$binary" => {'base64' => value, "subType" => subtype }}
|
128
|
+
end
|
95
129
|
end
|
96
130
|
|
97
131
|
# Instantiate the new binary object.
|
98
132
|
#
|
133
|
+
# This method accepts a string in any encoding; however, if a string is
|
134
|
+
# of a non-BINARY encoding, the encoding is set to BINARY. This does not
|
135
|
+
# change the bytes of the string but it means that applications referencing
|
136
|
+
# the data of a Binary instance cannot assume it is in a non-binary
|
137
|
+
# encoding, even if the string given to the constructor was in such an
|
138
|
+
# encoding.
|
139
|
+
#
|
99
140
|
# @example Instantiate a binary.
|
100
141
|
# BSON::Binary.new(data, :md5)
|
101
142
|
#
|
102
|
-
# @param [
|
143
|
+
# @param [ String ] data The raw binary data.
|
103
144
|
# @param [ Symbol ] type The binary type.
|
104
145
|
#
|
105
146
|
# @since 2.0.0
|
106
147
|
def initialize(data = "", type = :generic)
|
107
148
|
validate_type!(type)
|
149
|
+
|
150
|
+
# The Binary class used to force encoding to BINARY when serializing to
|
151
|
+
# BSON. Instead of doing that during serialization, perform this
|
152
|
+
# operation during Binary construction to make it clear that once
|
153
|
+
# the string is given to the Binary, the data is treated as a binary
|
154
|
+
# string and not a text string in any encoding.
|
155
|
+
unless data.encoding == Encoding.find('BINARY')
|
156
|
+
data = data.dup.force_encoding('BINARY')
|
157
|
+
end
|
158
|
+
|
108
159
|
@data = data
|
109
160
|
@type = type
|
110
161
|
end
|
@@ -121,6 +172,70 @@ module BSON
|
|
121
172
|
"<BSON::Binary:0x#{object_id} type=#{type} data=0x#{data[0, 8].unpack('H*').first}...>"
|
122
173
|
end
|
123
174
|
|
175
|
+
# Returns a string representation of the UUID stored in this Binary.
|
176
|
+
#
|
177
|
+
# If the Binary is of subtype 4 (:uuid), this method returns the UUID
|
178
|
+
# in RFC 4122 format. If the representation parameter is provided, it
|
179
|
+
# must be the value :standard as a symbol or a string.
|
180
|
+
#
|
181
|
+
# If the Binary is of subtype 3 (:uuid_old), this method requires that
|
182
|
+
# the representation parameter is provided and is one of :csharp_legacy,
|
183
|
+
# :java_legacy or :python_legacy or the equivalent strings. In this case
|
184
|
+
# the method assumes the Binary stores the UUID in the specified format,
|
185
|
+
# transforms the stored bytes to the standard RFC 4122 representation
|
186
|
+
# and returns the UUID in RFC 4122 format.
|
187
|
+
#
|
188
|
+
# If the Binary is of another subtype, this method raises TypeError.
|
189
|
+
#
|
190
|
+
# @param [ Symbol ] representation How to interpret the UUID.
|
191
|
+
#
|
192
|
+
# @return [ String ] The string representation of the UUID.
|
193
|
+
#
|
194
|
+
# @raise [ TypeError ] If the subtype of Binary is not :uuid nor :uuid_old.
|
195
|
+
# @raise [ ArgumentError ] If the representation other than :standard
|
196
|
+
# is requested for Binary subtype 4 (:uuid), if :standard representation
|
197
|
+
# is requested for Binary subtype 3 (:uuid_old), or if an invalid
|
198
|
+
# representation is requested.
|
199
|
+
#
|
200
|
+
# @api experimental
|
201
|
+
def to_uuid(representation = nil)
|
202
|
+
if representation.is_a?(String)
|
203
|
+
raise ArgumentError, "Representation must be given as a symbol: #{representation}"
|
204
|
+
end
|
205
|
+
case type
|
206
|
+
when :uuid
|
207
|
+
if representation && representation != :standard
|
208
|
+
raise ArgumentError, "Binary of type :uuid can only be stringified to :standard representation, requested: #{representation.inspect}"
|
209
|
+
end
|
210
|
+
|
211
|
+
data.split('').map { |n| '%02x' % n.ord }.join.sub(/\A(.{8})(.{4})(.{4})(.{4})(.{12})\z/, '\1-\2-\3-\4-\5')
|
212
|
+
when :uuid_old
|
213
|
+
if representation.nil?
|
214
|
+
raise ArgumentError, 'Representation must be specified for BSON::Binary objects of type :uuid_old'
|
215
|
+
end
|
216
|
+
|
217
|
+
hex = data.split('').map { |n| '%02x' % n.ord }.join
|
218
|
+
|
219
|
+
case representation
|
220
|
+
when :standard
|
221
|
+
raise ArgumentError, 'BSON::Binary objects of type :uuid_old cannot be stringified to :standard representation'
|
222
|
+
when :csharp_legacy
|
223
|
+
hex.sub(/\A(..)(..)(..)(..)(..)(..)(..)(..)(.{16})\z/, '\4\3\2\1\6\5\8\7\9')
|
224
|
+
when :java_legacy
|
225
|
+
hex.sub(/\A(..)(..)(..)(..)(..)(..)(..)(..)(..)(..)(..)(..)(..)(..)(..)(..)\z/) do |m|
|
226
|
+
"#{$8}#{$7}#{$6}#{$5}#{$4}#{$3}#{$2}#{$1}" +
|
227
|
+
"#{$16}#{$15}#{$14}#{$13}#{$12}#{$11}#{$10}#{$9}"
|
228
|
+
end
|
229
|
+
when :python_legacy
|
230
|
+
hex
|
231
|
+
else
|
232
|
+
raise ArgumentError, "Invalid representation: #{representation}"
|
233
|
+
end.sub(/\A(.{8})(.{4})(.{4})(.{4})(.{12})\z/, '\1-\2-\3-\4-\5')
|
234
|
+
else
|
235
|
+
raise TypeError, "The type of Binary must be :uuid or :uuid_old, this object is: #{type.inspect}"
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
124
239
|
# Encode the binary type
|
125
240
|
#
|
126
241
|
# @example Encode the binary.
|
@@ -136,7 +251,7 @@ module BSON
|
|
136
251
|
buffer.put_int32(0)
|
137
252
|
buffer.put_byte(SUBTYPES[type])
|
138
253
|
buffer.put_int32(data.bytesize) if type == :old
|
139
|
-
buffer.put_bytes(data
|
254
|
+
buffer.put_bytes(data)
|
140
255
|
buffer.replace_int32(position, buffer.length - position - 5)
|
141
256
|
end
|
142
257
|
|
@@ -144,19 +259,76 @@ module BSON
|
|
144
259
|
#
|
145
260
|
# @param [ ByteBuffer ] buffer The byte buffer.
|
146
261
|
#
|
262
|
+
# @option options [ nil | :bson ] :mode Decoding mode to use.
|
263
|
+
#
|
147
264
|
# @return [ Binary ] The decoded binary data.
|
148
265
|
#
|
149
266
|
# @see http://bsonspec.org/#/specification
|
150
267
|
#
|
151
268
|
# @since 2.0.0
|
152
|
-
def self.from_bson(buffer)
|
269
|
+
def self.from_bson(buffer, **options)
|
153
270
|
length = buffer.get_int32
|
154
|
-
|
271
|
+
type_byte = buffer.get_byte
|
272
|
+
type = TYPES[type_byte]
|
273
|
+
if type.nil?
|
274
|
+
raise Error::UnsupportedBinarySubtype,
|
275
|
+
"BSON data contains unsupported binary subtype #{'0x%02x' % type_byte.ord}"
|
276
|
+
end
|
277
|
+
|
155
278
|
length = buffer.get_int32 if type == :old
|
156
279
|
data = buffer.get_bytes(length)
|
157
280
|
new(data, type)
|
158
281
|
end
|
159
282
|
|
283
|
+
# Creates a BSON::Binary from a string representation of a UUID.
|
284
|
+
#
|
285
|
+
# The UUID may be given in either 00112233-4455-6677-8899-aabbccddeeff or
|
286
|
+
# 00112233445566778899AABBCCDDEEFF format - specifically, any dashes in
|
287
|
+
# the UUID are removed and both upper and lower case letters are acceptable.
|
288
|
+
#
|
289
|
+
# The input UUID string is always interpreted to be in the RFC 4122 format.
|
290
|
+
#
|
291
|
+
# If representation is not provided, this method creates a BSON::Binary
|
292
|
+
# of subtype 4 (:uuid). If representation is provided, it must be one of
|
293
|
+
# :standard, :csharp_legacy, :java_legacy or :python_legacy. If
|
294
|
+
# representation is :standard, this method creates a subtype 4 (:uuid)
|
295
|
+
# binary which is the same behavior as if representation was not provided.
|
296
|
+
# For other representations, this method creates a Binary of subtype 3
|
297
|
+
# (:uuid_old) with the UUID converted to the appropriate legacy MongoDB
|
298
|
+
# UUID storage format.
|
299
|
+
#
|
300
|
+
# @param [ String ] uuid The string representation of the UUID.
|
301
|
+
# @param [ Symbol ] representation How to interpret the UUID.
|
302
|
+
#
|
303
|
+
# @return [ Binary ] The binary.
|
304
|
+
#
|
305
|
+
# @raise [ ArgumentError ] If invalid representation is requested.
|
306
|
+
#
|
307
|
+
# @api experimental
|
308
|
+
def self.from_uuid(uuid, representation = nil)
|
309
|
+
if representation.is_a?(String)
|
310
|
+
raise ArgumentError, "Representation must be given as a symbol: #{representation}"
|
311
|
+
end
|
312
|
+
uuid_binary = uuid.gsub('-', '').scan(/../).map(&:hex).map(&:chr).join
|
313
|
+
case representation && representation
|
314
|
+
when nil, :standard
|
315
|
+
new(uuid_binary, :uuid)
|
316
|
+
when :csharp_legacy
|
317
|
+
uuid_binary.sub!(/\A(.)(.)(.)(.)(.)(.)(.)(.)(.{8})\z/, '\4\3\2\1\6\5\8\7\9')
|
318
|
+
new(uuid_binary, :uuid_old)
|
319
|
+
when :java_legacy
|
320
|
+
uuid_binary.sub!(/\A(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)\z/) do |m|
|
321
|
+
"#{$8}#{$7}#{$6}#{$5}#{$4}#{$3}#{$2}#{$1}" +
|
322
|
+
"#{$16}#{$15}#{$14}#{$13}#{$12}#{$11}#{$10}#{$9}"
|
323
|
+
end
|
324
|
+
new(uuid_binary, :uuid_old)
|
325
|
+
when :python_legacy
|
326
|
+
new(uuid_binary, :uuid_old)
|
327
|
+
else
|
328
|
+
raise ArgumentError, "Invalid representation: #{representation}"
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
160
332
|
# Raised when providing an invalid type to the Binary.
|
161
333
|
#
|
162
334
|
# @since 2.0.0
|
data/lib/bson/boolean.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2009-
|
1
|
+
# Copyright (C) 2009-2020 MongoDB Inc.
|
2
2
|
#
|
3
3
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
4
|
# you may not use this file except in compliance with the License.
|
@@ -31,13 +31,22 @@ module BSON
|
|
31
31
|
#
|
32
32
|
# @param [ ByteBuffer ] buffer The byte buffer.
|
33
33
|
#
|
34
|
+
# @option options [ nil | :bson ] :mode Decoding mode to use.
|
35
|
+
#
|
34
36
|
# @return [ TrueClass, FalseClass ] The decoded boolean.
|
35
37
|
#
|
36
38
|
# @see http://bsonspec.org/#/specification
|
37
39
|
#
|
38
40
|
# @since 2.0.0
|
39
|
-
def self.from_bson(buffer)
|
40
|
-
buffer.get_byte
|
41
|
+
def self.from_bson(buffer, **options)
|
42
|
+
case v = buffer.get_byte
|
43
|
+
when TrueClass::TRUE_BYTE
|
44
|
+
true
|
45
|
+
when FalseClass::FALSE_BYTE
|
46
|
+
false
|
47
|
+
else
|
48
|
+
raise Error::BSONDecodeError, "Invalid boolean byte value: #{v}"
|
49
|
+
end
|
41
50
|
end
|
42
51
|
|
43
52
|
# Register this type when the module is loaded.
|