lib/mongo/util/bson.rb in mongo-0.0.3 vs lib/mongo/util/bson.rb in mongo-0.0.4

- old
+ new

@@ -15,12 +15,15 @@ # ++ require 'base64' require 'mongo/util/byte_buffer' require 'mongo/util/ordered_hash' -require 'mongo/objectid' -require 'mongo/dbref' +require 'mongo/types/binary' +require 'mongo/types/dbref' +require 'mongo/types/objectid' +require 'mongo/types/regexp_of_holding' +require 'mongo/types/undefined' # A BSON seralizer/deserializer. class BSON MINKEY = -1 @@ -41,12 +44,22 @@ SYMBOL = 14 CODE_W_SCOPE = 15 NUMBER_INT = 16 MAXKEY = 127 + if RUBY_VERSION >= '1.9' + def self.to_utf8(str) + str.encode("utf-8") + end + else + def self.to_utf8(str) + str # TODO punt for now + end + end + def self.serialize_cstr(buf, val) - buf.put_array(val.to_s.unpack("C*") + [0]) + buf.put_array(to_utf8(val.to_s).unpack("C*") + [0]) end def initialize(db=nil) # db is only needed during deserialization when the data contains a DBRef @db = db @@ -65,11 +78,11 @@ @buf.put_int(0) obj.each {|k, v| type = bson_type(v, k) case type - when STRING, CODE + when STRING, CODE, SYMBOL serialize_string_element(@buf, k, v, type) when NUMBER, NUMBER_INT serialize_number_element(@buf, k, v, type) when OBJECT serialize_object_element(@buf, k, v) @@ -85,12 +98,10 @@ serialize_date_element(@buf, k, v) when NULL serialize_null_element(@buf, k) when REF serialize_dbref_element(@buf, k, v) - when SYMBOL - serialize_symbol_element(@buf, k, v) when BINARY serialize_binary_element(@buf, k, v) when UNDEFINED serialize_undefined_element(@buf, k) when CODE_W_SCOPE @@ -116,10 +127,13 @@ type = @buf.get case type when STRING, CODE key = deserialize_cstr(@buf) doc[key] = deserialize_string_data(@buf) + when SYMBOL + key = deserialize_cstr(@buf) + doc[key] = deserialize_string_data(@buf).intern when NUMBER key = deserialize_cstr(@buf) doc[key] = deserialize_number_data(@buf) when NUMBER_INT key = deserialize_cstr(@buf) @@ -149,13 +163,10 @@ key = deserialize_cstr(@buf) doc[key] = XGen::Mongo::Driver::Undefined.new when REF key = deserialize_cstr(@buf) doc[key] = deserialize_dbref_data(@buf, key, parent) - when SYMBOL - key = deserialize_cstr(@buf) - doc[key] = deserialize_symbol_data(@buf) when BINARY key = deserialize_cstr(@buf) doc[key] = deserialize_binary_data(@buf) when CODE_W_SCOPE # TODO @@ -168,10 +179,11 @@ end @buf.rewind doc end + # For debugging. def hex_dump str = '' @buf.to_a.each_with_index { |b,i| if (i % 8) == 0 str << "\n" if i > 0 @@ -219,17 +231,22 @@ options_str = deserialize_cstr(buf) options = 0 options |= Regexp::IGNORECASE if options_str.include?('i') options |= Regexp::MULTILINE if options_str.include?('m') options |= Regexp::EXTENDED if options_str.include?('x') - Regexp.new(str, options) + options_str.gsub!(/[imx]/, '') # Now remove the three we understand + XGen::Mongo::Driver::RegexpOfHolding.new(str, options, options_str) end def deserialize_string_data(buf) len = buf.get_int bytes = buf.get(len) - bytes[0..-2].pack("C*") + str = bytes[0..-2].pack("C*") + if RUBY_VERSION >= '1.9' + str.force_encoding("utf-8") + end + str end def deserialize_oid_data(buf) XGen::Mongo::Driver::ObjectID.new(buf.get(12)) end @@ -238,14 +255,10 @@ ns = deserialize_cstr(buf) oid = deserialize_oid_data(buf) XGen::Mongo::Driver::DBRef.new(parent, key, @db, ns, oid) end - def deserialize_symbol_data(buf) - deserialize_cstr(buf).intern - end - def deserialize_binary_data(buf) len = buf.get_int bytes = buf.get(len) str = '' bytes.each { |c| str << c.chr } @@ -266,16 +279,10 @@ self.class.serialize_cstr(buf, key) self.class.serialize_cstr(buf, val.namespace) buf.put_array(val.object_id.to_a) end - def serialize_symbol_element(buf, key, val) - buf.put(SYMBOL) - self.class.serialize_cstr(buf, key) - self.class.serialize_cstr(buf, val) - end - def serialize_binary_element(buf, key, val) buf.put(BINARY) self.class.serialize_cstr(buf, key) buf.put_int(val.length) bytes = if RUBY_VERSION >= '1.9' @@ -340,11 +347,13 @@ options = val.options options_str = '' options_str << 'i' if ((options & Regexp::IGNORECASE) != 0) options_str << 'm' if ((options & Regexp::MULTILINE) != 0) options_str << 'x' if ((options & Regexp::EXTENDED) != 0) - self.class.serialize_cstr(buf, options_str) + options_str << val.extra_options_str if val.respond_to?(:extra_options_str) + # Must store option chars in alphabetical order + self.class.serialize_cstr(buf, options_str.split(//).sort.uniq.join) end def serialize_oid_element(buf, key, val) buf.put(OID) self.class.serialize_cstr(buf, key) @@ -376,9 +385,12 @@ chars = "" while 1 b = buf.get break if b == 0 chars << b.chr + end + if RUBY_VERSION >= '1.9' + chars.force_encoding("utf-8") # Mongo stores UTF-8 end chars end def bson_type(o, key)