pax_global_header00006660000000000000000000000064122120063120014477gustar00rootroot0000000000000052 comment=ff932c11fabbe953762a9b9dff5779deb94eee13 ruby-bson-1.9.2/000077500000000000000000000000001221200631200134305ustar00rootroot00000000000000ruby-bson-1.9.2/LICENSE000066400000000000000000000250151221200631200144400ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS Copyright (C) 2008-2013 10gen, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ruby-bson-1.9.2/VERSION000066400000000000000000000000051221200631200144730ustar00rootroot000000000000001.9.2ruby-bson-1.9.2/bin/000077500000000000000000000000001221200631200142005ustar00rootroot00000000000000ruby-bson-1.9.2/bin/b2json000077500000000000000000000030711221200631200153240ustar00rootroot00000000000000#!/usr/bin/env ruby # encoding: UTF-8 # Copyright (C) 2013 10gen Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. require 'rubygems' require 'bson' # Note that this will not properly round-trip in all cases # from the output generated by j2bson. begin require 'yajl' rescue LoadError puts "This script requires yajl. Please install as follows:" puts " gem install yajl-ruby" Process.exit end # Convert all documents in an IO into JSON. def print_b2json(io) while not io.eof? do bsonobj = BSON.read_bson_document(io) Yajl::Encoder.encode(bsonobj, STDOUT) STDOUT << "\n" end end # print usage def usage() STDERR << < BSON::OrderedHash } ) bsonobj = BSON.serialize(jsonobj) STDOUT << bsonobj.to_s end end # print usage def usage() STDERR << < Z`])vPE, 6,{.I> ,f5$9BddtȗAJruby-bson-1.9.2/checksums.yaml.gz.sig000066400000000000000000000004001221200631200174730ustar00rootroot00000000000000a땅0vesG}߾Qc9 :t_h:(0,n>c9eupRm8Nߦ5㒖ˢ8M”7]hqh)qZ{5%s|FW^[͸sRMkYpaFxqyF堆#g~sO73@r7>JlX]GRYC$޸*ըս(6w?CJa2òUT9,F&3Mruby-bson-1.9.2/data.tar.gz.sig000066400000000000000000000004001221200631200162430ustar00rootroot000000000000000^h =eOޡ DH** 3>?x1r"NԮGTKJ(Ax"Cer ZF 9,4z#DNjM/=7䞔3y\Uz(O=L=͍M*7g*\|$e;d!rhRH1>Ll8b0,cQn#b! lyˠǽq}ԙ`vW~) *֑M¸ ?v\دBruby-bson-1.9.2/lib/000077500000000000000000000000001221200631200141765ustar00rootroot00000000000000ruby-bson-1.9.2/lib/bson.rb000066400000000000000000000062021221200631200154640ustar00rootroot00000000000000# Copyright (C) 2013 10gen Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. module BSON DEFAULT_MAX_BSON_SIZE = 4 * 1024 * 1024 def self.serialize(obj, check_keys=false, move_id=false) BSON_CODER.serialize(obj, check_keys, move_id) end def self.deserialize(buf=nil) BSON_CODER.deserialize(buf) end # Reads a single BSON document from an IO object. # This method is used in the executable b2json, bundled with # the bson gem, for reading a file of bson documents. # # @param [IO] io an io object containing a bson object. # # @return [ByteBuffer] def self.read_bson_document(io) bytebuf = BSON::ByteBuffer.new sz = io.read(4).unpack("V")[0] bytebuf.put_int(sz) bytebuf.put_array(io.read(sz-4).unpack("C*")) bytebuf.rewind return BSON.deserialize(bytebuf) end def self.extension? !((ENV.key?('BSON_EXT_DISABLED') && RUBY_PLATFORM =~ /java/) || (ENV.key?('BSON_EXT_DISABLED') || "\x01\x00\x00\x00".unpack("i")[0] != 1)) end end begin # Skips loading extensions if one of the following is true: # 1) JRuby and BSON_EXT_DISABLED is set. # -OR- # 2) Ruby MRI and big endian or BSON_EXT_DISABLED is set. raise LoadError unless BSON.extension? if RUBY_PLATFORM =~ /java/ require 'bson/bson_java' module BSON BSON_CODER = BSON_JAVA end else require 'bson_ext/cbson' raise LoadError unless defined?(CBson::VERSION) require 'bson/bson_c' module BSON BSON_CODER = BSON_C end end rescue LoadError require 'bson/bson_ruby' module BSON BSON_CODER = BSON_RUBY end if RUBY_PLATFORM =~ /java/ unless ENV['TEST_MODE'] warn <<-NOTICE ** Notice: The BSON extension was not loaded. ** For optimal performance, use of the BSON extension is recommended. To enable the extension make sure ENV['BSON_EXT_DISABLED'] is not set. NOTICE end else unless ENV['TEST_MODE'] warn <<-NOTICE ** Notice: The native BSON extension was not loaded. ** For optimal performance, use of the BSON extension is recommended. To enable the extension make sure ENV['BSON_EXT_DISABLED'] is not set and run the following command: gem install bson_ext If you continue to receive this message after installing, make sure that the bson_ext gem is in your load path. NOTICE end end end require 'base64' require 'bson/bson_ruby' require 'bson/byte_buffer' require 'bson/exceptions' require 'bson/ordered_hash' require 'bson/types/binary' require 'bson/types/code' require 'bson/types/dbref' require 'bson/types/min_max_keys' require 'bson/types/object_id' require 'bson/types/timestamp' ruby-bson-1.9.2/lib/bson/000077500000000000000000000000001221200631200151375ustar00rootroot00000000000000ruby-bson-1.9.2/lib/bson/bson_c.rb000066400000000000000000000024161221200631200167320ustar00rootroot00000000000000# Copyright (C) 2013 10gen Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # A thin wrapper for the BSON C-Extension module BSON class BSON_C def self.serialize(obj, check_keys=false, move_id=false, max_bson_size=DEFAULT_MAX_BSON_SIZE) ByteBuffer.new(CBson.serialize(obj, check_keys, move_id, max_bson_size)) end def self.deserialize(buf=nil) CBson.deserialize(ByteBuffer.new(buf).to_s) end def self.max_bson_size warn "BSON::BSON_CODER.max_bson_size is deprecated and will be removed in v2.0." CBson.max_bson_size end def self.update_max_bson_size(connection) warn "BSON::BSON_CODER.update_max_bson_size is deprecated and now a no-op. It will be removed in v2.0." CBson.update_max_bson_size(connection) end end end ruby-bson-1.9.2/lib/bson/bson_java.rb000066400000000000000000000033721221200631200174330ustar00rootroot00000000000000# Copyright (C) 2013 10gen Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. require 'jruby' include Java jar_dir = File.join(File.dirname(__FILE__), '../../ext/jbson') require File.join(jar_dir, 'lib/java-bson.jar') require File.join(jar_dir, 'target/jbson.jar') module BSON class BSON_JAVA def self.serialize(obj, check_keys=false, move_id=false, max_bson_size=DEFAULT_MAX_BSON_SIZE) raise InvalidDocument, "BSON_JAVA.serialize takes a Hash" unless obj.is_a?(Hash) enc = Java::OrgJbson::RubyBSONEncoder.new(JRuby.runtime, check_keys, move_id, max_bson_size) ByteBuffer.new(enc.encode(obj)) end def self.deserialize(buf) dec = Java::OrgJbson::RubyBSONDecoder.new callback = Java::OrgJbson::RubyBSONCallback.new(JRuby.runtime) dec.decode(buf.to_s.to_java_bytes, callback) callback.get end def self.max_bson_size warn "BSON::BSON_CODER.max_bson_size is deprecated and will be removed in v2.0." Java::OrgJbson::RubyBSONEncoder.max_bson_size(self) end def self.update_max_bson_size(connection) warn "BSON::BSON_CODER.update_max_bson_size is deprecated and now a no-op. It will be removed in v2.0." Java::OrgJbson::RubyBSONEncoder.update_max_bson_size(self, connection) end end end ruby-bson-1.9.2/lib/bson/bson_ruby.rb000066400000000000000000000425551221200631200175010ustar00rootroot00000000000000# Copyright (C) 2013 10gen Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. module BSON NULL_BYTE = "\x00" # A BSON seralizer/deserializer in pure Ruby. class BSON_RUBY @@max_bson_size = DEFAULT_MAX_BSON_SIZE MINKEY = -1 EOO = 0 NUMBER = 1 STRING = 2 OBJECT = 3 ARRAY = 4 BINARY = 5 UNDEFINED = 6 OID = 7 BOOLEAN = 8 DATE = 9 NULL = 10 REGEX = 11 REF = 12 CODE = 13 SYMBOL = 14 CODE_W_SCOPE = 15 NUMBER_INT = 16 TIMESTAMP = 17 NUMBER_LONG = 18 MAXKEY = 127 INT32_MIN = -(1 << 31) + 1 INT32_MAX = (1 << 31) - 1 INT64_MIN = -2**64 / 2 INT64_MAX = 2**64 / 2 - 1 def initialize(max_bson_size=DEFAULT_MAX_BSON_SIZE) @buf = ByteBuffer.new('', max_bson_size) @encoder = BSON_RUBY end if RUBY_VERSION >= '1.9' UTF8_ENCODING = Encoding.find('utf-8') BINARY_ENCODING = Encoding.find('binary') def self.to_utf8_binary(str) begin str.unpack("U*") rescue raise InvalidStringEncoding, "String not valid utf-8: #{str.inspect}" end str.dup.force_encoding(BINARY_ENCODING) end else def self.to_utf8_binary(str) begin str.unpack("U*") rescue raise InvalidStringEncoding, "String not valid utf-8: #{str.inspect}" end str end end def self.update_max_bson_size(connection) warn "BSON::BSON_CODER.update_max_bson_size is deprecated and now a no-op. It will be removed in v2.0." @@max_bson_size = connection.max_bson_size end def self.max_bson_size warn "BSON::BSON_CODER.max_bson_size is deprecated and will be removed in v2.0." @@max_bson_size end def self.serialize_cstr(buf, val) buf.put_binary(to_utf8_binary(val.to_s)) buf.put_binary(NULL_BYTE) end def self.serialize_key(buf, key) raise InvalidDocument, "Key names / regex patterns must not contain the NULL byte" if key.include? "\x00" self.serialize_cstr(buf, key) end def to_a @buf.to_a end def to_s @buf.to_s end # Serializes an object. # Implemented to ensure an API compatible with BSON extension. def self.serialize(obj, check_keys=false, move_id=false, max_bson_size=DEFAULT_MAX_BSON_SIZE) new(max_bson_size).serialize(obj, check_keys, move_id) end def self.deserialize(buf=nil) new.deserialize(buf) end def serialize(obj, check_keys=false, move_id=false) raise(InvalidDocument, "BSON.serialize takes a Hash but got a #{obj.class}") unless obj.is_a?(Hash) raise "Document is null" unless obj @buf.rewind # put in a placeholder for the total size @buf.put_int(0) # Write key/value pairs. Always write _id first if it exists. if move_id if obj.has_key? '_id' serialize_key_value('_id', obj['_id'], false) elsif obj.has_key? :_id serialize_key_value('_id', obj[:_id], false) end obj.each {|k, v| serialize_key_value(k, v, check_keys) unless k == '_id' || k == :_id } else if obj.has_key?('_id') && obj.has_key?(:_id) obj['_id'] = obj.delete(:_id) end obj.each {|k, v| serialize_key_value(k, v, check_keys) } end serialize_eoo_element(@buf) if @buf.size > @buf.max_size raise InvalidDocument, "Document is too large (#{@buf.size}). " + "This BSON document is limited to #{@buf.max_size} bytes." end @buf.put_int(@buf.size, 0) @buf end # Returns the array stored in the buffer. # Implemented to ensure an API compatible with BSON extension. def unpack @buf.to_a end def serialize_key_value(k, v, check_keys) k = k.to_s if check_keys if k[0] == ?$ raise InvalidKeyName.new("key #{k} must not start with '$'") end if k.include? ?. raise InvalidKeyName.new("key #{k} must not contain '.'") end end type = bson_type(v) case type when STRING, 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, check_keys) when OID serialize_oid_element(@buf, k, v) when ARRAY serialize_array_element(@buf, k, v, check_keys) when REGEX serialize_regex_element(@buf, k, v) when BOOLEAN serialize_boolean_element(@buf, k, v) when DATE serialize_date_element(@buf, k, v) when NULL serialize_null_element(@buf, k) when REF serialize_dbref_element(@buf, k, v) when BINARY serialize_binary_element(@buf, k, v) when UNDEFINED serialize_null_element(@buf, k) when CODE_W_SCOPE serialize_code_w_scope(@buf, k, v) when MAXKEY serialize_max_key_element(@buf, k) when MINKEY serialize_min_key_element(@buf, k) when TIMESTAMP serialize_timestamp_element(@buf, k, v) else raise "unhandled type #{type}" end end def deserialize(buf=nil) # If buf is nil, use @buf, assumed to contain already-serialized BSON. # This is only true during testing. if buf.is_a? String @buf = ByteBuffer.new(buf.unpack("C*")) if buf else @buf = ByteBuffer.new(buf.to_a) if buf end @buf.rewind @buf.get_int # eat message size doc = BSON::OrderedHash.new while @buf.more? 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) doc[key] = deserialize_number_int_data(@buf) when NUMBER_LONG key = deserialize_cstr(@buf) doc[key] = deserialize_number_long_data(@buf) when OID key = deserialize_cstr(@buf) doc[key] = deserialize_oid_data(@buf) when ARRAY key = deserialize_cstr(@buf) doc[key] = deserialize_array_data(@buf) when REGEX key = deserialize_cstr(@buf) doc[key] = deserialize_regex_data(@buf) when OBJECT key = deserialize_cstr(@buf) doc[key] = deserialize_object_data(@buf) when BOOLEAN key = deserialize_cstr(@buf) doc[key] = deserialize_boolean_data(@buf) when DATE key = deserialize_cstr(@buf) doc[key] = deserialize_date_data(@buf) when NULL key = deserialize_cstr(@buf) doc[key] = nil when UNDEFINED key = deserialize_cstr(@buf) doc[key] = nil when REF key = deserialize_cstr(@buf) doc[key] = deserialize_dbref_data(@buf) when BINARY key = deserialize_cstr(@buf) doc[key] = deserialize_binary_data(@buf) when CODE_W_SCOPE key = deserialize_cstr(@buf) doc[key] = deserialize_code_w_scope_data(@buf) when TIMESTAMP key = deserialize_cstr(@buf) doc[key] = deserialize_timestamp_data(@buf) when MAXKEY key = deserialize_cstr(@buf) doc[key] = MaxKey.new when MINKEY, 255 # This is currently easier than unpack the type byte as an unsigned char. key = deserialize_cstr(@buf) doc[key] = MinKey.new when EOO break else raise "Unknown type #{type}, key = #{key}" end 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 str << '%4d: ' % i else str << ' ' end str << '%02X' % b } str end def deserialize_date_data(buf) milliseconds = buf.get_long Time.at(milliseconds.to_f / 1000.0).utc # at() takes fractional seconds end def deserialize_boolean_data(buf) buf.get == 1 end def deserialize_number_data(buf) buf.get_double end def deserialize_number_int_data(buf) buf.get_int end def deserialize_number_long_data(buf) buf.get_long end def deserialize_object_data(buf) size = buf.get_int buf.position -= 4 object = @encoder.new.deserialize(buf.get(size)) if object.has_key? "$ref" DBRef.new(object["$ref"], object["$id"]) else object end end def deserialize_array_data(buf) h = deserialize_object_data(buf) a = [] h.each { |k, v| a[k.to_i] = v } a end def deserialize_regex_data(buf) str = deserialize_cstr(buf) options_str = deserialize_cstr(buf) opts = 0 opts |= Regexp::IGNORECASE if options_str.include?('i') opts |= Regexp::MULTILINE if options_str.include?('m') opts |= Regexp::MULTILINE if options_str.include?('s') opts |= Regexp::EXTENDED if options_str.include?('x') Regexp.new(str, opts) end def deserialize_timestamp_data(buf) increment = buf.get_int seconds = buf.get_int Timestamp.new(seconds, increment) end def encoded_str(str) if RUBY_VERSION >= '1.9' str.force_encoding("utf-8") if Encoding.default_internal str.encode!(Encoding.default_internal) end end str end def deserialize_string_data(buf) len = buf.get_int bytes = buf.get(len) str = bytes[0..-2] if str.respond_to? "pack" str = str.pack("C*") end encoded_str(str) end def deserialize_code_w_scope_data(buf) buf.get_int len = buf.get_int code = buf.get(len)[0..-2] if code.respond_to? "pack" code = code.pack("C*") end scope_size = buf.get_int buf.position -= 4 scope = @encoder.new.deserialize(buf.get(scope_size)) Code.new(encoded_str(code), scope) end def deserialize_oid_data(buf) ObjectId.new(buf.get(12)) end def deserialize_dbref_data(buf) ns = deserialize_string_data(buf) oid = deserialize_oid_data(buf) DBRef.new(ns, oid) end def deserialize_binary_data(buf) len = buf.get_int type = buf.get len = buf.get_int if type == Binary::SUBTYPE_BYTES Binary.new(buf.get(len), type) end def serialize_eoo_element(buf) buf.put(EOO) end def serialize_null_element(buf, key) buf.put(NULL) self.class.serialize_key(buf, key) end def serialize_dbref_element(buf, key, val) # this does NOT use the BSON "\x0C" DBPointer type oh = BSON::OrderedHash.new oh['$ref'] = val.namespace oh['$id'] = val.object_id serialize_object_element(buf, key, oh, false) end def serialize_binary_element(buf, key, val) buf.put(BINARY) self.class.serialize_key(buf, key) bytes = val.to_a num_bytes = bytes.length subtype = val.respond_to?(:subtype) ? val.subtype : Binary::SUBTYPE_BYTES if subtype == Binary::SUBTYPE_BYTES buf.put_int(num_bytes + 4) buf.put(subtype) buf.put_int(num_bytes) buf.put_array(bytes) else buf.put_int(num_bytes) buf.put(subtype) buf.put_array(bytes) end end def serialize_boolean_element(buf, key, val) buf.put(BOOLEAN) self.class.serialize_key(buf, key) buf.put(val ? 1 : 0) end def serialize_date_element(buf, key, val) buf.put(DATE) self.class.serialize_key(buf, key) millisecs = (val.to_f * 1000).to_i buf.put_long(millisecs) end def serialize_number_element(buf, key, val, type) if type == NUMBER buf.put(type) self.class.serialize_key(buf, key) buf.put_double(val) else if val > INT64_MAX or val < INT64_MIN raise RangeError.new("MongoDB can only handle 8-byte ints") end if val > INT32_MAX or val < INT32_MIN buf.put(NUMBER_LONG) self.class.serialize_key(buf, key) buf.put_long(val) else buf.put(type) self.class.serialize_key(buf, key) buf.put_int(val) end end end def serialize_object_element(buf, key, val, check_keys, opcode=OBJECT) buf.put(opcode) self.class.serialize_key(buf, key) buf.put_array(@encoder.new.serialize(val, check_keys).to_a) end def serialize_array_element(buf, key, val, check_keys) # Turn array into hash with integer indices as keys h = BSON::OrderedHash.new i = 0 val.each { |v| h[i] = v; i += 1 } serialize_object_element(buf, key, h, check_keys, ARRAY) end def serialize_regex_element(buf, key, val) buf.put(REGEX) self.class.serialize_key(buf, key) str = val.source # We use serialize_key here since regex patterns aren't prefixed with # length (can't contain the NULL byte). self.class.serialize_key(buf, str) options = val.options options_str = '' options_str << 'i' if ((options & Regexp::IGNORECASE) != 0) if ((options & Regexp::MULTILINE) != 0) options_str << 'm' options_str << 's' end options_str << 'x' if ((options & Regexp::EXTENDED) != 0) 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_max_key_element(buf, key) buf.put(MAXKEY) self.class.serialize_key(buf, key) end def serialize_min_key_element(buf, key) buf.put(MINKEY) self.class.serialize_key(buf, key) end def serialize_timestamp_element(buf, key, val) buf.put(TIMESTAMP) self.class.serialize_key(buf, key) buf.put_int(val.increment) buf.put_int(val.seconds) end def serialize_oid_element(buf, key, val) buf.put(OID) self.class.serialize_key(buf, key) buf.put_array(val.to_a) end def serialize_string_element(buf, key, val, type) buf.put(type) self.class.serialize_key(buf, key) # Make a hole for the length len_pos = buf.position buf.put_int(0) # Save the string start_pos = buf.position self.class.serialize_cstr(buf, val) end_pos = buf.position # Put the string size in front buf.put_int(end_pos - start_pos, len_pos) # Go back to where we were buf.position = end_pos end def serialize_code_w_scope(buf, key, val) buf.put(CODE_W_SCOPE) self.class.serialize_key(buf, key) # Make a hole for the length len_pos = buf.position buf.put_int(0) buf.put_int(val.code.length + 1) self.class.serialize_cstr(buf, val.code) buf.put_array(@encoder.new.serialize(val.scope).to_a) end_pos = buf.position buf.put_int(end_pos - len_pos, len_pos) buf.position = end_pos end def deserialize_cstr(buf) chars = "" while true b = buf.get break if b == 0 chars << b.chr end encoded_str(chars) end def bson_type(o) case o when nil NULL when Integer NUMBER_INT when Float NUMBER when ByteBuffer BINARY when Code CODE_W_SCOPE when String STRING when Array ARRAY when Regexp REGEX when ObjectId OID when DBRef REF when true, false BOOLEAN when Time DATE when Hash OBJECT when Symbol SYMBOL when MaxKey MAXKEY when MinKey MINKEY when Timestamp TIMESTAMP when Numeric raise InvalidDocument, "Cannot serialize the Numeric type #{o.class} as BSON; only Fixum, Bignum, and Float are supported." when Date, DateTime raise InvalidDocument, "#{o.class} is not currently supported; " + "use a UTC Time instance instead." else if defined?(ActiveSupport::Multibyte::Chars) && o.is_a?(ActiveSupport::Multibyte::Chars) STRING elsif defined?(ActiveSupport::TimeWithZone) && o.is_a?(ActiveSupport::TimeWithZone) raise InvalidDocument, "ActiveSupport::TimeWithZone is not currently supported; " + "use a UTC Time instance instead." else raise InvalidDocument, "Cannot serialize #{o.class} as a BSON type; it either isn't supported or won't translate to BSON." end end end end end ruby-bson-1.9.2/lib/bson/byte_buffer.rb000066400000000000000000000120721221200631200177620ustar00rootroot00000000000000# Copyright (C) 2013 10gen Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. module BSON class ByteBuffer attr_reader :order, :max_size INT32_PACK = 'l<'.freeze INT64_PACK = 'q<'.freeze DOUBLE_PACK = 'E'.freeze def initialize(initial_data="", max_size=DEFAULT_MAX_BSON_SIZE) @str = case initial_data when String then if initial_data.respond_to?(:force_encoding) initial_data.force_encoding('binary') else initial_data end when BSON::ByteBuffer then initial_data.to_a.pack('C*') else initial_data.pack('C*') end @cursor = @str.length @max_size = max_size end def rewind @cursor = 0 end def position @cursor end def position=(val) @cursor = val end def clear @str = "" @str.force_encoding('binary') if @str.respond_to?(:force_encoding) rewind end def size @str.size end alias_method :length, :size # Appends a second ByteBuffer object, +buffer+, to the current buffer. def append!(buffer) @str << buffer.to_s self end # Prepends a second ByteBuffer object, +buffer+, to the current buffer. def prepend!(buffer) @str = buffer.to_s + @str self end def put(byte, offset=nil) @cursor = offset if offset if more? @str[@cursor] = chr(byte) else ensure_length(@cursor) @str << chr(byte) end @cursor += 1 end def put_binary(data, offset=nil) @cursor = offset if offset if defined?(BINARY_ENCODING) data = data.dup.force_encoding(BINARY_ENCODING) end if more? @str[@cursor, data.length] = data else ensure_length(@cursor) @str << data end @cursor += data.length end def put_array(array, offset=nil) @cursor = offset if offset if more? @str[@cursor, array.length] = array.pack("C*") else ensure_length(@cursor) @str << array.pack("C*") end @cursor += array.length end def put_num(i, offset, bytes) pack_type = bytes == 4 ? INT32_PACK : INT64_PACK @cursor = offset if offset if more? @str[@cursor, bytes] = [i].pack(pack_type) else ensure_length(@cursor) @str << [i].pack(pack_type) end @cursor += bytes end def put_int(i, offset=nil) put_num(i, offset, 4) end def put_long(i, offset=nil) put_num(i, offset, 8) end def put_double(d, offset=nil) a = [] [d].pack(DOUBLE_PACK).each_byte { |b| a << b } put_array(a, offset) end # If +size+ == nil, returns one byte. Else returns array of bytes of length # # +size+. if "x"[0].is_a?(Integer) def get(len=nil) one_byte = len.nil? len ||= 1 check_read_length(len) start = @cursor @cursor += len if one_byte @str[start] else @str[start, len].unpack("C*") end end else def get(len=nil) one_byte = len.nil? len ||= 1 check_read_length(len) start = @cursor @cursor += len if one_byte @str[start, 1].ord else @str[start, len].unpack("C*") end end end def get_int check_read_length(4) vals = @str[@cursor..@cursor+3] @cursor += 4 vals.unpack(INT32_PACK)[0] end def get_long check_read_length(8) vals = @str[@cursor..@cursor+7] @cursor += 8 vals.unpack(INT64_PACK)[0] end def get_double check_read_length(8) vals = @str[@cursor..@cursor+7] @cursor += 8 vals.unpack(DOUBLE_PACK)[0] end def more? @cursor < @str.size end def ==(other) other.respond_to?(:to_s) && @str == other.to_s end def to_a(format="C*") @str.unpack(format) end def unpack(format="C*") to_a(format) end def to_s @str end def dump @str.each_byte do |c, i| $stderr.puts "#{'%04d' % i}: #{'%02x' % c} #{'%03o' % c} #{'%s' % c.chr} #{'%3d' % c}" i += 1 end end private def ensure_length(length) if @str.size < length @str << NULL_BYTE * (length - @str.size) end end def chr(byte) if byte < 0 [byte].pack('c') else byte.chr end end def check_read_length(len) raise "attempt to read past end of buffer" if @cursor + len > @str.length end end end ruby-bson-1.9.2/lib/bson/exceptions.rb000066400000000000000000000025011221200631200176430ustar00rootroot00000000000000# Copyright (C) 2013 10gen Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. module BSON # Generic Mongo Ruby Driver exception class. class MongoRubyError < StandardError; end # Raised when MongoDB itself has returned an error. class MongoDBError < RuntimeError; end # This will replace MongoDBError. class BSONError < MongoDBError; end # Raised when given a string is not valid utf-8 (Ruby 1.8 only). class InvalidStringEncoding < BSONError; end # Raised when attempting to initialize an invalid ObjectId. class InvalidObjectId < BSONError; end # Raised when trying to insert a document that exceeds the 4MB limit or # when the document contains objects that can't be serialized as BSON. class InvalidDocument < BSONError; end # Raised when an invalid name is used. class InvalidKeyName < BSONError; end end ruby-bson-1.9.2/lib/bson/ordered_hash.rb000066400000000000000000000104551221200631200201200ustar00rootroot00000000000000# Copyright (C) 2013 10gen Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # A hash in which the order of keys are preserved. # # Under Ruby 1.9 and greater, this class has no added methods because Ruby's # Hash already keeps its keys ordered by order of insertion. module BSON class OrderedHash < Hash def ==(other) begin case other when BSON::OrderedHash keys == other.keys && values == other.values else super end rescue false end end # Allows activesupport Array#extract_options! to extract options # when they are instance of BSON::OrderedHash # # @return [true, false] true if options can be extracted def extractable_options? instance_of?(BSON::OrderedHash) end # We only need the body of this class if the RUBY_VERSION is before 1.9 if RUBY_VERSION < '1.9' attr_accessor :ordered_keys def self.[] *args oh = BSON::OrderedHash.new if Hash === args[0] oh.merge! args[0] elsif (args.size % 2) != 0 raise ArgumentError, "odd number of elements for Hash" else 0.step(args.size - 1, 2) do |key| value = key + 1 oh[args[key]] = args[value] end end oh end def initialize(*a, &b) @ordered_keys = [] super end def yaml_initialize(tag, val) @ordered_keys = [] super end def keys @ordered_keys.dup end def []=(key, value) unless has_key?(key) @ordered_keys << key end super(key, value) end def each @ordered_keys.each { |k| yield k, self[k] } self end alias :each_pair :each def to_a @ordered_keys.map { |k| [k, self[k]] } end def values collect { |k, v| v } end def replace(other) @ordered_keys.replace(other.keys) super end def merge(other) oh = self.dup oh.merge!(other) oh end def merge!(other) @ordered_keys += other.keys # unordered if not an BSON::OrderedHash @ordered_keys.uniq! super(other) end alias :update :merge! def dup result = OrderedHash.new @ordered_keys.each do |key| result[key] = self[key] end result end def inspect str = "##{self.[](k).inspect}" }.join(", ") str << '}>' end def delete(key, &block) @ordered_keys.delete(key) if @ordered_keys super end def delete_if(&block) keys.each do |key| if yield key, self[key] delete(key) end end self end def reject(&block) clone = self.clone return clone unless block_given? clone.delete_if(&block) end def reject!(&block) changed = false self.each do |k,v| if yield k, v changed = true delete(k) end end changed ? self : nil end def clear super @ordered_keys = [] end def initialize_copy(original) super @ordered_keys = original.ordered_keys.dup end if RUBY_VERSION =~ /1.8.6/ def hash code = 17 each_pair do |key, value| code = 37 * code + key.hash code = 37 * code + value.hash end code & 0x7fffffff end def eql?(o) if o.instance_of? BSON::OrderedHash self.hash == o.hash else false end end end end end end ruby-bson-1.9.2/lib/bson/support/000077500000000000000000000000001221200631200166535ustar00rootroot00000000000000ruby-bson-1.9.2/lib/bson/support/hash_with_indifferent_access.rb000066400000000000000000000107621221200631200250620ustar00rootroot00000000000000# Copyright (C) 2013 10gen Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. require 'active_support' begin require 'active_support/hash_with_indifferent_access' rescue LoadError # For ActiveSupport 2 require 'active_support/core_ext/hash/indifferent_access' end module ActiveSupport class HashWithIndifferentAccess < Hash def extractable_options? true end def initialize(constructor = {}) if constructor.is_a?(Hash) super() update(constructor) else super(constructor) end end def default(key = nil) if key.is_a?(Symbol) && include?(key = key.to_s) self[key] else super end end def self.new_from_hash_copying_default(hash) ActiveSupport::HashWithIndifferentAccess.new(hash).tap do |new_hash| new_hash.default = hash.default end end alias_method :regular_writer, :[]= unless method_defined?(:regular_writer) alias_method :regular_update, :update unless method_defined?(:regular_update) # Assigns a new value to the hash: # # hash = HashWithIndifferentAccess.new # hash[:key] = "value" # def []=(key, value) regular_writer(convert_key(key), convert_value(value)) end # Updates the instantized hash with values from the second: # # hash_1 = HashWithIndifferentAccess.new # hash_1[:key] = "value" # # hash_2 = HashWithIndifferentAccess.new # hash_2[:key] = "New Value!" # # hash_1.update(hash_2) # => {"key"=>"New Value!"} # def update(other_hash) other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) } self end alias_method :merge!, :update # Checks the hash for a key matching the argument passed in: # # hash = HashWithIndifferentAccess.new # hash["key"] = "value" # hash.key? :key # => true # hash.key? "key" # => true # def key?(key) super(convert_key(key)) end alias_method :include?, :key? alias_method :has_key?, :key? alias_method :member?, :key? # Fetches the value for the specified key, same as doing hash[key] def fetch(key, *extras) super(convert_key(key), *extras) end # Returns an array of the values at the specified indices: # # hash = HashWithIndifferentAccess.new # hash[:a] = "x" # hash[:b] = "y" # hash.values_at("a", "b") # => ["x", "y"] # def values_at(*indices) indices.collect {|key| self[convert_key(key)]} end # Returns an exact copy of the hash. def dup HashWithIndifferentAccess.new(self) end # Merges the instantized and the specified hashes together, giving precedence to the values from the second hash # Does not overwrite the existing hash. def merge(hash) self.dup.update(hash) end # Performs the opposite of merge, with the keys and values from the first hash taking precedence over the second. # This overloaded definition prevents returning a regular hash, if reverse_merge is called on a HashWithDifferentAccess. def reverse_merge(other_hash) super self.class.new_from_hash_copying_default(other_hash) end def reverse_merge!(other_hash) replace(reverse_merge( other_hash )) end # Removes a specified key from the hash. def delete(key) super(convert_key(key)) end def stringify_keys!; self end def stringify_keys; dup end def symbolize_keys; to_hash.symbolize_keys end def to_options!; self end # Convert to a Hash with String keys. def to_hash Hash.new(default).merge!(self) end protected def convert_key(key) key.kind_of?(Symbol) ? key.to_s : key end def convert_value(value) case value when Hash self.class.new_from_hash_copying_default(value) when Array value.collect { |e| e.is_a?(Hash) ? self.class.new_from_hash_copying_default(e) : e } else value end end end end ruby-bson-1.9.2/lib/bson/types/000077500000000000000000000000001221200631200163035ustar00rootroot00000000000000ruby-bson-1.9.2/lib/bson/types/binary.rb000066400000000000000000000032671221200631200201240ustar00rootroot00000000000000# Copyright (C) 2013 10gen Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. require 'bson/byte_buffer' module BSON # An array of binary bytes with a MongoDB subtype. See the subtype # constants for reference. # # Use this class when storing binary data in documents. class Binary < ByteBuffer SUBTYPE_SIMPLE = 0x00 SUBTYPE_BYTES = 0x02 SUBTYPE_UUID = 0x03 SUBTYPE_MD5 = 0x05 SUBTYPE_USER_DEFINED = 0x80 # One of the SUBTYPE_* constants. Default is SUBTYPE_BYTES. attr_accessor :subtype # Create a buffer for storing binary data in MongoDB. # # @param [Array, String] data to story as BSON binary. If a string is given, the on # Ruby 1.9 it will be forced to the binary encoding. # @param [Fixnum] one of four values specifying a BSON binary subtype. Possible values are # SUBTYPE_BYTES, SUBTYPE_UUID, SUBTYPE_MD5, and SUBTYPE_USER_DEFINED. # # @see http://www.mongodb.org/display/DOCS/BSON#BSON-noteondatabinary BSON binary subtypes. def initialize(data=[], subtype=SUBTYPE_SIMPLE) super(data) @subtype = subtype end def inspect "" end end end ruby-bson-1.9.2/lib/bson/types/code.rb000066400000000000000000000027521221200631200175500ustar00rootroot00000000000000# Copyright (C) 2013 10gen Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. module BSON # JavaScript code to be evaluated by MongoDB. class Code # Hash mapping identifiers to their values attr_accessor :scope, :code # Wrap code to be evaluated by MongoDB. # # @param [String] code the JavaScript code. # @param [Hash] a document mapping identifiers to values, which # represent the scope in which the code is to be executed. def initialize(code, scope={}) @code = code @scope = scope unless @code.is_a?(String) raise ArgumentError, "BSON::Code must be in the form of a String; #{@code.class} is not allowed." end end def length @code.length end def ==(other) self.class == other.class && @code == other.code && @scope == other.scope end def inspect "" end def to_bson_code self end end end ruby-bson-1.9.2/lib/bson/types/dbref.rb000066400000000000000000000022111221200631200177060ustar00rootroot00000000000000# Copyright (C) 2013 10gen Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. module BSON # A reference to another object in a MongoDB database. class DBRef attr_reader :namespace, :object_id # Create a DBRef. Use this class in conjunction with DB#dereference. # # @param [String] a collection name # @param [ObjectId] an object id # # @core dbrefs constructor_details def initialize(namespace, object_id) @namespace = namespace @object_id = object_id end def to_s "ns: #{namespace}, id: #{object_id}" end def to_hash {"$ns" => @namespace, "$id" => @object_id } end end end ruby-bson-1.9.2/lib/bson/types/min_max_keys.rb000066400000000000000000000035221221200631200213150ustar00rootroot00000000000000# Copyright (C) 2013 10gen Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. module BSON # A class representing the BSON MaxKey type. MaxKey will always compare greater than # all other BSON types and values. # # @example Sorting (assume @numbers is a collection): # # >> @numbers.save({"n" => Mongo::MaxKey.new}) # >> @numbers.save({"n" => 0}) # >> @numbers.save({"n" => 5_000_000}) # >> @numbers.find.sort("n").to_a # => [{"_id"=>4b5a050c238d3bace2000004, "n"=>0}, # {"_id"=>4b5a04e6238d3bace2000002, "n"=>5_000_000}, # {"_id"=>4b5a04ea238d3bace2000003, "n"=>#}, # ] class MaxKey def ==(obj) obj.class == MaxKey end end # A class representing the BSON MinKey type. MinKey will always compare less than # all other BSON types and values. # # @example Sorting (assume @numbers is a collection): # # >> @numbers.save({"n" => Mongo::MinKey.new}) # >> @numbers.save({"n" => -1_000_000}) # >> @numbers.save({"n" => 1_000_000}) # >> @numbers.find.sort("n").to_a # => [{"_id"=>4b5a050c238d3bace2000004, "n"=>#}, # {"_id"=>4b5a04e6238d3bace2000002, "n"=>-1_000_000}, # {"_id"=>4b5a04ea238d3bace2000003, "n"=>1_000_000}, # ] class MinKey def ==(obj) obj.class == MinKey end end end ruby-bson-1.9.2/lib/bson/types/object_id.rb000066400000000000000000000153261221200631200205610ustar00rootroot00000000000000# Copyright (C) 2013 10gen Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. require 'thread' require 'socket' require 'digest/md5' module BSON def BSON::ObjectId(s) ObjectId.from_string(s) end # Generates MongoDB object ids. # # @core objectids class ObjectId attr_accessor :data # Create a new object id. If no parameter is given, an id corresponding # to the ObjectId BSON data type will be created. This is a 12-byte value # consisting of a 4-byte timestamp, a 3-byte machine id, a 2-byte process id, # and a 3-byte counter. # # @param [Array] data should be an array of bytes. If you want # to generate a standard MongoDB object id, leave this argument blank. # # @option opts :data (nil) An array of bytes to use as the object id. # @option opts :time (nil) The value of this object ids timestamp. Note that # the remaining bytes will consist of the standard machine id, pid, and counter. If # you need a zeroed timestamp, used ObjectId.from_time. def initialize(data=nil, time=nil) if data && (!data.is_a?(Array) || data.size != 12) raise InvalidObjectId, 'ObjectId requires 12 byte array' end @data = data || generate(time) end # Determine if the supplied string is legal. Legal strings will # consist of 24 hexadecimal characters. # # @param [String] str # # @return [Boolean] def self.legal?(str) str =~ /^[0-9a-f]{24}$/i ? true : false end # Create an object id from the given time. This is useful for doing range # queries; it works because MongoDB's object ids begin # with a timestamp. # # @param [Time] time a utc time to encode as an object id. # # @option opts [:unique] (false) If false, the object id's bytes # succeeding the timestamp will be zeroed; if true, they'll # consist of the standard machine id, pid, and counter. # # @return [BSON::ObjectId] # # @example Return all document created before Jan 1, 2010. # time = Time.utc(2010, 1, 1) # time_id = ObjectId.from_time(time) # collection.find({'_id' => {'$lt' => time_id}}) def self.from_time(time, opts={}) unique = opts.fetch(:unique, false) if unique self.new(nil, time) else self.new([time.to_i,0,0].pack("NNN").unpack("C12")) end end # Adds a primary key to the given document if needed. # # @param [Hash] doc a document requiring an _id. # # @return [BSON::ObjectId, Object] returns a newly-created or # current _id for the given document. def self.create_pk(doc) doc.has_key?(:_id) || doc.has_key?('_id') ? doc : doc.merge!(:_id => self.new) end # Check equality of this object id with another. # # @param [BSON::ObjectId] object_id def eql?(object_id) object_id.kind_of?(BSON::ObjectId) and self.data == object_id.data end alias_method :==, :eql? # Get a unique hashcode for this object. # This is required since we've defined an #eql? method. # # @return [Integer] def hash @data.hash end # Get an array representation of the object id. # # @return [Array] def to_a @data.dup end # Given a string representation of an ObjectId, return a new ObjectId # with that value. # # @param [String] str # # @return [BSON::ObjectId] def self.from_string(str) raise InvalidObjectId, "illegal ObjectId format: #{str}" unless legal?(str) data = [] 12.times do |i| data[i] = str[i * 2, 2].to_i(16) end self.new(data) end # Get a string representation of this object id. # # @return [String] def to_s @data.map {|e| v=e.to_s(16); v.size == 1 ? "0#{v}" : v }.join end def inspect "BSON::ObjectId('#{to_s}')" end # Convert to MongoDB extended JSON format. Since JSON includes type information, # but lacks an ObjectId type, this JSON format encodes the type using an $oid key. # # @return [String] the object id represented as MongoDB extended JSON. def to_json(*a) "{\"$oid\": \"#{to_s}\"}" end # Create the JSON hash structure convert to MongoDB extended format. Rails 2.3.3 # introduced as_json to create the needed hash structure to encode objects into JSON. # # @return [Hash] the hash representation as MongoDB extended JSON def as_json(options ={}) {"$oid" => to_s} end # Return the UTC time at which this ObjectId was generated. This may # be used in lieu of a created_at timestamp since this information # is always encoded in the object id. # # @return [Time] the time at which this object was created. def generation_time Time.at(@data.pack("C4").unpack("N")[0]).utc end def self.machine_id @@machine_id end private if RUBY_PLATFORM =~ /java/ && BSON.extension? @@generator = Java::OrgBsonTypes::ObjectId @@machine_id = [@@generator.genMachineId].pack("N")[0,3] def generate(oid_time=nil) data = (oid_time ? @@generator.new(oid_time) : @@generator.new) oid = '' oid += [data.timeSecond].pack("N") oid += [data._machine].pack("N") oid += [data._inc].pack("N") oid.unpack("C12") end else @@lock = Mutex.new @@index = 0 @@machine_id = Digest::MD5.digest(Socket.gethostname)[0, 3] # We need to check whether BSON_CODER is defined because it's required by # the BSON C extensions. if defined?(BSON::BSON_CODER) && BSON::BSON_CODER == BSON::BSON_RUBY # This gets overwritten by the C extension if it loads. def generate(oid_time=nil) oid = '' # 4 bytes current time if oid_time t = oid_time.to_i else t = Time.new.to_i end oid += [t].pack("N") # 3 bytes machine oid += @@machine_id # 2 bytes pid oid += [Process.pid % 0xFFFF].pack("n") # 3 bytes inc oid += [get_inc].pack("N")[1, 3] oid.unpack("C12") end def get_inc @@lock.synchronize do @@index = (@@index + 1) % 0xFFFFFF end end end end end end ruby-bson-1.9.2/lib/bson/types/timestamp.rb000066400000000000000000000037061221200631200206410ustar00rootroot00000000000000# Copyright (C) 2013 10gen Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. module BSON # A class for representing BSON Timestamps. The Timestamp type is used # by MongoDB internally; thus, it should be used by application developers # for diagnostic purposes only. class Timestamp include Enumerable attr_reader :seconds, :increment # Create a new BSON Timestamp. # # @param [Integer] seconds The number of seconds # @param increment def initialize(seconds, increment) @seconds = seconds @increment = increment end def to_s "seconds: #{seconds}, increment: #{increment}" end def ==(other) self.seconds == other.seconds && self.increment == other.increment end # This is for backward-compatibility. Timestamps in the Ruby # driver used to deserialize as arrays. So we provide # an equivalent interface. # # @deprecated def [](index) warn "Timestamps are no longer deserialized as arrays. If you're working " + "with BSON Timestamp objects, see the BSON::Timestamp class. This usage will " + "be deprecated in Ruby Driver v2.0." if index == 0 self.increment elsif index == 1 self.seconds else nil end end # This method exists only for backward-compatibility. # # @deprecated def each i = 0 while i < 2 yield self[i] i += 1 end end end end ruby-bson-1.9.2/metadata.gz.sig000066400000000000000000000004001221200631200163250ustar00rootroot000000000000000x Ą|En ƣg8h`|K؏0Y'O%T[xcn.k);fSEu>$4 @0潚 ~CG8 ӧ\٢@4^8/7qY$V{/xsZQѸxb:Q446ha%taK,$#9]|e>sr("isGnVruby-bson-1.9.2/metadata.yml000066400000000000000000000054121221200631200157350ustar00rootroot00000000000000--- !ruby/object:Gem::Specification name: bson version: !ruby/object:Gem::Version version: 1.9.2 platform: ruby authors: - Tyler Brock - Gary Murakami - Emily Stolfo - Brandon Black - Durran Jordan autorequire: bindir: bin cert_chain: - | -----BEGIN CERTIFICATE----- MIIDODCCAiCgAwIBAgIBADANBgkqhkiG9w0BAQUFADBCMRQwEgYDVQQDDAtkcml2 ZXItcnVieTEVMBMGCgmSJomT8ixkARkWBTEwZ2VuMRMwEQYKCZImiZPyLGQBGRYD Y29tMB4XDTEzMDIwMTE0MTEzN1oXDTE0MDIwMTE0MTEzN1owQjEUMBIGA1UEAwwL ZHJpdmVyLXJ1YnkxFTATBgoJkiaJk/IsZAEZFgUxMGdlbjETMBEGCgmSJomT8ixk ARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANFdSAa8fRm1 bAM9za6Z0fAH4g02bqM1NGnw8zJQrE/PFrFfY6IFCT2AsLfOwr1maVm7iU1+kdVI IQ+iI/9+E+ArJ+rbGV3dDPQ+SLl3mLT+vXjfjcxMqI2IW6UuVtt2U3Rxd4QU0kdT JxmcPYs5fDN6BgYc6XXgUjy3m+Kwha2pGctdciUOwEfOZ4RmNRlEZKCMLRHdFP8j 4WTnJSGfXDiuoXICJb5yOPOZPuaapPSNXp93QkUdsqdKC32I+KMpKKYGBQ6yisfA 5MyVPPCzLR1lP5qXVGJPnOqUAkvEUfCahg7EP9tI20qxiXrR6TSEraYhIFXL0EGY u8KAcPHm5KkCAwEAAaM5MDcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUW3dZsX70mlSM CiPrZxAGA1vwfNcwCwYDVR0PBAQDAgSwMA0GCSqGSIb3DQEBBQUAA4IBAQCIa/Y6 xS7YWBxkn9WP0EMnJ3pY9vef9DTmLSi/2jz8PzwlKQ89zNTrqSUD8LoQZmBqCJBt dKSQ/RUnaHJuxh8HWvWubP8EBYTuf+I1DFnRv648IF3MR1tCQumVL0XcYMvZcxBj a/p+8DomWTQqUdNbNoGywwjtVBWfDdwFV8Po1XcN/AtpILOJQd9J77INIGGCHxZo 6SOHHaNknlE9H0w6q0SVxZKZI8/+2c447V0NrHIw1Qhe0tAGJ9V1u3ky8gyxe0SM 8v7zLF2XliYbfurYIwkcXs8yPn8ggApBIy9bX6VJxRs/l2+UvqzaHIFaFy/F8/GP RNTuXsVG5NDACo7Q -----END CERTIFICATE----- date: 2013-08-21 00:00:00.000000000 Z dependencies: [] description: A Ruby BSON implementation for MongoDB. For more information about Mongo, see http://www.mongodb.org. For more information on BSON, see http://www.bsonspec.org. email: mongodb-dev@googlegroups.com executables: - b2json - j2bson extensions: [] extra_rdoc_files: [] files: - bson.gemspec - LICENSE - VERSION - bin/b2json - bin/j2bson - lib/bson.rb - lib/bson/bson_c.rb - lib/bson/bson_java.rb - lib/bson/bson_ruby.rb - lib/bson/byte_buffer.rb - lib/bson/exceptions.rb - lib/bson/ordered_hash.rb - lib/bson/support/hash_with_indifferent_access.rb - lib/bson/types/binary.rb - lib/bson/types/code.rb - lib/bson/types/dbref.rb - lib/bson/types/min_max_keys.rb - lib/bson/types/object_id.rb - lib/bson/types/timestamp.rb homepage: http://www.mongodb.org licenses: - Apache License Version 2.0 metadata: {} post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement requirements: - - '>=' - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: bson rubygems_version: 2.0.7 signing_key: specification_version: 4 summary: Ruby implementation of BSON test_files: [] has_rdoc: yard