Merge branch 'master' of git://github.com/jimm/mongo-ruby-driver

This commit is contained in:
Adrian Madrid 2008-12-16 14:36:36 -07:00
commit 9392b7778a
5 changed files with 122 additions and 30 deletions

View File

@ -3,9 +3,9 @@
This is a simple pure-Ruby driver for the 10gen Mongo DB. For more information This is a simple pure-Ruby driver for the 10gen Mongo DB. For more information
about Mongo, see http://www.mongodb.org. about Mongo, see http://www.mongodb.org.
Note: this driver is still alpha quality. The API will change, as will the Note: this driver is still alpha quality. The API will change, as may the
data saved to the database (especially primary key values). Do *_not_* use this data saved to the database (especially primary key values). Do *_not_* use this
for any production data. for any production data yet.
= Demo = Demo
@ -27,7 +27,7 @@ The tests assume that the Mongo database is running on the default port.
$ rake rdoc $ rake rdoc
Then open the file doc/index.html. (I need to figure out where to put this on Then open the file doc/index.html. (I need to figure out where to put this on
the Web, or even how to publish this to the Wiki at the Web, or perhaps how to publish this to the Wiki at
http://github.com/jimm/mongo-ruby-driver/wikis automatically.) http://github.com/jimm/mongo-ruby-driver/wikis automatically.)
@ -53,7 +53,7 @@ type
= To Do = To Do
* Tests that prove that this driver's ObjectID and Geir's Java version do the * Tests that prove that this driver's ObjectID and Geir's Java version do the
same thing. same thing. (I've done so manually.)
* Capped collection support. * Capped collection support.
@ -100,9 +100,3 @@ details.
See http://www.gnu.org/licenses/ for a copy of the GNU Affero General Public See http://www.gnu.org/licenses/ for a copy of the GNU Affero General Public
License. License.
--
# Local Variables:
# mode:rdoc
# End:
++

View File

@ -3,35 +3,34 @@ require 'mongo/util/ordered_hash'
require 'mongo/objectid' require 'mongo/objectid'
# See http://github.com/10gen/mongo/tree/master/db/jsobj.h # See http://github.com/10gen/mongo/tree/master/db/jsobj.h
# and
class BSON class BSON
EOO = 0 # x MINKEY = -1
MAXKEY = -1 # x EOO = 0
NUMBER = 1 # x t NUMBER = 1
STRING = 2 # x t STRING = 2
OBJECT = 3 # x t OBJECT = 3
ARRAY = 4 ARRAY = 4
BINARY = 5 BINARY = 5
UNDEFINED = 6 UNDEFINED = 6
OID = 7 # x OID = 7
BOOLEAN = 8 # x t BOOLEAN = 8
DATE = 9 # x t DATE = 9
NULL = 10 # x t NULL = 10
REGEX = 11 REGEX = 11
REF = 12 REF = 12
CODE = 13 CODE = 13
SYMBOL = 14 SYMBOL = 14
CODE_W_SCOPE = 15 CODE_W_SCOPE = 15
NUMBER_INT = 16 NUMBER_INT = 16
MAXKEY = 127
def self.serialize_cstr(buf, val) def self.serialize_cstr(buf, val)
buf.put_array(val.to_s.unpack("C*") + [0]) buf.put_array(val.to_s.unpack("C*") + [0])
end end
def initialize def initialize
@private_buf = ByteBuffer.new
@buf = ByteBuffer.new @buf = ByteBuffer.new
end end
@ -67,8 +66,10 @@ class BSON
serialize_date_element(@buf, k, v) serialize_date_element(@buf, k, v)
when NULL when NULL
serialize_null_element(@buf, k) serialize_null_element(@buf, k)
when BINARY, UNDEFINED, REF, SYMBOL, CODE_W_SCOPE
raise "unimplemented type #{type}"
else else
raise "Unhandled Type #{type}" raise "unhandled type #{type}"
end end
} }
serialize_eoo_element(@buf) serialize_eoo_element(@buf)
@ -76,15 +77,17 @@ class BSON
self self
end end
def deserialize(buf) def deserialize(buf=nil)
@buf = ByteBuffer.new(buf.to_a) # If buf is nil, use @buf, assumed to contain already-serialized BSON.
# This is only true during testing.
@buf = ByteBuffer.new(buf.to_a) if buf
@buf.rewind @buf.rewind
@buf.get_int # eat message size @buf.get_int # eat message size
doc = {} doc = {}
while @buf.more? while @buf.more?
type = @buf.get type = @buf.get
case type case type
when STRING when STRING, CODE
key = deserialize_element_name(@buf) key = deserialize_element_name(@buf)
doc[key] = deserialize_string_data(@buf) doc[key] = deserialize_string_data(@buf)
when NUMBER when NUMBER
@ -302,7 +305,7 @@ class BSON
when XGen::Mongo::Driver::ObjectID when XGen::Mongo::Driver::ObjectID
OID OID
when true, false when true, false
Boolean BOOLEAN
when Time when Time
DATE DATE
when Hash when Hash

View File

@ -49,8 +49,14 @@ class ByteBuffer
@cursor += array.length @cursor += array.length
end end
def put_int(i, offset=nil) if RUBY_VERSION >= '1.9'
put_array([i].pack(@int_pack_order).split(//).collect{|c| c[0]}, offset) def put_int(i, offset=nil)
put_array([i].pack(@int_pack_order).split(//).collect{|c| c.bytes.first}, offset)
end
else
def put_int(i, offset=nil)
put_array([i].pack(@int_pack_order).split(//).collect{|c| c[0]}, offset)
end
end end
def put_long(i, offset=nil) def put_long(i, offset=nil)
@ -64,8 +70,14 @@ class ByteBuffer
end end
end end
def put_double(d, offset=nil) if RUBY_VERSION >= '1.9'
put_array([d].pack(@double_pack_order).split(//), offset) def put_double(d, offset=nil)
put_array([d].pack(@double_pack_order).split(//).collect{|c| c.bytes.first}, offset)
end
else
def put_double(d, offset=nil)
put_array([d].pack(@double_pack_order).split(//).collect{|c| c[0]}, offset)
end
end end
# If +size+ == 1, returns one byte. Else returns array of bytes of length # If +size+ == 1, returns one byte. Else returns array of bytes of length

77
tests/test_bson.rb Normal file
View File

@ -0,0 +1,77 @@
$LOAD_PATH[0,0] = File.join(File.dirname(__FILE__), '..', 'lib')
require 'mongo'
require 'test/unit'
# NOTE: assumes Mongo is running
class BSONTest < Test::Unit::TestCase
def setup
@b = BSON.new
end
def test_string
doc = {'doc' => 'hello, world'}
@b.serialize(doc)
assert_equal doc, @b.deserialize
end
def test_code
doc = {'$where' => 'this.a.b < this.b'}
@b.serialize(doc)
assert_equal doc, @b.deserialize
end
def test_number
doc = {'doc' => 41.99}
@b.serialize(doc)
assert_equal doc, @b.deserialize
end
def test_int
doc = {'doc' => 42}
@b.serialize(doc)
assert_equal doc, @b.deserialize
end
def test_object
doc = {'doc' => {'age' => 42, 'name' => 'Spongebob', 'shoe_size' => 9.5}}
@b.serialize(doc)
assert_equal doc, @b.deserialize
end
def test_oid
doc = {'doc' => XGen::Mongo::Driver::ObjectID.new}
@b.serialize(doc)
assert_equal doc, @b.deserialize
end
def test_array
doc = {'doc' => [1, 2, 'a', 'b']}
@b.serialize(doc)
assert_equal doc, @b.deserialize
end
def test_regex
doc = {'doc' => /foobar/i}
@b.serialize(doc)
assert_equal doc, @b.deserialize
end
def test_boolean
doc = {'doc' => true}
@b.serialize(doc)
assert_equal doc, @b.deserialize
end
def test_date
doc = {'date' => Time.now}
@b.serialize(doc)
doc2 = @b.deserialize
# Mongo only stores seconds, so comparing raw Time objects will fail
# because the fractional seconds will be different.
assert_equal doc['date'].to_i, doc2['date'].to_i
end
def test_null
end
end

View File

@ -32,6 +32,12 @@ class ByteBufferTest < Test::Unit::TestCase
assert_equal 1027, @buf.get_long assert_equal 1027, @buf.get_long
end end
def test_get_double
@buf.put_double 41.2
@buf.rewind
assert_equal 41.2, @buf.get_double
end
def test_rewrite def test_rewrite
@buf.put_int(0) @buf.put_int(0)
@buf.rewind @buf.rewind