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,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.
@@ -205,7 +205,22 @@ module BSON
205
205
  #
206
206
  # @since 4.2.0
207
207
  def as_json(*args)
208
- { "$regex" => source, "$options" => options }
208
+ as_extended_json(mode: :legacy)
209
+ end
210
+
211
+ # Converts this object to a representation directly serializable to
212
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
213
+ #
214
+ # @option opts [ nil | :relaxed | :legacy ] :mode Serialization mode
215
+ # (default is canonical extended JSON)
216
+ #
217
+ # @return [ Hash ] The extended json representation.
218
+ def as_extended_json(**opts)
219
+ if opts[:mode] == :legacy
220
+ { "$regex" => source, "$options" => options }
221
+ else
222
+ {"$regularExpression" => {'pattern' => source, "options" => options}}
223
+ end
209
224
  end
210
225
 
211
226
  # Check equality of the raw bson regexp against another.
@@ -248,12 +263,14 @@ module BSON
248
263
  #
249
264
  # @param [ ByteBuffer ] buffer The byte buffer.
250
265
  #
266
+ # @option opts [ nil | :bson ] :mode Decoding mode to use.
267
+ #
251
268
  # @return [ Regexp ] The decoded regular expression.
252
269
  #
253
270
  # @see http://bsonspec.org/#/specification
254
271
  #
255
272
  # @since 2.0.0
256
- def from_bson(buffer)
273
+ def from_bson(buffer, **opts)
257
274
  pattern = buffer.get_cstring
258
275
  options = buffer.get_cstring
259
276
  Raw.new(pattern, options)
@@ -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.
@@ -61,12 +61,14 @@ module BSON
61
61
  #
62
62
  # @param [ ByteBuffer ] buffer The byte buffer.
63
63
  #
64
+ # @option options [ nil | :bson ] :mode Decoding mode to use.
65
+ #
64
66
  # @return [ Specialized ] The decoded specialized class.
65
67
  #
66
68
  # @see http://bsonspec.org/#/specification
67
69
  #
68
70
  # @since 2.0.0
69
- def from_bson(buffer)
71
+ def from_bson(buffer, **options)
70
72
  new
71
73
  end
72
74
  end
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
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.
@@ -124,12 +124,14 @@ module BSON
124
124
  #
125
125
  # @param [ ByteBuffer ] buffer The byte buffer.
126
126
  #
127
+ # @option options [ nil | :bson ] :mode Decoding mode to use.
128
+ #
127
129
  # @return [ Regexp ] The decoded string.
128
130
  #
129
131
  # @see http://bsonspec.org/#/specification
130
132
  #
131
133
  # @since 2.0.0
132
- def from_bson(buffer)
134
+ def from_bson(buffer, **options)
133
135
  buffer.get_string
134
136
  end
135
137
  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.
@@ -89,19 +89,108 @@ module BSON
89
89
  to_s
90
90
  end
91
91
 
92
+ # Converts this object to a representation directly serializable to
93
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
94
+ #
95
+ # @option options [ true | false ] :relaxed Whether to produce relaxed
96
+ # extended JSON representation.
97
+ #
98
+ # @return [ Hash ] The extended json representation.
99
+ def as_extended_json(**options)
100
+ { "$symbol" => to_s }
101
+ end
102
+
103
+ class Raw
104
+ # Create a BSON Symbol
105
+ #
106
+ # @param [ String | Symbol ] str_or_sym The symbol represented by this
107
+ # object. Can be specified as a Symbol or a String.
108
+ #
109
+ # @see http://bsonspec.org/#/specification
110
+ def initialize(str_or_sym)
111
+ unless str_or_sym.is_a?(String) || str_or_sym.is_a?(Symbol)
112
+ raise ArgumentError, "BSON::Symbol::Raw must be given a symbol or a string, not #{str_or_sym}"
113
+ end
114
+
115
+ @symbol = str_or_sym.to_sym
116
+ end
117
+
118
+ # Get the underlying symbol as a Ruby symbol.
119
+ #
120
+ # @return [ Symbol ] The symbol represented by this BSON object.
121
+ def to_sym
122
+ @symbol
123
+ end
124
+
125
+ # Get the underlying symbol as a Ruby string.
126
+ #
127
+ # @return [ String ] The symbol as a string.
128
+ def to_s
129
+ @symbol.to_s
130
+ end
131
+
132
+ # Check equality of the raw bson symbol against another.
133
+ #
134
+ # @param [ Object ] other The object to check against.
135
+ #
136
+ # @return [ true, false ] If the objects are equal.
137
+ def ==(other)
138
+ return false unless other.is_a?(Raw)
139
+ to_sym == other.to_sym
140
+ end
141
+ alias :eql? :==
142
+
143
+ # Get the symbol as encoded BSON.
144
+ #
145
+ # @raise [ EncodingError ] If the symbol is not UTF-8.
146
+ #
147
+ # @return [ BSON::ByteBuffer ] The buffer with the encoded object.
148
+ #
149
+ # @see http://bsonspec.org/#/specification
150
+ def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
151
+ buffer.put_string(to_s)
152
+ end
153
+
154
+ def bson_type
155
+ Symbol::BSON_TYPE
156
+ end
157
+
158
+ # Converts this object to a representation directly serializable to
159
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
160
+ #
161
+ # This method returns the integer value if relaxed representation is
162
+ # requested, otherwise a $numberLong hash.
163
+ #
164
+ # @option options [ true | false ] :relaxed Whether to produce relaxed
165
+ # extended JSON representation.
166
+ #
167
+ # @return [ Hash | Integer ] The extended json representation.
168
+ def as_extended_json(**options)
169
+ {'$symbol' => to_s}
170
+ end
171
+ end
172
+
92
173
  module ClassMethods
93
174
 
94
175
  # Deserialize a symbol from BSON.
95
176
  #
96
177
  # @param [ ByteBuffer ] buffer The byte buffer.
97
178
  #
98
- # @return [ Regexp ] The decoded symbol.
179
+ # @option options [ nil | :bson ] :mode Decoding mode to use.
180
+ #
181
+ # @return [ Symbol | BSON::Symbol::Raw ] The decoded symbol.
99
182
  #
100
183
  # @see http://bsonspec.org/#/specification
101
184
  #
102
185
  # @since 2.0.0
103
- def from_bson(buffer)
104
- buffer.get_string.intern
186
+ def from_bson(buffer, **options)
187
+ sym = buffer.get_string.intern
188
+
189
+ if options[:mode] == :bson
190
+ Raw.new(sym)
191
+ else
192
+ sym
193
+ end
105
194
  end
106
195
  end
107
196
 
@@ -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.
@@ -17,6 +17,20 @@ module BSON
17
17
  # Injects behaviour for encoding and decoding time values to
18
18
  # and from raw bytes as specified by the BSON spec.
19
19
  #
20
+ # @note
21
+ # Ruby time can have nanosecond precision:
22
+ # +Time.utc(2020, 1, 1, 0, 0, 0, 999_999_999/1000r)+
23
+ # +Time#usec+ returns the number of microseconds in the time, and
24
+ # if the time has nanosecond precision the sub-microsecond part is
25
+ # truncated (the value is floored to the nearest millisecond).
26
+ # MongoDB only supports millisecond precision; we truncate the
27
+ # sub-millisecond part of microseconds (floor to the nearest millisecond).
28
+ # Note that if a time is constructed from a floating point value,
29
+ # the microsecond value may round to the starting floating point value
30
+ # but due to flooring, the time after serialization may end up to
31
+ # be different than the starting floating point value.
32
+ # It is recommended that time calculations use integer math only.
33
+ #
20
34
  # @see http://bsonspec.org/#/specification
21
35
  #
22
36
  # @since 2.0.0
@@ -29,6 +43,8 @@ module BSON
29
43
 
30
44
  # Get the time as encoded BSON.
31
45
  #
46
+ # @note The time is floored to the nearest millisecond.
47
+ #
32
48
  # @example Get the time as encoded BSON.
33
49
  # Time.new(2012, 1, 1, 0, 0, 0).to_bson
34
50
  #
@@ -38,7 +54,48 @@ module BSON
38
54
  #
39
55
  # @since 2.0.0
40
56
  def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?)
41
- buffer.put_int64((to_i * 1000) + (usec / 1000))
57
+ value = _bson_to_i * 1000 + usec.divmod(1000).first
58
+ buffer.put_int64(value)
59
+ end
60
+
61
+ # Converts this object to a representation directly serializable to
62
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
63
+ #
64
+ # @note The time is floored to the nearest millisecond.
65
+ #
66
+ # @option options [ true | false ] :relaxed Whether to produce relaxed
67
+ # extended JSON representation.
68
+ #
69
+ # @return [ Hash ] The extended json representation.
70
+ def as_extended_json(**options)
71
+ utc_time = utc
72
+ if options[:mode] == :relaxed && (1970..9999).include?(utc_time.year)
73
+ if utc_time.usec != 0
74
+ if utc_time.respond_to?(:floor)
75
+ # Ruby 2.7+
76
+ utc_time = utc_time.floor(3)
77
+ else
78
+ utc_time -= utc_time.usec.divmod(1000).last.to_r / 1000000
79
+ end
80
+ {'$date' => utc_time.strftime('%Y-%m-%dT%H:%M:%S.%LZ')}
81
+ else
82
+ {'$date' => utc_time.strftime('%Y-%m-%dT%H:%M:%SZ')}
83
+ end
84
+ else
85
+ sec = utc_time._bson_to_i
86
+ msec = utc_time.usec.divmod(1000).first
87
+ {'$date' => {'$numberLong' => (sec * 1000 + msec).to_s}}
88
+ end
89
+ end
90
+
91
+ def _bson_to_i
92
+ # Workaround for JRuby's #to_i rounding negative timestamps up
93
+ # rather than down (https://github.com/jruby/jruby/issues/6104)
94
+ if BSON::Environment.jruby?
95
+ (self - usec.to_r/1000000).to_i
96
+ else
97
+ to_i
98
+ end
42
99
  end
43
100
 
44
101
  module ClassMethods
@@ -47,13 +104,15 @@ module BSON
47
104
  #
48
105
  # @param [ ByteBuffer ] buffer The byte buffer.
49
106
  #
107
+ # @option options [ nil | :bson ] :mode Decoding mode to use.
108
+ #
50
109
  # @return [ Time ] The decoded UTC datetime.
51
110
  #
52
111
  # @see http://bsonspec.org/#/specification
53
112
  #
54
113
  # @since 2.0.0
55
- def from_bson(buffer)
56
- seconds, fragment = Int64.from_bson(buffer).divmod(1000)
114
+ def from_bson(buffer, **options)
115
+ seconds, fragment = Int64.from_bson(buffer, mode: nil).divmod(1000)
57
116
  at(seconds, fragment * 1000).utc
58
117
  end
59
118
  end
@@ -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.
@@ -84,7 +84,19 @@ module BSON
84
84
  # @return [ Hash ] The timestamp as a JSON hash.
85
85
  #
86
86
  # @since 2.0.0
87
+ # @deprecated Use as_extended_json instead.
87
88
  def as_json(*args)
89
+ as_extended_json
90
+ end
91
+
92
+ # Converts this object to a representation directly serializable to
93
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
94
+ #
95
+ # @option opts [ nil | :relaxed | :legacy ] :mode Serialization mode
96
+ # (default is canonical extended JSON)
97
+ #
98
+ # @return [ Hash ] The extended json representation.
99
+ def as_extended_json(**options)
88
100
  { "$timestamp" => { "t" => seconds, "i" => increment } }
89
101
  end
90
102
 
@@ -120,12 +132,14 @@ module BSON
120
132
  #
121
133
  # @param [ ByteBuffer ] buffer The byte buffer.
122
134
  #
135
+ # @option options [ nil | :bson ] :mode Decoding mode to use.
136
+ #
123
137
  # @return [ Timestamp ] The decoded timestamp.
124
138
  #
125
139
  # @see http://bsonspec.org/#/specification
126
140
  #
127
141
  # @since 2.0.0
128
- def self.from_bson(buffer)
142
+ def self.from_bson(buffer, **options)
129
143
  increment = buffer.get_int32
130
144
  seconds = buffer.get_int32
131
145
  new(seconds, increment)
@@ -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.
@@ -41,6 +41,17 @@ module BSON
41
41
  self.class == other.class
42
42
  end
43
43
 
44
+ # Converts this object to a representation directly serializable to
45
+ # Extended JSON (https://github.com/mongodb/specifications/blob/master/source/extended-json.rst).
46
+ #
47
+ # @option opts [ nil | :relaxed | :legacy ] :mode Serialization mode
48
+ # (default is canonical extended JSON)
49
+ #
50
+ # @return [ Hash ] The extended json representation.
51
+ def as_extended_json(**options)
52
+ { "$undefined" => true }
53
+ end
54
+
44
55
  # Register this type when the module is loaded.
45
56
  #
46
57
  # @since 2.0.0
@@ -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.
@@ -13,5 +13,5 @@
13
13
  # limitations under the License.
14
14
 
15
15
  module BSON
16
- VERSION = "4.7.1".freeze
16
+ VERSION = "4.9.1".freeze
17
17
  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.
@@ -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.
@@ -63,7 +63,7 @@ describe BSON::Binary do
63
63
 
64
64
  it "returns the binary data plus type" do
65
65
  expect(object.as_json).to eq(
66
- { "$binary" => Base64.encode64("testing"), "$type" => :user }
66
+ { "$binary" => {'base64' => Base64.encode64("testing").strip, "subType" => '80' }}
67
67
  )
68
68
  end
69
69
 
@@ -126,12 +126,34 @@ describe BSON::Binary do
126
126
  end
127
127
 
128
128
  describe '#from_bson' do
129
- let(:bson) { BSON::ByteBuffer.new("#{5.to_bson}#{0.chr}hello".force_encoding('BINARY')) }
130
- let(:obj) { described_class.from_bson(bson) }
129
+ let(:buffer) { BSON::ByteBuffer.new(bson) }
130
+ let(:obj) { described_class.from_bson(buffer) }
131
+
132
+ let(:bson) { "#{5.to_bson}#{0.chr}hello".force_encoding('BINARY') }
131
133
 
132
134
  it 'sets data encoding to binary' do
133
135
  expect(obj.data.encoding).to eq(Encoding.find('BINARY'))
134
136
  end
137
+
138
+ context 'when binary subtype is supported' do
139
+ let(:bson) { [3, 0, 0, 0, 1].map(&:chr).join.force_encoding('BINARY') + 'foo' }
140
+
141
+ it 'works' do
142
+ obj.should be_a(described_class)
143
+ obj.type.should be :function
144
+ end
145
+ end
146
+
147
+ context 'when binary subtype is not supported' do
148
+ let(:bson) { [3, 0, 0, 0, 16].map(&:chr).join.force_encoding('BINARY') + 'foo' }
149
+
150
+ it 'raises an exception' do
151
+ lambda do
152
+ obj
153
+ end.should raise_error(BSON::Error::UnsupportedBinarySubtype,
154
+ /BSON data contains unsupported binary subtype 0x10/)
155
+ end
156
+ end
135
157
  end
136
158
 
137
159
  describe "#to_bson/#from_bson" do
@@ -203,6 +225,14 @@ describe BSON::Binary do
203
225
  it_behaves_like "a deserializable bson element"
204
226
  end
205
227
 
228
+ context "when the type is :cyphertext" do
229
+ let(:obj) { described_class.new("testing", :ciphertext) }
230
+ let(:bson) { "#{7.to_bson}#{6.chr}testing" }
231
+
232
+ it_behaves_like "a serializable bson element"
233
+ it_behaves_like "a deserializable bson element"
234
+ end
235
+
206
236
  context 'when given binary string' do
207
237
  let(:obj) { described_class.new("\x00\xfe\xff".force_encoding('BINARY')) }
208
238
  let(:bson) { "#{3.to_bson}#{0.chr}\x00\xfe\xff".force_encoding('BINARY') }