mongo-find_replace 0.18.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/LICENSE.txt +202 -0
  2. data/README.rdoc +358 -0
  3. data/Rakefile +133 -0
  4. data/bin/bson_benchmark.rb +59 -0
  5. data/bin/fail_if_no_c.rb +11 -0
  6. data/examples/admin.rb +42 -0
  7. data/examples/capped.rb +22 -0
  8. data/examples/cursor.rb +48 -0
  9. data/examples/gridfs.rb +88 -0
  10. data/examples/index_test.rb +126 -0
  11. data/examples/info.rb +31 -0
  12. data/examples/queries.rb +70 -0
  13. data/examples/simple.rb +24 -0
  14. data/examples/strict.rb +35 -0
  15. data/examples/types.rb +36 -0
  16. data/lib/mongo.rb +61 -0
  17. data/lib/mongo/admin.rb +95 -0
  18. data/lib/mongo/collection.rb +664 -0
  19. data/lib/mongo/connection.rb +555 -0
  20. data/lib/mongo/cursor.rb +393 -0
  21. data/lib/mongo/db.rb +527 -0
  22. data/lib/mongo/exceptions.rb +60 -0
  23. data/lib/mongo/gridfs.rb +22 -0
  24. data/lib/mongo/gridfs/chunk.rb +90 -0
  25. data/lib/mongo/gridfs/grid_store.rb +555 -0
  26. data/lib/mongo/types/binary.rb +48 -0
  27. data/lib/mongo/types/code.rb +36 -0
  28. data/lib/mongo/types/dbref.rb +38 -0
  29. data/lib/mongo/types/min_max_keys.rb +58 -0
  30. data/lib/mongo/types/objectid.rb +219 -0
  31. data/lib/mongo/types/regexp_of_holding.rb +45 -0
  32. data/lib/mongo/util/bson_c.rb +18 -0
  33. data/lib/mongo/util/bson_ruby.rb +595 -0
  34. data/lib/mongo/util/byte_buffer.rb +222 -0
  35. data/lib/mongo/util/conversions.rb +97 -0
  36. data/lib/mongo/util/ordered_hash.rb +135 -0
  37. data/lib/mongo/util/server_version.rb +69 -0
  38. data/lib/mongo/util/support.rb +26 -0
  39. data/lib/mongo/util/xml_to_ruby.rb +112 -0
  40. data/mongo-ruby-driver.gemspec +28 -0
  41. data/test/replica/count_test.rb +34 -0
  42. data/test/replica/insert_test.rb +50 -0
  43. data/test/replica/pooled_insert_test.rb +54 -0
  44. data/test/replica/query_test.rb +39 -0
  45. data/test/test_admin.rb +67 -0
  46. data/test/test_bson.rb +397 -0
  47. data/test/test_byte_buffer.rb +81 -0
  48. data/test/test_chunk.rb +82 -0
  49. data/test/test_collection.rb +534 -0
  50. data/test/test_connection.rb +160 -0
  51. data/test/test_conversions.rb +120 -0
  52. data/test/test_cursor.rb +386 -0
  53. data/test/test_db.rb +254 -0
  54. data/test/test_db_api.rb +783 -0
  55. data/test/test_db_connection.rb +16 -0
  56. data/test/test_grid_store.rb +306 -0
  57. data/test/test_helper.rb +42 -0
  58. data/test/test_objectid.rb +156 -0
  59. data/test/test_ordered_hash.rb +168 -0
  60. data/test/test_round_trip.rb +114 -0
  61. data/test/test_slave_connection.rb +36 -0
  62. data/test/test_threading.rb +87 -0
  63. data/test/threading/test_threading_large_pool.rb +90 -0
  64. data/test/unit/collection_test.rb +52 -0
  65. data/test/unit/connection_test.rb +59 -0
  66. data/test/unit/cursor_test.rb +94 -0
  67. data/test/unit/db_test.rb +97 -0
  68. metadata +123 -0
@@ -0,0 +1,18 @@
1
+ # A thin wrapper for the CBson class
2
+ class BSON_C
3
+
4
+ def self.serialize(obj, check_keys=false)
5
+ ByteBuffer.new(CBson.serialize(obj, check_keys))
6
+ end
7
+
8
+ def self.deserialize(buf=nil)
9
+ if buf.is_a? String
10
+ to_deserialize = ByteBuffer.new(buf) if buf
11
+ else
12
+ buf = ByteBuffer.new(buf.to_a) if buf
13
+ end
14
+ buf.rewind
15
+ CBson.deserialize(buf.to_s)
16
+ end
17
+
18
+ end
@@ -0,0 +1,595 @@
1
+ # --
2
+ # Copyright (C) 2008-2009 10gen Inc.
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify it
5
+ # under the terms of the GNU Affero General Public License, version 3, as
6
+ # published by the Free Software Foundation.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but WITHOUT
9
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
11
+ # for more details.
12
+ #
13
+ # You should have received a copy of the GNU Affero General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+ # ++
16
+
17
+ require 'base64'
18
+ require 'mongo/util/byte_buffer'
19
+ require 'mongo/util/ordered_hash'
20
+ require 'mongo/types/binary'
21
+ require 'mongo/types/dbref'
22
+ require 'mongo/types/objectid'
23
+ require 'mongo/types/regexp_of_holding'
24
+
25
+ # A BSON seralizer/deserializer in pure Ruby.
26
+ class BSON_RUBY
27
+
28
+ include Mongo
29
+
30
+ MINKEY = -1
31
+ EOO = 0
32
+ NUMBER = 1
33
+ STRING = 2
34
+ OBJECT = 3
35
+ ARRAY = 4
36
+ BINARY = 5
37
+ UNDEFINED = 6
38
+ OID = 7
39
+ BOOLEAN = 8
40
+ DATE = 9
41
+ NULL = 10
42
+ REGEX = 11
43
+ REF = 12
44
+ CODE = 13
45
+ SYMBOL = 14
46
+ CODE_W_SCOPE = 15
47
+ NUMBER_INT = 16
48
+ TIMESTAMP = 17
49
+ NUMBER_LONG = 18
50
+ MAXKEY = 127
51
+
52
+ def initialize
53
+ @buf = ByteBuffer.new
54
+ end
55
+
56
+ if RUBY_VERSION >= '1.9'
57
+ def self.to_utf8(str)
58
+ str.encode("utf-8")
59
+ end
60
+ else
61
+ def self.to_utf8(str)
62
+ begin
63
+ str.unpack("U*")
64
+ rescue => ex
65
+ raise InvalidStringEncoding, "String not valid utf-8: #{str}"
66
+ end
67
+ str
68
+ end
69
+ end
70
+
71
+ def self.serialize_cstr(buf, val)
72
+ buf.put_array(to_utf8(val.to_s).unpack("C*") << 0)
73
+ end
74
+
75
+ def self.serialize_key(buf, key)
76
+ raise InvalidDocument, "Key names / regex patterns must not contain the NULL byte" if key.include? "\x00"
77
+ self.serialize_cstr(buf, key)
78
+ end
79
+
80
+ def to_a
81
+ @buf.to_a
82
+ end
83
+
84
+ def to_s
85
+ @buf.to_s
86
+ end
87
+
88
+ # Serializes an object.
89
+ # Implemented to ensure an API compatible with BSON extension.
90
+ def self.serialize(obj, check_keys=false)
91
+ new.serialize(obj, check_keys)
92
+ end
93
+
94
+ def self.deserialize(buf=nil)
95
+ new.deserialize(buf)
96
+ end
97
+
98
+ def serialize(obj, check_keys=false)
99
+ raise "Document is null" unless obj
100
+
101
+ @buf.rewind
102
+ # put in a placeholder for the total size
103
+ @buf.put_int(0)
104
+
105
+ # Write key/value pairs. Always write _id first if it exists.
106
+ if obj.has_key? '_id'
107
+ serialize_key_value('_id', obj['_id'], check_keys)
108
+ elsif obj.has_key? :_id
109
+ serialize_key_value('_id', obj[:_id], check_keys)
110
+ end
111
+
112
+ obj.each {|k, v| serialize_key_value(k, v, check_keys) unless k == '_id' || k == :_id }
113
+
114
+ serialize_eoo_element(@buf)
115
+ if @buf.size > 4 * 1024 * 1024
116
+ raise InvalidDocument, "Document is too large (#{@buf.size}). BSON documents are limited to 4MB (#{4 * 1024 * 1024})."
117
+ end
118
+ @buf.put_int(@buf.size, 0)
119
+ self
120
+ end
121
+
122
+ # Returns the array stored in the buffer.
123
+ # Implemented to ensure an API compatible with BSON extension.
124
+ def unpack(arg)
125
+ @buf.to_a
126
+ end
127
+
128
+ def serialize_key_value(k, v, check_keys)
129
+ k = k.to_s
130
+ if check_keys
131
+ if k[0] == ?$
132
+ raise InvalidName.new("key #{k} must not start with '$'")
133
+ end
134
+ if k.include? ?.
135
+ raise InvalidName.new("key #{k} must not contain '.'")
136
+ end
137
+ end
138
+ type = bson_type(v)
139
+ case type
140
+ when STRING, SYMBOL
141
+ serialize_string_element(@buf, k, v, type)
142
+ when NUMBER, NUMBER_INT
143
+ serialize_number_element(@buf, k, v, type)
144
+ when OBJECT
145
+ serialize_object_element(@buf, k, v, check_keys)
146
+ when OID
147
+ serialize_oid_element(@buf, k, v)
148
+ when ARRAY
149
+ serialize_array_element(@buf, k, v, check_keys)
150
+ when REGEX
151
+ serialize_regex_element(@buf, k, v)
152
+ when BOOLEAN
153
+ serialize_boolean_element(@buf, k, v)
154
+ when DATE
155
+ serialize_date_element(@buf, k, v)
156
+ when NULL
157
+ serialize_null_element(@buf, k)
158
+ when REF
159
+ serialize_dbref_element(@buf, k, v)
160
+ when BINARY
161
+ serialize_binary_element(@buf, k, v)
162
+ when UNDEFINED
163
+ serialize_null_element(@buf, k)
164
+ when CODE_W_SCOPE
165
+ serialize_code_w_scope(@buf, k, v)
166
+ when MAXKEY
167
+ serialize_max_key_element(@buf, k)
168
+ when MINKEY
169
+ serialize_min_key_element(@buf, k)
170
+ else
171
+ raise "unhandled type #{type}"
172
+ end
173
+ end
174
+
175
+ def deserialize(buf=nil)
176
+ # If buf is nil, use @buf, assumed to contain already-serialized BSON.
177
+ # This is only true during testing.
178
+ if buf.is_a? String
179
+ @buf = ByteBuffer.new(buf) if buf
180
+ else
181
+ @buf = ByteBuffer.new(buf.to_a) if buf
182
+ end
183
+ @buf.rewind
184
+ @buf.get_int # eat message size
185
+ doc = OrderedHash.new
186
+ while @buf.more?
187
+ type = @buf.get
188
+ case type
189
+ when STRING, CODE
190
+ key = deserialize_cstr(@buf)
191
+ doc[key] = deserialize_string_data(@buf)
192
+ when SYMBOL
193
+ key = deserialize_cstr(@buf)
194
+ doc[key] = deserialize_string_data(@buf).intern
195
+ when NUMBER
196
+ key = deserialize_cstr(@buf)
197
+ doc[key] = deserialize_number_data(@buf)
198
+ when NUMBER_INT
199
+ key = deserialize_cstr(@buf)
200
+ doc[key] = deserialize_number_int_data(@buf)
201
+ when NUMBER_LONG
202
+ key = deserialize_cstr(@buf)
203
+ doc[key] = deserialize_number_long_data(@buf)
204
+ when OID
205
+ key = deserialize_cstr(@buf)
206
+ doc[key] = deserialize_oid_data(@buf)
207
+ when ARRAY
208
+ key = deserialize_cstr(@buf)
209
+ doc[key] = deserialize_array_data(@buf)
210
+ when REGEX
211
+ key = deserialize_cstr(@buf)
212
+ doc[key] = deserialize_regex_data(@buf)
213
+ when OBJECT
214
+ key = deserialize_cstr(@buf)
215
+ doc[key] = deserialize_object_data(@buf)
216
+ when BOOLEAN
217
+ key = deserialize_cstr(@buf)
218
+ doc[key] = deserialize_boolean_data(@buf)
219
+ when DATE
220
+ key = deserialize_cstr(@buf)
221
+ doc[key] = deserialize_date_data(@buf)
222
+ when NULL
223
+ key = deserialize_cstr(@buf)
224
+ doc[key] = nil
225
+ when UNDEFINED
226
+ key = deserialize_cstr(@buf)
227
+ doc[key] = nil
228
+ when REF
229
+ key = deserialize_cstr(@buf)
230
+ doc[key] = deserialize_dbref_data(@buf)
231
+ when BINARY
232
+ key = deserialize_cstr(@buf)
233
+ doc[key] = deserialize_binary_data(@buf)
234
+ when CODE_W_SCOPE
235
+ key = deserialize_cstr(@buf)
236
+ doc[key] = deserialize_code_w_scope_data(@buf)
237
+ when TIMESTAMP
238
+ key = deserialize_cstr(@buf)
239
+ doc[key] = [deserialize_number_int_data(@buf),
240
+ deserialize_number_int_data(@buf)]
241
+ when MAXKEY
242
+ key = deserialize_cstr(@buf)
243
+ doc[key] = MaxKey.new
244
+ when MINKEY, 255 # This is currently easier than unpack the type byte as an unsigned char.
245
+ key = deserialize_cstr(@buf)
246
+ doc[key] = MinKey.new
247
+ when EOO
248
+ break
249
+ else
250
+ raise "Unknown type #{type}, key = #{key}"
251
+ end
252
+ end
253
+ @buf.rewind
254
+ doc
255
+ end
256
+
257
+ # For debugging.
258
+ def hex_dump
259
+ str = ''
260
+ @buf.to_a.each_with_index { |b,i|
261
+ if (i % 8) == 0
262
+ str << "\n" if i > 0
263
+ str << '%4d: ' % i
264
+ else
265
+ str << ' '
266
+ end
267
+ str << '%02X' % b
268
+ }
269
+ str
270
+ end
271
+
272
+ def deserialize_date_data(buf)
273
+ unsigned = buf.get_long()
274
+ # see note for deserialize_number_long_data below
275
+ milliseconds = unsigned >= 2 ** 64 / 2 ? unsigned - 2**64 : unsigned
276
+ Time.at(milliseconds.to_f / 1000.0).utc # at() takes fractional seconds
277
+ end
278
+
279
+ def deserialize_boolean_data(buf)
280
+ buf.get == 1
281
+ end
282
+
283
+ def deserialize_number_data(buf)
284
+ buf.get_double
285
+ end
286
+
287
+ def deserialize_number_int_data(buf)
288
+ # sometimes ruby makes me angry... why would the same code pack as signed
289
+ # but unpack as unsigned
290
+ unsigned = buf.get_int
291
+ unsigned >= 2**32 / 2 ? unsigned - 2**32 : unsigned
292
+ end
293
+
294
+ def deserialize_number_long_data(buf)
295
+ # same note as above applies here...
296
+ unsigned = buf.get_long
297
+ unsigned >= 2 ** 64 / 2 ? unsigned - 2**64 : unsigned
298
+ end
299
+
300
+ def deserialize_object_data(buf)
301
+ size = buf.get_int
302
+ buf.position -= 4
303
+ object = BSON.new().deserialize(buf.get(size))
304
+ if object.has_key? "$ref"
305
+ DBRef.new(object["$ref"], object["$id"])
306
+ else
307
+ object
308
+ end
309
+ end
310
+
311
+ def deserialize_array_data(buf)
312
+ h = deserialize_object_data(buf)
313
+ a = []
314
+ h.each { |k, v| a[k.to_i] = v }
315
+ a
316
+ end
317
+
318
+ def deserialize_regex_data(buf)
319
+ str = deserialize_cstr(buf)
320
+ options_str = deserialize_cstr(buf)
321
+ options = 0
322
+ options |= Regexp::IGNORECASE if options_str.include?('i')
323
+ options |= Regexp::MULTILINE if options_str.include?('m')
324
+ options |= Regexp::EXTENDED if options_str.include?('x')
325
+ options_str.gsub!(/[imx]/, '') # Now remove the three we understand
326
+ RegexpOfHolding.new(str, options, options_str)
327
+ end
328
+
329
+ def deserialize_string_data(buf)
330
+ len = buf.get_int
331
+ bytes = buf.get(len)
332
+ str = bytes[0..-2]
333
+ if str.respond_to? "pack"
334
+ str = str.pack("C*")
335
+ end
336
+ if RUBY_VERSION >= '1.9'
337
+ str.force_encoding("utf-8")
338
+ end
339
+ str
340
+ end
341
+
342
+ def deserialize_code_w_scope_data(buf)
343
+ buf.get_int
344
+ len = buf.get_int
345
+ code = buf.get(len)[0..-2]
346
+ if code.respond_to? "pack"
347
+ code = code.pack("C*")
348
+ end
349
+ if RUBY_VERSION >= '1.9'
350
+ code.force_encoding("utf-8")
351
+ end
352
+
353
+ scope_size = buf.get_int
354
+ buf.position -= 4
355
+ scope = BSON.new().deserialize(buf.get(scope_size))
356
+
357
+ Code.new(code, scope)
358
+ end
359
+
360
+ def deserialize_oid_data(buf)
361
+ ObjectID.new(buf.get(12))
362
+ end
363
+
364
+ def deserialize_dbref_data(buf)
365
+ ns = deserialize_string_data(buf)
366
+ oid = deserialize_oid_data(buf)
367
+ DBRef.new(ns, oid)
368
+ end
369
+
370
+ def deserialize_binary_data(buf)
371
+ len = buf.get_int
372
+ type = buf.get
373
+ len = buf.get_int if type == Binary::SUBTYPE_BYTES
374
+ Binary.new(buf.get(len), type)
375
+ end
376
+
377
+ def serialize_eoo_element(buf)
378
+ buf.put(EOO)
379
+ end
380
+
381
+ def serialize_null_element(buf, key)
382
+ buf.put(NULL)
383
+ self.class.serialize_key(buf, key)
384
+ end
385
+
386
+ def serialize_dbref_element(buf, key, val)
387
+ oh = OrderedHash.new
388
+ oh['$ref'] = val.namespace
389
+ oh['$id'] = val.object_id
390
+ serialize_object_element(buf, key, oh, false)
391
+ end
392
+
393
+ def serialize_binary_element(buf, key, val)
394
+ buf.put(BINARY)
395
+ self.class.serialize_key(buf, key)
396
+
397
+ bytes = val.to_a
398
+ num_bytes = bytes.length
399
+ subtype = val.respond_to?(:subtype) ? val.subtype : Binary::SUBTYPE_BYTES
400
+ if subtype == Binary::SUBTYPE_BYTES
401
+ buf.put_int(num_bytes + 4)
402
+ buf.put(subtype)
403
+ buf.put_int(num_bytes)
404
+ buf.put_array(bytes)
405
+ else
406
+ buf.put_int(num_bytes)
407
+ buf.put(subtype)
408
+ buf.put_array(bytes)
409
+ end
410
+ end
411
+
412
+ def serialize_boolean_element(buf, key, val)
413
+ buf.put(BOOLEAN)
414
+ self.class.serialize_key(buf, key)
415
+ buf.put(val ? 1 : 0)
416
+ end
417
+
418
+ def serialize_date_element(buf, key, val)
419
+ buf.put(DATE)
420
+ self.class.serialize_key(buf, key)
421
+ millisecs = (val.to_f * 1000).to_i
422
+ buf.put_long(millisecs)
423
+ end
424
+
425
+ def serialize_number_element(buf, key, val, type)
426
+ if type == NUMBER
427
+ buf.put(type)
428
+ self.class.serialize_key(buf, key)
429
+ buf.put_double(val)
430
+ else
431
+ if val > 2**64 / 2 - 1 or val < -2**64 / 2
432
+ raise RangeError.new("MongoDB can only handle 8-byte ints")
433
+ end
434
+ if val > 2**32 / 2 - 1 or val < -2**32 / 2
435
+ buf.put(NUMBER_LONG)
436
+ self.class.serialize_key(buf, key)
437
+ buf.put_long(val)
438
+ else
439
+ buf.put(type)
440
+ self.class.serialize_key(buf, key)
441
+ buf.put_int(val)
442
+ end
443
+ end
444
+ end
445
+
446
+ def serialize_object_element(buf, key, val, check_keys, opcode=OBJECT)
447
+ buf.put(opcode)
448
+ self.class.serialize_key(buf, key)
449
+ buf.put_array(BSON.new.serialize(val, check_keys).to_a)
450
+ end
451
+
452
+ def serialize_array_element(buf, key, val, check_keys)
453
+ # Turn array into hash with integer indices as keys
454
+ h = OrderedHash.new
455
+ i = 0
456
+ val.each { |v| h[i] = v; i += 1 }
457
+ serialize_object_element(buf, key, h, check_keys, ARRAY)
458
+ end
459
+
460
+ def serialize_regex_element(buf, key, val)
461
+ buf.put(REGEX)
462
+ self.class.serialize_key(buf, key)
463
+
464
+ str = val.source
465
+ # We use serialize_key here since regex patterns aren't prefixed with
466
+ # length (can't contain the NULL byte).
467
+ self.class.serialize_key(buf, str)
468
+
469
+ options = val.options
470
+ options_str = ''
471
+ options_str << 'i' if ((options & Regexp::IGNORECASE) != 0)
472
+ options_str << 'm' if ((options & Regexp::MULTILINE) != 0)
473
+ options_str << 'x' if ((options & Regexp::EXTENDED) != 0)
474
+ options_str << val.extra_options_str if val.respond_to?(:extra_options_str)
475
+ # Must store option chars in alphabetical order
476
+ self.class.serialize_cstr(buf, options_str.split(//).sort.uniq.join)
477
+ end
478
+
479
+ def serialize_max_key_element(buf, key)
480
+ buf.put(MAXKEY)
481
+ self.class.serialize_key(buf, key)
482
+ end
483
+
484
+ def serialize_min_key_element(buf, key)
485
+ buf.put(MINKEY)
486
+ self.class.serialize_key(buf, key)
487
+ end
488
+
489
+ def serialize_oid_element(buf, key, val)
490
+ buf.put(OID)
491
+ self.class.serialize_key(buf, key)
492
+
493
+ buf.put_array(val.to_a)
494
+ end
495
+
496
+ def serialize_string_element(buf, key, val, type)
497
+ buf.put(type)
498
+ self.class.serialize_key(buf, key)
499
+
500
+ # Make a hole for the length
501
+ len_pos = buf.position
502
+ buf.put_int(0)
503
+
504
+ # Save the string
505
+ start_pos = buf.position
506
+ self.class.serialize_cstr(buf, val)
507
+ end_pos = buf.position
508
+
509
+ # Put the string size in front
510
+ buf.put_int(end_pos - start_pos, len_pos)
511
+
512
+ # Go back to where we were
513
+ buf.position = end_pos
514
+ end
515
+
516
+ def serialize_code_w_scope(buf, key, val)
517
+ buf.put(CODE_W_SCOPE)
518
+ self.class.serialize_key(buf, key)
519
+
520
+ # Make a hole for the length
521
+ len_pos = buf.position
522
+ buf.put_int(0)
523
+
524
+ buf.put_int(val.length + 1)
525
+ self.class.serialize_cstr(buf, val)
526
+ buf.put_array(BSON.new.serialize(val.scope).to_a)
527
+
528
+ end_pos = buf.position
529
+ buf.put_int(end_pos - len_pos, len_pos)
530
+ buf.position = end_pos
531
+ end
532
+
533
+ def deserialize_cstr(buf)
534
+ chars = ""
535
+ while true
536
+ b = buf.get
537
+ break if b == 0
538
+ chars << b.chr
539
+ end
540
+ if RUBY_VERSION >= '1.9'
541
+ chars.force_encoding("utf-8") # Mongo stores UTF-8
542
+ end
543
+ chars
544
+ end
545
+
546
+ def bson_type(o)
547
+ case o
548
+ when nil
549
+ NULL
550
+ when Integer
551
+ NUMBER_INT
552
+ when Float
553
+ NUMBER
554
+ when ByteBuffer
555
+ BINARY
556
+ when Code
557
+ CODE_W_SCOPE
558
+ when String
559
+ STRING
560
+ when Array
561
+ ARRAY
562
+ when Regexp
563
+ REGEX
564
+ when ObjectID
565
+ OID
566
+ when DBRef
567
+ REF
568
+ when true, false
569
+ BOOLEAN
570
+ when Time
571
+ DATE
572
+ when Hash
573
+ OBJECT
574
+ when Symbol
575
+ SYMBOL
576
+ when MaxKey
577
+ MAXKEY
578
+ when MinKey
579
+ MINKEY
580
+ when Numeric
581
+ raise InvalidDocument, "Cannot serialize the Numeric type #{o.class} as BSON; only Fixum, Bignum, and Float are supported."
582
+ when Date, DateTime
583
+ raise InvalidDocument, "#{o.class} is not currently supported; " +
584
+ "use a UTC Time instance instead."
585
+ else
586
+ if defined?(ActiveSupport::TimeWithZone) && o.is_a?(ActiveSupport::TimeWithZone)
587
+ raise InvalidDocument, "ActiveSupport::TimeWithZone is not currently supported; " +
588
+ "use a UTC Time instance instead."
589
+ else
590
+ raise InvalidDocument, "Cannot serialize #{o.class} as a BSON type; it either isn't supported or won't translate to BSON."
591
+ end
592
+ end
593
+ end
594
+
595
+ end