kbaum-mongo 0.18.3p

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