bson 4.9.0 → 4.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +15 -6
  4. data/ext/bson/bson-native.h +4 -0
  5. data/ext/bson/init.c +75 -23
  6. data/ext/bson/read.c +63 -11
  7. data/ext/bson/write.c +42 -3
  8. data/lib/bson/active_support.rb +1 -0
  9. data/lib/bson/array.rb +5 -1
  10. data/lib/bson/big_decimal.rb +67 -0
  11. data/lib/bson/binary.rb +8 -5
  12. data/lib/bson/boolean.rb +2 -1
  13. data/lib/bson/code.rb +2 -1
  14. data/lib/bson/code_with_scope.rb +2 -1
  15. data/lib/bson/config.rb +1 -0
  16. data/lib/bson/date.rb +1 -0
  17. data/lib/bson/date_time.rb +2 -1
  18. data/lib/bson/db_pointer.rb +2 -1
  19. data/lib/bson/dbref.rb +152 -0
  20. data/lib/bson/decimal128/builder.rb +27 -20
  21. data/lib/bson/decimal128.rb +39 -14
  22. data/lib/bson/document.rb +61 -18
  23. data/lib/bson/environment.rb +1 -0
  24. data/lib/bson/error.rb +13 -0
  25. data/lib/bson/ext_json.rb +24 -11
  26. data/lib/bson/false_class.rb +2 -1
  27. data/lib/bson/float.rb +21 -32
  28. data/lib/bson/hash.rb +18 -6
  29. data/lib/bson/int32.rb +3 -2
  30. data/lib/bson/int64.rb +3 -2
  31. data/lib/bson/integer.rb +3 -2
  32. data/lib/bson/json.rb +1 -0
  33. data/lib/bson/max_key.rb +3 -2
  34. data/lib/bson/min_key.rb +3 -2
  35. data/lib/bson/nil_class.rb +2 -1
  36. data/lib/bson/object.rb +1 -0
  37. data/lib/bson/object_id.rb +4 -3
  38. data/lib/bson/open_struct.rb +1 -0
  39. data/lib/bson/regexp.rb +24 -7
  40. data/lib/bson/registry.rb +1 -0
  41. data/lib/bson/specialized.rb +1 -0
  42. data/lib/bson/string.rb +3 -2
  43. data/lib/bson/symbol.rb +2 -1
  44. data/lib/bson/time.rb +4 -3
  45. data/lib/bson/time_with_zone.rb +1 -0
  46. data/lib/bson/timestamp.rb +7 -6
  47. data/lib/bson/true_class.rb +2 -1
  48. data/lib/bson/undefined.rb +2 -1
  49. data/lib/bson/version.rb +2 -1
  50. data/lib/bson.rb +8 -5
  51. data/spec/README.md +14 -0
  52. data/spec/bson/array_spec.rb +17 -0
  53. data/spec/bson/big_decimal_spec.rb +316 -0
  54. data/spec/bson/binary_spec.rb +1 -1
  55. data/spec/bson/binary_uuid_spec.rb +12 -0
  56. data/spec/bson/byte_buffer_read_spec.rb +59 -3
  57. data/spec/bson/byte_buffer_spec.rb +129 -6
  58. data/spec/bson/byte_buffer_write_spec.rb +96 -0
  59. data/spec/bson/date_time_spec.rb +53 -0
  60. data/spec/bson/dbref_legacy_spec.rb +169 -0
  61. data/spec/bson/dbref_spec.rb +487 -0
  62. data/spec/bson/decimal128_spec.rb +231 -0
  63. data/spec/bson/document_as_spec.rb +46 -0
  64. data/spec/bson/document_spec.rb +43 -1
  65. data/spec/bson/ext_json_parse_spec.rb +37 -0
  66. data/spec/bson/hash_as_spec.rb +57 -0
  67. data/spec/bson/hash_spec.rb +105 -0
  68. data/spec/bson/int64_spec.rb +4 -24
  69. data/spec/bson/raw_spec.rb +18 -1
  70. data/spec/bson/regexp_spec.rb +52 -0
  71. data/spec/runners/common_driver.rb +1 -1
  72. data/spec/shared/LICENSE +20 -0
  73. data/spec/shared/bin/get-mongodb-download-url +17 -0
  74. data/spec/shared/bin/s3-copy +45 -0
  75. data/spec/shared/bin/s3-upload +69 -0
  76. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  77. data/spec/shared/lib/mrss/cluster_config.rb +231 -0
  78. data/spec/shared/lib/mrss/constraints.rb +386 -0
  79. data/spec/shared/lib/mrss/docker_runner.rb +271 -0
  80. data/spec/shared/lib/mrss/event_subscriber.rb +200 -0
  81. data/spec/shared/lib/mrss/lite_constraints.rb +191 -0
  82. data/spec/shared/lib/mrss/server_version_registry.rb +120 -0
  83. data/spec/shared/lib/mrss/spec_organizer.rb +179 -0
  84. data/spec/shared/lib/mrss/utils.rb +15 -0
  85. data/spec/shared/share/Dockerfile.erb +338 -0
  86. data/spec/shared/share/haproxy-1.conf +16 -0
  87. data/spec/shared/share/haproxy-2.conf +17 -0
  88. data/spec/shared/shlib/distro.sh +74 -0
  89. data/spec/shared/shlib/server.sh +367 -0
  90. data/spec/shared/shlib/set_env.sh +131 -0
  91. data/spec/spec_helper.rb +31 -0
  92. data/spec/spec_tests/common_driver_spec.rb +2 -1
  93. data/spec/spec_tests/data/corpus/binary.json +33 -0
  94. data/spec/spec_tests/data/corpus/dbref.json +21 -1
  95. data/spec/spec_tests/data/corpus/document.json +4 -0
  96. data/spec/spec_tests/data/corpus/regex.json +2 -2
  97. data/spec/spec_tests/data/corpus/timestamp.json +10 -0
  98. data/spec/spec_tests/data/corpus/top.json +23 -12
  99. data/spec/support/spec_config.rb +8 -1
  100. data.tar.gz.sig +0 -0
  101. metadata +168 -93
  102. metadata.gz.sig +1 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 05c17fcaee2ceaefe97d801594460178acaf6a2f82c152ce33db819f01d624fa
4
- data.tar.gz: 3343dfda6f4038fa261d077ddf860dd43ff001d2fbea7189110b6fa500fb2558
3
+ metadata.gz: 3d0c420e8204cb354acfc6adadb5097b71f4a8346620a5461153c6461aece1e2
4
+ data.tar.gz: ce5e7172180e7e9f5c60d2af3207b50e0ead96283d36828e75a118cc53cdd7fa
5
5
  SHA512:
6
- metadata.gz: 7756cee7923f3ca584e6a1bfa3666f70d2f14804b3ddb913f0695be3495a061a632803a90d1cd87a63c95d5b9222c02b18fe475a38e2a8a680914819f90f4471
7
- data.tar.gz: 88bf0b45ecbe2aa47c955ca5281568cbe6d48a4c144a5b49680f6f7d8684fa61524dcc80474118c12e9df13b6bfc4ffca1a0d0e55679c0325dcdfd48543aab96
6
+ metadata.gz: 990f1be935132660ad51dab98c9233e12f9af5d03eac5f52a5bef82a78af2d258c12721564bfaf042977766c65d9adc7dbc7d88241283207213fe9ac15c9a024
7
+ data.tar.gz: 8004b3cd0e51a769df76fd9027058f403efe6b5a565eff39aca3e43f700f0b77a7a670793dfb043d0cf963537eda0426e8a885dd4044adc2800934beaeb59286
checksums.yaml.gz.sig ADDED
Binary file
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
- BSON [![Build Status](https://secure.travis-ci.org/mongodb/bson-ruby.svg?branch=master)](http://travis-ci.org/mongodb/bson-ruby)
2
- [![Build status Windows](https://ci.appveyor.com/api/projects/status/p5aqko7umsx351nm?svg=true)](https://ci.appveyor.com/project/p-mongo/bson-ruby/branch/master)
3
- [![Code Climate](https://codeclimate.com/github/mongodb/bson-ruby.svg)](https://codeclimate.com/github/mongodb/bson-ruby)
4
- [![Coverage Status](https://coveralls.io/repos/mongodb/bson-ruby/badge.svg?branch=master)](https://coveralls.io/r/mongodb/bson-ruby?branch=master)
5
- [![Inline docs](http://inch-ci.org/github/mongodb/bson-ruby.svg?branch=master)](http://inch-ci.org/github/mongodb/bson-ruby)
1
+ BSON
2
+ [![Gem Version][rubygems-img]][rubygems-url]
3
+ [![Build Status][ghactions-img]][ghactions-url]
4
+ [![Coverage Status][coveralls-img]][coveralls-url]
5
+ [![Inline docs][inch-img]][inch-url]
6
6
  ====
7
7
 
8
8
  An implementation of the BSON specification in Ruby.
@@ -10,7 +10,7 @@ An implementation of the BSON specification in Ruby.
10
10
  Compatibility
11
11
  -------------
12
12
 
13
- BSON is tested against MRI (2.3+) and JRuby (9.2+).
13
+ BSON is tested against MRI (2.5) and JRuby (9.2+).
14
14
 
15
15
  Documentation
16
16
  -------------
@@ -51,3 +51,12 @@ distributed under the License is distributed on an "AS IS" BASIS,
51
51
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
52
52
  See the License for the specific language governing permissions and
53
53
  limitations under the License.
54
+
55
+ [rubygems-img]: https://badge.fury.io/rb/bson.svg
56
+ [rubygems-url]: http://badge.fury.io/rb/bson
57
+ [ghactions-img]: https://github.com/mongodb/bson-ruby/actions/workflows/bson-ruby.yml/badge.svg?query=branch%3Amaster
58
+ [ghactions-url]: https://github.com/mongodb/bson-ruby/actions/workflows/bson-ruby.yml?query=branch%3Amaster
59
+ [coveralls-img]: https://coveralls.io/repos/mongodb/bson-ruby/badge.svg?branch=master
60
+ [coveralls-url]: https://coveralls.io/r/mongodb/bson-ruby?branch=master
61
+ [inch-img]: http://inch-ci.org/github/mongodb/bson-ruby.svg?branch=master
62
+ [inch-url]: http://inch-ci.org/github/mongodb/bson-ruby
@@ -76,6 +76,7 @@ VALUE rb_bson_byte_buffer_get_cstring(VALUE self);
76
76
  VALUE rb_bson_byte_buffer_get_decimal128_bytes(VALUE self);
77
77
  VALUE rb_bson_byte_buffer_get_double(VALUE self);
78
78
  VALUE rb_bson_byte_buffer_get_int32(VALUE self);
79
+ VALUE rb_bson_byte_buffer_get_uint32(VALUE self);
79
80
  VALUE rb_bson_byte_buffer_get_int64(VALUE self);
80
81
  VALUE rb_bson_byte_buffer_get_string(VALUE self);
81
82
  VALUE rb_bson_byte_buffer_get_hash(int argc, VALUE *argv, VALUE self);
@@ -86,6 +87,7 @@ VALUE rb_bson_byte_buffer_put_cstring(VALUE self, VALUE string);
86
87
  VALUE rb_bson_byte_buffer_put_decimal128(VALUE self, VALUE low, VALUE high);
87
88
  VALUE rb_bson_byte_buffer_put_double(VALUE self, VALUE f);
88
89
  VALUE rb_bson_byte_buffer_put_int32(VALUE self, VALUE i);
90
+ VALUE rb_bson_byte_buffer_put_uint32(VALUE self, VALUE i);
89
91
  VALUE rb_bson_byte_buffer_put_int64(VALUE self, VALUE i);
90
92
  VALUE rb_bson_byte_buffer_put_string(VALUE self, VALUE string);
91
93
  VALUE rb_bson_byte_buffer_put_symbol(VALUE self, VALUE symbol);
@@ -121,3 +123,5 @@ extern VALUE rb_bson_registry;
121
123
  extern VALUE rb_bson_illegal_key;
122
124
 
123
125
  extern const rb_data_type_t rb_byte_buffer_data_type;
126
+
127
+ extern VALUE _ref_str, _id_str, _db_str;
data/ext/bson/init.c CHANGED
@@ -30,6 +30,8 @@ const rb_data_type_t rb_byte_buffer_data_type = {
30
30
  { NULL, rb_bson_byte_buffer_free, rb_bson_byte_buffer_memsize }
31
31
  };
32
32
 
33
+ VALUE _ref_str, _id_str, _db_str;
34
+
33
35
  /**
34
36
  * Initialize the bson_native extension.
35
37
  */
@@ -37,26 +39,44 @@ void Init_bson_native()
37
39
  {
38
40
  char rb_bson_machine_id[256];
39
41
 
42
+ _ref_str = rb_str_new_cstr("$ref");
43
+ rb_gc_register_mark_object(_ref_str);
44
+ _id_str = rb_str_new_cstr("$id");
45
+ rb_gc_register_mark_object(_id_str);
46
+ _db_str = rb_str_new_cstr("$db");
47
+ rb_gc_register_mark_object(_db_str);
48
+
40
49
  VALUE rb_bson_module = rb_define_module("BSON");
41
-
50
+
42
51
  /* Document-class: BSON::ByteBuffer
43
52
  *
44
53
  * Stores BSON-serialized data and provides efficient serialization and
45
54
  * deserialization of common Ruby classes using native code.
46
55
  */
47
56
  VALUE rb_byte_buffer_class = rb_define_class_under(rb_bson_module, "ByteBuffer", rb_cObject);
48
-
57
+
49
58
  VALUE rb_bson_object_id_class = rb_const_get(rb_bson_module, rb_intern("ObjectId"));
50
59
  VALUE rb_bson_object_id_generator_class = rb_const_get(rb_bson_object_id_class, rb_intern("Generator"));
51
60
  VALUE rb_digest_class = rb_const_get(rb_cObject, rb_intern("Digest"));
52
61
  VALUE rb_md5_class = rb_const_get(rb_digest_class, rb_intern("MD5"));
53
62
 
54
63
  rb_bson_illegal_key = rb_const_get(rb_const_get(rb_bson_module, rb_intern("String")),rb_intern("IllegalKey"));
64
+ rb_gc_register_mark_object(rb_bson_illegal_key);
55
65
 
56
66
  rb_define_alloc_func(rb_byte_buffer_class, rb_bson_byte_buffer_allocate);
57
67
  rb_define_method(rb_byte_buffer_class, "initialize", rb_bson_byte_buffer_initialize, -1);
68
+
69
+ /*
70
+ * call-seq:
71
+ * buffer.length -> Fixnum
72
+ *
73
+ * Returns the number of bytes available to be read in the buffer.
74
+ *
75
+ * When a buffer is being written to, each added byte increases its length.
76
+ * When a buffer is being read from, each read byte decreases its length.
77
+ */
58
78
  rb_define_method(rb_byte_buffer_class, "length", rb_bson_byte_buffer_length, 0);
59
-
79
+
60
80
  /*
61
81
  * call-seq:
62
82
  * buffer.read_position -> Fixnum
@@ -64,13 +84,13 @@ void Init_bson_native()
64
84
  * Returns the read position in the buffer.
65
85
  */
66
86
  rb_define_method(rb_byte_buffer_class, "read_position", rb_bson_byte_buffer_read_position, 0);
67
-
87
+
68
88
  rb_define_method(rb_byte_buffer_class, "get_byte", rb_bson_byte_buffer_get_byte, 0);
69
89
  rb_define_method(rb_byte_buffer_class, "get_bytes", rb_bson_byte_buffer_get_bytes, 1);
70
90
  rb_define_method(rb_byte_buffer_class, "get_cstring", rb_bson_byte_buffer_get_cstring, 0);
71
91
  rb_define_method(rb_byte_buffer_class, "get_decimal128_bytes", rb_bson_byte_buffer_get_decimal128_bytes, 0);
72
92
  rb_define_method(rb_byte_buffer_class, "get_double", rb_bson_byte_buffer_get_double, 0);
73
-
93
+
74
94
  /*
75
95
  * call-seq:
76
96
  * buffer.get_hash(**options) -> Hash
@@ -82,23 +102,35 @@ void Init_bson_native()
82
102
  * @return [ BSON::Document ] The decoded document.
83
103
  */
84
104
  rb_define_method(rb_byte_buffer_class, "get_hash", rb_bson_byte_buffer_get_hash, -1);
85
-
105
+
86
106
  /*
87
107
  * call-seq:
88
108
  * buffer.get_array(**options) -> Array
89
109
  *
90
- * Reads an array from the byte buffer..
110
+ * Reads an array from the byte buffer.
91
111
  *
92
112
  * @option options [ nil | :bson ] :mode Decoding mode to use.
93
113
  *
94
114
  * @return [ Array ] The decoded array.
95
115
  */
96
116
  rb_define_method(rb_byte_buffer_class, "get_array", rb_bson_byte_buffer_get_array, -1);
97
-
117
+
98
118
  rb_define_method(rb_byte_buffer_class, "get_int32", rb_bson_byte_buffer_get_int32, 0);
119
+
120
+ /*
121
+ * call-seq:
122
+ * buffer.get_uint32(buffer) -> Fixnum
123
+ *
124
+ * Reads an unsigned 32 bit number from the byte buffer.
125
+ *
126
+ * @return [ Fixnum ] The unsigned 32 bits integer from the buffer
127
+ *
128
+ * @api private
129
+ */
130
+ rb_define_method(rb_byte_buffer_class, "get_uint32", rb_bson_byte_buffer_get_uint32, 0);
99
131
  rb_define_method(rb_byte_buffer_class, "get_int64", rb_bson_byte_buffer_get_int64, 0);
100
132
  rb_define_method(rb_byte_buffer_class, "get_string", rb_bson_byte_buffer_get_string, 0);
101
-
133
+
102
134
  /*
103
135
  * call-seq:
104
136
  * buffer.write_position -> Fixnum
@@ -106,7 +138,7 @@ void Init_bson_native()
106
138
  * Returns the write position in the buffer.
107
139
  */
108
140
  rb_define_method(rb_byte_buffer_class, "write_position", rb_bson_byte_buffer_write_position, 0);
109
-
141
+
110
142
  /*
111
143
  * call-seq:
112
144
  * buffer.put_byte(binary_str) -> ByteBuffer
@@ -117,7 +149,7 @@ void Init_bson_native()
117
149
  * Returns the modified +self+.
118
150
  */
119
151
  rb_define_method(rb_byte_buffer_class, "put_byte", rb_bson_byte_buffer_put_byte, 1);
120
-
152
+
121
153
  /*
122
154
  * call-seq:
123
155
  * buffer.put_bytes(binary_str) -> ByteBuffer
@@ -170,7 +202,7 @@ void Init_bson_native()
170
202
  * instead on the null terminator), unlike the BSON string serialization.
171
203
  */
172
204
  rb_define_method(rb_byte_buffer_class, "put_cstring", rb_bson_byte_buffer_put_cstring, 1);
173
-
205
+
174
206
  /**
175
207
  * call-seq:
176
208
  * buffer.put_symbol(sym) -> ByteBuffer
@@ -188,7 +220,7 @@ void Init_bson_native()
188
220
  * indistinguishable from a string with the same value written to the buffer.
189
221
  */
190
222
  rb_define_method(rb_byte_buffer_class, "put_symbol", rb_bson_byte_buffer_put_symbol, 1);
191
-
223
+
192
224
  /*
193
225
  * call-seq:
194
226
  * buffer.put_int32(fixnum) -> ByteBuffer
@@ -200,7 +232,22 @@ void Init_bson_native()
200
232
  * Returns the modified +self+.
201
233
  */
202
234
  rb_define_method(rb_byte_buffer_class, "put_int32", rb_bson_byte_buffer_put_int32, 1);
203
-
235
+
236
+ /*
237
+ * call-seq:
238
+ * buffer.put_uint32(fixnum) -> ByteBuffer
239
+ *
240
+ * Writes an unsigned 32-bit integer value to the buffer.
241
+ *
242
+ * If the argument cannot be represented in 32 bits, raises RangeError.
243
+ *
244
+ * Returns the modified +self+.
245
+ *
246
+ * @api private
247
+ *
248
+ */
249
+ rb_define_method(rb_byte_buffer_class, "put_uint32", rb_bson_byte_buffer_put_uint32, 1);
250
+
204
251
  /*
205
252
  * call-seq:
206
253
  * buffer.put_int64(fixnum) -> ByteBuffer
@@ -212,7 +259,7 @@ void Init_bson_native()
212
259
  * Returns the modified +self+.
213
260
  */
214
261
  rb_define_method(rb_byte_buffer_class, "put_int64", rb_bson_byte_buffer_put_int64, 1);
215
-
262
+
216
263
  /*
217
264
  * call-seq:
218
265
  * buffer.put_double(double) -> ByteBuffer
@@ -222,7 +269,7 @@ void Init_bson_native()
222
269
  * Returns the modified +self+.
223
270
  */
224
271
  rb_define_method(rb_byte_buffer_class, "put_double", rb_bson_byte_buffer_put_double, 1);
225
-
272
+
226
273
  /*
227
274
  * call-seq:
228
275
  * buffer.put_decimal128(low_64bit, high_64bit) -> ByteBuffer
@@ -235,17 +282,17 @@ void Init_bson_native()
235
282
  * Returns the modified +self+.
236
283
  */
237
284
  rb_define_method(rb_byte_buffer_class, "put_decimal128", rb_bson_byte_buffer_put_decimal128, 2);
238
-
285
+
239
286
  /*
240
287
  * call-seq:
241
- * buffer.put_hash(hash) -> ByteBuffer
288
+ * buffer.put_hash(hash, validating_keys) -> ByteBuffer
242
289
  *
243
290
  * Writes a Hash into the byte buffer.
244
291
  *
245
292
  * Returns the modified +self+.
246
293
  */
247
294
  rb_define_method(rb_byte_buffer_class, "put_hash", rb_bson_byte_buffer_put_hash, 2);
248
-
295
+
249
296
  /*
250
297
  * call-seq:
251
298
  * buffer.put_array(array) -> ByteBuffer
@@ -255,7 +302,7 @@ void Init_bson_native()
255
302
  * Returns the modified +self+.
256
303
  */
257
304
  rb_define_method(rb_byte_buffer_class, "put_array", rb_bson_byte_buffer_put_array, 2);
258
-
305
+
259
306
  /*
260
307
  * call-seq:
261
308
  * buffer.replace_int32(position, fixnum) -> ByteBuffer
@@ -272,7 +319,7 @@ void Init_bson_native()
272
319
  * Returns the modified +self+.
273
320
  */
274
321
  rb_define_method(rb_byte_buffer_class, "replace_int32", rb_bson_byte_buffer_replace_int32, 2);
275
-
322
+
276
323
  /*
277
324
  * call-seq:
278
325
  * buffer.rewind! -> ByteBuffer
@@ -284,19 +331,23 @@ void Init_bson_native()
284
331
  * Returns the modified +self+.
285
332
  */
286
333
  rb_define_method(rb_byte_buffer_class, "rewind!", rb_bson_byte_buffer_rewind, 0);
287
-
334
+
288
335
  /*
289
336
  * call-seq:
290
337
  * buffer.to_s -> String
291
338
  *
292
339
  * Returns the contents of the buffer as a binary string.
293
340
  *
341
+ * If the buffer is used for reading, the returned contents is the data
342
+ * that was not yet read. If the buffer is used for writing, the returned
343
+ * contents is the complete data that has been written so far.
344
+ *
294
345
  * Note: this method copies the buffer's contents into a newly allocated
295
346
  * +String+ instance. It does not return a reference to the data stored in
296
347
  * the buffer itself.
297
348
  */
298
349
  rb_define_method(rb_byte_buffer_class, "to_s", rb_bson_byte_buffer_to_s, 0);
299
-
350
+
300
351
  rb_define_method(rb_bson_object_id_generator_class, "next_object_id", rb_bson_object_id_generator_next, -1);
301
352
 
302
353
  // Get the object id machine id and hash it.
@@ -309,4 +360,5 @@ void Init_bson_native()
309
360
  rb_bson_object_id_counter = FIX2INT(rb_funcall(rb_mKernel, rb_intern("rand"), 1, INT2FIX(0x1000000)));
310
361
 
311
362
  rb_bson_registry = rb_const_get(rb_bson_module, rb_intern("Registry"));
363
+ rb_gc_register_mark_object(rb_bson_registry);
312
364
  }
data/ext/bson/read.c CHANGED
@@ -21,6 +21,7 @@ static void pvt_raise_decode_error(volatile VALUE msg);
21
21
  static int32_t pvt_validate_length(byte_buffer_t *b);
22
22
  static uint8_t pvt_get_type_byte(byte_buffer_t *b);
23
23
  static VALUE pvt_get_int32(byte_buffer_t *b);
24
+ static VALUE pvt_get_uint32(byte_buffer_t *b);
24
25
  static VALUE pvt_get_int64(byte_buffer_t *b, int argc, VALUE *argv);
25
26
  static VALUE pvt_get_double(byte_buffer_t *b);
26
27
  static VALUE pvt_get_string(byte_buffer_t *b, const char *data_type);
@@ -41,12 +42,12 @@ void pvt_raise_decode_error(volatile VALUE msg) {
41
42
  int32_t pvt_validate_length(byte_buffer_t *b)
42
43
  {
43
44
  int32_t length;
44
-
45
+
45
46
  ENSURE_BSON_READ(b, 4);
46
47
  memcpy(&length, READ_PTR(b), 4);
47
48
  length = BSON_UINT32_TO_LE(length);
48
49
 
49
- /* minimum valid length is 4 (byte count) + 1 (terminating byte) */
50
+ /* minimum valid length is 4 (byte count) + 1 (terminating byte) */
50
51
  if(length >= 5){
51
52
  ENSURE_BSON_READ(b, length);
52
53
 
@@ -59,7 +60,7 @@ int32_t pvt_validate_length(byte_buffer_t *b)
59
60
  else{
60
61
  rb_raise(rb_eRangeError, "Buffer contained invalid length %d at %zu", length, b->read_position);
61
62
  }
62
-
63
+
63
64
  return length;
64
65
  }
65
66
 
@@ -175,13 +176,13 @@ VALUE pvt_get_string(byte_buffer_t *b, const char *data_type)
175
176
  }
176
177
  ENSURE_BSON_READ(b, 4 + length);
177
178
  str_ptr = READ_PTR(b) + 4;
178
- last_byte = *(READ_PTR(b) + 4 + length_le - 1);
179
+ last_byte = *(READ_PTR(b) + 4 + length - 1);
179
180
  if (last_byte != 0) {
180
181
  pvt_raise_decode_error(rb_sprintf("Last byte of the string is not null: 0x%x", (int) last_byte));
181
182
  }
182
183
  rb_bson_utf8_validate(str_ptr, length - 1, true, data_type);
183
184
  string = rb_enc_str_new(str_ptr, length - 1, rb_utf8_encoding());
184
- b->read_position += 4 + length_le;
185
+ b->read_position += 4 + length;
185
186
  return string;
186
187
  }
187
188
 
@@ -205,7 +206,7 @@ VALUE pvt_get_symbol(byte_buffer_t *b, VALUE rb_buffer, int argc, VALUE *argv)
205
206
  klass = rb_funcall(rb_bson_registry, rb_intern("get"), 1, INT2FIX(BSON_TYPE_SYMBOL));
206
207
  value = rb_funcall(klass, rb_intern("from_bson"), 1, rb_buffer);
207
208
  }
208
-
209
+
209
210
  RB_GC_GUARD(klass);
210
211
  return value;
211
212
  }
@@ -259,6 +260,28 @@ VALUE pvt_get_int32(byte_buffer_t *b)
259
260
  return INT2NUM(BSON_UINT32_FROM_LE(i32));
260
261
  }
261
262
 
263
+ /**
264
+ * Get an unsigned int32 from the buffer.
265
+ */
266
+ VALUE rb_bson_byte_buffer_get_uint32(VALUE self)
267
+ {
268
+ byte_buffer_t *b;
269
+
270
+ TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
271
+ return pvt_get_uint32(b);
272
+ }
273
+
274
+ VALUE pvt_get_uint32(byte_buffer_t *b)
275
+ {
276
+ uint32_t i32;
277
+
278
+ ENSURE_BSON_READ(b, 4);
279
+ memcpy(&i32, READ_PTR(b), 4);
280
+ b->read_position += 4;
281
+ return UINT2NUM(BSON_UINT32_FROM_LE(i32));
282
+ }
283
+
284
+
262
285
  /**
263
286
  * Get a int64 from the buffer.
264
287
  */
@@ -284,7 +307,7 @@ VALUE pvt_get_int64(byte_buffer_t *b, int argc, VALUE *argv)
284
307
  memcpy(&i64, READ_PTR(b), 8);
285
308
  b->read_position += 8;
286
309
  num = LL2NUM(BSON_UINT64_FROM_LE(i64));
287
-
310
+
288
311
  if (pvt_get_mode_option(argc, argv) == BSON_MODE_BSON) {
289
312
  VALUE klass = rb_funcall(rb_bson_registry,rb_intern("get"),1, INT2FIX(BSON_TYPE_INT64));
290
313
  VALUE value = rb_funcall(klass, rb_intern("new"), 1, num);
@@ -293,7 +316,7 @@ VALUE pvt_get_int64(byte_buffer_t *b, int argc, VALUE *argv)
293
316
  } else {
294
317
  return num;
295
318
  }
296
-
319
+
297
320
  RB_GC_GUARD(num);
298
321
  }
299
322
 
@@ -333,6 +356,30 @@ VALUE rb_bson_byte_buffer_get_decimal128_bytes(VALUE self)
333
356
  return bytes;
334
357
  }
335
358
 
359
+ /**
360
+ * This duplicates the DBRef validation code in DBRef constructor.
361
+ */
362
+ static int pvt_is_dbref(VALUE doc) {
363
+ VALUE ref, id, db;
364
+
365
+ ref = rb_hash_aref(doc, _ref_str);
366
+ if (NIL_P(ref) || !RB_TYPE_P(ref, T_STRING)) {
367
+ return 0;
368
+ }
369
+
370
+ id = rb_hash_aref(doc, _id_str);
371
+ if (NIL_P(id)) {
372
+ return 0;
373
+ }
374
+
375
+ db = rb_hash_aref(doc, _db_str);
376
+ if (!NIL_P(db) && !RB_TYPE_P(db, T_STRING)) {
377
+ return 0;
378
+ }
379
+
380
+ return 1;
381
+ }
382
+
336
383
  VALUE rb_bson_byte_buffer_get_hash(int argc, VALUE *argv, VALUE self){
337
384
  VALUE doc = Qnil;
338
385
  byte_buffer_t *b = NULL;
@@ -353,11 +400,16 @@ VALUE rb_bson_byte_buffer_get_hash(int argc, VALUE *argv, VALUE self){
353
400
  rb_hash_aset(doc, field, pvt_read_field(b, self, type, argc, argv));
354
401
  RB_GC_GUARD(field);
355
402
  }
356
-
403
+
357
404
  if (READ_PTR(b) - start_ptr != length) {
358
405
  pvt_raise_decode_error(rb_sprintf("Expected to read %d bytes for the hash but read %ld bytes", length, READ_PTR(b) - start_ptr));
359
406
  }
360
407
 
408
+ if (pvt_is_dbref(doc)) {
409
+ VALUE cDBRef = pvt_const_get_2("BSON", "DBRef");
410
+ doc = rb_funcall(cDBRef, rb_intern("new"), 1, doc);
411
+ }
412
+
361
413
  return doc;
362
414
  }
363
415
 
@@ -379,10 +431,10 @@ VALUE rb_bson_byte_buffer_get_array(int argc, VALUE *argv, VALUE self){
379
431
  rb_ary_push(array, pvt_read_field(b, self, type, argc, argv));
380
432
  }
381
433
  RB_GC_GUARD(array);
382
-
434
+
383
435
  if (READ_PTR(b) - start_ptr != length) {
384
436
  pvt_raise_decode_error(rb_sprintf("Expected to read %d bytes for the hash but read %ld bytes", length, READ_PTR(b) - start_ptr));
385
437
  }
386
-
438
+
387
439
  return array;
388
440
  }
data/ext/bson/write.c CHANGED
@@ -27,6 +27,7 @@ static void pvt_replace_int32(byte_buffer_t *b, int32_t position, int32_t newval
27
27
  static void pvt_put_field(byte_buffer_t *b, VALUE rb_buffer, VALUE val, VALUE validating_keys);
28
28
  static void pvt_put_byte(byte_buffer_t *b, const char byte);
29
29
  static void pvt_put_int32(byte_buffer_t *b, const int32_t i32);
30
+ static void pvt_put_uint32(byte_buffer_t *b, const uint32_t i32);
30
31
  static void pvt_put_int64(byte_buffer_t *b, const int64_t i);
31
32
  static void pvt_put_double(byte_buffer_t *b, double f);
32
33
  static void pvt_put_cstring(byte_buffer_t *b, const char *str, int32_t length, const char *data_type);
@@ -154,8 +155,15 @@ void pvt_put_type_byte(byte_buffer_t *b, VALUE val){
154
155
  case T_FLOAT:
155
156
  type_byte = BSON_TYPE_DOUBLE;
156
157
  break;
157
- default:{
158
- VALUE type = rb_funcall(val, rb_intern("bson_type"), 0);
158
+ default: {
159
+ VALUE type;
160
+ VALUE responds = rb_funcall(val, rb_intern("respond_to?"), 1, ID2SYM(rb_intern("bson_type")));
161
+ if (!RTEST(responds)) {
162
+ VALUE klass = pvt_const_get_3("BSON", "Error", "UnserializableClass");
163
+ VALUE val_str = rb_funcall(val, rb_intern("to_s"), 0);
164
+ rb_raise(klass, "Value does not define its BSON serialized type: %s", RSTRING_PTR(val_str));
165
+ }
166
+ type = rb_funcall(val, rb_intern("bson_type"), 0);
159
167
  type_byte = *RSTRING_PTR(type);
160
168
  RB_GC_GUARD(type);
161
169
  break;
@@ -383,6 +391,37 @@ void pvt_put_int32(byte_buffer_t *b, const int32_t i)
383
391
  b->write_position += 4;
384
392
  }
385
393
 
394
+ /* The docstring is in init.c. */
395
+ VALUE rb_bson_byte_buffer_put_uint32(VALUE self, VALUE i)
396
+ {
397
+ byte_buffer_t *b;
398
+ int64_t temp;
399
+ uint32_t i32;
400
+
401
+ if (RB_TYPE_P(i, T_FLOAT)) {
402
+ rb_raise(rb_eArgError, "put_uint32: incorrect type: float, expected: integer");
403
+ }
404
+
405
+ temp = NUM2LL(i);
406
+ if (temp < 0 || temp > UINT32_MAX) {
407
+ rb_raise(rb_eRangeError, "Number %lld is out of range [0, 2^32)", (long long)temp);
408
+ }
409
+
410
+ i32 = NUM2UINT(i);
411
+
412
+ TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b);
413
+ pvt_put_uint32(b, i32);
414
+ return self;
415
+ }
416
+
417
+ void pvt_put_uint32(byte_buffer_t *b, const uint32_t i)
418
+ {
419
+ const uint32_t i32 = BSON_UINT32_TO_LE(i);
420
+ ENSURE_BSON_WRITE(b, 4);
421
+ memcpy(WRITE_PTR(b), &i32, 4);
422
+ b->write_position += 4;
423
+ }
424
+
386
425
  /* The docstring is in init.c. */
387
426
  VALUE rb_bson_byte_buffer_put_int64(VALUE self, VALUE i)
388
427
  {
@@ -627,7 +666,7 @@ VALUE rb_bson_byte_buffer_put_array(VALUE self, VALUE array, VALUE validating_ke
627
666
 
628
667
  for(int32_t index=0; index < RARRAY_LEN(array); index++, array_element++){
629
668
  pvt_put_type_byte(b, *array_element);
630
- pvt_put_array_index(b,index);
669
+ pvt_put_array_index(b, index);
631
670
  pvt_put_field(b, self, *array_element, validating_keys);
632
671
  }
633
672
  pvt_put_byte(b, 0);
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # Copyright (C) 2018-2020 MongoDB Inc.
2
3
  #
3
4
  # Licensed under the Apache License, Version 2.0 (the "License");
data/lib/bson/array.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # Copyright (C) 2009-2020 MongoDB Inc.
2
3
  #
3
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -25,7 +26,7 @@ module BSON
25
26
  # An array is type 0x04 in the BSON spec.
26
27
  #
27
28
  # @since 2.0.0
28
- BSON_TYPE = 4.chr.force_encoding(BINARY).freeze
29
+ BSON_TYPE = ::String.new(4.chr, encoding: BINARY).freeze
29
30
 
30
31
  # Get the array as encoded BSON.
31
32
  #
@@ -47,6 +48,9 @@ module BSON
47
48
  position = buffer.length
48
49
  buffer.put_int32(0)
49
50
  each_with_index do |value, index|
51
+ unless value.respond_to?(:bson_type)
52
+ raise Error::UnserializableClass, "Array element at position #{index} does not define its BSON serialized type: #{value}"
53
+ end
50
54
  buffer.put_byte(value.bson_type)
51
55
  buffer.put_cstring(index.to_s)
52
56
  value.to_bson(buffer, validating_keys)
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+ # Copyright (C) 2009-2021 MongoDB Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ module BSON
17
+
18
+ # Injects behaviour for encoding and decoding BigDecimals
19
+ # to and from raw bytes as specified by the BSON spec.
20
+ #
21
+ # @see http://bsonspec.org/#/specification
22
+ module BigDecimal
23
+
24
+ # BigDecimals are serialized as Decimal128s under the hood. A Decimal128
25
+ # is type 0x13 in the BSON spec.
26
+ BSON_TYPE = ::String.new(19.chr, encoding: BINARY).freeze
27
+
28
+ # Get the BigDecimal as encoded BSON.
29
+ #
30
+ # @example Get the BigDecimal as encoded BSON.
31
+ # BigDecimal("1").to_bson
32
+ #
33
+ # @return [ BSON::ByteBuffer ] The buffer with the encoded object.
34
+ #
35
+ # @see http://bsonspec.org/#/specification
36
+ def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
37
+ BSON::Decimal128.new(to_s).to_bson(buffer, validating_keys)
38
+ end
39
+
40
+ # Get the BSON type for BigDecimal. This is the same BSON type as
41
+ # BSON::Decimal128.
42
+ def bson_type
43
+ BSON_TYPE
44
+ end
45
+
46
+ module ClassMethods
47
+
48
+ # Deserialize the BigDecimal from raw BSON bytes.
49
+ #
50
+ # @example Get the BigDecimal from BSON.
51
+ # BigDecimal.from_bson(bson)
52
+ #
53
+ # @param [ ByteBuffer ] buffer The byte buffer.
54
+ #
55
+ # @option options [ nil | :bson ] :mode Decoding mode to use.
56
+ #
57
+ # @return [ BigDecimal ] The decimal object.
58
+ def from_bson(buffer, **options)
59
+ Decimal128.from_bson(buffer, **options).to_big_decimal
60
+ end
61
+ end
62
+ end
63
+
64
+ # Enrich the core BigDecimal class with this module.
65
+ ::BigDecimal.send(:include, BigDecimal)
66
+ ::BigDecimal.send(:extend, BigDecimal::ClassMethods)
67
+ end