kbaum-mongo 0.18.3p

Sign up to get free protection for your applications and to get access to all the features.
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