bson 4.7.0 → 4.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (159) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -2
  3. data/ext/bson/bson-endian.h +1 -1
  4. data/ext/bson/bson-native.h +16 -5
  5. data/ext/bson/bytebuf.c +1 -1
  6. data/ext/bson/endian.c +2 -1
  7. data/ext/bson/init.c +26 -3
  8. data/ext/bson/read.c +127 -33
  9. data/ext/bson/util.c +41 -1
  10. data/ext/bson/write.c +18 -14
  11. data/lib/bson.rb +4 -1
  12. data/lib/bson/active_support.rb +1 -1
  13. data/lib/bson/array.rb +34 -5
  14. data/lib/bson/binary.rb +42 -4
  15. data/lib/bson/boolean.rb +12 -3
  16. data/lib/bson/code.rb +16 -2
  17. data/lib/bson/code_with_scope.rb +32 -5
  18. data/lib/bson/config.rb +1 -1
  19. data/lib/bson/date.rb +1 -1
  20. data/lib/bson/date_time.rb +1 -1
  21. data/lib/bson/db_pointer.rb +110 -0
  22. data/lib/bson/decimal128.rb +16 -2
  23. data/lib/bson/decimal128/builder.rb +1 -1
  24. data/lib/bson/document.rb +1 -1
  25. data/lib/bson/environment.rb +2 -1
  26. data/lib/bson/error.rb +21 -0
  27. data/lib/bson/ext_json.rb +375 -0
  28. data/lib/bson/false_class.rb +1 -1
  29. data/lib/bson/float.rb +48 -2
  30. data/lib/bson/hash.rb +36 -5
  31. data/lib/bson/int32.rb +22 -2
  32. data/lib/bson/int64.rb +29 -4
  33. data/lib/bson/integer.rb +35 -1
  34. data/lib/bson/json.rb +1 -1
  35. data/lib/bson/max_key.rb +13 -1
  36. data/lib/bson/min_key.rb +13 -1
  37. data/lib/bson/nil_class.rb +4 -2
  38. data/lib/bson/object.rb +28 -1
  39. data/lib/bson/object_id.rb +16 -2
  40. data/lib/bson/open_struct.rb +1 -1
  41. data/lib/bson/regexp.rb +20 -3
  42. data/lib/bson/registry.rb +1 -1
  43. data/lib/bson/specialized.rb +4 -2
  44. data/lib/bson/string.rb +4 -2
  45. data/lib/bson/symbol.rb +93 -4
  46. data/lib/bson/time.rb +63 -4
  47. data/lib/bson/time_with_zone.rb +1 -1
  48. data/lib/bson/timestamp.rb +16 -2
  49. data/lib/bson/true_class.rb +1 -1
  50. data/lib/bson/undefined.rb +12 -1
  51. data/lib/bson/version.rb +2 -2
  52. data/spec/bson/array_spec.rb +1 -1
  53. data/spec/bson/binary_spec.rb +34 -4
  54. data/spec/bson/binary_uuid_spec.rb +1 -1
  55. data/spec/bson/boolean_spec.rb +1 -1
  56. data/spec/bson/code_spec.rb +1 -1
  57. data/spec/bson/code_with_scope_spec.rb +1 -1
  58. data/spec/bson/date_spec.rb +1 -1
  59. data/spec/bson/date_time_spec.rb +1 -1
  60. data/spec/bson/decimal128_spec.rb +1 -1
  61. data/spec/bson/document_spec.rb +1 -1
  62. data/spec/bson/ext_json_parse_spec.rb +308 -0
  63. data/spec/bson/false_class_spec.rb +1 -1
  64. data/spec/bson/float_spec.rb +37 -1
  65. data/spec/bson/hash_spec.rb +71 -1
  66. data/spec/bson/int32_spec.rb +21 -1
  67. data/spec/bson/int64_spec.rb +39 -1
  68. data/spec/bson/integer_spec.rb +27 -1
  69. data/spec/bson/json_spec.rb +1 -1
  70. data/spec/bson/max_key_spec.rb +1 -1
  71. data/spec/bson/min_key_spec.rb +1 -1
  72. data/spec/bson/nil_class_spec.rb +1 -1
  73. data/spec/bson/object_id_spec.rb +1 -1
  74. data/spec/bson/object_spec.rb +1 -1
  75. data/spec/bson/open_struct_spec.rb +1 -1
  76. data/spec/bson/raw_spec.rb +22 -1
  77. data/spec/bson/regexp_spec.rb +1 -1
  78. data/spec/bson/registry_spec.rb +1 -1
  79. data/spec/bson/string_spec.rb +1 -1
  80. data/spec/bson/symbol_raw_spec.rb +45 -0
  81. data/spec/bson/symbol_spec.rb +61 -1
  82. data/spec/bson/time_spec.rb +205 -2
  83. data/spec/bson/time_with_zone_spec.rb +1 -1
  84. data/spec/bson/timestamp_spec.rb +1 -1
  85. data/spec/bson/true_class_spec.rb +1 -1
  86. data/spec/bson/undefined_spec.rb +1 -1
  87. data/spec/bson_spec.rb +1 -1
  88. data/spec/{support → runners}/common_driver.rb +1 -1
  89. data/spec/runners/corpus.rb +185 -0
  90. data/spec/{support/corpus.rb → runners/corpus_legacy.rb} +41 -59
  91. data/spec/spec_helper.rb +10 -3
  92. data/spec/{bson/driver_bson_spec.rb → spec_tests/common_driver_spec.rb} +1 -0
  93. data/spec/{bson/corpus_spec.rb → spec_tests/corpus_legacy_spec.rb} +4 -4
  94. data/spec/spec_tests/corpus_spec.rb +124 -0
  95. data/spec/spec_tests/data/corpus/README.md +15 -0
  96. data/spec/spec_tests/data/corpus/array.json +49 -0
  97. data/spec/spec_tests/data/corpus/binary.json +85 -0
  98. data/spec/spec_tests/data/corpus/boolean.json +27 -0
  99. data/spec/spec_tests/data/corpus/code.json +67 -0
  100. data/spec/spec_tests/data/corpus/code_w_scope.json +78 -0
  101. data/spec/spec_tests/data/corpus/datetime.json +42 -0
  102. data/spec/spec_tests/data/corpus/dbpointer.json +56 -0
  103. data/spec/spec_tests/data/corpus/dbref.json +31 -0
  104. data/spec/spec_tests/data/corpus/decimal128-1.json +317 -0
  105. data/spec/spec_tests/data/corpus/decimal128-2.json +793 -0
  106. data/spec/spec_tests/data/corpus/decimal128-3.json +1771 -0
  107. data/spec/spec_tests/data/corpus/decimal128-4.json +117 -0
  108. data/spec/spec_tests/data/corpus/decimal128-5.json +402 -0
  109. data/spec/spec_tests/data/corpus/decimal128-6.json +119 -0
  110. data/spec/spec_tests/data/corpus/decimal128-7.json +323 -0
  111. data/spec/spec_tests/data/corpus/document.json +36 -0
  112. data/spec/spec_tests/data/corpus/double.json +87 -0
  113. data/spec/spec_tests/data/corpus/int32.json +43 -0
  114. data/spec/spec_tests/data/corpus/int64.json +43 -0
  115. data/spec/spec_tests/data/corpus/maxkey.json +12 -0
  116. data/spec/spec_tests/data/corpus/minkey.json +12 -0
  117. data/spec/spec_tests/data/corpus/multi-type-deprecated.json +15 -0
  118. data/spec/spec_tests/data/corpus/multi-type.json +11 -0
  119. data/spec/spec_tests/data/corpus/null.json +12 -0
  120. data/spec/spec_tests/data/corpus/oid.json +28 -0
  121. data/spec/spec_tests/data/corpus/regex.json +65 -0
  122. data/spec/spec_tests/data/corpus/string.json +72 -0
  123. data/spec/spec_tests/data/corpus/symbol.json +80 -0
  124. data/spec/spec_tests/data/corpus/timestamp.json +24 -0
  125. data/spec/spec_tests/data/corpus/top.json +236 -0
  126. data/spec/spec_tests/data/corpus/undefined.json +15 -0
  127. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/array.json +0 -0
  128. data/spec/{support/corpus-tests/failures → spec_tests/data/corpus_legacy}/binary.json +0 -0
  129. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/boolean.json +0 -0
  130. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/code.json +1 -1
  131. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/code_w_scope.json +1 -1
  132. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/document.json +1 -1
  133. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/double.json +1 -1
  134. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/failures/datetime.json +0 -0
  135. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/failures/dbpointer.json +0 -0
  136. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/failures/int64.json +0 -0
  137. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/failures/symbol.json +0 -0
  138. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/int32.json +1 -1
  139. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/maxkey.json +1 -1
  140. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/minkey.json +1 -1
  141. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/null.json +1 -1
  142. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/oid.json +0 -0
  143. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/regex.json +1 -1
  144. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/string.json +0 -0
  145. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/timestamp.json +1 -1
  146. data/spec/{support/corpus-tests → spec_tests/data/corpus_legacy}/top.json +0 -0
  147. data/spec/{support/corpus-tests/failures → spec_tests/data/corpus_legacy}/undefined.json +0 -0
  148. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-1.json +0 -0
  149. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-2.json +0 -0
  150. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-3.json +0 -0
  151. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-4.json +0 -0
  152. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-5.json +0 -0
  153. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-6.json +0 -0
  154. data/spec/{support/driver-spec-tests → spec_tests/data}/decimal128/decimal128-7.json +0 -0
  155. data/spec/support/shared_examples.rb +1 -1
  156. metadata +172 -120
  157. checksums.yaml.gz.sig +0 -0
  158. data.tar.gz.sig +0 -1
  159. metadata.gz.sig +0 -1
@@ -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