bson 4.12.1 → 4.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +4 -7
  4. data/ext/bson/bson-native.h +2 -0
  5. data/ext/bson/init.c +9 -0
  6. data/ext/bson/read.c +29 -0
  7. data/lib/bson/active_support.rb +1 -0
  8. data/lib/bson/array.rb +2 -1
  9. data/lib/bson/binary.rb +5 -3
  10. data/lib/bson/boolean.rb +2 -1
  11. data/lib/bson/code.rb +2 -1
  12. data/lib/bson/code_with_scope.rb +2 -1
  13. data/lib/bson/config.rb +1 -0
  14. data/lib/bson/date.rb +1 -0
  15. data/lib/bson/date_time.rb +1 -0
  16. data/lib/bson/db_pointer.rb +2 -1
  17. data/lib/bson/dbref.rb +125 -0
  18. data/lib/bson/decimal128/builder.rb +18 -15
  19. data/lib/bson/decimal128.rb +10 -9
  20. data/lib/bson/document.rb +14 -0
  21. data/lib/bson/environment.rb +1 -0
  22. data/lib/bson/error.rb +7 -0
  23. data/lib/bson/ext_json.rb +16 -11
  24. data/lib/bson/false_class.rb +2 -1
  25. data/lib/bson/float.rb +20 -31
  26. data/lib/bson/hash.rb +15 -6
  27. data/lib/bson/int32.rb +3 -2
  28. data/lib/bson/int64.rb +3 -2
  29. data/lib/bson/integer.rb +3 -2
  30. data/lib/bson/json.rb +1 -0
  31. data/lib/bson/max_key.rb +3 -2
  32. data/lib/bson/min_key.rb +3 -2
  33. data/lib/bson/nil_class.rb +2 -1
  34. data/lib/bson/object.rb +1 -0
  35. data/lib/bson/object_id.rb +4 -3
  36. data/lib/bson/open_struct.rb +1 -0
  37. data/lib/bson/regexp.rb +17 -6
  38. data/lib/bson/registry.rb +1 -0
  39. data/lib/bson/specialized.rb +1 -0
  40. data/lib/bson/string.rb +3 -2
  41. data/lib/bson/symbol.rb +2 -1
  42. data/lib/bson/time.rb +4 -3
  43. data/lib/bson/time_with_zone.rb +1 -0
  44. data/lib/bson/timestamp.rb +3 -2
  45. data/lib/bson/true_class.rb +2 -1
  46. data/lib/bson/undefined.rb +2 -1
  47. data/lib/bson/version.rb +2 -1
  48. data/lib/bson.rb +6 -4
  49. data/spec/README.md +14 -0
  50. data/spec/bson/dbref_spec.rb +461 -0
  51. data/spec/bson/document_spec.rb +7 -1
  52. data/spec/bson/ext_json_parse_spec.rb +37 -0
  53. data/spec/bson/int64_spec.rb +4 -24
  54. data/spec/bson/raw_spec.rb +7 -1
  55. data/spec/bson/regexp_spec.rb +52 -0
  56. data/spec/runners/common_driver.rb +1 -1
  57. data/spec/shared/LICENSE +20 -0
  58. data/spec/shared/bin/get-mongodb-download-url +17 -0
  59. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  60. data/spec/shared/lib/mrss/cluster_config.rb +221 -0
  61. data/spec/shared/lib/mrss/constraints.rb +346 -0
  62. data/spec/shared/lib/mrss/docker_runner.rb +265 -0
  63. data/spec/shared/lib/mrss/lite_constraints.rb +191 -0
  64. data/spec/shared/lib/mrss/server_version_registry.rb +115 -0
  65. data/spec/shared/lib/mrss/spec_organizer.rb +152 -0
  66. data/spec/shared/lib/mrss/utils.rb +15 -0
  67. data/spec/shared/share/Dockerfile.erb +231 -0
  68. data/spec/shared/shlib/distro.sh +73 -0
  69. data/spec/shared/shlib/server.sh +290 -0
  70. data/spec/shared/shlib/set_env.sh +128 -0
  71. data/spec/spec_helper.rb +9 -1
  72. data/spec/spec_tests/data/corpus/binary.json +5 -0
  73. data/spec/spec_tests/data/corpus/dbref.json +21 -1
  74. data/spec/spec_tests/data/corpus/document.json +4 -0
  75. data/spec/spec_tests/data/corpus/regex.json +2 -2
  76. data/spec/spec_tests/data/corpus/top.json +20 -9
  77. data.tar.gz.sig +0 -0
  78. metadata +123 -90
  79. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 18f69f1d0f65a2c4883500061a6637f6fb314e7758a15cda3941432a7e6fbd0a
4
- data.tar.gz: b26789d1b2da697b6113897040ecd297d88367267fd28411609f23229ec8be2e
3
+ metadata.gz: f6a42388fd836eb9cd8caee93899ca84eea84d14a0eb79346d7c96deba08b0d1
4
+ data.tar.gz: d0d20e09019369dea160278abee5929ea89f91efcdbd0523f68dd83fa0d2b30f
5
5
  SHA512:
6
- metadata.gz: 7f90cd2d60cb0904d80ec6a3d75ba7d88af3872b5b1fdd27f9a283026f7c27ffbe84ad5331e571ebe120c7cd8c94d06190da8f1dc9fc783c349667f0ee963de1
7
- data.tar.gz: da4c4edb81e99a804789c3914555376db3510a65437cc7b80829ae1f38f3c0f5a45894c8b4d8b24127367d0a9d1f46c9094a7b4f0f18633dbd4c4a8890675b02
6
+ metadata.gz: 3210c3ef66059b6b44e4286755df4ed8508e4c367c20b6ff89698d21dd89151c4aee54e4a31cc92c5b09db3b7d33ec8ece2dc17372920885d9808aa13d5eed09
7
+ data.tar.gz: '0086253724f6b26a1e1a40ee89d9c434c5005bbfbdcf28b11aa40b1f5742eb4a030d4ca26c331b71cfabfb911e9a8200719c72e4327cad3e6d825a8e3de5d346'
checksums.yaml.gz.sig CHANGED
Binary file
data/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  BSON
2
2
  [![Gem Version][rubygems-img]][rubygems-url]
3
- [![Build Status][travis-img]][travis-url]
4
- [![Build status Windows][appveyor-img]][appveyor-url]
3
+ [![Build Status][ghactions-img]][ghactions-url]
5
4
  [![Coverage Status][coveralls-img]][coveralls-url]
6
5
  [![Inline docs][inch-img]][inch-url]
7
6
  ====
@@ -11,7 +10,7 @@ An implementation of the BSON specification in Ruby.
11
10
  Compatibility
12
11
  -------------
13
12
 
14
- BSON is tested against MRI (2.3+) and JRuby (9.2+).
13
+ BSON is tested against MRI (2.5) and JRuby (9.2+).
15
14
 
16
15
  Documentation
17
16
  -------------
@@ -55,10 +54,8 @@ limitations under the License.
55
54
 
56
55
  [rubygems-img]: https://badge.fury.io/rb/bson.svg
57
56
  [rubygems-url]: http://badge.fury.io/rb/bson
58
- [travis-img]: https://secure.travis-ci.org/mongodb/bson-ruby.svg?branch=master
59
- [travis-url]: http://travis-ci.org/mongodb/bson-ruby
60
- [appveyor-img]: https://ci.appveyor.com/api/projects/status/p5aqko7umsx351nm?svg=true
61
- [appveyor-url]: https://ci.appveyor.com/project/p-mongo/bson-ruby/branch/master
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
62
59
  [coveralls-img]: https://coveralls.io/repos/mongodb/bson-ruby/badge.svg?branch=master
63
60
  [coveralls-url]: https://coveralls.io/r/mongodb/bson-ruby?branch=master
64
61
  [inch-img]: http://inch-ci.org/github/mongodb/bson-ruby.svg?branch=master
@@ -123,3 +123,5 @@ extern VALUE rb_bson_registry;
123
123
  extern VALUE rb_bson_illegal_key;
124
124
 
125
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,6 +39,13 @@ 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
data/ext/bson/read.c CHANGED
@@ -356,6 +356,30 @@ VALUE rb_bson_byte_buffer_get_decimal128_bytes(VALUE self)
356
356
  return bytes;
357
357
  }
358
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
+
359
383
  VALUE rb_bson_byte_buffer_get_hash(int argc, VALUE *argv, VALUE self){
360
384
  VALUE doc = Qnil;
361
385
  byte_buffer_t *b = NULL;
@@ -380,6 +404,11 @@ VALUE rb_bson_byte_buffer_get_hash(int argc, VALUE *argv, VALUE self){
380
404
  if (READ_PTR(b) - start_ptr != length) {
381
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));
382
406
  }
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
+ }
383
412
 
384
413
  return doc;
385
414
  }
@@ -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
  #
data/lib/bson/binary.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");
@@ -27,7 +28,7 @@ module BSON
27
28
  # A binary is type 0x05 in the BSON spec.
28
29
  #
29
30
  # @since 2.0.0
30
- BSON_TYPE = 5.chr.force_encoding(BINARY).freeze
31
+ BSON_TYPE = ::String.new(5.chr, encoding: BINARY).freeze
31
32
 
32
33
  # The mappings of subtypes to their single byte identifiers.
33
34
  #
@@ -46,7 +47,8 @@ module BSON
46
47
  :uuid => 4.chr,
47
48
  :md5 => 5.chr,
48
49
  :ciphertext => 6.chr,
49
- :user => 128.chr
50
+ :column => 7.chr,
51
+ :user => 128.chr,
50
52
  }.freeze
51
53
 
52
54
  # The mappings of single byte subtypes to their symbol counterparts.
@@ -169,7 +171,7 @@ module BSON
169
171
  #
170
172
  # @since 2.3.0
171
173
  def inspect
172
- "<BSON::Binary:0x#{object_id} type=#{type} data=0x#{data[0, 8].unpack('H*').first}...>"
174
+ "<BSON::Binary:0x#{object_id} type=#{type} data=0x#{data[0, 8].unpack1('H*')}...>"
173
175
  end
174
176
 
175
177
  # Returns a string representation of the UUID stored in this Binary.
data/lib/bson/boolean.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
  # A boolean is type 0x08 in the BSON spec.
26
27
  #
27
28
  # @since 2.0.0
28
- BSON_TYPE = 8.chr.force_encoding(BINARY).freeze
29
+ BSON_TYPE = ::String.new(8.chr, encoding: BINARY).freeze
29
30
 
30
31
  # Deserialize a boolean from BSON.
31
32
  #
data/lib/bson/code.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
  # A code is type 0x0D in the BSON spec.
26
27
  #
27
28
  # @since 2.0.0
28
- BSON_TYPE = 13.chr.force_encoding(BINARY).freeze
29
+ BSON_TYPE = ::String.new(13.chr, encoding: BINARY).freeze
29
30
 
30
31
  # @!attribute javascript
31
32
  # @return [ String ] The javascript code.
@@ -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");
@@ -26,7 +27,7 @@ module BSON
26
27
  # A code with scope is type 0x0F in the BSON spec.
27
28
  #
28
29
  # @since 2.0.0
29
- BSON_TYPE = 15.chr.force_encoding(BINARY).freeze
30
+ BSON_TYPE = ::String.new(15.chr, encoding: BINARY).freeze
30
31
 
31
32
  # @!attribute javascript
32
33
  # @return [ String ] The javascript code.
data/lib/bson/config.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # Copyright (C) 2016-2020 MongoDB Inc.
2
3
  #
3
4
  # Licensed under the Apache License, Version 2.0 (the "License");
data/lib/bson/date.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");
@@ -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");
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # Copyright (C) 2020 MongoDB Inc.
2
3
  #
3
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,7 +23,7 @@ module BSON
22
23
  include JSON
23
24
 
24
25
  # A DBPointer is type 0x0C in the BSON spec.
25
- BSON_TYPE = 0x0C.chr.force_encoding(BINARY).freeze
26
+ BSON_TYPE = ::String.new(0x0C.chr, encoding: BINARY).freeze
26
27
 
27
28
  # Create a new DBPointer object.
28
29
  #
data/lib/bson/dbref.rb ADDED
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+
4
+ # Copyright (C) 2015-2021 MongoDB Inc.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the 'License');
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an 'AS IS' BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ module BSON
19
+
20
+ # Represents a DBRef document in the database.
21
+ class DBRef < Document
22
+ include JSON
23
+
24
+ # The constant for the collection reference field.
25
+ #
26
+ # @deprecated
27
+ COLLECTION = '$ref'.freeze
28
+
29
+ # The constant for the id field.
30
+ #
31
+ # @deprecated
32
+ ID = '$id'.freeze
33
+
34
+ # The constant for the database field.
35
+ #
36
+ # @deprecated
37
+ DATABASE = '$db'.freeze
38
+
39
+ # @return [ String ] collection The collection name.
40
+ def collection
41
+ self['$ref']
42
+ end
43
+
44
+ # @return [ BSON::ObjectId ] id The referenced document id.
45
+ def id
46
+ self['$id']
47
+ end
48
+
49
+ # @return [ String ] database The database name.
50
+ def database
51
+ self['$db']
52
+ end
53
+
54
+ # Get the DBRef as a JSON document
55
+ #
56
+ # @example Get the DBRef as a JSON hash.
57
+ # dbref.as_json
58
+ #
59
+ # @return [ Hash ] The max key as a JSON hash.
60
+ def as_json(*args)
61
+ {}.update(self)
62
+ end
63
+
64
+ # Instantiate a new DBRef.
65
+ #
66
+ # @example Create the DBRef.
67
+ # BSON::DBRef.new({'$ref' => 'users', '$id' => id, '$db' => 'database'})
68
+ #
69
+ # @param [ Hash ] hash the DBRef hash. It must contain $ref and $id.
70
+ def initialize(hash)
71
+ hash = reorder_fields(hash)
72
+ %w($ref $id).each do |key|
73
+ unless hash[key]
74
+ raise ArgumentError, "DBRef must have #{key}: #{hash}"
75
+ end
76
+ end
77
+
78
+ unless hash['$ref'].is_a?(String)
79
+ raise ArgumentError, "The value for key $ref must be a string, got: #{hash['$ref']}"
80
+ end
81
+
82
+ if db = hash['$db']
83
+ unless db.is_a?(String)
84
+ raise ArgumentError, "The value for key $db must be a string, got: #{hash['$db']}"
85
+ end
86
+ end
87
+
88
+ super
89
+ end
90
+
91
+ # Converts the DBRef to raw BSON.
92
+ #
93
+ # @example Convert the DBRef to raw BSON.
94
+ # dbref.to_bson
95
+ #
96
+ # @param [ BSON::ByteBuffer ] buffer The encoded BSON buffer to append to.
97
+ # @param [ true, false ] validating_keys Whether keys should be validated when serializing.
98
+ #
99
+ # @return [ BSON::ByteBuffer ] The buffer with the encoded object.
100
+ def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
101
+ as_json.to_bson(buffer, validating_keys)
102
+ end
103
+
104
+ private
105
+
106
+ # Reorder the fields of the given Hash to have $ref first, $id second,
107
+ # and $db third. The rest of the fields in the hash can come in any
108
+ # order after that.
109
+ #
110
+ # @param [ Hash ] hash The input hash. Must be a valid dbref.
111
+ #
112
+ # @return [ Hash ] The hash with it's fields reordered.
113
+ def reorder_fields(hash)
114
+ hash = BSON::Document.new(hash)
115
+ reordered = {}
116
+ reordered['$ref'] = hash.delete('$ref')
117
+ reordered['$id'] = hash.delete('$id')
118
+ if db = hash.delete('$db')
119
+ reordered['$db'] = db
120
+ end
121
+
122
+ reordered.update(hash)
123
+ end
124
+ end
125
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # Copyright (C) 2016-2020 MongoDB Inc.
2
3
  #
3
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -26,27 +27,27 @@ module BSON
26
27
  # Infinity mask.
27
28
  #
28
29
  # @since 4.2.0
29
- INFINITY_MASK = 0x7800000000000000.freeze
30
+ INFINITY_MASK = 0x7800000000000000
30
31
 
31
32
  # NaN mask.
32
33
  #
33
34
  # @since 4.2.0
34
- NAN_MASK = 0x7c00000000000000.freeze
35
+ NAN_MASK = 0x7c00000000000000
35
36
 
36
37
  # SNaN mask.
37
38
  #
38
39
  # @since 4.2.0
39
- SNAN_MASK = (1 << 57).freeze
40
+ SNAN_MASK = (1 << 57)
40
41
 
41
42
  # Signed bit mask.
42
43
  #
43
44
  # @since 4.2.0
44
- SIGN_BIT_MASK = (1 << 63).freeze
45
+ SIGN_BIT_MASK = (1 << 63)
45
46
 
46
47
  # The two highest bits of the 64 high order bits.
47
48
  #
48
49
  # @since 4.2.0
49
- TWO_HIGHEST_BITS_SET = (3 << 61).freeze
50
+ TWO_HIGHEST_BITS_SET = (3 << 61)
50
51
 
51
52
  extend self
52
53
 
@@ -109,14 +110,14 @@ module BSON
109
110
  # @return [ Regex ] A regex matching a NaN string.
110
111
  #
111
112
  # @since 4.2.0
112
- NAN_REGEX = /^(\-)?(S)?NaN$/i.freeze
113
+ NAN_REGEX = /^(\-)?(S)?NaN$/i
113
114
 
114
115
  # Regex matching a string representing positive or negative Infinity.
115
116
  #
116
117
  # @return [ Regex ] A regex matching a positive or negative Infinity string.
117
118
  #
118
119
  # @since 4.2.0
119
- INFINITY_REGEX = /^(\+|\-)?Inf(inity)?$/i.freeze
120
+ INFINITY_REGEX = /^(\+|\-)?Inf(inity)?$/i
120
121
 
121
122
  # Regex for the fraction, including leading zeros.
122
123
  #
@@ -124,33 +125,33 @@ module BSON
124
125
  # including leading zeros.
125
126
  #
126
127
  # @since 4.2.0
127
- SIGNIFICAND_WITH_LEADING_ZEROS_REGEX = /(0*)(\d+)/.freeze
128
+ SIGNIFICAND_WITH_LEADING_ZEROS_REGEX = /(0*)(\d+)/
128
129
 
129
130
  # Regex for separating a negative sign from the significands.
130
131
  #
131
132
  # @return [ Regex ] The regex for separating a sign from significands.
132
133
  #
133
134
  # @since 4.2.0
134
- SIGN_AND_DIGITS_REGEX = /^(\-)?(\S+)/.freeze
135
+ SIGN_AND_DIGITS_REGEX = /^(\-)?(\S+)/
135
136
 
136
137
  # Regex matching a scientific exponent.
137
138
  #
138
139
  # @return [ Regex ] A regex matching E, e, E+, e+.
139
140
  #
140
141
  # @since 4.2.0
141
- SCIENTIFIC_EXPONENT_REGEX = /E\+?/i.freeze
142
+ SCIENTIFIC_EXPONENT_REGEX = /E\+?/i
142
143
 
143
144
  # Regex for capturing trailing zeros.
144
145
  #
145
146
  # @since 4.2.0
146
- TRAILING_ZEROS_REGEX = /[1-9]*(0+)$/.freeze
147
+ TRAILING_ZEROS_REGEX = /[1-9]*(0+)$/
147
148
 
148
149
  # Regex for a valid decimal128 string format.
149
150
  #
150
151
  # @return [ Regex ] The regex for a valid decimal128 string.
151
152
  #
152
153
  # @since 4.2.0
153
- VALID_DECIMAL128_STRING_REGEX = /^[\-\+]?(\d+(\.\d*)?|\.\d+)(E[\-\+]?\d+)?$/i.freeze
154
+ VALID_DECIMAL128_STRING_REGEX = /^[\-\+]?(\d+(\.\d*)?|\.\d+)(E[\-\+]?\d+)?$/i
154
155
 
155
156
  # Initialize the FromString Builder object.
156
157
  #
@@ -337,14 +338,14 @@ module BSON
337
338
  # @return [ String ] The string representing NaN.
338
339
  #
339
340
  # @since 4.2.0
340
- NAN_STRING = 'NaN'.freeze
341
+ NAN_STRING = 'NaN'
341
342
 
342
343
  # String representing an Infinity value.
343
344
  #
344
345
  # @return [ String ] The string representing Infinity.
345
346
  #
346
347
  # @since 4.2.0
347
- INFINITY_STRING = 'Infinity'.freeze
348
+ INFINITY_STRING = 'Infinity'
348
349
 
349
350
  # Initialize the FromBigDecimal Builder object.
350
351
  #
@@ -366,11 +367,13 @@ module BSON
366
367
  #
367
368
  # @return [ String ] The string representing the decimal128 object.
368
369
  #
370
+ # @note The returned string may be frozen.
371
+ #
369
372
  # @since 4.2.0
370
373
  def string
371
374
  return NAN_STRING if nan?
372
375
  str = infinity? ? INFINITY_STRING : create_string
373
- negative? ? '-' << str : str
376
+ negative? ? "-#{str}" : str
374
377
  end
375
378
 
376
379
  private
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # Copyright (C) 2016-2020 MongoDB Inc.
2
3
  #
3
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -23,32 +24,32 @@ module BSON
23
24
  # A Decimal128 is type 0x13 in the BSON spec.
24
25
  #
25
26
  # @since 4.2.0
26
- BSON_TYPE = 19.chr.force_encoding(BINARY).freeze
27
+ BSON_TYPE = ::String.new(19.chr, encoding: BINARY).freeze
27
28
 
28
29
  # Exponent offset.
29
30
  #
30
31
  # @since 4.2.0
31
- EXPONENT_OFFSET = 6176.freeze
32
+ EXPONENT_OFFSET = 6176
32
33
 
33
34
  # Minimum exponent.
34
35
  #
35
36
  # @since 4.2.0
36
- MIN_EXPONENT = -6176.freeze
37
+ MIN_EXPONENT = -6176
37
38
 
38
39
  # Maximum exponent.
39
40
  #
40
41
  # @since 4.2.0
41
- MAX_EXPONENT = 6111.freeze
42
+ MAX_EXPONENT = 6111
42
43
 
43
44
  # Maximum digits of precision.
44
45
  #
45
46
  # @since 4.2.0
46
- MAX_DIGITS_OF_PRECISION = 34.freeze
47
+ MAX_DIGITS_OF_PRECISION = 34
47
48
 
48
49
  # Key for this type when converted to extended json.
49
50
  #
50
51
  # @since 4.2.0
51
- EXTENDED_JSON_KEY = "$numberDecimal".freeze
52
+ EXTENDED_JSON_KEY = "$numberDecimal"
52
53
 
53
54
  # The native type to which this object can be converted.
54
55
  #
@@ -262,7 +263,7 @@ module BSON
262
263
  # The custom error message for this error.
263
264
  #
264
265
  # @since 4.2.0
265
- MESSAGE = 'A Decimal128 can only be created from a String or BigDecimal.'.freeze
266
+ MESSAGE = 'A Decimal128 can only be created from a String or BigDecimal.'
266
267
 
267
268
  # Get the custom error message for the exception.
268
269
  #
@@ -288,7 +289,7 @@ module BSON
288
289
  # The custom error message for this error.
289
290
  #
290
291
  # @since 4.2.0
291
- MESSAGE = 'Invalid string format for creating a Decimal128 object.'.freeze
292
+ MESSAGE = 'Invalid string format for creating a Decimal128 object.'
292
293
 
293
294
  # Get the custom error message for the exception.
294
295
  #
@@ -313,7 +314,7 @@ module BSON
313
314
  # The custom error message for this error.
314
315
  #
315
316
  # @since 4.2.0
316
- MESSAGE = 'Value out of range for Decimal128 representation.'.freeze
317
+ MESSAGE = 'Value out of range for Decimal128 representation.'
317
318
 
318
319
  # Get the custom error message for the exception.
319
320
  #
data/lib/bson/document.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");
@@ -319,6 +320,19 @@ module BSON
319
320
  raise ArgumentError, 'symbolize_keys! is not supported on BSON::Document instances. Please convert the document to hash first (using #to_h), then call #symbolize_keys! on the Hash instance'
320
321
  end
321
322
 
323
+ # Override the Hash implementation of to_bson_normalized_value.
324
+ #
325
+ # BSON::Document is already of the correct type and already provides
326
+ # indifferent access to keys, hence no further conversions are necessary.
327
+ #
328
+ # Attempting to perform Hash's conversion on Document instances converts
329
+ # DBRefs to Documents which is wrong.
330
+ #
331
+ # @return [ BSON::Document ] The normalized hash.
332
+ def to_bson_normalized_value
333
+ self
334
+ end
335
+
322
336
  private
323
337
 
324
338
  def convert_key(key)
@@ -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");
data/lib/bson/error.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module BSON
2
3
  # Base exception class for all BSON-related errors.
3
4
  #
@@ -23,5 +24,11 @@ module BSON
23
24
  # itself to BSON.
24
25
  class UnserializableClass < Error
25
26
  end
27
+
28
+ # Exception raised when there is an invalid argument passed into the
29
+ # constructor of regexp object. This includes when the argument contains
30
+ # a null byte.
31
+ class InvalidRegexpPattern < Error
32
+ end
26
33
  end
27
34
  end
data/lib/bson/ext_json.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # Copyright (C) 2019-2020 MongoDB Inc.
2
3
  #
3
4
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -138,7 +139,7 @@ module BSON
138
139
  return {}
139
140
  end
140
141
 
141
- if hash.key?('$ref')
142
+ if dbref?(hash)
142
143
  # Legacy dbref handling.
143
144
  # Note that according to extended json spec, only hash values (but
144
145
  # not the top-level BSON document itself) may be of type "dbref".
@@ -147,10 +148,6 @@ module BSON
147
148
  # logic to top level hashes doesn't cause harm.
148
149
  hash = hash.dup
149
150
  ref = hash.delete('$ref')
150
- # $ref can be a string value or an ObjectId
151
- unless ref.is_a?(String)
152
- raise Error::ExtJSONParseError, "Invalid $ref value: #{ref}"
153
- end
154
151
  # $id, if present, can be anything
155
152
  id = hash.delete('$id')
156
153
  if id.is_a?(Hash)
@@ -163,13 +160,9 @@ module BSON
163
160
  out = {'$ref' => ref, '$id' => id}
164
161
  if hash.key?('$db')
165
162
  # $db must always be a string, if provided
166
- db = hash.delete('$db')
167
- unless db.is_a?(String)
168
- raise Error::ExtJSONParseError, "Invalid $db value: #{db}"
169
- end
170
- out['$db'] = db
163
+ out['$db'] = hash.delete('$db')
171
164
  end
172
- return out.update(hash)
165
+ return out.update(parse_hash(hash))
173
166
  end
174
167
 
175
168
  if hash.length == 1
@@ -362,6 +355,9 @@ module BSON
362
355
 
363
356
  module_function def map_hash(hash, **options)
364
357
  ::Hash[hash.map do |key, value|
358
+ if (key.is_a?(String) || key.is_a?(Symbol)) && key.to_s.include?(NULL_BYTE)
359
+ raise Error::ExtJSONParseError, "Hash key cannot contain a null byte: #{key}"
360
+ end
365
361
  [key, parse_obj(value, **options)]
366
362
  end]
367
363
  end
@@ -379,5 +375,14 @@ module BSON
379
375
  module_function def create_regexp(pattern, options)
380
376
  Regexp::Raw.new(pattern, options)
381
377
  end
378
+
379
+ module_function def dbref?(hash)
380
+ if db = hash.key?('$db')
381
+ unless db.is_a?(String)
382
+ return false
383
+ end
384
+ end
385
+ return hash['$ref']&.is_a?(String) && hash.key?('$id')
386
+ end
382
387
  end
383
388
  end