bson 4.7.1 → 4.9.1

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 (159) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +2 -1
  4. data/README.md +6 -2
  5. data/ext/bson/bson-endian.h +1 -1
  6. data/ext/bson/bson-native.h +15 -5
  7. data/ext/bson/bytebuf.c +1 -1
  8. data/ext/bson/endian.c +1 -1
  9. data/ext/bson/init.c +26 -3
  10. data/ext/bson/read.c +127 -33
  11. data/ext/bson/util.c +41 -1
  12. data/ext/bson/write.c +18 -14
  13. data/lib/bson.rb +4 -1
  14. data/lib/bson/active_support.rb +1 -1
  15. data/lib/bson/array.rb +34 -5
  16. data/lib/bson/binary.rb +42 -4
  17. data/lib/bson/boolean.rb +12 -3
  18. data/lib/bson/code.rb +16 -2
  19. data/lib/bson/code_with_scope.rb +32 -5
  20. data/lib/bson/config.rb +1 -1
  21. data/lib/bson/date.rb +1 -1
  22. data/lib/bson/date_time.rb +1 -1
  23. data/lib/bson/db_pointer.rb +110 -0
  24. data/lib/bson/decimal128.rb +16 -2
  25. data/lib/bson/decimal128/builder.rb +1 -1
  26. data/lib/bson/document.rb +1 -1
  27. data/lib/bson/environment.rb +2 -1
  28. data/lib/bson/error.rb +21 -0
  29. data/lib/bson/ext_json.rb +375 -0
  30. data/lib/bson/false_class.rb +1 -1
  31. data/lib/bson/float.rb +48 -2
  32. data/lib/bson/hash.rb +36 -5
  33. data/lib/bson/int32.rb +22 -2
  34. data/lib/bson/int64.rb +29 -4
  35. data/lib/bson/integer.rb +35 -1
  36. data/lib/bson/json.rb +1 -1
  37. data/lib/bson/max_key.rb +13 -1
  38. data/lib/bson/min_key.rb +13 -1
  39. data/lib/bson/nil_class.rb +4 -2
  40. data/lib/bson/object.rb +28 -1
  41. data/lib/bson/object_id.rb +16 -2
  42. data/lib/bson/open_struct.rb +1 -1
  43. data/lib/bson/regexp.rb +20 -3
  44. data/lib/bson/registry.rb +1 -1
  45. data/lib/bson/specialized.rb +4 -2
  46. data/lib/bson/string.rb +4 -2
  47. data/lib/bson/symbol.rb +93 -4
  48. data/lib/bson/time.rb +63 -4
  49. data/lib/bson/time_with_zone.rb +1 -1
  50. data/lib/bson/timestamp.rb +16 -2
  51. data/lib/bson/true_class.rb +1 -1
  52. data/lib/bson/undefined.rb +12 -1
  53. data/lib/bson/version.rb +2 -2
  54. data/spec/bson/array_spec.rb +1 -1
  55. data/spec/bson/binary_spec.rb +34 -4
  56. data/spec/bson/binary_uuid_spec.rb +1 -1
  57. data/spec/bson/boolean_spec.rb +1 -1
  58. data/spec/bson/code_spec.rb +1 -1
  59. data/spec/bson/code_with_scope_spec.rb +1 -1
  60. data/spec/bson/date_spec.rb +1 -1
  61. data/spec/bson/date_time_spec.rb +1 -1
  62. data/spec/bson/decimal128_spec.rb +1 -1
  63. data/spec/bson/document_spec.rb +1 -1
  64. data/spec/bson/ext_json_parse_spec.rb +308 -0
  65. data/spec/bson/false_class_spec.rb +1 -1
  66. data/spec/bson/float_spec.rb +37 -1
  67. data/spec/bson/hash_spec.rb +71 -1
  68. data/spec/bson/int32_spec.rb +21 -1
  69. data/spec/bson/int64_spec.rb +39 -1
  70. data/spec/bson/integer_spec.rb +27 -1
  71. data/spec/bson/json_spec.rb +1 -1
  72. data/spec/bson/max_key_spec.rb +1 -1
  73. data/spec/bson/min_key_spec.rb +1 -1
  74. data/spec/bson/nil_class_spec.rb +1 -1
  75. data/spec/bson/object_id_spec.rb +1 -1
  76. data/spec/bson/object_spec.rb +1 -1
  77. data/spec/bson/open_struct_spec.rb +1 -1
  78. data/spec/bson/raw_spec.rb +22 -1
  79. data/spec/bson/regexp_spec.rb +1 -1
  80. data/spec/bson/registry_spec.rb +1 -1
  81. data/spec/bson/string_spec.rb +1 -1
  82. data/spec/bson/symbol_raw_spec.rb +45 -0
  83. data/spec/bson/symbol_spec.rb +61 -1
  84. data/spec/bson/time_spec.rb +205 -2
  85. data/spec/bson/time_with_zone_spec.rb +1 -1
  86. data/spec/bson/timestamp_spec.rb +1 -1
  87. data/spec/bson/true_class_spec.rb +1 -1
  88. data/spec/bson/undefined_spec.rb +1 -1
  89. data/spec/bson_spec.rb +1 -1
  90. data/spec/{support → runners}/common_driver.rb +1 -1
  91. data/spec/runners/corpus.rb +185 -0
  92. data/spec/{support/corpus.rb → runners/corpus_legacy.rb} +41 -59
  93. data/spec/spec_helper.rb +10 -3
  94. data/spec/{bson/driver_bson_spec.rb → spec_tests/common_driver_spec.rb} +1 -0
  95. data/spec/{bson/corpus_spec.rb → spec_tests/corpus_legacy_spec.rb} +4 -4
  96. data/spec/spec_tests/corpus_spec.rb +124 -0
  97. data/spec/spec_tests/data/corpus/README.md +15 -0
  98. data/spec/spec_tests/data/corpus/array.json +49 -0
  99. data/spec/spec_tests/data/corpus/binary.json +85 -0
  100. data/spec/spec_tests/data/corpus/boolean.json +27 -0
  101. data/spec/spec_tests/data/corpus/code.json +67 -0
  102. data/spec/spec_tests/data/corpus/code_w_scope.json +78 -0
  103. data/spec/spec_tests/data/corpus/datetime.json +42 -0
  104. data/spec/spec_tests/data/corpus/dbpointer.json +56 -0
  105. data/spec/spec_tests/data/corpus/dbref.json +31 -0
  106. data/spec/spec_tests/data/corpus/decimal128-1.json +317 -0
  107. data/spec/spec_tests/data/corpus/decimal128-2.json +793 -0
  108. data/spec/spec_tests/data/corpus/decimal128-3.json +1771 -0
  109. data/spec/spec_tests/data/corpus/decimal128-4.json +117 -0
  110. data/spec/spec_tests/data/corpus/decimal128-5.json +402 -0
  111. data/spec/spec_tests/data/corpus/decimal128-6.json +119 -0
  112. data/spec/spec_tests/data/corpus/decimal128-7.json +323 -0
  113. data/spec/spec_tests/data/corpus/document.json +36 -0
  114. data/spec/spec_tests/data/corpus/double.json +87 -0
  115. data/spec/spec_tests/data/corpus/int32.json +43 -0
  116. data/spec/spec_tests/data/corpus/int64.json +43 -0
  117. data/spec/spec_tests/data/corpus/maxkey.json +12 -0
  118. data/spec/spec_tests/data/corpus/minkey.json +12 -0
  119. data/spec/spec_tests/data/corpus/multi-type-deprecated.json +15 -0
  120. data/spec/spec_tests/data/corpus/multi-type.json +11 -0
  121. data/spec/spec_tests/data/corpus/null.json +12 -0
  122. data/spec/spec_tests/data/corpus/oid.json +28 -0
  123. data/spec/spec_tests/data/corpus/regex.json +65 -0
  124. data/spec/spec_tests/data/corpus/string.json +72 -0
  125. data/spec/spec_tests/data/corpus/symbol.json +80 -0
  126. data/spec/spec_tests/data/corpus/timestamp.json +24 -0
  127. data/spec/spec_tests/data/corpus/top.json +236 -0
  128. data/spec/spec_tests/data/corpus/undefined.json +15 -0
  129. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/array.json +0 -0
  130. data/spec/{support/corpus-tests/failures → spec_tests/data/corpus_legacy}/binary.json +0 -0
  131. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/boolean.json +0 -0
  132. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/code.json +1 -1
  133. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/code_w_scope.json +1 -1
  134. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/document.json +1 -1
  135. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/double.json +1 -1
  136. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/failures/datetime.json +0 -0
  137. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/failures/dbpointer.json +0 -0
  138. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/failures/int64.json +0 -0
  139. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/failures/symbol.json +0 -0
  140. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/int32.json +1 -1
  141. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/maxkey.json +1 -1
  142. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/minkey.json +1 -1
  143. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/null.json +1 -1
  144. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/oid.json +0 -0
  145. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/regex.json +1 -1
  146. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/string.json +0 -0
  147. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/timestamp.json +1 -1
  148. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/top.json +0 -0
  149. data/spec/{support/corpus-tests/failures → spec_tests/data/corpus_legacy}/undefined.json +0 -0
  150. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-1.json +0 -0
  151. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-2.json +0 -0
  152. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-3.json +0 -0
  153. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-4.json +0 -0
  154. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-5.json +0 -0
  155. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-6.json +0 -0
  156. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-7.json +0 -0
  157. data/spec/support/shared_examples.rb +1 -1
  158. metadata +176 -102
  159. metadata.gz.sig +0 -0
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (C) 2009-2019 MongoDB, Inc.
2
+ * Copyright (C) 2009-2020 MongoDB Inc.
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -125,40 +125,44 @@ VALUE rb_bson_byte_buffer_put_bytes(VALUE self, VALUE bytes)
125
125
  return self;
126
126
  }
127
127
 
128
- /* write the byte denoting the BSON type for the passed object*/
128
+ /* write the byte denoting the BSON type for the passed object */
129
129
  void pvt_put_type_byte(byte_buffer_t *b, VALUE val){
130
- switch(TYPE(val)){
130
+ char type_byte;
131
+
132
+ switch (TYPE(val)){
131
133
  case T_BIGNUM:
132
134
  case T_FIXNUM:
133
- if(fits_int32(NUM2LL(val))){
134
- pvt_put_byte(b, BSON_TYPE_INT32);
135
- }else{
136
- pvt_put_byte(b, BSON_TYPE_INT64);
135
+ if (fits_int32(NUM2LL(val))) {
136
+ type_byte = BSON_TYPE_INT32;
137
+ } else {
138
+ type_byte = BSON_TYPE_INT64;
137
139
  }
138
140
  break;
139
141
  case T_STRING:
140
- pvt_put_byte(b, BSON_TYPE_STRING);
142
+ type_byte = BSON_TYPE_STRING;
141
143
  break;
142
144
  case T_ARRAY:
143
- pvt_put_byte(b, BSON_TYPE_ARRAY);
145
+ type_byte = BSON_TYPE_ARRAY;
144
146
  break;
145
147
  case T_TRUE:
146
148
  case T_FALSE:
147
- pvt_put_byte(b, BSON_TYPE_BOOLEAN);
149
+ type_byte = BSON_TYPE_BOOLEAN;
148
150
  break;
149
151
  case T_HASH:
150
- pvt_put_byte(b, BSON_TYPE_DOCUMENT);
152
+ type_byte = BSON_TYPE_DOCUMENT;
151
153
  break;
152
154
  case T_FLOAT:
153
- pvt_put_byte(b, BSON_TYPE_DOUBLE);
155
+ type_byte = BSON_TYPE_DOUBLE;
154
156
  break;
155
157
  default:{
156
- VALUE type = rb_funcall(val, rb_intern("bson_type"),0);
158
+ VALUE type = rb_funcall(val, rb_intern("bson_type"), 0);
159
+ type_byte = *RSTRING_PTR(type);
157
160
  RB_GC_GUARD(type);
158
- pvt_put_byte(b, *RSTRING_PTR(type));
159
161
  break;
160
162
  }
161
163
  }
164
+
165
+ pvt_put_byte(b, type_byte);
162
166
  }
163
167
 
164
168
  /**
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2009-2019 MongoDB Inc.
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"
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2018-2019 MongoDB Inc.
1
+ # Copyright (C) 2018-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.
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2009-2019 MongoDB Inc.
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.
@@ -85,26 +85,55 @@ module BSON
85
85
  map { |value| value.to_bson_normalized_value }
86
86
  end
87
87
 
88
+ # Converts this object to a representation directly serializable to
89
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
90
+ #
91
+ # This method recursively invokes +as_extended_json+ with the provided
92
+ # options on each array element.
93
+ #
94
+ # @option opts [ nil | :relaxed | :legacy ] :mode Serialization mode
95
+ # (default is canonical extended JSON)
96
+ #
97
+ # @return [ Array ] This array converted to extended json representation.
98
+ def as_extended_json(**options)
99
+ map do |item|
100
+ item.as_extended_json(**options)
101
+ end
102
+ end
103
+
88
104
  module ClassMethods
89
105
 
90
106
  # Deserialize the array from BSON.
91
107
  #
92
108
  # @param [ ByteBuffer ] buffer The byte buffer.
93
109
  #
110
+ # @option options [ nil | :bson ] :mode Decoding mode to use.
111
+ #
94
112
  # @return [ Array ] The decoded array.
95
113
  #
96
114
  # @see http://bsonspec.org/#/specification
97
115
  #
98
116
  # @since 2.0.0
99
- def from_bson(buffer)
117
+ def from_bson(buffer, **options)
100
118
  if buffer.respond_to?(:get_array)
101
- buffer.get_array
119
+ buffer.get_array(**options)
102
120
  else
103
121
  array = new
104
- buffer.get_int32 # throw away the length
122
+ start_position = buffer.read_position
123
+ expected_byte_size = buffer.get_int32
105
124
  while (type = buffer.get_byte) != NULL_BYTE
106
125
  buffer.get_cstring
107
- array << BSON::Registry.get(type).from_bson(buffer)
126
+ cls = BSON::Registry.get(type)
127
+ value = if options.empty?
128
+ cls.from_bson(buffer)
129
+ else
130
+ cls.from_bson(buffer, **options)
131
+ end
132
+ array << value
133
+ end
134
+ actual_byte_size = buffer.read_position - start_position
135
+ if actual_byte_size != expected_byte_size
136
+ raise Error::BSONDecodeError, "Expected array to take #{expected_byte_size} bytes but it took #{actual_byte_size} bytes"
108
137
  end
109
138
  array
110
139
  end
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2009-2019 MongoDB Inc.
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
 
@@ -94,8 +101,31 @@ module BSON
94
101
  # @return [ Hash ] The binary as a JSON hash.
95
102
  #
96
103
  # @since 2.0.0
104
+ # @deprecated Use as_extended_json instead.
97
105
  def as_json(*args)
98
- { "$binary" => Base64.encode64(data), "$type" => type }
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
99
129
  end
100
130
 
101
131
  # Instantiate the new binary object.
@@ -228,14 +258,22 @@ module BSON
228
258
  #
229
259
  # @param [ ByteBuffer ] buffer The byte buffer.
230
260
  #
261
+ # @option options [ nil | :bson ] :mode Decoding mode to use.
262
+ #
231
263
  # @return [ Binary ] The decoded binary data.
232
264
  #
233
265
  # @see http://bsonspec.org/#/specification
234
266
  #
235
267
  # @since 2.0.0
236
- def self.from_bson(buffer)
268
+ def self.from_bson(buffer, **options)
237
269
  length = buffer.get_int32
238
- type = TYPES[buffer.get_byte]
270
+ type_byte = buffer.get_byte
271
+ type = TYPES[type_byte]
272
+ if type.nil?
273
+ raise Error::UnsupportedBinarySubtype,
274
+ "BSON data contains unsupported binary subtype #{'0x%02x' % type_byte.ord}"
275
+ end
276
+
239
277
  length = buffer.get_int32 if type == :old
240
278
  data = buffer.get_bytes(length)
241
279
  new(data, type)
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2009-2019 MongoDB Inc.
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 == TrueClass::TRUE_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.
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2009-2019 MongoDB Inc.
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.
@@ -55,7 +55,19 @@ module BSON
55
55
  # @return [ Hash ] The code as a JSON hash.
56
56
  #
57
57
  # @since 2.0.0
58
+ # @deprecated Use as_extended_json instead.
58
59
  def as_json(*args)
60
+ as_extended_json
61
+ end
62
+
63
+ # Converts this object to a representation directly serializable to
64
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
65
+ #
66
+ # @option opts [ nil | :relaxed | :legacy ] :mode Serialization mode
67
+ # (default is canonical extended JSON)
68
+ #
69
+ # @return [ Hash ] The extended json representation.
70
+ def as_extended_json(**options)
59
71
  { "$code" => javascript }
60
72
  end
61
73
 
@@ -89,12 +101,14 @@ module BSON
89
101
  #
90
102
  # @param [ ByteBuffer ] buffer The byte buffer.
91
103
  #
104
+ # @option options [ nil | :bson ] :mode Decoding mode to use.
105
+ #
92
106
  # @return [ TrueClass, FalseClass ] The decoded code.
93
107
  #
94
108
  # @see http://bsonspec.org/#/specification
95
109
  #
96
110
  # @since 2.0.0
97
- def self.from_bson(buffer)
111
+ def self.from_bson(buffer, **options)
98
112
  new(buffer.get_string)
99
113
  end
100
114
 
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2009-2019 MongoDB Inc.
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.
@@ -59,8 +59,20 @@ module BSON
59
59
  # @return [ Hash ] The code with scope as a JSON hash.
60
60
  #
61
61
  # @since 2.0.0
62
+ # @deprecated Use as_extended_json instead.
62
63
  def as_json(*args)
63
- { "$code" => javascript, "$scope" => scope }
64
+ as_extended_json
65
+ end
66
+
67
+ # Converts this object to a representation directly serializable to
68
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
69
+ #
70
+ # @option opts [ nil | :relaxed | :legacy ] :mode Serialization mode
71
+ # (default is canonical extended JSON)
72
+ #
73
+ # @return [ Hash ] The extended json representation.
74
+ def as_extended_json(**options)
75
+ { "$code" => javascript, "$scope" => scope.as_extended_json(**options) }
64
76
  end
65
77
 
66
78
  # Instantiate the new code with scope.
@@ -99,14 +111,29 @@ module BSON
99
111
  #
100
112
  # @param [ ByteBuffer ] buffer The byte buffer.
101
113
  #
114
+ # @option options [ nil | :bson ] :mode Decoding mode to use.
115
+ #
102
116
  # @return [ TrueClass, FalseClass ] The decoded code with scope.
103
117
  #
104
118
  # @see http://bsonspec.org/#/specification
105
119
  #
106
120
  # @since 2.0.0
107
- def self.from_bson(buffer)
108
- buffer.get_int32 # Throw away the total length.
109
- new(buffer.get_string, ::Hash.from_bson(buffer))
121
+ def self.from_bson(buffer, **options)
122
+ # Code with scope has a length (?) field which is not needed for
123
+ # decoding, but spec tests want this field validated.
124
+ start_position = buffer.read_position
125
+ length = buffer.get_int32
126
+ javascript = buffer.get_string
127
+ scope = if options.empty?
128
+ ::Hash.from_bson(buffer)
129
+ else
130
+ ::Hash.from_bson(buffer, **options)
131
+ end
132
+ read_bytes = buffer.read_position - start_position
133
+ if read_bytes != length
134
+ raise Error::BSONDecodeError, "CodeWithScope invalid: claimed length #{length}, actual length #{read_bytes}"
135
+ end
136
+ new(javascript, scope)
110
137
  end
111
138
 
112
139
  # Register this type when the module is loaded.
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2016-2019 MongoDB Inc.
1
+ # Copyright (C) 2016-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.
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2009-2019 MongoDB Inc.
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.
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2009-2019 MongoDB Inc.
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.
@@ -0,0 +1,110 @@
1
+ # Copyright (C) 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
+ module BSON
16
+
17
+ # Injects behaviour for encoding and decoding DBPointer values to and from
18
+ # raw bytes as specified by the BSON spec.
19
+ #
20
+ # @see http://bsonspec.org/#/specification
21
+ class DbPointer
22
+ include JSON
23
+
24
+ # A DBPointer is type 0x0C in the BSON spec.
25
+ BSON_TYPE = 0x0C.chr.force_encoding(BINARY).freeze
26
+
27
+ # Create a new DBPointer object.
28
+ #
29
+ # @param [ String ] ref The database collection name.
30
+ # @param [ BSON::ObjectId ] id The DBPointer id.
31
+ def initialize(ref, id)
32
+ @ref = ref
33
+ @id = id
34
+ end
35
+
36
+ # Return the collection name.
37
+ #
38
+ # @return [ String ] The database collection name.
39
+ attr_reader :ref
40
+
41
+ # Return the DbPointer's id.
42
+ #
43
+ # @return [ BSON::ObjectId ] The id of the DbPointer instance
44
+ attr_reader :id
45
+
46
+ # Determine if this DBPointer object is equal to another object.
47
+ #
48
+ # @param [ Object ] other The object to compare against.
49
+ #
50
+ # @return [ true | false ] If the objects are equal
51
+ def ==(other)
52
+ return false unless other.is_a?(DbPointer)
53
+ ref == other.ref && id == other.id
54
+ end
55
+
56
+ # Get the DBPointer as JSON hash data
57
+ #
58
+ # @return [ Hash ] The DBPointer as a JSON hash.
59
+ #
60
+ # @deprecated Use as_extended_json instead.
61
+ def as_json(*args)
62
+ as_extended_json
63
+ end
64
+
65
+ # Converts this object to a representation directly serializable to
66
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
67
+ #
68
+ # @option options [ true | false ] :relaxed Whether to produce relaxed
69
+ # extended JSON representation.
70
+ #
71
+ # @return [ Hash ] The extended json representation.
72
+ def as_extended_json(**options)
73
+ {'$dbPointer' => { "$ref" => ref, '$id' => id.as_extended_json }}
74
+ end
75
+
76
+ # Encode the DBPointer.
77
+ #
78
+ # @return [ BSON::ByteBuffer ] The buffer with the encoded object.
79
+ #
80
+ # @see http://bsonspec.org/#/specification
81
+ def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
82
+ buffer.put_string(ref)
83
+ id.to_bson(buffer, validating_keys)
84
+ buffer
85
+ end
86
+
87
+ # Deserialize a DBPointer from BSON.
88
+ #
89
+ # @param [ ByteBuffer ] buffer The byte buffer.
90
+ # @param [ Hash ] options
91
+ #
92
+ # @option options [ nil | :bson ] :mode Decoding mode to use.
93
+ #
94
+ # @return [ BSON::DbPointer ] The decoded DBPointer.
95
+ #
96
+ # @see http://bsonspec.org/#/specification
97
+ def self.from_bson(buffer, **options)
98
+ ref = buffer.get_string
99
+ id = if options.empty?
100
+ ObjectId.from_bson(buffer)
101
+ else
102
+ ObjectId.from_bson(buffer, **options)
103
+ end
104
+ new(ref, id)
105
+ end
106
+
107
+ # Register this type when the module is loaded.
108
+ Registry.register(BSON_TYPE, self)
109
+ end
110
+ end