bson-4.3.0/0000755000004100000410000000000013236361476012522 5ustar www-datawww-databson-4.3.0/Rakefile0000644000004100000410000000555013236361476014174 0ustar www-datawww-data# Copyright (C) 2009-2013 MongoDB 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 "bundler" Bundler.setup $LOAD_PATH.unshift(File.expand_path("../lib", __FILE__)) require "rake" require "rake/extensiontask" require "rspec/core/rake_task" def jruby? defined?(JRUBY_VERSION) end if jruby? require "rake/javaextensiontask" Rake::JavaExtensionTask.new do |ext| ext.name = "bson-ruby" ext.ext_dir = "src" ext.lib_dir = "lib" end else require "rake/extensiontask" Rake::ExtensionTask.new do |ext| ext.name = "bson_native" ext.ext_dir = "ext/bson" ext.lib_dir = "lib" end end require "bson/version" def extension RUBY_PLATFORM =~ /darwin/ ? "bundle" : "so" end require_relative "perf/bench" RSpec::Core::RakeTask.new(:rspec) if jruby? task :build => [ :clean_all, :compile ] do system "gem build bson.gemspec" end else task :build => :clean_all do system "gem build bson.gemspec" end end task :clean_all => :clean do begin Dir.chdir(Pathname(__FILE__).dirname + "lib") do `rm bson_native.#{extension}` `rm bson_native.o` `rm bson-ruby.jar` end rescue Exception => e puts e.message end end task :spec => :compile do Rake::Task["rspec"].invoke end # Run bundle exec rake release with mri and jruby. Ex: # # rvm use 2.1.0@bson # bundle exec rake release # rvm use jruby@bson # bundle exec rake release task :release => :build do system "git tag -a v#{BSON::VERSION} -m 'Tagging release: #{BSON::VERSION}'" system "git push --tags" if jruby? system "gem push bson-#{BSON::VERSION}-java.gem" system "rm bson-#{BSON::VERSION}-java.gem" else system "gem push bson-#{BSON::VERSION}.gem" system "rm bson-#{BSON::VERSION}.gem" end end namespace :benchmark do task :ruby => :clean_all do puts "Benchmarking pure Ruby..." require "bson" benchmark! end task :native => :compile do puts "Benchmarking with native extensions..." require "bson" benchmark! end namespace :decimal128 do task :from_string do puts "Benchmarking creating Decimal128 objects from a string" require 'bson' benchmark_decimal128_from_string! end task :to_string do puts "Benchmarking getting a string representation of a Decimal128" require 'bson' benchmark_decimal128_to_string! end end end task :default => [ :clean_all, :spec ] bson-4.3.0/bson.gemspec0000644000004100000410000002053713236361476015037 0ustar www-datawww-data######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- Gem::Specification.new do |s| s.name = "bson" s.version = "4.3.0" s.required_rubygems_version = Gem::Requirement.new(">= 1.3.6") if s.respond_to? :required_rubygems_version= s.authors = ["Tyler Brock", "Durran Jordan", "Brandon Black", "Emily Stolfo", "Gary Murakami"] s.cert_chain = ["-----BEGIN CERTIFICATE-----\nMIIDfDCCAmSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBCMRQwEgYDVQQDDAtkcml2\nZXItcnVieTEVMBMGCgmSJomT8ixkARkWBTEwZ2VuMRMwEQYKCZImiZPyLGQBGRYD\nY29tMB4XDTE3MDcwMzEyMTMyOVoXDTE4MDcwMzEyMTMyOVowQjEUMBIGA1UEAwwL\nZHJpdmVyLXJ1YnkxFTATBgoJkiaJk/IsZAEZFgUxMGdlbjETMBEGCgmSJomT8ixk\nARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANFdSAa8fRm1\nbAM9za6Z0fAH4g02bqM1NGnw8zJQrE/PFrFfY6IFCT2AsLfOwr1maVm7iU1+kdVI\nIQ+iI/9+E+ArJ+rbGV3dDPQ+SLl3mLT+vXjfjcxMqI2IW6UuVtt2U3Rxd4QU0kdT\nJxmcPYs5fDN6BgYc6XXgUjy3m+Kwha2pGctdciUOwEfOZ4RmNRlEZKCMLRHdFP8j\n4WTnJSGfXDiuoXICJb5yOPOZPuaapPSNXp93QkUdsqdKC32I+KMpKKYGBQ6yisfA\n5MyVPPCzLR1lP5qXVGJPnOqUAkvEUfCahg7EP9tI20qxiXrR6TSEraYhIFXL0EGY\nu8KAcPHm5KkCAwEAAaN9MHswCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0O\nBBYEFFt3WbF+9JpUjAoj62cQBgNb8HzXMCAGA1UdEQQZMBeBFWRyaXZlci1ydWJ5\nQDEwZ2VuLmNvbTAgBgNVHRIEGTAXgRVkcml2ZXItcnVieUAxMGdlbi5jb20wDQYJ\nKoZIhvcNAQEFBQADggEBABQRiVDNfa+gKXHHgnJdafFGk6c3jzAGqc6YHq6ZIhol\noxxpgDxd3IxQfca7zvs9AYQcOrQtH1xcw3yanJp+pBTTweqYzbwZNe6QTyetjM+L\nhhudM1vXidPJMo7ZzzZ3z0rOpE6aPjqZihSDPcoKYw0FIAqxgrRqitYYdDoq3dup\nYbzsDYb5G4lbzCmqX2pu0ravi0XF9qDOgvm4j7ss9BnGuwQhhb44nevlIEv+sTg4\nUgLdYyyGANc+TOKLFmx0eAJlCljAurbX7ctO2XI0f1AUdEYSqGzut+datXK/9nwQ\nFACf8zd11PEds/Opai2Qp4aOBgaxXhhFG357umy1vRs=\n-----END CERTIFICATE-----\n"] s.date = "2018-01-17" s.description = "A full featured BSON specification implementation, in Ruby" s.email = ["mongodb-dev@googlegroups.com"] s.extensions = ["ext/bson/extconf.rb"] s.files = ["CHANGELOG.md", "CONTRIBUTING.md", "LICENSE", "NOTICE", "README.md", "Rakefile", "ext/bson/bson_native.c", "ext/bson/extconf.rb", "ext/bson/native-endian.h", "lib/bson.rb", "lib/bson/array.rb", "lib/bson/binary.rb", "lib/bson/boolean.rb", "lib/bson/code.rb", "lib/bson/code_with_scope.rb", "lib/bson/config.rb", "lib/bson/date.rb", "lib/bson/date_time.rb", "lib/bson/decimal128.rb", "lib/bson/decimal128/builder.rb", "lib/bson/document.rb", "lib/bson/environment.rb", "lib/bson/false_class.rb", "lib/bson/float.rb", "lib/bson/hash.rb", "lib/bson/int32.rb", "lib/bson/int64.rb", "lib/bson/integer.rb", "lib/bson/json.rb", "lib/bson/max_key.rb", "lib/bson/min_key.rb", "lib/bson/nil_class.rb", "lib/bson/object.rb", "lib/bson/object_id.rb", "lib/bson/open_struct.rb", "lib/bson/regexp.rb", "lib/bson/registry.rb", "lib/bson/specialized.rb", "lib/bson/string.rb", "lib/bson/symbol.rb", "lib/bson/time.rb", "lib/bson/timestamp.rb", "lib/bson/true_class.rb", "lib/bson/undefined.rb", "lib/bson/version.rb", "spec/bson/array_spec.rb", "spec/bson/binary_spec.rb", "spec/bson/boolean_spec.rb", "spec/bson/byte_buffer_spec.rb", "spec/bson/code_spec.rb", "spec/bson/code_with_scope_spec.rb", "spec/bson/config_spec.rb", "spec/bson/corpus_spec.rb", "spec/bson/date_spec.rb", "spec/bson/date_time_spec.rb", "spec/bson/decimal128_spec.rb", "spec/bson/document_spec.rb", "spec/bson/driver_bson_spec.rb", "spec/bson/false_class_spec.rb", "spec/bson/float_spec.rb", "spec/bson/hash_spec.rb", "spec/bson/int32_spec.rb", "spec/bson/int64_spec.rb", "spec/bson/integer_spec.rb", "spec/bson/json_spec.rb", "spec/bson/max_key_spec.rb", "spec/bson/min_key_spec.rb", "spec/bson/nil_class_spec.rb", "spec/bson/object_id_spec.rb", "spec/bson/object_spec.rb", "spec/bson/open_struct_spec.rb", "spec/bson/raw_spec.rb", "spec/bson/regexp_spec.rb", "spec/bson/registry_spec.rb", "spec/bson/string_spec.rb", "spec/bson/symbol_spec.rb", "spec/bson/time_spec.rb", "spec/bson/timestamp_spec.rb", "spec/bson/true_class_spec.rb", "spec/bson/undefined_spec.rb", "spec/bson_spec.rb", "spec/spec_helper.rb", "spec/support/common_driver.rb", "spec/support/corpus-tests/array.json", "spec/support/corpus-tests/boolean.json", "spec/support/corpus-tests/code.json", "spec/support/corpus-tests/code_w_scope.json", "spec/support/corpus-tests/document.json", "spec/support/corpus-tests/double.json", "spec/support/corpus-tests/failures/binary.json", "spec/support/corpus-tests/failures/datetime.json", "spec/support/corpus-tests/failures/dbpointer.json", "spec/support/corpus-tests/failures/int64.json", "spec/support/corpus-tests/failures/symbol.json", "spec/support/corpus-tests/failures/undefined.json", "spec/support/corpus-tests/int32.json", "spec/support/corpus-tests/maxkey.json", "spec/support/corpus-tests/minkey.json", "spec/support/corpus-tests/null.json", "spec/support/corpus-tests/oid.json", "spec/support/corpus-tests/regex.json", "spec/support/corpus-tests/string.json", "spec/support/corpus-tests/timestamp.json", "spec/support/corpus-tests/top.json", "spec/support/corpus.rb", "spec/support/driver-spec-tests/decimal128/decimal128-1.json", "spec/support/driver-spec-tests/decimal128/decimal128-2.json", "spec/support/driver-spec-tests/decimal128/decimal128-3.json", "spec/support/driver-spec-tests/decimal128/decimal128-4.json", "spec/support/driver-spec-tests/decimal128/decimal128-5.json", "spec/support/driver-spec-tests/decimal128/decimal128-6.json", "spec/support/driver-spec-tests/decimal128/decimal128-7.json", "spec/support/shared_examples.rb"] s.homepage = "http://bsonspec.org" s.licenses = ["Apache License Version 2.0"] s.require_paths = ["lib"] s.required_ruby_version = Gem::Requirement.new(">= 1.9.3") s.rubyforge_project = "bson" s.rubygems_version = "1.8.23" s.summary = "Ruby Implementation of the BSON specification" s.test_files = ["spec/bson/array_spec.rb", "spec/bson/binary_spec.rb", "spec/bson/boolean_spec.rb", "spec/bson/byte_buffer_spec.rb", "spec/bson/code_spec.rb", "spec/bson/code_with_scope_spec.rb", "spec/bson/config_spec.rb", "spec/bson/corpus_spec.rb", "spec/bson/date_spec.rb", "spec/bson/date_time_spec.rb", "spec/bson/decimal128_spec.rb", "spec/bson/document_spec.rb", "spec/bson/driver_bson_spec.rb", "spec/bson/false_class_spec.rb", "spec/bson/float_spec.rb", "spec/bson/hash_spec.rb", "spec/bson/int32_spec.rb", "spec/bson/int64_spec.rb", "spec/bson/integer_spec.rb", "spec/bson/json_spec.rb", "spec/bson/max_key_spec.rb", "spec/bson/min_key_spec.rb", "spec/bson/nil_class_spec.rb", "spec/bson/object_id_spec.rb", "spec/bson/object_spec.rb", "spec/bson/open_struct_spec.rb", "spec/bson/raw_spec.rb", "spec/bson/regexp_spec.rb", "spec/bson/registry_spec.rb", "spec/bson/string_spec.rb", "spec/bson/symbol_spec.rb", "spec/bson/time_spec.rb", "spec/bson/timestamp_spec.rb", "spec/bson/true_class_spec.rb", "spec/bson/undefined_spec.rb", "spec/bson_spec.rb", "spec/spec_helper.rb", "spec/support/common_driver.rb", "spec/support/corpus-tests/array.json", "spec/support/corpus-tests/boolean.json", "spec/support/corpus-tests/code.json", "spec/support/corpus-tests/code_w_scope.json", "spec/support/corpus-tests/document.json", "spec/support/corpus-tests/double.json", "spec/support/corpus-tests/failures/binary.json", "spec/support/corpus-tests/failures/datetime.json", "spec/support/corpus-tests/failures/dbpointer.json", "spec/support/corpus-tests/failures/int64.json", "spec/support/corpus-tests/failures/symbol.json", "spec/support/corpus-tests/failures/undefined.json", "spec/support/corpus-tests/int32.json", "spec/support/corpus-tests/maxkey.json", "spec/support/corpus-tests/minkey.json", "spec/support/corpus-tests/null.json", "spec/support/corpus-tests/oid.json", "spec/support/corpus-tests/regex.json", "spec/support/corpus-tests/string.json", "spec/support/corpus-tests/timestamp.json", "spec/support/corpus-tests/top.json", "spec/support/corpus.rb", "spec/support/driver-spec-tests/decimal128/decimal128-1.json", "spec/support/driver-spec-tests/decimal128/decimal128-2.json", "spec/support/driver-spec-tests/decimal128/decimal128-3.json", "spec/support/driver-spec-tests/decimal128/decimal128-4.json", "spec/support/driver-spec-tests/decimal128/decimal128-5.json", "spec/support/driver-spec-tests/decimal128/decimal128-6.json", "spec/support/driver-spec-tests/decimal128/decimal128-7.json", "spec/support/shared_examples.rb"] if s.respond_to? :specification_version then s.specification_version = 4 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then else end else end end bson-4.3.0/data.tar.gz.sig0000444000004100000410000000040013236361476015333 0ustar www-datawww-data-/_|2{b=o¨uK, dB.,?MC&ކ~kũ3Y<]Y$2,lXxV[Y;ZkweYOm4XJ#D[iM/w xn|rTlW32F$\9JOznAS{R6fͅ7ws#id hRGQL.N| T (=U@~bson-4.3.0/spec/0000755000004100000410000000000013236361476013454 5ustar www-datawww-databson-4.3.0/spec/bson_spec.rb0000644000004100000410000000255713236361476015765 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe BSON do describe ".ObjectId" do let(:string) { "4e4d66343b39b68407000001" } it "returns an BSON::ObjectId from given string" do expect(described_class::ObjectId(string)).to be_a BSON::ObjectId expect(described_class::ObjectId(string)).to eq BSON::ObjectId.from_string(string) end end describe "::BINARY" do it "returns BINARY" do expect(BSON::BINARY).to eq("BINARY") end end describe "::NO_VAUE" do it "returns an empty string" do expect(BSON::NO_VALUE).to be_empty end end describe "::NULL_BYTE" do it "returns the char 0x00" do expect(BSON::NULL_BYTE).to eq(0.chr) end end describe "::UTF8" do it "returns UTF-8" do expect(BSON::UTF8).to eq("UTF-8") end end end bson-4.3.0/spec/spec_helper.rb0000644000004100000410000000270113236361476016272 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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. CURRENT_PATH = File.expand_path(File.dirname(__FILE__)) DRIVER_COMMON_BSON_TESTS = Dir.glob("#{CURRENT_PATH}/support/driver-spec-tests/**/*.json") BSON_CORPUS_TESTS = Dir.glob("#{CURRENT_PATH}/support/corpus-tests/*.json") $LOAD_PATH.unshift(File.dirname(__FILE__)) $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib")) require "ostruct" require "bson" require "json" require "rspec" require "yaml" Dir["./spec/support/**/*.rb"].each { |file| require file } # Alternate IO class that returns a String from #readbyte. # See RUBY-898 for more information on why we need to test this. # Ruby core documentation says IO#readbyte returns a Fixnum, but # OpenSSL::SSL::SSLSocket#readbyte returns a String. class AlternateIO < StringIO # Read a byte from the stream. # # @returns [ String ] A String representation of the next byte. def readbyte super.chr end end bson-4.3.0/spec/bson/0000755000004100000410000000000013236361476014415 5ustar www-datawww-databson-4.3.0/spec/bson/true_class_spec.rb0000644000004100000410000000147413236361476020126 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe TrueClass do describe "#to_bson" do let(:obj) { true } let(:bson) { 1.chr } let(:type) { 8.chr } it_behaves_like "a bson element" it_behaves_like "a serializable bson element" end end bson-4.3.0/spec/bson/code_with_scope_spec.rb0000644000004100000410000000463513236361476021122 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe BSON::CodeWithScope do describe "#==" do let(:object) do BSON::CodeWithScope.new("this.value = val", "test") end context "when the objects are equal" do let(:other) { described_class.new("this.value = val", "test") } it "returns true" do expect(object).to eq(other) end end context "when the other object is not equal" do let(:other) { described_class.new("this.value = otherVal", "test") } it "returns false" do expect(object).to_not eq(other) end end end describe "#as_json" do let(:object) do described_class.new("this.value = val", :val => "test") end it "returns the binary data plus type" do expect(object.as_json).to eq( { "$code" => "this.value = val", "$scope" => { :val => "test" }} ) end it_behaves_like "a JSON serializable object" end describe "#to_bson" do let(:type) { 15.chr } let(:code) { "this.value == name" } let(:scope) do { :name => "test" } end let(:obj) { described_class.new(code, scope) } let(:bson) do "#{47.to_bson.to_s}#{(code.length + 1).to_bson.to_s}#{code}#{BSON::NULL_BYTE}" + "#{scope.to_bson.to_s}" end it_behaves_like "a bson element" it_behaves_like "a serializable bson element" end describe "#from_bson" do let(:type) { 15.chr } let(:code) { "this.value == name" } let(:scope) do { "name" => "test" } end let(:obj) { described_class.new(code, scope) } let(:bson) { BSON::ByteBuffer.new(obj.to_bson.to_s) } let!(:deserialized) { described_class.from_bson(bson) } it "deserializes the javascript" do expect(deserialized.javascript).to eq(code) end it "deserializes the scope" do expect(deserialized.scope).to eq(scope) end end end bson-4.3.0/spec/bson/decimal128_spec.rb0000644000004100000410000012030513236361476017606 0ustar www-datawww-data# Copyright (C) 2016 MongoDB 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 "spec_helper" describe BSON::Decimal128 do let(:low_bits) do decimal128.instance_variable_get(:@low) end let(:high_bits) do decimal128.instance_variable_get(:@high) end describe '#initialize' do context 'when the argument is neither a BigDecimal or String' do it 'raises an ArgumentError' do expect { described_class.new(:invalid) }.to raise_exception(ArgumentError) end end shared_examples_for 'an initialized BSON::Decimal128' do let(:decimal128) do described_class.new(argument) end let(:buffer) do decimal128.to_bson end let(:from_bson) do described_class.from_bson(buffer) end let(:expected_bson) do [expected_low_bits].pack(BSON::Int64::PACK) + [expected_high_bits].pack(BSON::Int64::PACK) end it 'sets the correct high order bits' do expect(high_bits).to eq(expected_high_bits) end it 'sets the correct low order bits' do expect(low_bits).to eq(expected_low_bits) end it 'serializes to bson' do expect(buffer.to_s).to eq(expected_bson) end it 'deserializes to the correct bits' do expect(from_bson.instance_variable_get(:@high)).to eq(expected_high_bits) expect(from_bson.instance_variable_get(:@low)).to eq(expected_low_bits) end end context 'when the object represents positive infinity' do let(:expected_high_bits) { 0x7800000000000000 } let(:expected_low_bits) { 0x0000000000000000 } context 'when a BigDecimal is passed' do let(:argument) { BigDecimal.new("Infinity") } it_behaves_like 'an initialized BSON::Decimal128' end context 'when a String is passed' do let(:argument) { "Infinity" } it_behaves_like 'an initialized BSON::Decimal128' end end context 'when the object represents negative infinity' do let(:expected_high_bits) { 0xf800000000000000 } let(:expected_low_bits) { 0x0000000000000000 } context 'when a BigDecimal is passed' do let(:argument) { BigDecimal.new("-Infinity") } it_behaves_like 'an initialized BSON::Decimal128' end context 'when a String is passed' do let(:argument) { "-Infinity" } it_behaves_like 'an initialized BSON::Decimal128' end end context 'when the object represents NaN' do let(:expected_high_bits) { 0x7c00000000000000 } let(:expected_low_bits) { 0x0000000000000000 } context 'when a BigDecimal is passed' do let(:argument) { BigDecimal.new("NaN") } it_behaves_like 'an initialized BSON::Decimal128' end context 'when a String is passed' do let(:argument) { "NaN" } it_behaves_like 'an initialized BSON::Decimal128' end end context 'when the object represents -NaN' do let(:expected_high_bits) { 0xfc00000000000000 } let(:expected_low_bits) { 0x0000000000000000 } context 'when a String is passed' do let(:argument) { "-NaN" } it_behaves_like 'an initialized BSON::Decimal128' end end context 'when the object represents SNaN' do let(:expected_high_bits) { 0x7e00000000000000 } let(:expected_low_bits) { 0x0000000000000000 } context 'when a String is passed' do let(:argument) { "SNaN" } it_behaves_like 'an initialized BSON::Decimal128' end end context 'when the object represents -SNaN' do let(:expected_high_bits) { 0xfe00000000000000 } let(:expected_low_bits) { 0x0000000000000000 } context 'when a String is passed' do let(:argument) { "-SNaN" } it_behaves_like 'an initialized BSON::Decimal128' end end context 'when the object represents -0' do let(:expected_high_bits) { 0xb040000000000000 } let(:expected_low_bits) { 0x0000000000000000 } context 'when a BigDecimal is passed' do let(:argument) { BigDecimal.new("-0") } it_behaves_like 'an initialized BSON::Decimal128' end context 'when a String is passed' do let(:argument) { "-0" } it_behaves_like 'an initialized BSON::Decimal128' end end context 'when the object represents a positive integer' do let(:expected_high_bits) { 0x3040000000000000 } let(:expected_low_bits) { 0x000000000000000c } context 'when a BigDecimal is passed' do let(:argument) { BigDecimal.new(12) } it_behaves_like 'an initialized BSON::Decimal128' end context 'when a String is passed' do let(:argument) { "12" } it_behaves_like 'an initialized BSON::Decimal128' end end context 'when the object represents a negative integer' do let(:expected_high_bits) { 0xb040000000000000 } let(:expected_low_bits) { 0x000000000000000c } context 'when a BigDecimal is passed' do let(:argument) { BigDecimal.new(-12) } it_behaves_like 'an initialized BSON::Decimal128' end context 'when a String is passed' do let(:argument) { "-12" } it_behaves_like 'an initialized BSON::Decimal128' end end context 'when the object represents a positive float' do let(:expected_high_bits) { 0x3036000000000000 } let(:expected_low_bits) { 0x0000000000003039 } context 'when a BigDecimal is passed' do let(:argument) { BigDecimal.new(0.12345, 5) } it_behaves_like 'an initialized BSON::Decimal128' end context 'when a String is passed' do let(:argument) { "0.12345" } it_behaves_like 'an initialized BSON::Decimal128' end end context 'when the object represents a negative float' do let(:expected_high_bits) { 0xb036000000000000 } let(:expected_low_bits) { 0x0000000000003039 } context 'when a BigDecimal is passed' do let(:argument) { BigDecimal.new(-0.12345, 5) } it_behaves_like 'an initialized BSON::Decimal128' end context 'when a String is passed' do let(:argument) { "-0.12345" } it_behaves_like 'an initialized BSON::Decimal128' end end context 'when the object represents a large positive integer' do let(:expected_high_bits) { 0x30403cde6fff9732 } let(:expected_low_bits) { 0xde825cd07e96aff2 } context 'when a BigDecimal is passed' do let(:argument) { BigDecimal.new(1234567890123456789012345678901234) } it_behaves_like 'an initialized BSON::Decimal128' end context 'when a String is passed' do let(:argument) { "1234567890123456789012345678901234" } it_behaves_like 'an initialized BSON::Decimal128' end end context 'when the object represents a large negative integer' do let(:expected_high_bits) { 0xb0403cde6fff9732 } let(:expected_low_bits) { 0xde825cd07e96aff2 } context 'when a BigDecimal is passed' do let(:argument) { BigDecimal.new(-1234567890123456789012345678901234) } it_behaves_like 'an initialized BSON::Decimal128' end context 'when a String is passed' do let(:argument) { "-1234567890123456789012345678901234" } it_behaves_like 'an initialized BSON::Decimal128' end end end context 'when deserializing' do context 'When the value has trailing zeroes' do let(:hex) do '18000000136400D0070000000000000000000000003A3000' end let(:packed) do [ hex ].pack('H*') end let(:buffer) do BSON::ByteBuffer.new(packed) end let(:decimal128) do BSON::Document.from_bson(buffer)['d'] end let(:object_from_string) do BSON::Decimal128.from_string('2.000') end it 'has the correct high order' do expect(decimal128.instance_variable_get(:@high)).to eq(3475090062469758976) end it 'has the correct low order' do expect(decimal128.instance_variable_get(:@low)).to eq(2000) end it 'matches the object created from a string' do expect(object_from_string).to eq(decimal128) end end end describe '#from_string' do shared_examples_for 'a decimal128 initialized from a string' do let(:decimal128) do BSON::Decimal128.from_string(string) end let(:low_bits) do decimal128.instance_variable_get(:@low) end let(:high_bits) do decimal128.instance_variable_get(:@high) end it 'sets the correct high order bits' do expect(high_bits).to eq(expected_high_bits) end it 'sets the correct low order bits' do expect(low_bits).to eq(expected_low_bits) end end context 'when the string represents a special type' do context "when the string is 'NaN'" do let(:string) { 'NaN' } let(:expected_high_bits) { 0x7c00000000000000 } let(:expected_low_bits) { 0x0000000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '-NaN'" do let(:string) { '-NaN' } let(:expected_high_bits) { 0xfc00000000000000 } let(:expected_low_bits) { 0x0000000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is 'SNaN'" do let(:string) { 'SNaN' } let(:expected_high_bits) { 0x7e00000000000000 } let(:expected_low_bits) { 0x0000000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '-SNaN'" do let(:string) { '-SNaN' } let(:expected_high_bits) { 0xfe00000000000000 } let(:expected_low_bits) { 0x0000000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is 'Infinity'" do let(:string) { 'Infinity' } let(:expected_exponent) { nil } let(:expected_significand) { nil } let(:expected_high_bits) { 0x7800000000000000 } let(:expected_low_bits) { 0x0000000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '-Infinity'" do let(:string) { '-Infinity' } let(:expected_exponent) { nil } let(:expected_significand) { nil } let(:expected_high_bits) { 0xf800000000000000 } let(:expected_low_bits) { 0x0000000000000000 } it_behaves_like 'a decimal128 initialized from a string' end end context 'when the string represents 0' do context "when the string is '0'" do let(:string) { '0' } let(:expected_exponent) { 0 } let(:expected_significand) { 0 } let(:expected_high_bits) { 0x3040000000000000 } let(:expected_low_bits) { 0 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '-0'" do let(:string) { '-0' } let(:expected_exponent) { 0 } let(:expected_significand) { 0 } let(:expected_high_bits) { 0xb040000000000000 } let(:expected_low_bits) { 0 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '0.0'" do let(:string) { '0.0' } let(:expected_exponent) { -1 } let(:expected_significand) { 0 } let(:expected_high_bits) { 0x303e000000000000 } let(:expected_low_bits) { 0 } it_behaves_like 'a decimal128 initialized from a string' end end context 'when the string represents an integer' do context "when the string is '1'" do let(:string) { '1' } let(:expected_exponent) { 0 } let(:expected_significand) { 1 } let(:expected_high_bits) { 0x3040000000000000 } let(:expected_low_bits) { 0x1 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '-1'" do let(:string) { '-1'} let(:expected_exponent) { 0 } let(:expected_significand) { 1 } let(:expected_high_bits) { 0xb040000000000000 } let(:expected_low_bits) { 0x1 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '20'" do let(:string) { '20' } let(:expected_exponent) { 0 } let(:expected_significand) { 20 } let(:expected_low_bits) { 0x14 } let(:expected_high_bits) { 0x3040000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '-20'" do let(:string) { '-20' } let(:expected_exponent) { 0 } let(:expected_significand) { 20 } let(:expected_low_bits) { 0x14 } let(:expected_high_bits) { 0xb040000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '12345678901234567'" do let(:string) { '12345678901234567' } let(:expected_exponent) { 0 } let(:expected_significand) { 12345678901234567 } let(:expected_low_bits) { 0x002bdc545d6b4b87 } let(:expected_high_bits) { 0x3040000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '-12345678901234567'" do let(:string) { '-12345678901234567' } let(:expected_exponent) { 0 } let(:expected_significand) { 12345678901234567 } let(:expected_low_bits) { 0x002bdc545d6b4b87 } let(:expected_high_bits) { 0xb040000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '12345689012345789012345'" do let(:string) { '12345689012345789012345' } let(:expected_exponent) { 0 } let(:expected_significand) { 12345689012345789012345 } let(:expected_low_bits) { 0x42da3a76f9e0d979 } let(:expected_high_bits) { 0x304000000000029d } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '-12345689012345789012345'" do let(:string) { '-12345689012345789012345' } let(:expected_exponent) { 0 } let(:expected_significand) { 12345689012345789012345 } let(:expected_low_bits) { 0x42da3a76f9e0d979 } let(:expected_high_bits) { 0xb04000000000029d } it_behaves_like 'a decimal128 initialized from a string' end end context 'when the string represents a fraction' do context "when the string is '0.1'" do let(:string) { '0.1' } let(:expected_exponent) { -1 } let(:expected_significand) { 1 } let(:expected_low_bits) { 0x1 } let(:expected_high_bits) { 0x303e000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '-0.1'" do let(:string) { '-0.1' } let(:expected_exponent) { -1 } let(:expected_significand) { 1 } let(:expected_low_bits) { 0x1 } let(:expected_high_bits) { 0xb03e000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '0.123'" do let(:string) { '0.123' } let(:expected_exponent) { -3 } let(:expected_significand) { 123 } let(:expected_low_bits) { 0x7b } let(:expected_high_bits) { 0x303a000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '-0.123'" do let(:string) { '-0.123' } let(:expected_exponent) { -3 } let(:expected_significand) { 123 } let(:expected_low_bits) { 0x7b } let(:expected_high_bits) { 0xb03a000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '0.1234567890123456789012345678901234'" do let(:string) { '0.1234567890123456789012345678901234' } let(:expected_exponent) { -34 } let(:expected_significand) { 1234567890123456789012345678901234 } let(:expected_low_bits) { 0xde825cd07e96aff2 } let(:expected_high_bits) { 0x2ffc3cde6fff9732 } it_behaves_like 'a decimal128 initialized from a string' end end context 'when the string represents a fraction with a whole number' do context "when the string is '1.2'" do let(:string) { '1.2' } let(:expected_exponent) { -1 } let(:expected_significand) { 12 } let(:expected_low_bits) { 0xc } let(:expected_high_bits) { 0x303e000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '-1.2'" do let(:string) { '-1.2' } let(:expected_exponent) { -1 } let(:expected_significand) { 12 } let(:expected_low_bits) { 0xc } let(:expected_high_bits) { 0xb03e000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '1.234'" do let(:string) { '1.234' } let(:expected_exponent) { -3 } let(:expected_significand) { 1234 } let(:expected_low_bits) { 0x4d2 } let(:expected_high_bits) { 0x303a000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '-1.234'" do let(:string) { '-1.234' } let(:expected_exponent) { -3 } let(:expected_significand) { 1234 } let(:expected_low_bits) { 0x4d2 } let(:expected_high_bits) { 0xb03a000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '123456789.123456789'" do let(:string) { '123456789.123456789' } let(:expected_exponent) { -9 } let(:expected_significand) { 123456789123456789 } let(:expected_low_bits) { 0x1b69b4bacd05f15 } let(:expected_high_bits) { 0x302e000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '-123456789.123456789'" do let(:string) { '-123456789.123456789' } let(:expected_exponent) { -9 } let(:expected_significand) { 123456789123456789 } let(:expected_low_bits) { 0x1b69b4bacd05f15 } let(:expected_high_bits) { 0xb02e000000000000 } it_behaves_like 'a decimal128 initialized from a string' end end context 'when the string represents a decimal with trailing zeros' do context "when the string is '1.000'" do let(:string) { '1.000' } let(:expected_exponent) { -3 } let(:expected_significand) { 1000 } let(:expected_low_bits) { 0x3e8 } let(:expected_high_bits) { 0x303a000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '-1.000'" do let(:string) { '-1.000' } let(:expected_exponent) { -3 } let(:expected_significand) { 1000 } let(:expected_low_bits) { 0x3e8 } let(:expected_high_bits) { 0xb03a000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '100.000'" do let(:string) { '100.000' } let(:expected_exponent) { -3 } let(:expected_significand) { 100000 } let(:expected_low_bits) { 0x186a0 } let(:expected_high_bits) { 0x303a000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '-100.000'" do let(:string) { '-100.000' } let(:expected_exponent) { -3 } let(:expected_significand) { 100000 } let(:expected_low_bits) { 0x186a0 } let(:expected_high_bits) { 0xb03a000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '1.234000000'" do let(:string) { '1.234000000' } let(:expected_exponent) { -9 } let(:expected_significand) { 1234000000 } let(:expected_low_bits) { 0x498d5880 } let(:expected_high_bits) { 0x302e000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '-1.234000000'" do let(:string) { '-1.234000000' } let(:expected_exponent) { -9 } let(:expected_significand) { 1234000000 } let(:expected_low_bits) { 0x498d5880 } let(:expected_high_bits) { 0xb02e000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context 'when there are zeros following the decimal that are not trailing' do context "when the string is '0.001234'" do let(:string) { '0.001234' } let(:expected_exponent) { -6 } let(:expected_significand) { 1234 } let(:expected_low_bits) { 0x4d2 } let(:expected_high_bits) { 0x3034000000000000 } it_behaves_like 'a decimal128 initialized from a string' end end context 'when there are zeros following the decimal that are not trailing' do context "when the string is '0.00123400000'" do let(:string) { '0.00123400000' } let(:expected_exponent) { -11 } let(:expected_significand) { 123400000 } let(:expected_low_bits) { 0x75aef40 } let(:expected_high_bits) { 0x302a000000000000 } it_behaves_like 'a decimal128 initialized from a string' end end end context 'when the string uses scientific notation' do context 'when the exponent is positive' do context 'when the positive exponent is denoted with E' do context "when the string is '1.2E4'" do let(:string) { '1.2E4' } let(:expected_exponent) { 3 } let(:expected_significand) { 12 } let(:expected_low_bits) { 0xc } let(:expected_high_bits) { 0x3046000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '-1.2E4'" do let(:string) { '-1.2E4' } let(:expected_exponent) { 3 } let(:expected_significand) { 12 } let(:expected_low_bits) { 0xc } let(:expected_high_bits) { 0xb046000000000000 } it_behaves_like 'a decimal128 initialized from a string' end end context 'when the positive exponent is denoted with E+' do context "when the string is '1.2E+4'" do let(:string) { '1.2E4' } let(:expected_exponent) { 3 } let(:expected_significand) { 12 } let(:expected_low_bits) { 0xc } let(:expected_high_bits) { 0x3046000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '-1.2E+4'" do let(:string) { '-1.2E4' } let(:expected_exponent) { 3 } let(:expected_significand) { 12 } let(:expected_low_bits) { 0xc } let(:expected_high_bits) { 0xb046000000000000 } it_behaves_like 'a decimal128 initialized from a string' end end end context 'when the exponent is negative' do context "when the string is '1.2E-4'" do let(:string) { '1.2E-4' } let(:expected_exponent) { -5 } let(:expected_significand) { 12 } let(:expected_low_bits) { 0xc } let(:expected_high_bits) { 0x3036000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '-1.2E-4'" do let(:string) { '-1.2E-4' } let(:expected_exponent) { -5 } let(:expected_significand) { 12 } let(:expected_low_bits) { 0xc } let(:expected_high_bits) { 0xb036000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context 'when there are trailing zeros' do context "when the string is '1.200E-4'" do let(:string) { '1.200E-4' } let(:expected_exponent) { -7 } let(:expected_significand) { 1200 } let(:expected_low_bits) { 0x4b0 } let(:expected_high_bits) { 0x3032000000000000 } it_behaves_like 'a decimal128 initialized from a string' end context "when the string is '-1.200E-4'" do let(:string) { '-1.200E-4' } let(:expected_exponent) { -7 } let(:expected_significand) { 1200 } let(:expected_low_bits) { 0x4b0 } let(:expected_high_bits) { 0xb032000000000000 } it_behaves_like 'a decimal128 initialized from a string' end end end end end describe '#to_s' do shared_examples_for 'a decimal128 printed to a string' do let(:buffer) do buffer = BSON::ByteBuffer.new buffer.put_decimal128(low_bits, high_bits) end let(:decimal) { BSON::Decimal128.from_bson(buffer) } it 'prints the correct string' do expect(decimal.to_s).to eq(expected_string) end end context 'when the bits represent a special type' do context 'when the decimal is NaN' do let(:expected_string) { 'NaN' } let(:high_bits) { 0x7c00000000000000 } let(:low_bits) { 0x0 } it_behaves_like 'a decimal128 printed to a string' end context 'when the decimal is negative NaN' do let(:expected_string) { 'NaN' } let(:high_bits) { 0xfc00000000000000 } let(:low_bits) { 0x0000000000000000 } it_behaves_like 'a decimal128 printed to a string' end context 'when the decimal is SNaN' do let(:expected_string) { 'NaN' } let(:high_bits) { 0x7e00000000000000 } let(:low_bits) { 0x0000000000000000 } it_behaves_like 'a decimal128 printed to a string' end context 'when the decimal is -SNaN' do let(:expected_string) { 'NaN' } let(:high_bits) { 0xfe00000000000000 } let(:low_bits) { 0x0000000000000000 } it_behaves_like 'a decimal128 printed to a string' end context 'when the decimal is NaN with a payload' do let(:expected_string) { 'NaN' } let(:high_bits) { 0x7e00000000000000 } let(:low_bits) { 0x0000000000000008 } it_behaves_like 'a decimal128 printed to a string' end context 'when the decimal is positive Infinity' do let(:expected_string) { 'Infinity' } let(:high_bits) { 0x7800000000000000 } let(:low_bits) { 0x0000000000000000 } it_behaves_like 'a decimal128 printed to a string' end context 'when the decimal is negative Infinity' do let(:expected_string) { '-Infinity' } let(:high_bits) { 0xf800000000000000 } let(:low_bits) { 0x0000000000000000 } it_behaves_like 'a decimal128 printed to a string' end end context 'when the string represents an integer' do context 'when the decimal is 1' do let(:expected_string) { '1' } let(:high_bits) { 0x3040000000000000 } let(:low_bits) { 0x0000000000000001 } it_behaves_like 'a decimal128 printed to a string' end context 'when the decimal is -1' do let(:expected_string) { '-1' } let(:high_bits) { 0xb040000000000000 } let(:low_bits) { 0x0000000000000001 } it_behaves_like 'a decimal128 printed to a string' end context 'when the decimal is 20' do let(:expected_string) { '20' } let(:high_bits) { 0x3040000000000000 } let(:low_bits) { 0x0000000000000014 } it_behaves_like 'a decimal128 printed to a string' end context 'when the decimal is -20' do let(:expected_string) { '-20' } let(:high_bits) { 0xb040000000000000 } let(:low_bits) { 0x0000000000000014 } it_behaves_like 'a decimal128 printed to a string' end context 'when the decimal is 12345678901234567' do let(:expected_string) { '12345678901234567' } let(:high_bits) { 0x3040000000000000 } let(:low_bits) { 0x002bdc545d6b4b87 } it_behaves_like 'a decimal128 printed to a string' end context 'when the decimal is -12345678901234567' do let(:expected_string) { '-12345678901234567' } let(:high_bits) { 0xb040000000000000 } let(:low_bits) { 0x002bdc545d6b4b87 } it_behaves_like 'a decimal128 printed to a string' end context 'when the decimal is 12345689012345789012345' do let(:expected_string) { '12345689012345789012345' } let(:high_bits) { 0x304000000000029d } let(:low_bits) { 0x42da3a76f9e0d979 } it_behaves_like 'a decimal128 printed to a string' end context 'when the decimal is -12345689012345789012345' do let(:expected_string) { '-12345689012345789012345' } let(:high_bits) { 0xb04000000000029d } let(:low_bits) { 0x42da3a76f9e0d979 } it_behaves_like 'a decimal128 printed to a string' end end context 'when the string represents a fraction' do context 'when the decimal is 0.1' do let(:expected_string) { '0.1' } let(:high_bits) { 0x303e000000000000 } let(:low_bits) { 0x0000000000000001 } it_behaves_like 'a decimal128 printed to a string' end context 'when the decimal is -0.1' do let(:expected_string) { '-0.1' } let(:high_bits) { 0xb03e000000000000 } let(:low_bits) { 0x0000000000000001 } it_behaves_like 'a decimal128 printed to a string' end context 'when the decimal is 0.123' do let(:expected_string) { '0.123' } let(:high_bits) { 0x303a000000000000 } let(:low_bits) { 0x000000000000007b } it_behaves_like 'a decimal128 printed to a string' end context 'when the decimal is -0.123' do let(:expected_string) { '-0.123' } let(:high_bits) { 0xb03a000000000000 } let(:low_bits) { 0x000000000000007b } it_behaves_like 'a decimal128 printed to a string' end end context 'when the decimal should have leading zeros' do let(:expected_string) { '0.001234' } let(:high_bits) { 0x3034000000000000 } let(:low_bits) { 0x00000000000004d2 } it_behaves_like 'a decimal128 printed to a string' end context 'when the decimal has trailing zeros' do let(:expected_string) { '2.000' } let(:high_bits) { 0x303a000000000000 } let(:low_bits) { 0x00000000000007d0 } it_behaves_like 'a decimal128 printed to a string' end end describe "#==" do context "when the high and low bits are identical" do let(:string) do '1.23' end let(:decimal128) do described_class.from_string(string) end let(:other_decimal) do described_class.from_string(string) end it "returns true" do expect(decimal128).to eq(other_decimal) end end context "when the high and low bits are different" do let(:string) do '1.23' end let(:decimal128) do described_class.from_string(string) end it "returns false" do expect(decimal128).to_not eq(described_class.new(BigDecimal.new('2.00'))) end end context "when other is not a decimal128" do it "returns false" do expect(described_class.from_string('1')).to_not eq(nil) end end end describe "#===" do let(:decimal128) do described_class.new(BigDecimal.new('1.23')) end context "when comparing with another decimal128" do context "when the high and low bits are equal" do let(:other) do described_class.from_string(decimal128.to_s) end it "returns true" do expect(decimal128 === other).to be true end end context "when the high and low bits are not equal" do let(:other) do described_class.new(BigDecimal.new('1000.003')) end it "returns false" do expect(decimal128 === other).to be false end end end context "when comparing to an decimal128 class" do it "returns false" do expect(decimal128 === BSON::Decimal128).to be false end end context "when comparing with a non string or decimal128" do it "returns false" do expect(decimal128 === "test").to be false end end context "when comparing with a non decimal128 class" do it "returns false" do expect(decimal128 === String).to be false end end end describe "#as_json" do let(:object) do described_class.new(BigDecimal.new('1.23')) end it "returns the decimal128 with $numberDecimal key" do expect(object.as_json).to eq({ "$numberDecimal" => object.to_s }) end it_behaves_like "a JSON serializable object" end describe "::BSON_TYPE" do it "returns 0x13" do expect(described_class::BSON_TYPE).to eq(19.chr) end end describe "#bson_type" do let(:code) do described_class.new(BigDecimal.new('1.23')) end it "returns 0x13" do expect(code.bson_type).to eq(described_class::BSON_TYPE) end end describe "#eql" do context "when high and low bits are identical" do let(:string) do '2.00' end let(:decimal128) do described_class.from_string(string) end let(:other_decimal) do described_class.from_string(string) end it "returns true" do expect(decimal128).to eql(other_decimal) end end context "when the high and low bit are different" do let(:string) do '2.00' end let(:decimal128) do described_class.from_string(string) end it "returns false" do expect(decimal128).to_not eql(described_class.new(BigDecimal.new('2'))) end end context "when other is not a Decimal128" do it "returns false" do expect(described_class.from_string('2')).to_not eql(nil) end end end describe "#hash" do let(:decimal128) do described_class.new(BigDecimal.new('-1234E+33')) end it "returns a hash of the high and low bits" do expect(decimal128.hash).to eq(BSON::Decimal128.from_bson(decimal128.to_bson).hash) end end describe "#inspect" do let(:decimal128) do described_class.new(BigDecimal.new('1.23')) end it "returns the inspection with the decimal128 to_s" do expect(decimal128.inspect).to eq("BSON::Decimal128('#{decimal128.to_s}')") end end describe "#to_big_decimal" do shared_examples_for 'a decimal128 convertible to a Ruby BigDecimal' do let(:decimal128) do described_class.new(big_decimal) end it 'properly converts the Decimal128 to a BigDecimal' do expect(decimal128.to_big_decimal).to eq(expected_big_decimal) end end context 'when the Decimal128 is a special type' do context 'when the value is Infinity' do let(:big_decimal) do BigDecimal.new('Infinity') end let(:expected_big_decimal) do big_decimal end it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal' end context 'when the value is -Infinity' do let(:big_decimal) do BigDecimal.new('-Infinity') end let(:expected_big_decimal) do big_decimal end it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal' end end context 'when the value represents an Integer' do context 'when the value is 1' do let(:big_decimal) do BigDecimal.new(1) end let(:expected_big_decimal) do big_decimal end it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal' end context 'when the value is -1' do let(:big_decimal) do BigDecimal.new(-1) end let(:expected_big_decimal) do big_decimal end it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal' end context 'when the value is 20' do let(:big_decimal) do BigDecimal.new(20) end let(:expected_big_decimal) do big_decimal end it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal' end context 'when the value is -20' do let(:big_decimal) do BigDecimal.new(-20) end let(:expected_big_decimal) do big_decimal end it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal' end context 'when the value is 12345678901234567' do let(:big_decimal) do BigDecimal.new(12345678901234567) end let(:expected_big_decimal) do big_decimal end it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal' end context 'when the value is -12345678901234567' do let(:big_decimal) do BigDecimal.new(-12345678901234567) end let(:expected_big_decimal) do big_decimal end it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal' end context 'when the value is 12345689012345789012345' do let(:big_decimal) do BigDecimal.new(12345689012345789012345) end let(:expected_big_decimal) do big_decimal end it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal' end context 'when the value is -12345689012345789012345' do let(:big_decimal) do BigDecimal.new(-12345689012345789012345) end let(:expected_big_decimal) do big_decimal end it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal' end end context 'when the value has a fraction' do context 'when the value is 0.1' do let(:big_decimal) do BigDecimal.new(0.1, 1) end let(:expected_big_decimal) do big_decimal end it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal' end context 'when the value is -0.1' do let(:big_decimal) do BigDecimal.new(-0.1, 1) end let(:expected_big_decimal) do big_decimal end it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal' end context 'when the value is 0.123' do let(:big_decimal) do BigDecimal.new(0.123, 3) end let(:expected_big_decimal) do big_decimal end it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal' end context 'when the value is -0.123' do let(:big_decimal) do BigDecimal.new(-0.123, 3) end let(:expected_big_decimal) do big_decimal end it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal' end end context 'when the value has leading zeros' do let(:big_decimal) do BigDecimal.new(0.001234, 4) end let(:expected_big_decimal) do big_decimal end it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal' end context 'when the value has trailing zeros' do let(:big_decimal) do BigDecimal.new(2.000, 4) end let(:expected_big_decimal) do big_decimal end it_behaves_like 'a decimal128 convertible to a Ruby BigDecimal' end end context "when the class is loaded" do let(:registered) do BSON::Registry.get(described_class::BSON_TYPE, 'field') end it "registers the type" do expect(registered).to eq(described_class) end end end bson-4.3.0/spec/bson/date_time_spec.rb0000644000004100000410000000227313236361476017713 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe DateTime do it_behaves_like "a class which converts to Time" describe "#to_bson" do context "when the date time is post epoch" do let(:obj) { DateTime.new(2012, 1, 1, 0, 0, 0) } let(:bson) { [ (obj.to_time.to_f * 1000).to_i ].pack(BSON::Int64::PACK) } it_behaves_like "a serializable bson element" end context "when the date time is pre epoch" do let(:obj) { DateTime.new(1969, 1, 1, 0, 0, 0) } let(:bson) { [ (obj.to_time.to_f * 1000).to_i ].pack(BSON::Int64::PACK) } it_behaves_like "a serializable bson element" end end end bson-4.3.0/spec/bson/config_spec.rb0000644000004100000410000000135313236361476017223 0ustar www-datawww-datarequire "spec_helper" describe BSON::Config do describe "#validating_keys?" do context "when the default is used" do it "returns false" do expect(described_class).to_not be_validating_keys end end context "when configuring to false" do before do BSON::Config.validating_keys = false end it "returns false" do expect(described_class).to_not be_validating_keys end end context "when configuring to true" do before do BSON::Config.validating_keys = true end after do BSON::Config.validating_keys = false end it "returns true" do expect(described_class).to be_validating_keys end end end end bson-4.3.0/spec/bson/document_spec.rb0000644000004100000410000005144713236361476017605 0ustar www-datawww-data# encoding: utf-8 # Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe BSON::Document do let(:keys) { %w(blue green red pink orange) } let(:vals) { %w(000099 009900 aa0000 cc0066 cc6633) } let(:doc) { described_class.new } let(:hash) do {} end let(:enum_class) do Enumerator end before do keys.each_with_index do |key, index| hash[key] = vals[index] doc[key] = vals[index] end end describe "#keys" do it "retains the insertion order" do expect(doc.keys).to eq(keys) end end describe "#values" do it "retains the insertion order" do expect(doc.values).to eq(vals) end end describe "#[]" do let(:document) do described_class["key", "value", "key2", "value"] end context "when provided string keys" do it "returns the value" do expect(document["key"]).to eq("value") end end context "when provided symbol keys" do it "returns the value" do expect(document[:key]).to eq("value") end end end describe "#[]=" do let(:key) { "purple" } let(:val) { "5422a8" } before do doc[key] = val end it "updates the length" do expect(doc.length).to eq(keys.length + 1) end it "adds the key to the end" do expect(doc.keys.last).to eq(key) end it "adds the value to the end" do expect(doc.values.last).to eq(val) end it "sets the value" do expect(doc[key]).to eq(val) end end if described_class.instance_methods.include?(:dig) describe "#dig" do let(:document) do described_class.new("key1" => { :key2 => "value" }) end context "when provided string keys" do it "returns the value" do expect(document.dig("key1", "key2")).to eq("value") end end context "when provided symbol keys" do it "returns the value" do expect(document.dig(:key1, :key2)).to eq("value") end end end end describe "#delete" do shared_examples_for "a document with deletable pairs" do let!(:deleted) { doc.delete(key) } it "returns the deleted value" do expect(deleted).to eq(val) end it "removes the key from the list" do expect(doc.keys.length).to eq(keys.length) end it "matches the keys length to the document length" do expect(doc.length).to eq(doc.keys.length) end context "when removing a bad key" do it "returns nil" do expect(doc.delete(bad_key)).to be_nil end context "when a block is provided" do it "returns the result of the block" do expect(doc.delete(bad_key) { |k| "golden key" }).to eq("golden key") end end end end context "when keys are strings" do let(:key) { "white" } let(:val) { "ffffff" } let(:bad_key) { "black" } before do doc[key] = val end it_behaves_like "a document with deletable pairs" end context "when keys are symbols" do let(:key) { :white } let(:val) { "ffffff" } let(:bad_key) { :black } before do doc[key] = val end it_behaves_like "a document with deletable pairs" end end describe "#to_hash" do it "returns the document" do expect(doc.to_hash).to eq(doc) end end describe "#to_a" do it "returns the key/value pairs as an array" do expect(doc.to_a).to eq(keys.zip(vals)) end end [ :has_key?, :key?, :include?, :member? ].each do |method| describe "##{method}" do context "when the key exists" do it "returns true" do expect(doc.send(method, "blue")).to be true end end context "when the key does not exist" do it "returns false" do expect(doc.send(method, "indigo")).to be false end end context "when the key exists and is requested with a symbol" do it "returns true" do expect(doc.send(method, :blue)).to be true end end context "when the key does not exist and is requested with a symbol" do it "returns false" do expect(doc.send(method, :indigo)).to be false end end end end [ :has_value?, :value? ].each do |method| describe "##{method}" do let(:key) { :purple } let(:val) { :'5422a8' } before do doc[key] = val end context "when the value exists" do it "returns true" do expect(doc.send(method, "000099")).to be true end end context "when the value does not exist" do it "returns false" do expect(doc.send(method, "ABCABC")).to be false end end context "when the value exists and is requested with a symbol" do it "returns true" do expect(doc.send(method, :'5422a8')).to be true end end context "when the value does not exist and is requested with a symbol" do it "returns false" do expect(doc.send(method, :ABCABC)).to be false end end end end describe "#each_key" do let(:iter_keys) {[]} context "when passed a block" do let!(:enum) do doc.each_key{ |k| iter_keys << k } end it "returns the document" do expect(enum).to equal(doc) end it "iterates over each of the keys" do expect(iter_keys).to eq(keys) end end context "when not passed a block" do let!(:enum) do doc.each_key end it "returns an enumerator" do expect(enum).to be_a(enum_class) end end end describe "#each_value" do let(:iter_vals) {[]} context "when passed a block" do let!(:enum) do doc.each_value{ |v| iter_vals << v } end it "returns the document" do expect(enum).to equal(doc) end it "iterates over each of the vals" do expect(iter_vals).to eq(vals) end end context "when not passed a block" do let!(:enum) do doc.each_value end it "returns an enumerator" do expect(enum).to be_a(enum_class) end end end [ :each, :each_pair ].each do |method| describe "##{method}" do let(:iter_keys) {[]} let(:iter_vals) {[]} context "when passed a block" do let!(:enum) do doc.send(method) do |k, v| iter_keys << k iter_vals << v end end it "returns the document" do expect(enum).to equal(doc) end it "iterates over each of the keys" do expect(iter_keys).to eq(keys) end it "iterates over each of the vals" do expect(iter_vals).to eq(vals) end end context "when not passed a block" do let!(:enum) do doc.send(method) end it "returns an enumerator" do expect(enum).to be_a(enum_class) end end context "when the document has been serialized" do let(:deserialized) do YAML.load(YAML.dump(doc)) end let!(:enum) do deserialized.send(method) do |k, v| iter_keys << k iter_vals << v end end it "iterates over each of the keys" do expect(iter_keys).to eq(keys) end it "iterates over each of the vals" do expect(iter_vals).to eq(vals) end end end end describe "#each_with_index" do it "iterates over the document passing an index" do doc.each_with_index do |pair, index| expect(pair).to eq([ keys[index], vals[index] ]) end end end describe "#find_all" do it "iterates in the correct order" do expect(doc.find_all{ true }.map(&:first)).to eq(keys) end end describe "#select" do it "iterates in the correct order" do expect(doc.select{ true }.map(&:first)).to eq(keys) end end [ :delete_if, :reject! ].each do |method| describe "##{method}" do let(:copy) { doc.dup } before do copy.delete("pink") end let!(:deleted) do doc.send(method){ |k, _| k == "pink" } end it "deletes elements for which the block is true" do expect(deleted).to eq(copy) end it "deletes the matching keys from the document" do expect(doc.keys).to_not include("pink") end it "returns the same document" do expect(deleted).to equal(doc) end end end describe "#reject" do let(:copy) { doc.dup } before do copy.delete("pink") end let!(:deleted) do doc.reject{ |k, _| k == "pink" } end it "deletes elements for which the block is true" do expect(deleted).to eq(copy) end it "deletes the matching keys from the new document" do expect(deleted.keys).to_not include("pink") end it "returns a new document" do expect(deleted).to_not equal(doc) end end describe "#clear" do before do doc.clear end it "clears out the keys" do expect(doc.keys).to be_empty end end describe "#merge" do let(:other) { described_class.new } context "when passed no block" do before do other["purple"] = "800080" other["violet"] = "ee82ee" end let!(:merged) do doc.merge(other) end it "merges the keys" do expect(merged.keys).to eq(keys + [ "purple", "violet" ]) end it "adds to the length" do expect(merged.length).to eq(doc.length + other.length) end it "returns a new document" do expect(merged).to_not equal(doc) end end context "when passed a block" do before do other[:a] = 0 other[:b] = 0 end let(:merged) do other.merge(:b => 2, :c => 7) do |key, old_val, new_val| new_val + 1 end end it "executes the block on each merged element" do expect(merged[:a]).to eq(0) expect(merged[:b]).to eq(3) expect(merged[:c]).to eq(7) end end end describe "#merge!" do let(:other) { described_class.new } context "when passed no block" do before do other["purple"] = "800080" other["violet"] = "ee82ee" end let(:merged) do doc.merge!(other) end it "merges the keys" do expect(merged.keys).to eq(keys + [ "purple", "violet" ]) end it "adds to the length" do expect(merged.length).to eq(doc.length) end it "returns the same document" do expect(merged).to equal(doc) end end context "when passed a block" do before do other[:a] = 0 other[:b] = 0 end let!(:merged) do other.merge!(:b => 2, :c => 7) do |key, old_val, new_val| new_val + 1 end end it "executes the block on each merged element" do expect(other[:a]).to eq(0) expect(other[:b]).to eq(3) expect(other[:c]).to eq(7) end end context "and the documents have no common keys" do before { other[:a] = 1 } it "does not execute the block" do expect(other.merge(b: 1) { |key, old, new| old + new }).to eq( BSON::Document.new(a: 1, b: 1) ) end end end describe "#shift" do let(:pair) do doc.shift end it "returns the first pair in the document" do expect(pair).to eq([ keys.first, vals.first ]) end it "removes the pair from the document" do expect(doc.keys).to_not eq(pair.first) end end describe "#inspect" do it "includes the hash inspect" do expect(doc.inspect).to include(hash.inspect) end end describe "#initialize" do context "when providing symbol keys" do let(:document) do described_class.new(:test => 2, :testing => 4) end it "converts the symbols to strings" do expect(document).to eq({ "test" => 2, "testing" => 4 }) end end context "when providing duplicate symbol and string keys" do let(:document) do described_class.new(:test => 2, "test" => 4) end it "uses the last provided string key value" do expect(document[:test]).to eq(4) end end context "when providing a nested hash with symbol keys" do let(:document) do described_class.new(:test => { :test => 4 }) end it "converts the nested keys to strings" do expect(document).to eq({ "test" => { "test" => 4 }}) end end context "when providing a nested hash multiple levels deep with symbol keys" do let(:document) do described_class.new(:test => { :test => { :test => 4 }}) end it "converts the nested keys to strings" do expect(document).to eq({ "test" => { "test" => { "test" => 4 }}}) end end context "when providing an array of nested hashes" do let(:document) do described_class.new(:test => [{ :test => 4 }]) end it "converts the nested keys to strings" do expect(document).to eq({ "test" => [{ "test" => 4 }]}) end end end describe "#replace" do let(:other) do described_class[:black, "000000", :white, "000000"] end let!(:original) { doc.replace(other) } it "replaces the keys" do expect(doc.keys).to eq(other.keys) end it "returns the document" do expect(original).to eq(doc) end end describe "#update" do let(:updated) { described_class.new } before do updated.update(:name => "Bob") end it "updates the keys" do expect(updated.keys).to eq([ "name" ]) end it "updates the values" do expect(updated.values).to eq([ "Bob" ]) end it "returns the same document" do expect(updated.update(:name => "Bob")).to equal(updated) end end describe "#invert" do let(:expected) do described_class[vals.zip(keys)] end it "inverts the hash in inverse order" do expect(doc.invert).to eq(expected) end it "inverts the keys" do expect(vals.zip(keys)).to eq(doc.invert.to_a) end end describe "#from_bson" do context "when the document has embedded documents in an array" do let(:embedded_document) do BSON::Document.new(n: 1) end let(:embedded_documents) do [ embedded_document ] end let(:document) do BSON::Document.new(field: 'value', embedded: embedded_documents) end let(:serialized) do document.to_bson.to_s end let(:deserialized) do described_class.from_bson(BSON::ByteBuffer.new(serialized)) end it 'deserializes the documents' do expect(deserialized).to eq(document) end it 'deserializes embedded documents as document type' do expect(deserialized[:embedded].first).to be_a(BSON::Document) end end end describe "#to_bson/#from_bson" do let(:type) { 3.chr } it_behaves_like "a bson element" context "when the hash has symbol keys" do let(:obj) do described_class[:ismaster, 1].freeze end let(:bson) do "#{19.to_bson}#{BSON::Int32::BSON_TYPE}ismaster#{BSON::NULL_BYTE}" + "#{1.to_bson}#{BSON::NULL_BYTE}" end it "properly serializes the symbol" do expect(obj.to_bson.to_s).to eq(bson) end end context "when the hash contains an array of hashes" do let(:obj) do described_class["key",[{"a" => 1}, {"b" => 2}]] end let(:bson) do "#{45.to_bson}#{Array::BSON_TYPE}key#{BSON::NULL_BYTE}" + "#{35.to_bson}"+ "#{BSON::Document::BSON_TYPE}0#{BSON::NULL_BYTE}#{12.to_bson}#{BSON::Int32::BSON_TYPE}a#{BSON::NULL_BYTE}#{1.to_bson}#{BSON::NULL_BYTE}" + "#{BSON::Document::BSON_TYPE}1#{BSON::NULL_BYTE}#{12.to_bson}#{BSON::Int32::BSON_TYPE}b#{BSON::NULL_BYTE}#{2.to_bson}#{BSON::NULL_BYTE}" + "#{BSON::NULL_BYTE}" + "#{BSON::NULL_BYTE}" end it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end context "when the hash is a single level" do let(:obj) do described_class["key","value"] end let(:bson) do "#{20.to_bson}#{String::BSON_TYPE}key#{BSON::NULL_BYTE}" + "#{6.to_bson}value#{BSON::NULL_BYTE}#{BSON::NULL_BYTE}" end it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end context "when the hash is embedded" do let(:obj) do described_class["field", BSON::Document["key", "value"]] end let(:bson) do "#{32.to_bson}#{Hash::BSON_TYPE}field#{BSON::NULL_BYTE}" + "#{20.to_bson}#{String::BSON_TYPE}key#{BSON::NULL_BYTE}" + "#{6.to_bson}value#{BSON::NULL_BYTE}#{BSON::NULL_BYTE}#{BSON::NULL_BYTE}" end it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" let(:raw) do BSON::ByteBuffer.new(bson) end it "returns an instance of a BSON::Document" do expect(described_class.from_bson(raw)).to be_a(BSON::Document) end end end context "when encoding and decoding" do context "when the keys are utf-8" do let(:document) do described_class["gültig", "type"] end it_behaves_like "a document able to handle utf-8" end context "when the values are utf-8" do let(:document) do described_class["type", "gültig"] end it_behaves_like "a document able to handle utf-8" end context "when both the keys and values are utf-8" do let(:document) do described_class["gültig", "gültig"] end it_behaves_like "a document able to handle utf-8" end context "when the regexps are utf-8" do let(:document) do described_class["type", /^gültig/] end let(:deserialized) do described_class.from_bson(BSON::ByteBuffer.new(document.to_bson.to_s)) end it "serializes and deserializes properly" do expect(deserialized['type'].compile).to eq(/^gültig/) end end context "when utf-8 string values are in an array" do let(:document) do described_class["type", ["gültig"]] end it_behaves_like "a document able to handle utf-8" end context "when utf-8 code values are present" do let(:document) do described_class["code", BSON::Code.new("// gültig")] end it_behaves_like "a document able to handle utf-8" end context "when utf-8 code with scope values are present" do let(:document) do described_class["code", BSON::CodeWithScope.new("// gültig", {})] end it_behaves_like "a document able to handle utf-8" end context "when utf-8 values exist in wrong encoding" do let(:string) { "gültig" } let(:document) do described_class["type", string.encode("iso-8859-1")] end it "raises an exception", unless: BSON::Environment.jruby? do expect { document.to_bson }.to raise_error(ArgumentError) end it 'converts the values', if: BSON::Environment.jruby? do expect( BSON::Document.from_bson(BSON::ByteBuffer.new(document.to_bson.to_s)) ).to eq({ "type" => string }) end end context "when binary strings with utf-8 values exist", if: BSON::Environment.jruby? && (JRUBY_VERSION < '9') do let(:string) { "europäisch" } let(:document) do described_class["type", string.encode("binary")] end it "encodes and decodes the document properly" do expect( BSON::Document.from_bson(BSON::ByteBuffer.new(document.to_bson.to_s)) ).to eq({ "type" => string }) end end context "when binary strings with utf-8 values exist", unless: BSON::Environment.jruby? do let(:string) { "europäisch" } let(:document) do described_class["type", string.encode("binary", "binary")] end it "encodes and decodes the document properly" do expect( BSON::Document.from_bson(BSON::ByteBuffer.new(document.to_bson.to_s)) ).to eq({ "type" => string }) end end end end bson-4.3.0/spec/bson/object_id_spec.rb0000644000004100000410000002774713236361476017717 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" require "yaml" describe BSON::ObjectId do describe "#==" do context "when data is identical" do let(:time) do Time.now end let(:object_id) do described_class.from_time(time) end let(:other_id) do described_class.from_time(time) end it "returns true" do expect(object_id).to eq(other_id) end end context "when the data is different" do let(:time) do Time.now end let(:object_id) do described_class.from_time(time) end it "returns false" do expect(object_id).to_not eq(described_class.new) end end context "when other is not an object id" do it "returns false" do expect(described_class.new).to_not eq(nil) end end end describe "#===" do let(:object_id) do described_class.new end context "when comparing with another object id" do context "when the data is equal" do let(:other) do described_class.from_string(object_id.to_s) end it "returns true" do expect(object_id === other).to be true end end context "when the data is not equal" do let(:other) do described_class.new end it "returns false" do expect(object_id === other).to be false end end end context "when comparing to an object id class" do it "returns false" do expect(object_id === BSON::ObjectId).to be false end end context "when comparing with a string" do context "when the data is equal" do let(:other) do object_id.to_s end it "returns true" do expect(object_id === other).to be true end end context "when the data is not equal" do let(:other) do described_class.new.to_s end it "returns false" do expect(object_id === other).to be false end end end context "when comparing with a non string or object id" do it "returns false" do expect(object_id === "test").to be false end end context "when comparing with a non object id class" do it "returns false" do expect(object_id === String).to be false end end end describe "#<" do let(:object_id) do described_class.from_time(Time.utc(2012, 1, 1)) end let(:other_id) do described_class.from_time(Time.utc(2012, 1, 30)) end context "when the generation time before the other" do it "returns true" do expect(object_id < other_id).to be true end end context "when the generation time is after the other" do it "returns false" do expect(other_id < object_id).to be false end end end describe "#>" do let(:object_id) do described_class.from_time(Time.utc(2012, 1, 1)) end let(:other_id) do described_class.from_time(Time.utc(2012, 1, 30)) end context "when the generation time before the other" do it "returns false" do expect(object_id > other_id).to be false end end context "when the generation time is after the other" do it "returns true" do expect(other_id > object_id).to be true end end end describe "#<=>" do let(:object_id) do described_class.from_time(Time.utc(2012, 1, 1)) end let(:other_id) do described_class.from_time(Time.utc(2012, 1, 30)) end context "when the generation time before the other" do it "returns -1" do expect(object_id <=> other_id).to eq(-1) end end context "when the generation time is after the other" do it "returns false" do expect(other_id <=> object_id).to eq(1) end end end describe "#as_json" do let(:object) do described_class.new end it "returns the object id with $oid key" do expect(object.as_json).to eq({ "$oid" => object.to_s }) end it_behaves_like "a JSON serializable object" end describe "::BSON_TYPE" do it "returns 0x07" do expect(BSON::ObjectId::BSON_TYPE).to eq(7.chr) end end describe "#bson_type" do let(:code) do described_class.new end it "returns 0x0D" do expect(code.bson_type).to eq(BSON::ObjectId::BSON_TYPE) end end describe "#eql" do context "when data is identical" do let(:time) do Time.now end let(:object_id) do described_class.from_time(time) end let(:other_id) do described_class.from_time(time) end it "returns true" do expect(object_id).to eql(other_id) end end context "when the data is different" do let(:time) do Time.now end let(:object_id) do described_class.from_time(time) end it "returns false" do expect(object_id).to_not eql(described_class.new) end end context "when other is not an object id" do it "returns false" do expect(described_class.new).to_not eql(nil) end end end describe ".from_string" do context "when the string is valid" do let(:string) do "4e4d66343b39b68407000001" end let(:object_id) do described_class.from_string(string) end it "initializes with the string's bytes" do expect(object_id.to_s).to eq(string) end end context "when the string is not valid" do it "raises an error" do expect { described_class.from_string("asadsf") }.to raise_error(BSON::ObjectId::Invalid) end end end describe ".from_time" do context "when no unique option is provided" do let(:time) do Time.at((Time.now.utc - 64800).to_i).utc end let(:object_id) do described_class.from_time(time) end it "sets the generation time" do expect(object_id.generation_time).to eq(time) end it "does not include process or sequence information" do expect(object_id.to_s =~ /\A[0-9a-f]{8}[0]{16}\Z/).to be_truthy end end context "when a unique option is provided" do let(:time) do Time.at((Time.now.utc - 64800).to_i).utc end let(:object_id) do described_class.from_time(time, :unique => true) end let(:non_unique) do described_class.from_time(time, :unique => true) end it "creates a new unique object id" do expect(object_id).to_not eq(non_unique) end end end describe "#generation_time" do let(:time) do Time.utc(2013, 1, 1) end let(:object_id) do described_class.from_time(time) end it "returns the generation time" do expect(object_id.generation_time).to eq(time) end end describe "#hash" do let(:object_id) do described_class.new end it "returns a hash of the raw bytes" do expect(object_id.hash).to eq(object_id.to_bson.to_s.hash) end end describe "#initialize" do it "does not generate duplicate ids" do 100000.times do expect(BSON::ObjectId.new).to_not eq(BSON::ObjectId.new) end end end describe "#clone" do context "when the data has not been generated yet" do let!(:object_id) do described_class.new end let!(:clone) do object_id.clone end it "generates and copies the data" do expect(clone).to eq(object_id) end end context "when the data has been generated" do let!(:object_id) do described_class.new end let(:clone) do object_id.clone end before do object_id.to_s end it "copies the data" do expect(clone).to eq(object_id) end end end describe "#inspect" do let(:object_id) do described_class.new end it "returns the inspection with the object id to_s" do expect(object_id.inspect).to eq("BSON::ObjectId('#{object_id.to_s}')") end it "returns a string that evaluates into an equivalent object id" do expect(eval object_id.inspect).to eq object_id end end describe ".legal?" do context "when the string is too short to be an object id" do it "returns false" do expect(described_class).to_not be_legal("a" * 23) end end context "when the string contains invalid hex characters" do it "returns false" do expect(described_class).to_not be_legal("y" + "a" * 23) end end context "when the string is a valid object id" do it "returns true" do expect(described_class).to be_legal("a" * 24) end end context "when the string contains newlines" do it "returns false" do expect(described_class).to_not be_legal("\n\n" + "a" * 24 + "\n\n") end end context "when checking against another object id" do let(:object_id) do described_class.new end it "returns true" do expect(described_class).to be_legal(object_id) end end end describe "#marshal_dump" do let(:object_id) do described_class.new end let(:dumped) do Marshal.dump(object_id) end it "dumps the raw bytes data" do expect(Marshal.load(dumped)).to eq(object_id) end end describe "#marshal_load" do context "when the object id was dumped in the old format" do let(:legacy) do "\x04\bo:\x13BSON::ObjectId\x06:\n" + "@data[\x11iUi\x01\xE2i,i\x00i\x00i\x00i\x00i\x00i\x00i\x00i\x00i\x00" end let(:object_id) do Marshal.load(legacy) end let(:expected) do described_class.from_time(Time.utc(2013, 1, 1)) end it "properly loads the object id" do expect(object_id).to eq(expected) end it "removes the bad legacy data" do object_id.to_bson expect(object_id.instance_variable_get(:@data)).to be_nil end end end describe "#to_bson/#from_bson" do let(:time) { Time.utc(2013, 1, 1) } let(:type) { 7.chr } let(:obj) { described_class.from_time(time) } let(:bson) { obj.to_bson.to_s } it_behaves_like "a bson element" it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end describe "#to_s" do let(:time) do Time.utc(2013, 1, 1) end let(:expected) do "50e227000000000000000000" end let(:object_id) do described_class.from_time(time) end it "returns a hex string representation of the id" do expect(object_id.to_s).to eq(expected) end it "returns the string in UTF-8" do expect(object_id.to_s.encoding).to eq(Encoding.find(BSON::UTF8)) end it "converts to a readable yaml string" do expect(YAML.dump(object_id.to_s)).to include(expected) end end context "when the class is loaded" do let(:registered) do BSON::Registry.get(BSON::ObjectId::BSON_TYPE, 'field') end it "registers the type" do expect(registered).to eq(described_class) end end context "when the ids are used as keys" do let(:object_id) do described_class.new end let(:hash) do { object_id => 1 } end it "raises an exception on serialization" do expect { hash.to_bson }.to raise_error(BSON::InvalidKey) end end end bson-4.3.0/spec/bson/corpus_spec.rb0000644000004100000410000000465413236361476017300 0ustar www-datawww-datarequire 'spec_helper' describe 'Driver BSON Corpus spec tests' do specs = BSON_CORPUS_TESTS.map { |file| BSON::Corpus::Spec.new(file) } specs.each do |spec| context(spec.description) do spec.valid_tests.each do |test| context("VALID CASE: #{test.description}") do it 'roundtrips the given bson correctly' do expect(test.reencoded_bson).to eq(test.correct_bson) end context 'when the canonical bson is roundtripped', if: test.test_canonical_bson? do it 'encodes the canonical bson correctly' do expect(test.reencoded_canonical_bson).to eq(test.correct_bson) end end context 'when the document can be represented as extended json', if: test.test_extjson? do it 'decodes from the given bson, then encodes the document as extended json correctly' do skip 'The extended json in this test case does not match' unless (test.extjson_from_bson == test.correct_extjson) expect(test.extjson_from_bson).to eq(test.correct_extjson) expect(test.extjson_from_bson[test.test_key]).to eq(test.correct_extjson[test.test_key]) end it 'decodes from extended json, then encodes the document as extended json correctly' do expect(test.extjson_from_encoded_extjson).to eq(test.correct_extjson) expect(test.extjson_from_encoded_extjson[test.test_key]).to eq(test.correct_extjson[test.test_key]) end context 'when the canonical bson can be represented as extended json', if: (test.test_canonical_bson? && test.test_extjson?) do it 'encodes the canonical bson correctly as extended json' do expect(test.extjson_from_canonical_bson).to eq(test.correct_extjson) expect(test.extjson_from_canonical_bson[test.test_key]).to eq(test.correct_extjson[test.test_key]) end end end end end spec.invalid_tests.each do |test| context("INVALID CASE: #{test.description}") do let(:error) do begin; test.reencoded_bson; false; rescue => e; e; end end it 'raises an error' do skip 'This test case does not raise and error but should' unless error expect { test.reencoded_bson }.to raise_error end end end end end end bson-4.3.0/spec/bson/driver_bson_spec.rb0000644000004100000410000000456213236361476020277 0ustar www-datawww-datarequire 'spec_helper' describe 'Driver common bson tests' do specs = DRIVER_COMMON_BSON_TESTS.map { |file| BSON::CommonDriver::Spec.new(file) } specs.each do |spec| context(spec.description) do spec.valid_tests.each do |test| context(test.description << ' - ' << test.string) do it 'decodes the subject and displays as the correct string' do expect(test.object.to_s).to eq(test.expected_to_string) end it 'encodes the decoded object correctly (roundtrips)' do expect(test.reencoded_hex).to eq(test.subject.upcase) end it 'creates the correct object from extended json', if: test.from_ext_json? do expect(test.from_json_string).to eq(test.object) end it 'creates the correct extended json document from the decoded object', if: test.to_ext_json? do expect(test.document_as_json).to eq(test.ext_json) end it 'parses the string value to the same value as the decoded document', if: test.from_string? do expect(BSON::Decimal128.new(test.string)).to eq(test.object) end it 'parses the #to_s (match_string) value to the same value as the decoded document', if: test.match_string do expect(BSON::Decimal128.new(test.match_string)).to eq(test.object) end it 'creates the correct object from a non canonical string and then prints to the correct string', if: test.match_string do expect(BSON::Decimal128.new(test.string).to_s).to eq(test.match_string) end it 'can be converted to a native type' do expect(test.native_type_conversion).to be_a(test.native_type) end end end spec.invalid_tests.each do |test| context(test.description << " - " << test.subject ) do let(:error) do ex = nil begin test.parse_invalid_string rescue => e ex = e end ex end let(:valid_errors) do [ BSON::Decimal128::InvalidString, BSON::Decimal128::InvalidRange ] end it 'raises an exception when parsing' do expect(error.class).to satisfy { |e| valid_errors.include?(e) } end end end end end end bson-4.3.0/spec/bson/int32_spec.rb0000644000004100000410000000507213236361476016717 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe BSON::Int32 do describe "#intiialize" do let(:obj) { described_class.new(integer) } context "when the integer is 32-bit" do let(:integer) { Integer::MAX_32BIT } it "wraps the integer" do expect(obj.instance_variable_get(:@integer)).to be(integer) end end context "when the integer is too large" do let(:integer) { Integer::MAX_32BIT + 1 } it "raises an out of range error" do expect { obj }.to raise_error(RangeError) end end context "when the integer is too small" do let(:integer) { Integer::MIN_32BIT - 1 } it "raises an out of range error" do expect { obj }.to raise_error(RangeError) end end end describe "#from_bson" do let(:type) { 16.chr } let(:obj) { 123 } let(:bson) { [ obj ].pack(BSON::Int32::PACK) } it_behaves_like "a bson element" it_behaves_like "a deserializable bson element" end describe "when the integer is negative" do let(:decoded) { -1 } let(:encoded) { BSON::ByteBuffer.new([ -1 ].pack(BSON::Int32::PACK)) } let(:decoded_2) { -50 } let(:encoded_2) { BSON::ByteBuffer.new([ -50 ].pack(BSON::Int32::PACK)) } it "decodes a -1 correctly" do expect(BSON::Int32.from_bson(encoded)).to eq(decoded) end it "decodes a -50 correctly" do expect(BSON::Int32.from_bson(encoded_2)).to eq(decoded_2) end end describe "#to_bson" do context "when the integer is 32 bit" do let(:type) { 16.chr } let(:obj) { BSON::Int32.new(Integer::MAX_32BIT - 1) } let(:bson) { [ Integer::MAX_32BIT - 1 ].pack(BSON::Int32::PACK) } it_behaves_like "a serializable bson element" end end describe "#to_bson_key" do let(:obj) { BSON::Int32.new(Integer::MAX_32BIT - 1) } let(:encoded) { (Integer::MAX_32BIT - 1).to_s } it "returns the key as a string" do expect(obj.to_bson_key).to eq(encoded) end end end bson-4.3.0/spec/bson/undefined_spec.rb0000644000004100000410000000163113236361476017716 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe BSON::Undefined do describe "#to_bson/#from_bson" do let(:type) { 6.chr } let(:obj) { described_class.new } let(:bson) { BSON::NO_VALUE } it_behaves_like "a bson element" it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end end bson-4.3.0/spec/bson/false_class_spec.rb0000644000004100000410000000147613236361476020243 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe FalseClass do describe "#to_bson" do let(:obj) { false } let(:bson) { 0.chr } let(:type) { 8.chr } it_behaves_like "a bson element" it_behaves_like "a serializable bson element" end end bson-4.3.0/spec/bson/binary_spec.rb0000644000004100000410000001201013236361476017232 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" require "base64" describe BSON::Binary do let(:testing1) { described_class.new("testing") } let(:testing2) { described_class.new("testing") } let(:not_testing) { described_class.new("not testing") } describe "#eql?" do context "for two equal objects" do it "returns true" do expect(testing1).to eql(testing2) end end context "for two different objects" do it "returns false" do expect(testing1).not_to eql(not_testing) end end end describe "#hash" do context "for two equal objects" do it "is the same" do expect(testing1.hash).to eq(testing2.hash) end end context "for two different objects" do it "is different" do expect(testing1.hash).not_to eq(not_testing.hash) end end end let(:hash) do { testing1 => "my value" } end it "can be used as Hash key" do expect(hash[testing2]).to eq("my value") expect(hash[not_testing]).to be_nil end describe "#as_json" do let(:object) do described_class.new("testing", :user) end it "returns the binary data plus type" do expect(object.as_json).to eq( { "$binary" => Base64.encode64("testing"), "$type" => :user } ) end it_behaves_like "a JSON serializable object" end describe "#initialize" do context "when he type is invalid" do it "raises an error" do expect { described_class.new("testing", :error) }.to raise_error { |error| expect(error).to be_a(BSON::Binary::InvalidType) expect(error.message).to match /is not a valid binary type/ } end end end describe '#inspect' do let(:object) do described_class.new('testing123', :user) end it 'returns the truncated data and type' do expect(object.inspect).to eq("") end context 'with other encoding' do let(:object) do described_class.new("\x1F\x8B\b\x00\fxpU\x00\x03\xED\x1C\xDBv\xDB6\xF2\xBD_\x81UN\x9A\xE6T\x96H\xDD-\xDBjR7\xDD\xA6mR\x9F:m\xB7".force_encoding(Encoding::BINARY), :user) end it 'returns the truncated data and type' do expect(object.inspect).to eq("") end it 'is not different from default encoding' do expect(object.inspect.encoding).not_to eq(Encoding::BINARY) end end end describe "#to_bson/#from_bson" do let(:type) { 5.chr } it_behaves_like "a bson element" context "when the type is :generic" do let(:obj) { described_class.new("testing") } let(:bson) { "#{7.to_bson}#{0.chr}testing" } it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end context "when the type is :function" do let(:obj) { described_class.new("testing", :function) } let(:bson) { "#{7.to_bson}#{1.chr}testing" } it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end context "when the type is :old" do let(:obj) { described_class.new("testing", :old) } let(:bson) { "#{11.to_bson}#{2.chr}#{7.to_bson}testing" } it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end context "when the type is :uuid_old" do let(:obj) { described_class.new("testing", :uuid_old) } let(:bson) { "#{7.to_bson}#{3.chr}testing" } it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end context "when the type is :uuid" do let(:obj) { described_class.new("testing", :uuid) } let(:bson) { "#{7.to_bson}#{4.chr}testing" } it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end context "when the type is :md5" do let(:obj) { described_class.new("testing", :md5) } let(:bson) { "#{7.to_bson}#{5.chr}testing" } it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end context "when the type is :user" do let(:obj) { described_class.new("testing", :user) } let(:bson) { "#{7.to_bson}#{128.chr}testing" } it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end end end bson-4.3.0/spec/bson/symbol_spec.rb0000644000004100000410000000334113236361476017262 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe Symbol do describe "#bson_type" do it "returns the type for a string" do expect(:type.bson_type).to eq("type".bson_type) end end describe "#to_bson/#from_bson" do let(:type) { 2.chr } let(:obj) { :test } let(:bson) { "#{5.to_bson.to_s}test#{BSON::NULL_BYTE}" } it_behaves_like "a bson element" it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end describe "#to_bson_key" do let(:symbol) { :test } let(:encoded) { symbol.to_s } it "returns the encoded string" do expect(symbol.to_bson_key).to eq(encoded) end end describe "#to_bson_key" do context "when validating keys" do let(:symbol) do :'$testing.testing' end it "raises an exception" do expect { symbol.to_bson_key(true) }.to raise_error(BSON::String::IllegalKey) end end context "when not validating keys" do let(:symbol) do :'$testing.testing' end it "allows invalid keys" do expect(symbol.to_bson_key).to eq(symbol.to_s) end end end end bson-4.3.0/spec/bson/int64_spec.rb0000644000004100000410000000764013236361476016727 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe BSON::Int64 do describe "#intiialize" do let(:obj) { described_class.new(integer) } context "when the integer is 64-bit" do let(:integer) { Integer::MAX_64BIT - 1 } it "wraps the integer" do expect(obj.instance_variable_get(:@integer)).to be(integer) end end context "when the integer is too large" do let(:integer) { Integer::MAX_64BIT + 1 } it "raises an out of range error" do expect { obj }.to raise_error(RangeError) end end context "when the integer is too small" do let(:integer) { Integer::MIN_64BIT - 1 } it "raises an out of range error" do expect { obj }.to raise_error(RangeError) end end end describe "#from_bson" do let(:type) { 18.chr } let(:obj) { 1325376000000 } let(:bson) { [ obj ].pack(BSON::Int64::PACK) } it_behaves_like "a bson element" it_behaves_like "a deserializable bson element" context "when the integer is within the MRI Fixnum range" do let(:integer) { 2**30 - 1 } let(:bson) do BSON::ByteBuffer.new(BSON::Int64.new(integer).to_bson.to_s) end context "when on JRuby", if: BSON::Environment.jruby? do it "deserializes to a Fixnum object" do expect(described_class.from_bson(bson).class).to be(Fixnum) end end context "when using MRI < 2.4", if: (!BSON::Environment.jruby? && RUBY_VERSION < '2.4') do it "deserializes to a Fixnum object" do expect(described_class.from_bson(bson).class).to be(Fixnum) end end context "when using MRI >= 2.4", if: (!BSON::Environment.jruby? && RUBY_VERSION >= '2.4') do it "deserializes to an Integer object" do expect(described_class.from_bson(bson).class).to be(Integer) end end end context "when the 64-bit integer is the BSON max and thus larger than the MRI Fixnum range on all architectures" do let(:integer) { Integer::MAX_64BIT } let(:bson) do BSON::ByteBuffer.new(integer.to_bson.to_s) end context "when on JRuby", if: BSON::Environment.jruby? do it "deserializes to a Fixnum object" do expect(described_class.from_bson(bson).class).to be(Fixnum) end end context "when using MRI < 2.4", if: (!BSON::Environment.jruby? && RUBY_VERSION < '2.4') do it "deserializes to a Bignum object" do expect(described_class.from_bson(bson).class).to be(Bignum) end end context "when using MRI >= 2.4", if: (!BSON::Environment.jruby? && RUBY_VERSION >= '2.4') do it "deserializes to an Integer object" do expect(described_class.from_bson(bson).class).to be(Integer) end end end end describe "#to_bson" do context "when the integer is 64 bit" do let(:type) { 18.chr } let(:obj) { BSON::Int64.new(Integer::MAX_64BIT - 1) } let(:bson) { [ Integer::MAX_64BIT - 1 ].pack(BSON::Int64::PACK) } it_behaves_like "a serializable bson element" end end describe "#to_bson_key" do let(:obj) { BSON::Int64.new(Integer::MAX_64BIT - 1) } let(:encoded) { (Integer::MAX_64BIT - 1).to_s } it "returns the key as a string" do expect(obj.to_bson_key).to eq(encoded) end end end bson-4.3.0/spec/bson/boolean_spec.rb0000644000004100000410000000222713236361476017376 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe BSON::Boolean do describe "::BSON_TYPE" do it "returns 8" do expect(BSON::Boolean::BSON_TYPE).to eq(8.chr) end end describe "#from_bson" do let(:type) { 8.chr } it_behaves_like "a bson element" context "when the boolean is true" do let(:obj) { true } let(:bson) { 1.chr } it_behaves_like "a deserializable bson element" end context "when the boolean is false" do let(:obj) { false } let(:bson) { 0.chr } it_behaves_like "a deserializable bson element" end end end bson-4.3.0/spec/bson/open_struct_spec.rb0000644000004100000410000000771213236361476020330 0ustar www-datawww-data# Copyright (C) 2016 MongoDB 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 "spec_helper" describe OpenStruct do describe "#to_bson" do let(:type) { 3.chr } it_behaves_like "a bson element" context "when the struct is a single level" do let(:obj) do described_class.new({"key" => "value" }) end let(:bson) do "#{20.to_bson.to_s}#{String::BSON_TYPE}key#{BSON::NULL_BYTE}" + "#{6.to_bson.to_s}value#{BSON::NULL_BYTE}#{BSON::NULL_BYTE}" end it_behaves_like "a serializable bson element" end context "when the struct has invalid keys" do let(:obj) do described_class.new({ "$testing" => "value" }) end context "when validating keys" do context "when validating globally" do before do BSON::Config.validating_keys = true end after do BSON::Config.validating_keys = false end it "raises an error" do expect { obj.to_bson }.to raise_error(BSON::String::IllegalKey) end context "when the struct contains an array of documents containing invalid keys" do let(:obj) do described_class.new({ "array" => [{ "$testing" => "value" }] }) end it "raises an error" do expect { obj.to_bson }.to raise_error(BSON::String::IllegalKey) end end end context "when validating locally" do it "raises an error" do expect { obj.to_bson(BSON::ByteBuffer.new, true) }.to raise_error(BSON::String::IllegalKey) end context "when the struct contains an array of documents containing invalid keys" do let(:obj) do described_class.new({ "array" => [{ "$testing" => "value" }] }) end it "raises an error" do expect { obj.to_bson(BSON::ByteBuffer.new, true) }.to raise_error(BSON::String::IllegalKey) end end end end context "when not validating keys" do let(:bson) do "#{25.to_bson.to_s}#{String::BSON_TYPE}$testing#{BSON::NULL_BYTE}" + "#{6.to_bson.to_s}value#{BSON::NULL_BYTE}#{BSON::NULL_BYTE}" end it "serializes the struct" do expect(obj.to_bson.to_s).to eq(bson) end context "when the struct contains an array of documents containing invalid keys" do let(:obj) do described_class.new({ "array" => [{ "$testing" => "value" }] }) end let(:bson) do "#{45.to_bson.to_s}#{Array::BSON_TYPE}array#{BSON::NULL_BYTE}" + "#{[{ "$testing" => "value" }].to_bson.to_s}#{BSON::NULL_BYTE}" end it "serializes the struct" do expect(obj.to_bson.to_s).to eq(bson) end end end end context "when the struct is embedded" do let(:obj) do described_class.new({ "field" => OpenStruct.new({ "key" => "value" })}) end let(:bson) do "#{32.to_bson.to_s}#{Hash::BSON_TYPE}field#{BSON::NULL_BYTE}" + "#{20.to_bson.to_s}#{String::BSON_TYPE}key#{BSON::NULL_BYTE}" + "#{6.to_bson.to_s}value#{BSON::NULL_BYTE}#{BSON::NULL_BYTE}#{BSON::NULL_BYTE}" end it_behaves_like "a serializable bson element" end end end bson-4.3.0/spec/bson/max_key_spec.rb0000644000004100000410000000333313236361476017413 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe BSON::MaxKey do describe "#==" do context "when the objects are equal" do let(:other) { described_class.new } it "returns true" do expect(subject).to eq(other) end end context "when the other object is not a max_key" do it "returns false" do expect(subject).to_not eq("test") end end end describe "#>" do it "always returns true" do expect(subject > Integer::MAX_64BIT).to be true end end describe "#<" do it "always returns false" do expect(subject < Integer::MAX_64BIT).to be false end end describe "#as_json" do let(:object) do described_class.new end it "returns the binary data plus type" do expect(object.as_json).to eq({ "$maxKey" => 1 }) end it_behaves_like "a JSON serializable object" end describe "#to_bson/#from_bson" do let(:type) { 127.chr } let(:obj) { described_class.new } let(:bson) { BSON::NO_VALUE } it_behaves_like "a bson element" it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end end bson-4.3.0/spec/bson/float_spec.rb0000644000004100000410000000161513236361476017064 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe Float do describe "#to_bson/#from_bson" do let(:type) { 1.chr } let(:obj) { 1.2332 } let(:bson) { [ obj ].pack(Float::PACK) } it_behaves_like "a bson element" it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end end bson-4.3.0/spec/bson/raw_spec.rb0000644000004100000410000003335013236361476016551 0ustar www-datawww-datarequire 'spec_helper' describe Regexp::Raw do let(:pattern) { '\W+' } let(:options) { '' } let(:bson) { "#{pattern}#{BSON::NULL_BYTE}#{options}#{BSON::NULL_BYTE}" } describe "#as_json" do let(:object) do described_class.new(pattern, 'im') end it "returns the regex pattern and options" do expect(object.as_json).to eq({ "$regex" => "\\W+", "$options" => "im" }) end it_behaves_like "a JSON serializable object" end describe "#to_bson/#from_bson" do let(:options) { 'ilmsux' } let(:obj) { described_class.new(pattern, options) } let(:type) { 11.chr } let(:bson) { "#{pattern}#{BSON::NULL_BYTE}#{options}#{BSON::NULL_BYTE}" } let(:klass) { ::Regexp } it_behaves_like "a bson element" it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end describe "#initialize" do let(:object) do described_class.new(pattern, options) end context "when options are not passed" do it "sets the options on the raw regex" do expect(object.options). to eq(options) end context "When the raw regexp is compiled" do let(:regexp) do object.compile end it "sets the options on the compiled regexp object" do expect(regexp.options).to eq(0) end end end context "when options are passed" do context "when options are an Integer" do let(:options) { ::Regexp::EXTENDED } it "sets the options on the raw regex" do expect(object.options). to eq(options) end context "When the raw regexp is compiled" do let(:regexp) do object.compile end it "sets the options on the compiled regexp object" do expect(regexp.options).to eq(options) end end end context "when options are a String" do let(:options) { 'x' } it "sets the options on the raw regex" do expect(object.options). to eq(options) end context "When the raw regexp is compiled" do let(:regexp) do object.compile end it "sets the options on the compiled regexp object" do expect(regexp.options).to eq(::Regexp::EXTENDED) end end end end context 'when options are not passed' do let(:object) do described_class.new(pattern) end it "sets no options on the raw regex" do expect(object.options). to eq('') end context "When the raw regexp is compiled" do let(:regexp) do object.compile end it "sets the options on the compiled regexp object" do expect(regexp.options).to eq(0) end end end end describe "#from_bson" do let(:obj) { ::Regexp.from_bson(io) } let(:io) { BSON::ByteBuffer.new(bson) } it "deserializes to a Regexp::Raw object" do expect(obj).to be_a(Regexp::Raw) end it "deserializes the pattern" do expect(obj.pattern).to eq(pattern) end context "when there are no options" do it "does not set any options on the raw regexp object" do expect(obj.options).to eq(options) end end context "when there are options" do context "when there is the i ignorecase option" do let(:options) { 'i' } it "deserializes the pattern" do expect(obj.pattern).to eq(pattern) end it "sets the i option on the raw regexp object" do expect(obj.options).to eq(options) end end context "when there is the l locale dependent option" do let(:options) { 'l' } it "deserializes the pattern" do expect(obj.pattern).to eq(pattern) end it "sets the l option on the raw regexp object" do expect(obj.options).to eq(options) end end context "when there is the m multiline option" do let(:options) { 'm' } it "deserializes the pattern" do expect(obj.pattern).to eq(pattern) end it "sets the m option on the raw regexp object" do expect(obj.options).to eq(options) end end context "when there is the s dotall option" do let(:options) { 's' } it "deserializes the pattern" do expect(obj.pattern).to eq(pattern) end it "sets the s option on the raw regexp object" do expect(obj.options).to eq(options) end end context "when there is the u match unicode option" do let(:options) { 'u' } it "deserializes the pattern" do expect(obj.pattern).to eq(pattern) end it "sets the u option on the raw regexp object" do expect(obj.options).to eq(options) end end context "when there is the x verbose option" do let(:options) { 'x' } it "deserializes the pattern" do expect(obj.pattern).to eq(pattern) end it "sets the x option on the raw regexp object" do expect(obj.options).to eq(options) end end context "when all options are set" do let(:options) { 'ilmsux' } it "deserializes the pattern" do expect(obj.pattern).to eq(pattern) end it "sets all options on the raw regexp object" do expect(obj.options).to eq(options) end end end end context "when a method is called on a Raw regexp object" do let(:obj) { ::Regexp.from_bson(io) } let(:io) { BSON::ByteBuffer.new(bson) } it "forwards the method call on to the compiled Ruby Regexp object" do expect(obj.source).to eq(pattern) end end context "when respond_to? is called on the Raw Regexp object" do let(:obj) { Regexp::Raw.new(pattern, options) } context "when include_private is false" do it "does not consider private methods" do expect(obj.respond_to?(:initialize_copy)).to eq(false) end end context "when include private is true" do it "considers private methods" do expect(obj.respond_to?(:initialize_copy, true)).to eq(true) end end context "when include_private is not specified" do it "does not consider private methods" do expect(obj.respond_to?(:initialize_copy)).to eq(false) end end end context "#to_bson" do let(:obj) { Regexp::Raw.new(pattern, options) } let(:options) { '' } let(:bson) { "#{pattern}#{BSON::NULL_BYTE}#{options}#{BSON::NULL_BYTE}" } let(:serialized) { obj.to_bson.to_s } it "serializes the pattern" do expect(serialized).to eq(bson) end context "where there are no options" do it "does not set any options on the bson regex object" do expect(serialized).to eq(bson) end end context "when there are options" do context "when options are specified as an Integer" do let(:options) { ::Regexp::EXTENDED } let(:bson) { "#{pattern}#{BSON::NULL_BYTE}mx#{BSON::NULL_BYTE}" } it "sets the option on the serialized bson object" do expect(serialized).to eq(bson) end end context "when there is the i ignorecase option" do let(:options) { 'i' } it "sets the option on the serialized bson object" do expect(serialized).to eq(bson) end end context "when there is the l locale dependent option" do let(:options) { 'l' } it "sets the option on the serialized bson object" do expect(serialized).to eq(bson) end end context "when there is the m multiline option" do let(:options) { 'm' } it "sets the option on the serialized bson object" do expect(serialized).to eq(bson) end end context "when there is the s dotall option" do let(:options) { 's' } it "sets the option on the serialized bson object" do expect(serialized).to eq(bson) end end context "when there is the u match unicode option" do let(:options) { 'u' } it "sets the option on the serialized bson object" do expect(serialized).to eq(bson) end end context "when there is the x verbose option" do let(:options) { 'x' } it "sets the option on the serialized bson object" do expect(serialized).to eq(bson) end end context "when all options are set" do let(:options) { 'ilmsux' } it "sets all options on the serialized bson object" do expect(serialized).to eq(bson) end context "when the options are not provided in alphabetical order" do let(:options) { 'mislxu' } let(:bson) { "#{pattern}#{BSON::NULL_BYTE}ilmsux#{BSON::NULL_BYTE}" } it "serializes the options in alphabetical order" do expect(serialized).to eq(bson) end end end end end describe "#compile" do let(:obj) { Regexp.from_bson(io) } let(:io) { BSON::ByteBuffer.new(bson) } let(:ruby_regexp) { obj.compile } it "sets the pattern on the Ruby Regexp object" do expect(obj.pattern).to eq(ruby_regexp.source) end context "when there are no options set" do it "does not set any options on the Ruby Regexp object" do expect(ruby_regexp.options).to eq(0) end end context "when there are options set" do context "when there is the i ignorecase option" do let(:options) { 'i' } it "sets the i option on the Ruby Regexp object" do expect(ruby_regexp.options).to eq(::Regexp::IGNORECASE) end end context "when there is the l locale dependent option" do let(:options) { 'l' } it "does not set an option on the Ruby Regexp object" do expect(ruby_regexp.options).to eq(0) end end context "when there is the m multiline option" do let(:options) { 'm' } it "does not set an option on the Ruby Regexp object" do expect(ruby_regexp.options).to eq(0) end end context "when there is the s dotall option" do let(:options) { 's' } # s in a bson regex maps to a Ruby Multiline Regexp option it "sets the m option on the Ruby Regexp object" do expect(ruby_regexp.options).to eq(::Regexp::MULTILINE) end end context "when there is the u match unicode option" do let(:options) { 'u' } it "does not set an option on the Ruby Regexp object" do expect(ruby_regexp.options).to eq(0) end end context "when there is the x verbose option" do let(:options) { 'x' } it "sets the x option on the Ruby Regexp object" do expect(ruby_regexp.options).to eq(::Regexp::EXTENDED) end end context "when all options are set" do let(:options) { 'ilmsux' } # s in a bson regex maps to a Ruby Multiline Regexp option it "sets the i, m, and x options on the Ruby Regexp object" do expect(ruby_regexp.options).to eq(::Regexp::IGNORECASE | ::Regexp::MULTILINE | ::Regexp::EXTENDED) end end end end context "when a Regexp::Raw object is roundtripped" do let(:obj) { Regexp::Raw.new(pattern, options) } let(:serialized) { obj.to_bson.to_s } let(:roundtripped) { Regexp.from_bson(BSON::ByteBuffer.new(serialized)) } it "roundtrips the pattern" do expect(roundtripped.pattern).to eq(pattern) end context "when there are no options" do let(:options) { '' } it "does not set any options on the roundtripped Regexp::Raw object" do expect(roundtripped.options).to eq(options) end end context "when there are options set" do context "when there is the i ignorecase option" do let(:options) { 'i' } it "sets the i option on the roundtripped Regexp::Raw object" do expect(roundtripped.options).to eq(options) end end context "when there is the l locale dependent option" do let(:options) { 'l' } it "sets the l option on the roundtripped Regexp::Raw object" do expect(roundtripped.options).to eq(options) end end context "when there is the m multiline option" do let(:options) { 'm' } it "sets the m option on the roundtripped Regexp::Raw object" do expect(roundtripped.options).to eq(options) end end context "when there is the s dotall option" do let(:options) { 's' } it "sets the s option on the roundtripped Regexp::Raw object" do expect(roundtripped.options).to eq(options) end end context "when there is the u match unicode option" do let(:options) { 'u' } it "sets the u option on the roundtripped Regexp::Raw object" do expect(roundtripped.options).to eq(options) end end context "when there is the x verbose option" do let(:options) { 'x' } it "sets the x option on the roundtripped Regexp::Raw object" do expect(roundtripped.options).to eq(options) end end context "when all options are set" do let(:options) { 'ilmsux' } it "sets all the options on the roundtripped Regexp::Raw object" do expect(roundtripped.options).to eq(options) end context "when the options are passed in not in alphabetical order" do let(:options) { 'sumlxi' } it "sets all the options on the roundtripped Regexp::Raw object in order" do expect(roundtripped.options).to eq(options.chars.sort.join) end end end end end endbson-4.3.0/spec/bson/registry_spec.rb0000644000004100000410000000232713236361476017630 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe BSON::Registry do describe ".get" do context "when the type has a correspoding class" do before do described_class.register(BSON::MinKey::BSON_TYPE, BSON::MinKey) end let(:klass) do described_class.get(BSON::MinKey::BSON_TYPE, "field") end it "returns the class" do expect(klass).to eq(BSON::MinKey) end end context "when the type has no corresponding class" do it "raises an error" do expect { described_class.get(25.chr, "field") }.to raise_error(BSON::Registry::UnsupportedType) end end end end bson-4.3.0/spec/bson/object_spec.rb0000644000004100000410000000150413236361476017222 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe BSON::Object do describe "#to_bson_key" do let(:object) do 1..3 end it "raises an exception" do expect { object.to_bson_key }.to raise_error(BSON::InvalidKey) end end end bson-4.3.0/spec/bson/min_key_spec.rb0000644000004100000410000000333313236361476017411 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe BSON::MinKey do describe "#as_json" do let(:object) do described_class.new end it "returns the binary data plus type" do expect(object.as_json).to eq({ "$minKey" => 1 }) end it_behaves_like "a JSON serializable object" end describe "#==" do context "when the objects are equal" do let(:other) { described_class.new } it "returns true" do expect(subject).to eq(other) end end context "when the other object is not a max_key" do it "returns false" do expect(subject).to_not eq("test") end end end describe "#>" do it "always returns false" do expect(subject > Integer::MAX_64BIT).to be false end end describe "#<" do it "always returns true" do expect(subject < Integer::MAX_64BIT).to be true end end describe "#to_bson/#from_bson" do let(:type) { 255.chr } let(:obj) { described_class.new } let(:bson) { BSON::NO_VALUE } it_behaves_like "a bson element" it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end end bson-4.3.0/spec/bson/byte_buffer_spec.rb0000644000004100000410000002504213236361476020253 0ustar www-datawww-datarequire 'spec_helper' describe BSON::ByteBuffer do describe '#allocate' do let(:buffer) do described_class.allocate end it 'allocates a buffer' do expect(buffer).to be_a(BSON::ByteBuffer) end end describe '#get_byte' do let(:buffer) do described_class.new(BSON::Int32::BSON_TYPE) end let!(:byte) do buffer.get_byte end it 'gets the byte from the buffer' do expect(byte).to eq(BSON::Int32::BSON_TYPE) end it 'increments the read position by 1' do expect(buffer.read_position).to eq(1) end end describe '#get_bytes' do let(:string) do "#{BSON::Int32::BSON_TYPE}#{BSON::Int32::BSON_TYPE}" end let(:buffer) do described_class.new(string) end let!(:bytes) do buffer.get_bytes(2) end it 'gets the bytes from the buffer' do expect(bytes).to eq(string) end it 'increments the position by the length' do expect(buffer.read_position).to eq(string.bytesize) end end describe '#get_cstring' do let(:buffer) do described_class.new("testing#{BSON::NULL_BYTE}") end let!(:string) do buffer.get_cstring end it 'gets the cstring from the buffer' do expect(string).to eq("testing") end it 'increments the position by string length + 1' do expect(buffer.read_position).to eq(8) end end describe '#get_double' do let(:buffer) do described_class.new("#{12.5.to_bson.to_s}") end let!(:double) do buffer.get_double end it 'gets the double from the buffer' do expect(double).to eq(12.5) end it 'increments the read position by 8' do expect(buffer.read_position).to eq(8) end end describe '#get_int32' do let(:buffer) do described_class.new("#{12.to_bson.to_s}") end let!(:int32) do buffer.get_int32 end it 'gets the int32 from the buffer' do expect(int32).to eq(12) end it 'increments the position by 4' do expect(buffer.read_position).to eq(4) end end describe '#get_int64' do let(:buffer) do described_class.new("#{(Integer::MAX_64BIT - 1).to_bson.to_s}") end let!(:int64) do buffer.get_int64 end it 'gets the int64 from the buffer' do expect(int64).to eq(Integer::MAX_64BIT - 1) end it 'increments the position by 8' do expect(buffer.read_position).to eq(8) end end describe '#get_string' do let(:buffer) do described_class.new("#{8.to_bson.to_s}testing#{BSON::NULL_BYTE}") end let!(:string) do buffer.get_string end it 'gets the string from the buffer' do expect(string).to eq("testing") end it 'increments the position by string length + 5' do expect(buffer.read_position).to eq(12) end end describe '#length' do context 'when the byte buffer is initialized with no bytes' do let(:buffer) do described_class.new end before do buffer.put_int32(5) end it 'returns the length of the buffer' do expect(buffer.length).to eq(4) end end context 'when the byte buffer is initialized with some bytes' do let(:buffer) do described_class.new("#{BSON::Int32::BSON_TYPE}#{BSON::Int32::BSON_TYPE}") end it 'returns the length' do expect(buffer.length).to eq(2) end end end describe '#put_byte' do let(:buffer) do described_class.new end let!(:modified) do buffer.put_byte(BSON::Int32::BSON_TYPE) end it 'appends the byte to the byte buffer' do expect(modified.to_s).to eq(BSON::Int32::BSON_TYPE.chr) end it 'increments the write position by 1' do expect(modified.write_position).to eq(1) end end describe '#put_cstring' do let(:buffer) do described_class.new end context 'when the string is valid' do let!(:modified) do buffer.put_cstring('testing') end it 'appends the string plus null byte to the byte buffer' do expect(modified.to_s).to eq("testing#{BSON::NULL_BYTE}") end it 'increments the write position by the length + 1' do expect(modified.write_position).to eq(8) end end context "when the string contains a null byte" do let(:string) do "test#{BSON::NULL_BYTE}ing" end it "raises an error" do expect { buffer.put_cstring(string) }.to raise_error(ArgumentError) end end end describe '#put_double' do let(:buffer) do described_class.new end let!(:modified) do buffer.put_double(1.2332) end it 'appends the double to the buffer' do expect(modified.to_s).to eq([ 1.2332 ].pack(Float::PACK)) end it 'increments the write position by 8' do expect(modified.write_position).to eq(8) end end describe '#put_int32' do let(:buffer) do described_class.new end context 'when the integer is 32 bit' do context 'when the integer is positive' do let!(:modified) do buffer.put_int32(Integer::MAX_32BIT - 1) end let(:expected) do [ Integer::MAX_32BIT - 1 ].pack(BSON::Int32::PACK) end it 'appends the int32 to the byte buffer' do expect(modified.to_s).to eq(expected) end it 'increments the write position by 4' do expect(modified.write_position).to eq(4) end end context 'when the integer is negative' do let!(:modified) do buffer.put_int32(Integer::MIN_32BIT + 1) end let(:expected) do [ Integer::MIN_32BIT + 1 ].pack(BSON::Int32::PACK) end it 'appends the int32 to the byte buffer' do expect(modified.to_s).to eq(expected) end it 'increments the write position by 4' do expect(modified.write_position).to eq(4) end end context 'when the integer is not 32 bit' do it 'raises an exception' do expect { buffer.put_int32(Integer::MAX_64BIT - 1) }.to raise_error(RangeError) end end end end describe '#put_int64' do let(:buffer) do described_class.new end context 'when the integer is 64 bit' do context 'when the integer is positive' do let!(:modified) do buffer.put_int64(Integer::MAX_64BIT - 1) end let(:expected) do [ Integer::MAX_64BIT - 1 ].pack(BSON::Int64::PACK) end it 'appends the int64 to the byte buffer' do expect(modified.to_s).to eq(expected) end it 'increments the write position by 8' do expect(modified.write_position).to eq(8) end end context 'when the integer is negative' do let!(:modified) do buffer.put_int64(Integer::MIN_64BIT + 1) end let(:expected) do [ Integer::MIN_64BIT + 1 ].pack(BSON::Int64::PACK) end it 'appends the int64 to the byte buffer' do expect(modified.to_s).to eq(expected) end it 'increments the write position by 8' do expect(modified.write_position).to eq(8) end end context 'when the integer is larger than 64 bit' do it 'raises an exception' do expect { buffer.put_int64(Integer::MAX_64BIT + 1) }.to raise_error(RangeError) end end end end describe '#put_string' do context 'when the buffer does not need to be expanded' do let(:buffer) do described_class.new end context 'when the string is UTF-8' do let!(:modified) do buffer.put_string('testing') end it 'appends the string to the byte buffer' do expect(modified.to_s).to eq("#{8.to_bson.to_s}testing#{BSON::NULL_BYTE}") end it 'increments the write position by length + 5' do expect(modified.write_position).to eq(12) end end end context 'when the buffer needs to be expanded' do let(:buffer) do described_class.new end let(:string) do 300.times.inject(""){ |s, i| s << "#{i}" } end context 'when no bytes exist in the buffer' do let!(:modified) do buffer.put_string(string) end it 'appends the string to the byte buffer' do expect(modified.to_s).to eq("#{(string.bytesize + 1).to_bson.to_s}#{string}#{BSON::NULL_BYTE}") end it 'increments the write position by length + 5' do expect(modified.write_position).to eq(string.bytesize + 5) end end context 'when bytes exist in the buffer' do let!(:modified) do buffer.put_int32(4).put_string(string) end it 'appends the string to the byte buffer' do expect(modified.to_s).to eq( "#{[ 4 ].pack(BSON::Int32::PACK)}#{(string.bytesize + 1).to_bson.to_s}#{string}#{BSON::NULL_BYTE}" ) end it 'increments the write position by length + 5' do expect(modified.write_position).to eq(string.bytesize + 9) end end end end describe '#replace_int32' do let(:buffer) do described_class.new end let(:exp_first) do [ 5 ].pack(BSON::Int32::PACK) end let(:exp_second) do [ 4 ].pack(BSON::Int32::PACK) end let(:modified) do buffer.put_int32(0).put_int32(4).replace_int32(0, 5) end it 'replaces the int32 at the location' do expect(modified.to_s).to eq("#{exp_first}#{exp_second}") end end describe '#rewind!' do shared_examples_for 'a rewindable buffer' do let(:string) do "#{BSON::Int32::BSON_TYPE}#{BSON::Int32::BSON_TYPE}" end before do buffer.get_bytes(1) buffer.rewind! end it 'resets the read position to 0' do expect(buffer.read_position).to eq(0) end it 'starts subsequent reads at position 0' do expect(buffer.get_bytes(2)).to eq(string) end end context 'when the buffer is instantiated with a string' do let(:buffer) do described_class.new(string) end it_behaves_like 'a rewindable buffer' end context 'when the buffer is instantiated with nothing' do let(:buffer) do described_class.new end before do buffer.put_byte(BSON::Int32::BSON_TYPE).put_byte(BSON::Int32::BSON_TYPE) end it_behaves_like 'a rewindable buffer' end end end bson-4.3.0/spec/bson/time_spec.rb0000644000004100000410000000331113236361476016710 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe Time do describe "#to_bson/#from_bson" do let(:type) { 9.chr } it_behaves_like "a bson element" context "when the time is post epoch" do context "when the time has no microseconds" do let(:obj) { Time.utc(2012, 1, 1, 0, 0, 0) } let(:bson) { [ (obj.to_i * 1000) + (obj.usec / 1000) ].pack(BSON::Int64::PACK) } it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end context "when the time has microseconds" do let(:obj) { Time.at(Time.utc(2014, 03, 22, 18, 05, 05).to_i, 505000).utc } let(:bson) { [ (obj.to_i * 1000) + (obj.usec / 1000) ].pack(BSON::Int64::PACK) } it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end end context "when the time is pre epoch" do let(:obj) { Time.utc(1969, 1, 1, 0, 0, 0) } let(:bson) { [ (obj.to_f * 1000).to_i ].pack(BSON::Int64::PACK) } it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end end end bson-4.3.0/spec/bson/nil_class_spec.rb0000644000004100000410000000160313236361476017723 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe NilClass do describe "#to_bson/#from_bson" do let(:type) { 10.chr } let(:obj) { nil } let(:bson) { BSON::NO_VALUE } it_behaves_like "a bson element" it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end end bson-4.3.0/spec/bson/regexp_spec.rb0000644000004100000410000000627613236361476017261 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe Regexp do describe "#as_json" do let(:object) do /\W+/i end it "returns the binary data plus type" do expect(object.as_json).to eq( { "$regex" => "\\W+", "$options" => "im" } ) end it_behaves_like "a JSON serializable object" end describe "#to_bson/#from_bson" do let(:type) { 11.chr } let(:obj) { /test/ } let(:io) do BSON::ByteBuffer.new(bson) end let(:regex) do described_class.from_bson(io) end let(:result) do regex.compile end it_behaves_like "a bson element" context "when calling normal regexp methods on a Regexp::Raw" do let :obj do /\d+/ end let(:bson) { "#{obj.source}#{BSON::NULL_BYTE}m#{BSON::NULL_BYTE}" } it_behaves_like "a serializable bson element" it "runs the method on the Regexp object" do expect(regex.match('6')).not_to be_nil end end context "when the regexp has no options" do let(:obj) { /\d+/ } # Ruby always has a BSON regex's equivalent of multiline on # http://www.regular-expressions.info/modifiers.html let(:bson) { "#{obj.source}#{BSON::NULL_BYTE}m#{BSON::NULL_BYTE}" } it_behaves_like "a serializable bson element" it "deserializes from bson" do expect(result).to eq(obj) end end context "when the regexp has options" do context "when ignoring case" do let(:obj) { /\W+/i } let(:bson) { "#{obj.source}#{BSON::NULL_BYTE}im#{BSON::NULL_BYTE}" } it_behaves_like "a serializable bson element" it "deserializes from bson" do expect(result).to eq(obj) end end context "when matching multiline" do let(:obj) { /\W+/m } let(:bson) { "#{obj.source}#{BSON::NULL_BYTE}ms#{BSON::NULL_BYTE}" } it_behaves_like "a serializable bson element" it "deserializes from bson" do expect(result).to eq(obj) end end context "when matching extended" do let(:obj) { /\W+/x } let(:bson) { "#{obj.source}#{BSON::NULL_BYTE}mx#{BSON::NULL_BYTE}" } it_behaves_like "a serializable bson element" it "deserializes from bson" do expect(result).to eq(obj) end end context "when all options are present" do let(:obj) { /\W+/xim } let(:bson) { "#{obj.source}#{BSON::NULL_BYTE}imsx#{BSON::NULL_BYTE}" } it_behaves_like "a serializable bson element" it "deserializes from bson" do expect(result).to eq(obj) end end end end end bson-4.3.0/spec/bson/timestamp_spec.rb0000644000004100000410000000632613236361476017766 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe BSON::Timestamp do describe "#==" do let(:timestamp) do described_class.new(1, 10) end context "when the objects are equal" do let(:other) { described_class.new(1, 10) } it "returns true" do expect(timestamp).to eq(other) end end context "when the objects are not equal" do let(:other) { described_class.new(1, 15) } it "returns false" do expect(timestamp).to_not eq(other) end end context "when the other object is not a timestamp" do it "returns false" do expect(timestamp).to_not eq("test") end end end describe "#<=>" do let(:timestamp) do described_class.new(1, 10) end context "when the objects are equal" do let(:other) { described_class.new(1, 10) } it "returns 0" do expect(timestamp).to eq(other) expect(timestamp < other).to be(false) expect(timestamp > other).to be(false) expect(timestamp >= other).to be(true) expect(timestamp <= other).to be(true) end end context "when the first object is less than the second" do let(:other) { described_class.new(1, 15) } it "returns -1" do expect(timestamp <=> other).to be(-1) expect(timestamp < other).to be(true) expect(timestamp > other).to be(false) expect(timestamp >= other).to be(false) expect(timestamp <= other).to be(true) end end context "when the first object is greater than the second" do let(:other) { described_class.new(1, 5) } it "returns 1" do expect(timestamp <=> other).to be(1) expect(timestamp < other).to be(false) expect(timestamp > other).to be(true) expect(timestamp >= other).to be(true) expect(timestamp <= other).to be(false) end end context "when the other object is not a timestamp" do it "raises an ArgumentError" do expect { timestamp < 1 }.to raise_exception(ArgumentError) end end end describe "#as_json" do let(:object) do described_class.new(10, 50) end it "returns the binary data plus type" do expect(object.as_json).to eq({"$timestamp" => { "t" => 10, "i" => 50 } }) end it_behaves_like "a JSON serializable object" end describe "#to_bson/#from_bson" do let(:type) { 17.chr } let(:obj) { described_class.new(1, 10) } let(:bson) { [ 10, 1 ].pack(BSON::Int32::PACK * 2) } it_behaves_like "a bson element" it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end end bson-4.3.0/spec/bson/hash_spec.rb0000644000004100000410000001035013236361476016676 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe Hash do describe "#to_bson/#from_bson" do let(:type) { 3.chr } it_behaves_like "a bson element" context "when the hash is a single level" do let(:obj) do { "key" => "value" } end let(:bson) do "#{20.to_bson.to_s}#{String::BSON_TYPE}key#{BSON::NULL_BYTE}" + "#{6.to_bson.to_s}value#{BSON::NULL_BYTE}#{BSON::NULL_BYTE}" end it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end context "when the hash has non-string keys" do let(:obj) do { 1 => "value" } end let(:expected) do { "1" => "value" } end it "properly converts to bson" do expect(BSON::Document.from_bson(BSON::ByteBuffer.new(obj.to_bson.to_s))).to eq(expected) end end context "when the hash has invalid keys" do let(:obj) do { "$testing" => "value" } end context "when validating keys" do context "when validating globally" do before do BSON::Config.validating_keys = true end after do BSON::Config.validating_keys = false end it "raises an error" do expect { obj.to_bson }.to raise_error(BSON::String::IllegalKey) end context "when the hash contains an array of documents containing invalid keys" do let(:obj) do { "array" => [{ "$testing" => "value" }] } end it "raises an error" do expect { obj.to_bson }.to raise_error(BSON::String::IllegalKey) end end end context "when validating locally" do it "raises an error" do expect { obj.to_bson(BSON::ByteBuffer.new, true) }.to raise_error(BSON::String::IllegalKey) end context "when the hash contains an array of documents containing invalid keys" do let(:obj) do { "array" => [{ "$testing" => "value" }] } end it "raises an error" do expect { obj.to_bson(BSON::ByteBuffer.new, true) }.to raise_error(BSON::String::IllegalKey) end end end end context "when not validating keys" do let(:bson) do "#{25.to_bson.to_s}#{String::BSON_TYPE}$testing#{BSON::NULL_BYTE}" + "#{6.to_bson.to_s}value#{BSON::NULL_BYTE}#{BSON::NULL_BYTE}" end it "serializes the hash" do expect(obj.to_bson.to_s).to eq(bson) end context "when the hash contains an array of documents containing invalid keys" do let(:obj) do { "array" => [{ "$testing" => "value" }] } end let(:bson) do "#{45.to_bson.to_s}#{Array::BSON_TYPE}array#{BSON::NULL_BYTE}" + "#{[{ "$testing" => "value" }].to_bson.to_s}#{BSON::NULL_BYTE}" end it "serializes the hash" do expect(obj.to_bson.to_s).to eq(bson) end end end end context "when the hash is embedded" do let(:obj) do { "field" => { "key" => "value" }} end let(:bson) do "#{32.to_bson.to_s}#{Hash::BSON_TYPE}field#{BSON::NULL_BYTE}" + "#{20.to_bson.to_s}#{String::BSON_TYPE}key#{BSON::NULL_BYTE}" + "#{6.to_bson.to_s}value#{BSON::NULL_BYTE}#{BSON::NULL_BYTE}#{BSON::NULL_BYTE}" end it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end end end bson-4.3.0/spec/bson/integer_spec.rb0000644000004100000410000000341613236361476017415 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe Integer do describe "#to_bson" do context "when the integer is 32 bit" do let(:type) { 16.chr } let(:obj) { Integer::MAX_32BIT - 1 } let(:bson) { [ obj ].pack(BSON::Int32::PACK) } it_behaves_like "a serializable bson element" end context "when the integer is 64 bit" do let(:type) { 18.chr } let(:obj) { Integer::MAX_64BIT - 1 } let(:bson) { [ obj ].pack(BSON::Int64::PACK) } it_behaves_like "a serializable bson element" end context "when the integer is too large" do let(:integer) { Integer::MAX_64BIT + 1 } it "raises an out of range error" do expect { integer.to_bson }.to raise_error(RangeError) end end context "when the intger is too small" do let(:integer) { Integer::MIN_64BIT - 1 } it "raises an out of range error" do expect { integer.to_bson }.to raise_error(RangeError) end end end describe "#to_bson_key" do let(:obj) { Integer::MAX_32BIT - 1 } let(:encoded) { obj.to_s } it "returns the key as a string" do expect(obj.to_bson_key).to eq(encoded) end end end bson-4.3.0/spec/bson/string_spec.rb0000644000004100000410000000547713236361476017277 0ustar www-datawww-data# encoding: utf-8 # Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe String do describe "#to_bson/#from_bson" do let(:type) { 2.chr } let(:obj) { "test" } let(:bson) { "#{5.to_bson.to_s}test#{BSON::NULL_BYTE}" } it_behaves_like "a bson element" it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end describe "#to_bson_object_id" do context "when the string has 12 characters" do let(:string) do "123456789012" end let(:converted) do string.to_bson_object_id end it "returns the array as a string" do expect(converted).to eq(string) end end context "when the array does not have 12 elements" do it "raises an exception" do expect { "test".to_bson_object_id }.to raise_error(BSON::ObjectId::Invalid) end end end context "when the class is loaded" do let(:registered) do BSON::Registry.get(String::BSON_TYPE, 'field') end it "registers the type" do expect(registered).to eq(String) end end describe "#to_bson_key" do let(:string) { "test" } let(:encoded) { string.to_s } it "returns the encoded string" do expect(string.to_bson_key).to eq(encoded) end end describe "#to_hex_string" do let(:string) do "testing123" end it "converts the string to hex" do expect(string.to_hex_string).to eq("74657374696e67313233") end end describe "#to_bson_key" do context "when validating keys" do context "when validating globally" do before do BSON::Config.validating_keys = true end after do BSON::Config.validating_keys = false end let(:validated) do string.to_bson_key end it_behaves_like "a validated BSON key" end context "when validating locally" do let(:validated) do string.to_bson_key(true) end it_behaves_like "a validated BSON key" end end context "when allowing invalid keys" do let(:string) do "$testing.testing" end it "allows invalid keys" do expect(string.to_bson_key).to eq(string) end end end end bson-4.3.0/spec/bson/date_spec.rb0000644000004100000410000000233113236361476016670 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe Date do it_behaves_like "a class which converts to Time" describe "#to_bson" do context "when the date is post epoch" do let(:obj) { Date.new(2012, 1, 1) } let(:time) { Time.utc(2012, 1, 1) } let(:bson) { [ (time.to_f * 1000).to_i ].pack(BSON::Int64::PACK) } it_behaves_like "a serializable bson element" end context "when the date is pre epoch" do let(:obj) { Date.new(1969, 1, 1) } let(:time) { Time.utc(1969, 1, 1) } let(:bson) { [ (time.to_f * 1000).to_i ].pack(BSON::Int64::PACK) } it_behaves_like "a serializable bson element" end end end bson-4.3.0/spec/bson/json_spec.rb0000644000004100000410000000234313236361476016727 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe BSON::JSON do describe "#to_json" do let(:klass) do Class.new do include BSON::JSON def as_json(*args) { :test => "value" } end end end context "when provided no arguments" do let(:json) do klass.new.to_json end it "returns the object as json" do expect(json).to eq("{\"test\":\"value\"}") end end context "when provided arguments" do let(:json) do klass.new.to_json(:test) end it "returns the object as json" do expect(json).to eq("{\"test\":\"value\"}") end end end end bson-4.3.0/spec/bson/array_spec.rb0000644000004100000410000001113413236361476017072 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe Array do describe "#to_bson/#from_bson" do let(:type) { 4.chr } let(:obj) {[ "one", "two" ]} let(:bson) do BSON::Document["0", "one", "1", "two"].to_bson.to_s end it_behaves_like "a bson element" it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" context "when the array has documents containing invalid keys" do let(:obj) do [ { "$testing" => "value" } ] end context "when validating keys" do context "when validating globally" do before do BSON::Config.validating_keys = true end after do BSON::Config.validating_keys = false end it "raises an error" do expect { obj.to_bson }.to raise_error(BSON::String::IllegalKey) end end context "when validating locally" do it "raises an error" do expect { obj.to_bson(BSON::ByteBuffer.new, true) }.to raise_error(BSON::String::IllegalKey) end context "when serializing different types" do let(:obj) do [ BSON::Binary.new("testing", :generic), BSON::Code.new("this.value = 5"), BSON::CodeWithScope.new("this.value = val", "test"), Date.new(2012, 1, 1), Time.utc(2012, 1, 1), DateTime.new(2012, 1, 1, 0, 0, 0), false, 1.2332, Integer::MAX_32BIT - 1, BSON::ObjectId.new, /\W+/i, 'a string', :a_symbol, Time.utc(2012, 1, 1, 0, 0, 0), BSON::Timestamp.new(1, 10), true, { "$testing" => "value" } ] end it "raises an error" do expect { obj.to_bson(BSON::ByteBuffer.new, true) }.to raise_error(BSON::String::IllegalKey) end end end end context "when not validating keys" do let(:bson) do BSON::Document["0", { "$testing" => "value" }].to_bson.to_s end it "serializes the hash" do expect(obj.to_bson.to_s).to eq(bson) end context "when serializing different types" do let(:obj) do [ BSON::Binary.new("testing", :generic), BSON::Code.new("this.value = 5"), BSON::CodeWithScope.new("this.value = val", "test"), Date.new(2012, 1, 1), Time.utc(2012, 1, 1), DateTime.new(2012, 1, 1, 0, 0, 0), false, 1.2332, Integer::MAX_32BIT - 1, BSON::ObjectId.new, /\W+/i, 'a string', :a_symbol, Time.utc(2012, 1, 1, 0, 0, 0), BSON::Timestamp.new(1, 10), true, { "$testing" => "value" } ] end it "serializes the hash" do expect(obj.to_bson.length).to eq(252) end end end end end describe "#to_bson_normalized_value" do let(:klass) { Class.new(Hash) } let(:obj) {[ Foo.new ]} before(:each) { stub_const "Foo", klass } it "does not mutate the receiver" do obj.to_bson_normalized_value expect(obj.first.class).to eq(Foo) end end describe "#to_bson_object_id" do context "when the array has 12 elements" do let(:array) do [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ] end let(:converted) do array.to_bson_object_id end it "returns the array as a string" do expect(converted).to eq(array.pack("C*")) end end context "when the array does not have 12 elements" do it "raises an exception" do expect { [ 1 ].to_bson_object_id }.to raise_error(BSON::ObjectId::Invalid) end end end end bson-4.3.0/spec/bson/code_spec.rb0000644000004100000410000000233613236361476016672 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "spec_helper" describe BSON::Code do describe "#as_json" do let(:object) do described_class.new("this.value = 5") end it "returns the binary data plus type" do expect(object.as_json).to eq({ "$code" => "this.value = 5" }) end it_behaves_like "a JSON serializable object" end describe "#to_bson/#from_bson" do let(:type) { 13.chr } let(:obj) { described_class.new("this.value = 5") } let(:bson) { "#{15.to_bson}this.value = 5#{BSON::NULL_BYTE}" } it_behaves_like "a bson element" it_behaves_like "a serializable bson element" it_behaves_like "a deserializable bson element" end end bson-4.3.0/spec/support/0000755000004100000410000000000013236361476015170 5ustar www-datawww-databson-4.3.0/spec/support/corpus-tests/0000755000004100000410000000000013236361476017643 5ustar www-datawww-databson-4.3.0/spec/support/corpus-tests/null.json0000644000004100000410000000035613236361476021514 0ustar www-datawww-data{ "description": "Null type", "bson_type": "0x0A", "test_key": "a", "valid": [ { "description": "Null", "bson": "080000000A610000", "extjson": "{\"a\" : null}" } ] } bson-4.3.0/spec/support/corpus-tests/timestamp.json0000644000004100000410000000074513236361476022547 0ustar www-datawww-data{ "description": "Timestamp type", "bson_type": "0x11", "test_key": "a", "valid": [ { "description": "Timestamp: (123456789, 42)", "bson": "100000001161002A00000015CD5B0700", "extjson": "{\"a\" : {\"$timestamp\" : {\"t\" : 123456789, \"i\" : 42}}}" } ], "decodeErrors": [ { "description": "Truncated timestamp field", "bson": "0f0000001161002A00000015CD5B00" } ] } bson-4.3.0/spec/support/corpus-tests/int32.json0000644000004100000410000000171313236361476021477 0ustar www-datawww-data{ "description": "Int32 type", "bson_type": "0x10", "test_key": "i", "valid": [ { "description": "MinValue", "bson": "0C0000001069000000008000", "extjson": "{\"i\" : -2147483648}" }, { "description": "MaxValue", "bson": "0C000000106900FFFFFF7F00", "extjson": "{\"i\" : 2147483647}" }, { "description": "-1", "bson": "0C000000106900FFFFFFFF00", "extjson": "{\"i\" : -1}" }, { "description": "0", "bson": "0C0000001069000000000000", "extjson": "{\"i\" : 0}" }, { "description": "1", "bson": "0C0000001069000100000000", "extjson": "{\"i\" : 1}" } ], "decodeErrors": [ { "description": "Bad int32 field length", "bson": "090000001061000500" } ] } bson-4.3.0/spec/support/corpus-tests/double.json0000644000004100000410000000374413236361476022020 0ustar www-datawww-data{ "description": "Double type", "bson_type": "0x01", "test_key": "d", "valid": [ { "description": "+1.0", "bson": "10000000016400000000000000F03F00", "extjson": "{\"d\" : 1.0}" }, { "description": "-1.0", "bson": "10000000016400000000000000F0BF00", "extjson": "{\"d\" : -1.0}" }, { "description": "+1.0001220703125", "bson": "10000000016400000000008000F03F00", "extjson": "{\"d\" : 1.0001220703125}" }, { "description": "-1.0001220703125", "bson": "10000000016400000000008000F0BF00", "extjson": "{\"d\" : -1.0001220703125}" }, { "description": "+2.0001220703125e10", "bson": "1000000001640000807ca1a9a0124200", "extjson": "{\"d\" : 2.0001220703125e10}" }, { "description": "-2.0001220703125e10", "bson": "1000000001640000807ca1a9a012c200", "extjson": "{\"d\" : -2.0001220703125e10}" }, { "description": "0.0", "bson": "10000000016400000000000000000000", "extjson": "{\"d\" : 0.0}" }, { "description": "-0.0", "bson": "10000000016400000000000000008000", "extjson": "{\"d\" : -0.0}" }, { "description": "NaN", "bson": "10000000016400000000000000F87F00" }, { "description": "NaN with payload", "bson": "10000000016400120000000000F87F00" }, { "description": "Inf", "bson": "10000000016400000000000000F07F00" }, { "description": "-Inf", "bson": "10000000016400000000000000F0FF00" } ], "decodeErrors": [ { "description": "double truncated", "bson": "0B0000000164000000F03F00" } ] } bson-4.3.0/spec/support/corpus-tests/failures/0000755000004100000410000000000013236361476021455 5ustar www-datawww-databson-4.3.0/spec/support/corpus-tests/failures/undefined.json0000644000004100000410000000046013236361476024311 0ustar www-datawww-data{ "description": "Undefined type (deprecated)", "bson_type": "0x06", "deprecated": true, "test_key": "a", "valid": [ { "description": "Undefined", "bson": "0800000006610000", "extjson": "{\"a\" : {\"$undefined\" : true}}" } ] } bson-4.3.0/spec/support/corpus-tests/failures/dbpointer.json0000644000004100000410000000257013236361476024342 0ustar www-datawww-data{ "description": "DBPointer type (deprecated)", "bson_type": "0x0C", "deprecated": true, "test_key": "a", "valid": [ { "description": "DBpointer", "bson": "1A0000000C610002000000620056E1FC72E0C917E9C471416100" }, { "description": "With two-byte UTF-8", "bson": "1B0000000C610003000000C3A90056E1FC72E0C917E9C471416100" } ], "decodeErrors": [ { "description": "String with negative length", "bson": "1A0000000C6100FFFFFFFF620056E1FC72E0C917E9C471416100" }, { "description": "String with zero length", "bson": "1A0000000C610000000000620056E1FC72E0C917E9C471416100" }, { "description": "String not null terminated", "bson": "1A0000000C610002000000626256E1FC72E0C917E9C471416100" }, { "description": "short OID (less than minimum length for field)", "bson": "160000000C61000300000061620056E1FC72E0C91700" }, { "description": "short OID (greater than minimum, but truncated)", "bson": "1A0000000C61000300000061620056E1FC72E0C917E9C4716100" }, { "description": "String with bad UTF-8", "bson": "1A0000000C610002000000E90056E1FC72E0C917E9C471416100" } ] } bson-4.3.0/spec/support/corpus-tests/failures/datetime.json0000644000004100000410000000213413236361476024144 0ustar www-datawww-data{ "description": "DateTime", "bson_type": "0x09", "test_key": "a", "valid": [ { "description": "epoch", "bson": "10000000096100000000000000000000", "extjson": "{\"a\" : {\"$date\" : \"1970-01-01T00:00:00.000Z\"}}", "canonical_extjson": "{\"a\" : {\"$date\" : {\"$numberLong\" : \"0\"}}}" }, { "description": "positive ms", "bson": "10000000096100C4D8D6CC3B01000000", "extjson": "{\"a\" : {\"$date\" : \"2012-12-24T12:15:30.500Z\"}}", "canonical_extjson": "{\"a\" : {\"$date\" : {\"$numberLong\" : \"1356351330500\"}}}" }, { "description": "negative", "bson": "10000000096100C43CE7B9BDFFFFFF00", "extjson": "{\"a\" : {\"$date\" : \"1960-12-24T12:15:30.500Z\"}}", "canonical_extjson": "{\"a\" : {\"$date\" : {\"$numberLong\" : \"-284643869500\"}}}" } ], "decodeErrors": [ { "description": "datetime field truncated", "bson": "0C0000000961001234567800" } ] } bson-4.3.0/spec/support/corpus-tests/failures/binary.json0000644000004100000410000000502313236361476023634 0ustar www-datawww-data{ "description": "Binary type", "bson_type": "0x05", "test_key": "x", "valid": [ { "description": "subtype 0x00 (Zero-length)", "bson": "0D000000057800000000000000", "extjson": "{\"x\" : {\"$binary\" : \"\", \"$type\" : \"00\"}}" }, { "description": "subtype 0x00", "bson": "0F0000000578000200000000FFFF00", "extjson": "{\"x\" : {\"$binary\" : \"//8=\", \"$type\" : \"00\"}}" }, { "description": "subtype 0x01", "bson": "0F0000000578000200000001FFFF00", "extjson": "{\"x\" : {\"$binary\" : \"//8=\", \"$type\" : \"01\"}}" }, { "description": "subtype 0x02", "bson": "13000000057800060000000202000000ffff00", "extjson": "{\"x\" : {\"$binary\" : \"//8=\", \"$type\" : \"02\"}}" }, { "description": "subtype 0x03", "bson": "1D000000057800100000000373FFD26444B34C6990E8E7D1DFC035D400", "extjson": "{\"x\" : {\"$binary\" : \"c//SZESzTGmQ6OfR38A11A==\", \"$type\" : \"03\"}}" }, { "description": "subtype 0x04", "bson": "1D000000057800100000000473FFD26444B34C6990E8E7D1DFC035D400", "extjson": "{\"x\" : {\"$binary\" : \"c//SZESzTGmQ6OfR38A11A==\", \"$type\" : \"04\"}}" }, { "description": "subtype 0x05", "bson": "1D000000057800100000000573FFD26444B34C6990E8E7D1DFC035D400", "extjson": "{\"x\" : {\"$binary\" : \"c//SZESzTGmQ6OfR38A11A==\", \"$type\" : \"05\"}}" }, { "description": "subtype 0x80", "bson": "0F0000000578000200000080FFFF00", "extjson": "{\"x\" : {\"$binary\" : \"//8=\", \"$type\" : \"80\"}}" } ], "decodeErrors": [ { "description": "Length longer than document", "bson": "1D000000057800FF0000000573FFD26444B34C6990E8E7D1DFC035D400" }, { "description": "Negative length", "bson": "0D000000057800FFFFFFFF0000" }, { "description": "subtype 0x02 length too long ", "bson": "13000000057800060000000203000000FFFF00" }, { "description": "subtype 0x02 length too short", "bson": "13000000057800060000000201000000FFFF00" }, { "description": "subtype 0x02 length negative one", "bson": "130000000578000600000002FFFFFFFFFFFF00" } ] } bson-4.3.0/spec/support/corpus-tests/failures/int64.json0000644000004100000410000000220213236361476023310 0ustar www-datawww-data{ "description": "Int64 type", "bson_type": "0x12", "test_key": "a", "valid": [ { "description": "MinValue", "bson": "10000000126100000000000000008000", "extjson": "{\"a\" : {\"$numberLong\" : \"-9223372036854775808\"}}" }, { "description": "MaxValue", "bson": "10000000126100FFFFFFFFFFFFFF7F00", "extjson": "{\"a\" : {\"$numberLong\" : \"9223372036854775807\"}}" }, { "description": "-1", "bson": "10000000126100FFFFFFFFFFFFFFFF00", "extjson": "{\"a\" : {\"$numberLong\" : \"-1\"}}" }, { "description": "0", "bson": "10000000126100000000000000000000", "extjson": "{\"a\" : {\"$numberLong\" : \"0\"}}" }, { "description": "1", "bson": "10000000126100010000000000000000", "extjson": "{\"a\" : {\"$numberLong\" : \"1\"}}" } ], "decodeErrors": [ { "description": "int64 field truncated", "bson": "0C0000001261001234567800" } ] } bson-4.3.0/spec/support/corpus-tests/failures/symbol.json0000644000004100000410000000355613236361476023666 0ustar www-datawww-data{ "description": "Symbol", "bson_type": "0x0E", "deprecated": true, "test_key": "a", "valid": [ { "description": "Empty string", "bson": "0D0000000E6100010000000000" }, { "description": "Single character", "bson": "0E0000000E610002000000620000" }, { "description": "Multi-character", "bson": "190000000E61000D0000006162616261626162616261620000" }, { "description": "two-byte UTF-8 (\u00e9)", "bson": "190000000E61000D000000C3A9C3A9C3A9C3A9C3A9C3A90000" }, { "description": "three-byte UTF-8 (\u2606)", "bson": "190000000E61000D000000E29886E29886E29886E298860000" }, { "description": "Embedded nulls", "bson": "190000000E61000D0000006162006261620062616261620000" } ], "decodeErrors": [ { "description": "bad symbol length: 0 (but no 0x00 either)", "bson": "0C0000000261000000000000" }, { "description": "bad symbol length: -1", "bson": "0C000000026100FFFFFFFF00" }, { "description": "bad symbol length: eats terminator", "bson": "10000000026100050000006200620000" }, { "description": "bad symbol length: longer than rest of document", "bson": "120000000200FFFFFF00666F6F6261720000" }, { "description": "symbol is not null-terminated", "bson": "1000000002610004000000616263FF00" }, { "description": "empty symbol, but extra null", "bson": "0E00000002610001000000000000" }, { "description": "invalid UTF-8", "bson": "0E00000002610002000000E90000" } ] } bson-4.3.0/spec/support/corpus-tests/minkey.json0000644000004100000410000000037713236361476022041 0ustar www-datawww-data{ "description": "Minkey type", "bson_type": "0xFF", "test_key": "a", "valid": [ { "description": "Minkey", "bson": "08000000FF610000", "extjson": "{\"a\" : {\"$minKey\" : 1}}" } ] } bson-4.3.0/spec/support/corpus-tests/regex.json0000644000004100000410000000230113236361476021644 0ustar www-datawww-data{ "description": "Regular Expression type", "bson_type": "0x0B", "test_key": "a", "valid": [ { "description": "empty regex with no options", "bson": "0A0000000B6100000000", "extjson": "{\"a\" : {\"$regex\" : \"\", \"$options\" : \"\"}}" }, { "description": "regex without options", "bson": "0D0000000B6100616263000000", "extjson": "{\"a\" : {\"$regex\" : \"abc\", \"$options\" : \"\"}}" }, { "description": "regex with options", "bson": "0F0000000B610061626300696D0000", "extjson": "{\"a\" : {\"$regex\" : \"abc\", \"$options\" : \"im\"}}" }, { "description": "regex with slash", "bson": "110000000B610061622F636400696D0000", "extjson": "{\"a\" : {\"$regex\" : \"ab/cd\", \"$options\" : \"im\"}}" } ], "decodeErrors": [ { "description": "embedded null in pattern", "bson": "0F0000000B610061006300696D0000" }, { "description": "embedded null in flags", "bson": "100000000B61006162630069006D0000" } ] } bson-4.3.0/spec/support/corpus-tests/document.json0000644000004100000410000000226513236361476022361 0ustar www-datawww-data{ "description": "Document type (sub-documents)", "bson_type": "0x03", "test_key": "x", "valid": [ { "description": "Empty subdoc", "bson": "0D000000037800050000000000", "extjson": "{\"x\" : {}}" }, { "description": "Empty-string key subdoc", "bson": "150000000378000D00000002000200000062000000", "extjson": "{\"x\" : {\"\" : \"b\"}}" }, { "description": "Single-character key subdoc", "bson": "160000000378000E0000000261000200000062000000", "extjson": "{\"x\" : {\"a\" : \"b\"}}" } ], "decodeErrors": [ { "description": "Subdocument length too long: eats outer terminator", "bson": "1800000003666F6F000F0000001062617200FFFFFF7F0000" }, { "description": "Subdocument length too short: leaks terminator", "bson": "1500000003666F6F000A0000000862617200010000" }, { "description": "Invalid subdocument: bad string length in field", "bson": "1C00000003666F6F001200000002626172000500000062617A000000" } ] } bson-4.3.0/spec/support/corpus-tests/top.json0000644000004100000410000000427713236361476021352 0ustar www-datawww-data{ "description": "Top-level document validity", "bson_type": "0x00", "decodeErrors": [ { "description": "An object size that's too small to even include the object size, but is a well-formed, empty object", "bson": "0100000000" }, { "description": "An object size that's only enough for the object size, but is a well-formed, empty object", "bson": "0400000000" }, { "description": "One object, with length shorter than size (missing EOO)", "bson": "05000000" }, { "description": "One object, sized correctly, with a spot for an EOO, but the EOO is 0x01", "bson": "0500000001" }, { "description": "One object, sized correctly, with a spot for an EOO, but the EOO is 0xff", "bson": "05000000FF" }, { "description": "One object, sized correctly, with a spot for an EOO, but the EOO is 0x70", "bson": "0500000070" }, { "description": "Byte count is zero (with non-zero input length)", "bson": "00000000000000000000" }, { "description": "Stated length exceeds byte count, with truncated document", "bson": "1200000002666F6F0004000000626172" }, { "description": "Stated length less than byte count, with garbage after envelope", "bson": "1200000002666F6F00040000006261720000DEADBEEF" }, { "description": "Stated length exceeds byte count, with valid envelope", "bson": "1300000002666F6F00040000006261720000" }, { "description": "Stated length less than byte count, with valid envelope", "bson": "1100000002666F6F00040000006261720000" }, { "description": "Invalid BSON type low range", "bson": "07000000000000" }, { "description": "Invalid BSON type high range", "bson": "07000000800000" }, { "description": "Document truncated mid-key", "bson": "1200000002666F" } ] } bson-4.3.0/spec/support/corpus-tests/maxkey.json0000644000004100000410000000037713236361476022043 0ustar www-datawww-data{ "description": "Maxkey type", "bson_type": "0xFF", "test_key": "a", "valid": [ { "description": "Maxkey", "bson": "080000007F610000", "extjson": "{\"a\" : {\"$maxKey\" : 1}}" } ] } bson-4.3.0/spec/support/corpus-tests/oid.json0000644000004100000410000000152613236361476021315 0ustar www-datawww-data{ "description": "ObjectId", "bson_type": "0x07", "test_key": "a", "valid": [ { "description": "All zeroes", "bson": "1400000007610000000000000000000000000000", "extjson": "{\"a\" : {\"$oid\" : \"000000000000000000000000\"}}" }, { "description": "All ones", "bson": "14000000076100FFFFFFFFFFFFFFFFFFFFFFFF00", "extjson": "{\"a\" : {\"$oid\" : \"ffffffffffffffffffffffff\"}}" }, { "description": "Random", "bson": "1400000007610056E1FC72E0C917E9C471416100", "extjson": "{\"a\" : {\"$oid\" : \"56e1fc72e0c917e9c4714161\"}}" } ], "decodeErrors": [ { "description": "OID truncated", "bson": "1200000007610056E1FC72E0C917E9C471" } ] } bson-4.3.0/spec/support/corpus-tests/string.json0000644000004100000410000000426713236361476022055 0ustar www-datawww-data{ "description": "String", "bson_type": "0x02", "test_key": "a", "valid": [ { "description": "Empty string", "bson": "0D000000026100010000000000", "extjson": "{\"a\" : \"\"}" }, { "description": "Single character", "bson": "0E00000002610002000000620000", "extjson": "{\"a\" : \"b\"}" }, { "description": "Multi-character", "bson": "190000000261000D0000006162616261626162616261620000", "extjson": "{\"a\" : \"abababababab\"}" }, { "description": "two-byte UTF-8 (\u00e9)", "bson": "190000000261000D000000C3A9C3A9C3A9C3A9C3A9C3A90000", "extjson": "{\"a\" : \"\\u00e9\\u00e9\\u00e9\\u00e9\\u00e9\\u00e9\"}" }, { "description": "three-byte UTF-8 (\u2606)", "bson": "190000000261000D000000E29886E29886E29886E298860000", "extjson": "{\"a\" : \"\\u2606\\u2606\\u2606\\u2606\"}" }, { "description": "Embedded nulls", "bson": "190000000261000D0000006162006261620062616261620000", "extjson": "{\"a\" : \"ab\\u0000bab\\u0000babab\"}" } ], "decodeErrors": [ { "description": "bad string length: 0 (but no 0x00 either)", "bson": "0C0000000261000000000000" }, { "description": "bad string length: -1", "bson": "0C000000026100FFFFFFFF00" }, { "description": "bad string length: eats terminator", "bson": "10000000026100050000006200620000" }, { "description": "bad string length: longer than rest of document", "bson": "120000000200FFFFFF00666F6F6261720000" }, { "description": "string is not null-terminated", "bson": "1000000002610004000000616263FF00" }, { "description": "empty string, but extra null", "bson": "0E00000002610001000000000000" }, { "description": "invalid UTF-8", "bson": "0E00000002610002000000E90000" } ] } bson-4.3.0/spec/support/corpus-tests/code.json0000644000004100000410000000441013236361476021447 0ustar www-datawww-data{ "description": "Javascript Code", "bson_type": "0x0D", "test_key": "a", "valid": [ { "description": "Empty string", "bson": "0D0000000D6100010000000000", "extjson": "{\"a\" : {\"$code\" : \"\"}}" }, { "description": "Single character", "bson": "0E0000000D610002000000620000", "extjson": "{\"a\" : {\"$code\" : \"b\"}}" }, { "description": "Multi-character", "bson": "190000000D61000D0000006162616261626162616261620000", "extjson": "{\"a\" : {\"$code\" : \"abababababab\"}}" }, { "description": "two-byte UTF-8 (\u00e9)", "bson": "190000000261000D000000C3A9C3A9C3A9C3A9C3A9C3A90000", "extjson": "{\"a\" : \"\\u00e9\\u00e9\\u00e9\\u00e9\\u00e9\\u00e9\"}" }, { "description": "three-byte UTF-8 (\u2606)", "bson": "190000000261000D000000E29886E29886E29886E298860000", "extjson": "{\"a\" : \"\\u2606\\u2606\\u2606\\u2606\"}" }, { "description": "Embedded nulls", "bson": "190000000261000D0000006162006261620062616261620000", "extjson": "{\"a\" : \"ab\\u0000bab\\u0000babab\"}" } ], "decodeErrors": [ { "description": "bad code string length: 0 (but no 0x00 either)", "bson": "0C0000000261000000000000" }, { "description": "bad code string length: -1", "bson": "0C000000026100FFFFFFFF00" }, { "description": "bad code string length: eats terminator", "bson": "10000000026100050000006200620000" }, { "description": "bad code string length: longer than rest of document", "bson": "120000000200FFFFFF00666F6F6261720000" }, { "description": "code string is not null-terminated", "bson": "1000000002610004000000616263FF00" }, { "description": "empty code string, but extra null", "bson": "0E00000002610001000000000000" }, { "description": "invalid UTF-8", "bson": "0E00000002610002000000E90000" } ] } bson-4.3.0/spec/support/corpus-tests/code_w_scope.json0000644000004100000410000000655413236361476023201 0ustar www-datawww-data{ "description": "Javascript Code with Scope", "bson_type": "0x0F", "test_key": "a", "valid": [ { "description": "Empty code string, empty scope", "bson": "160000000F61000E0000000100000000050000000000", "extjson": "{\"a\" : {\"$code\" : \"\", \"$scope\" : {}}}" }, { "description": "Non-empty code string, empty scope", "bson": "1A0000000F610012000000050000006162636400050000000000", "extjson": "{\"a\" : {\"$code\" : \"abcd\", \"$scope\" : {}}}" }, { "description": "Empty code string, non-empty scope", "bson": "1D0000000F61001500000001000000000C000000107800010000000000", "extjson": "{\"a\" : {\"$code\" : \"\", \"$scope\" : {\"x\" : 1}}}" }, { "description": "Non-empty code string and non-empty scope", "bson": "210000000F6100190000000500000061626364000C000000107800010000000000", "extjson": "{\"a\" : {\"$code\" : \"abcd\", \"$scope\" : {\"x\" : 1}}}" }, { "description": "Unicode and embedded null in code string, empty scope", "bson": "1A0000000F61001200000005000000C3A9006400050000000000", "extjson": "{\"a\" : {\"$code\" : \"\\u00e9\\u0000d\", \"$scope\" : {}}}" } ], "decodeErrors": [ { "description": "field length zero", "bson": "280000000F6100000000000500000061626364001300000010780001000000107900010000000000" }, { "description": "field length negative", "bson": "280000000F6100FFFFFFFF0500000061626364001300000010780001000000107900010000000000" }, { "description": "field length too short (less than minimum size)", "bson": "160000000F61000D0000000100000000050000000000" }, { "description": "field length too short (truncates scope)", "bson": "280000000F61001F0000000500000061626364001300000010780001000000107900010000000000" }, { "description": "field length too long (clips outer doc)", "bson": "280000000F6100210000000500000061626364001300000010780001000000107900010000000000" }, { "description": "field length too long (longer than outer doc)", "bson": "280000000F6100FF0000000500000061626364001300000010780001000000107900010000000000" }, { "description": "bad code string: length too short", "bson": "280000000F6100200000000400000061626364001300000010780001000000107900010000000000" }, { "description": "bad code string: length too long (clips scope)", "bson": "280000000F6100200000000600000061626364001300000010780001000000107900010000000000" }, { "description": "bad code string: negative length", "bson": "280000000F610020000000FFFFFFFF61626364001300000010780001000000107900010000000000" }, { "description": "bad code string: length longer than field", "bson": "280000000F610020000000FF00000061626364001300000010780001000000107900010000000000" }, { "description": "bad scope doc (field has bad string length)", "bson": "1C0000000F001500000001000000000C000000020000000000000000" } ] } bson-4.3.0/spec/support/corpus-tests/array.json0000644000004100000410000000271313236361476021657 0ustar www-datawww-data{ "description": "Array", "bson_type": "0x04", "test_key": "a", "valid": [ { "description": "Empty", "bson": "0D000000046100050000000000", "extjson": "{\"a\" : []}" }, { "description": "Single Element Array", "bson": "140000000461000C0000001030000A0000000000", "extjson": "{\"a\" : [10]}" }, { "description": "Single Element Array with index set incorrectly", "bson": "130000000461000B00000010000A0000000000", "canonical_bson": "140000000461000C0000001030000A0000000000", "extjson": "{\"a\" : [10]}" }, { "description": "Single Element Array with index set incorrectly", "bson": "150000000461000D000000106162000A0000000000", "canonical_bson": "140000000461000C0000001030000A0000000000", "extjson": "{\"a\" : [10]}" } ], "decodeErrors": [ { "description": "Array length too long: eats outer terminator", "bson": "140000000461000D0000001030000A0000000000" }, { "description": "Array length too short: leaks terminator", "bson": "140000000461000B0000001030000A0000000000" }, { "description": "Invalid Array: bad string length in field", "bson": "1A00000004666F6F00100000000230000500000062617A000000" } ] } bson-4.3.0/spec/support/corpus-tests/boolean.json0000644000004100000410000000120513236361476022153 0ustar www-datawww-data{ "description": "Boolean", "bson_type": "0x08", "test_key": "b", "valid": [ { "description": "True", "bson": "090000000862000100", "extjson": "{\"b\" : true}" }, { "description": "False", "bson": "090000000862000000", "extjson": "{\"b\" : false}" } ], "decodeErrors": [ { "description": "Invalid boolean value of 2", "bson": "090000000862000200" }, { "description": "Invalid boolean value of -1", "bson": "09000000086200FF00" } ] } bson-4.3.0/spec/support/common_driver.rb0000644000004100000410000002203213236361476020357 0ustar www-datawww-data# Copyright (C) 2016 MongoDB, 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 'json' require 'bigdecimal' module BSON module CommonDriver # Represents a Common Driver specification test. # # @since 4.2.0 class Spec # The spec description. # # @return [ String ] The spec description. # # @since 4.2.0 attr_reader :description # The document key of the object to test. # # @return [ String ] The document key. # # @since 4.2.0 attr_reader :test_key # Instantiate the new spec. # # @example Create the spec. # Spec.new(file) # # @param [ String ] file The name of the yaml file. # # @since 4.2.0 def initialize(file) @spec = ::JSON.parse(File.read(file)) @valid = @spec['valid'] || [] @invalid = @spec['parseErrors'] || [] @description = @spec['description'] @test_key = @spec['test_key'] end # Get a list of tests that don't raise exceptions. # # @example Get the list of valid tests. # spec.valid_tests # # @return [ Array ] The list of valid Tests. # # @since 4.2.0 def valid_tests @valid_tests ||= @valid.collect do |test| BSON::CommonDriver::Test.new(self, test) end end # Get a list of tests that raise exceptions. # # @example Get the list of invalid tests. # spec.invalid_tests # # @return [ Array ] The list of invalid Tests. # # @since 4.2.0 def invalid_tests @invalid_tests ||= @invalid.collect do |test| BSON::CommonDriver::Test.new(self, test) end end # The class of the bson object to test. # # @example Get the class of the object to test. # spec.klass # # @return [ Class ] The object class. # # @since 4.2.0 def klass @klass ||= BSON.const_get(description) end end # Represents a single CommonDriver test. # # @since 4.2.0 class Test # The test description. # # @return [ String ] The test description. # # @since 4.2.0 attr_reader :description # The test subject. # # @return [ String ] The test subject. # # @since 4.2.0 attr_reader :subject # The string to use to create a Decimal128. # # @return [ String ] The string to use in creating a Decimal128 object. # # @since 4.2.0 attr_reader :string # The expected string representation of the Decimal128 object. # # @return [ String ] The object as a string. # # @since 4.2.0 attr_reader :match_string # The json representation of the object. # # @return [ Hash ] The json representation of the object. # # @since 4.2.0 attr_reader :ext_json # Instantiate the new Test. # # @example Create the test. # Test.new(test) # # @param [ CommonDriver::Spec ] spec The test specification. # @param [ Hash ] test The test specification. # # @since 4.2.0 def initialize(spec, test) @spec = spec @description = test['description'] @string = test['string'] @match_string = test['match_string'] @ext_json = ::JSON.parse(test['extjson']) if test['extjson'] @from_ext_json = test['from_extjson'].nil? ? true : test['from_extjson'] @to_ext_json = test['to_extjson'].nil? ? true : test['to_extjson'] @subject = test['subject'] @test_key = spec.test_key end # Get the reencoded document in hex format. # # @example Get the reencoded document as hex. # test.reencoded_hex # # @return [ String ] The reencoded document in hex format. # # @since 4.2.0 def reencoded_hex decoded_document.to_bson.to_s.unpack("H*").first.upcase end # The object tested. # # @example Get the object for this test. # test.object # # @return [ BSON::Object ] The object. # # @since 4.2.0 def object @object ||= decoded_document[@test_key] end # The object as json, in a document with the test key. # # @example Get a document with the object at the test key. # test.document_as_json # # @return [ BSON::Document ] The json document. # # @since 4.2.0 def document_as_json { @test_key => object.as_json } end # Use the string in the extended json to instantiate the bson object. # # @example Get a bson object from the string in the extended json. # test.from_json # # @return [ BSON::Object ] The BSON object. # # @since 4.2.0 def from_json_string klass.from_string(@ext_json[@test_key][klass::EXTENDED_JSON_KEY]) end # Create an object from the given test string. # # @example # test.parse_string # # @return [ BSON::Object ] The object. # # @since 4.2.0 def parse_string klass.from_string(string) end # Attempt to create an object from an invalid string. # # @example # test.parse_invalid_string # # @raise [ Error ] Parsing an invalid string will raise an error. # # @since 4.2.0 def parse_invalid_string klass.from_string(subject) end # The class of the object being tested. # # @example # test.klass # # @return [ Class ] The object class. # # @since 4.2.0 def klass @spec.klass end # The error class of a parse error. # # @example # test.parse_error # # @return [ Class ] The parse error class. # # @since 4.2.0 def parse_error klass::InvalidRange end # Whether the object can be instantiated from extended json. # # @example Check if an object can be instantiated from the extended json. # test.from_ex_json? # # @return [ true, false ] If the object can be instantiated from # the provided extended json. # # @since 4.2.0 def from_ext_json? @ext_json && @from_ext_json end # Whether the object can be represented as extended json. # # @example Check if an object can be represented as extended json. # test.to_ext_json? # # @return [ true, false ] If the object can be represented as # extended json. # # @since 4.2.0 def to_ext_json? @ext_json && @to_ext_json end # Whether the object can be instantiated from a string. # # @example Check if an object can be instantiated from a string. # test.from_string? # # @return [ true, false ] If the object can be instantiated from a string. # # @since 4.2.0 def from_string? @string && @from_ext_json end # The expected string representation of the test object. # # @example Get the expected String representation of the test object. # test.expected_to_string # # @return [ String ] The expected string representation. # # @since 4.2.0 def expected_to_string match_string || string end # The Ruby class to which this bson object can be converted via a helper. # # @example Get the native type to which this object can be converted. # test.native_type # # @return [ Class ] The Ruby native type. # # @since 4.2.0 def native_type klass::NATIVE_TYPE end # Get the object converted to an instance of the native Ruby type. # # @example Get a native Ruby instance. # test.native_type_conversion # # @return [ Object ] An instance of the Ruby native type. # # @since 4.2.0 def native_type_conversion object.send("to_#{to_snake_case(native_type)}") end private def to_snake_case(string) string.to_s.gsub(/::/, '/'). gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). gsub(/([a-z\d])([A-Z])/,'\1_\2'). tr("-", "_"). downcase end def decoded_document @document ||= (data = [ @subject ].pack('H*') buffer = BSON::ByteBuffer.new(data) BSON::Document.from_bson(buffer)) end end end end bson-4.3.0/spec/support/driver-spec-tests/0000755000004100000410000000000013236361476020553 5ustar www-datawww-databson-4.3.0/spec/support/driver-spec-tests/decimal128/0000755000004100000410000000000013236361476022404 5ustar www-datawww-databson-4.3.0/spec/support/driver-spec-tests/decimal128/decimal128-4.json0000644000004100000410000001357213236361476025301 0ustar www-datawww-data{ "description": "Decimal128", "bson_type": "0x13", "test_key": "d", "valid": [ { "description": "[basx023] conform to rules and exponent will be in permitted range).", "subject": "1800000013640001000000000000000000000000003EB000", "string": "-0.1" }, { "description": "[basx045] strings without E cannot generate E in result", "subject": "1800000013640003000000000000000000000000003A3000", "string": "+0.003", "match_string": "0.003" }, { "description": "[basx610] Zeros", "subject": "1800000013640000000000000000000000000000003E3000", "string": ".0", "match_string": "0.0" }, { "description": "[basx612] Zeros", "subject": "1800000013640000000000000000000000000000003EB000", "string": "-.0", "match_string": "-0.0" }, { "description": "[basx043] strings without E cannot generate E in result", "subject": "18000000136400FC040000000000000000000000003C3000", "string": "+12.76", "match_string": "12.76" }, { "description": "[basx055] strings without E cannot generate E in result", "subject": "180000001364000500000000000000000000000000303000", "string": "0.00000005", "match_string": "5E-8" }, { "description": "[basx054] strings without E cannot generate E in result", "subject": "180000001364000500000000000000000000000000323000", "string": "0.0000005", "match_string": "5E-7" }, { "description": "[basx052] strings without E cannot generate E in result", "subject": "180000001364000500000000000000000000000000343000", "string": "0.000005" }, { "description": "[basx051] strings without E cannot generate E in result", "subject": "180000001364000500000000000000000000000000363000", "string": "00.00005", "match_string": "0.00005" }, { "description": "[basx050] strings without E cannot generate E in result", "subject": "180000001364000500000000000000000000000000383000", "string": "0.0005" }, { "description": "[basx047] strings without E cannot generate E in result", "subject": "1800000013640005000000000000000000000000003E3000", "string": ".5", "match_string": "0.5" }, { "description": "[dqbsr431] check rounding modes heeded (Rounded)", "subject": "1800000013640099761CC7B548F377DC80A131C836FE2F00", "string": "1.1111111111111111111111111111123450", "match_string": "1.111111111111111111111111111112345" }, { "description": "OK2", "subject": "18000000136400000000000A5BC138938D44C64D31FC2F00", "string": ".100000000000000000000000000000000000000000000000000000000000", "match_string": "0.1000000000000000000000000000000000" } ], "parseErrors": [ { "description": "[basx564] Near-specials (Conversion_syntax)", "subject": "Infi" }, { "description": "[basx565] Near-specials (Conversion_syntax)", "subject": "Infin" }, { "description": "[basx566] Near-specials (Conversion_syntax)", "subject": "Infini" }, { "description": "[basx567] Near-specials (Conversion_syntax)", "subject": "Infinit" }, { "description": "[basx568] Near-specials (Conversion_syntax)", "subject": "-Infinit" }, { "description": "[basx590] some baddies with dots and Es and dots and specials (Conversion_syntax)", "subject": ".Infinity" }, { "description": "[basx562] Near-specials (Conversion_syntax)", "subject": "NaNq" }, { "description": "[basx563] Near-specials (Conversion_syntax)", "subject": "NaNs" }, { "description": "[dqbas939] overflow results at different rounding modes (Overflow & Inexact & Rounded)", "subject": "-7e10000" }, { "description": "[dqbsr534] negatives (Rounded & Inexact)", "subject": "-1.11111111111111111111111111111234650" }, { "description": "[dqbsr535] negatives (Rounded & Inexact)", "subject": "-1.11111111111111111111111111111234551" }, { "description": "[dqbsr533] negatives (Rounded & Inexact)", "subject": "-1.11111111111111111111111111111234550" }, { "description": "[dqbsr532] negatives (Rounded & Inexact)", "subject": "-1.11111111111111111111111111111234549" }, { "description": "[dqbsr432] check rounding modes heeded (Rounded & Inexact)", "subject": "1.11111111111111111111111111111234549" }, { "description": "[dqbsr433] check rounding modes heeded (Rounded & Inexact)", "subject": "1.11111111111111111111111111111234550" }, { "description": "[dqbsr435] check rounding modes heeded (Rounded & Inexact)", "subject": "1.11111111111111111111111111111234551" }, { "description": "[dqbsr434] check rounding modes heeded (Rounded & Inexact)", "subject": "1.11111111111111111111111111111234650" }, { "description": "[dqbas938] overflow results at different rounding modes (Overflow & Inexact & Rounded)", "subject": "7e10000" }, { "description": "Inexact rounding#1", "subject": "100000000000000000000000000000000000000000000000000000000001" }, { "description": "Inexact rounding#2", "subject": "1E-6177" } ] } bson-4.3.0/spec/support/driver-spec-tests/decimal128/decimal128-2.json0000644000004100000410000007270513236361476025302 0ustar www-datawww-data{ "description": "Decimal128", "bson_type": "0x13", "test_key": "d", "valid": [ { "description": "[decq021] Normality", "subject": "18000000136400F2AF967ED05C82DE3297FF6FDE3C40B000", "string": "-1234567890123456789012345678901234" }, { "description": "[decq823] values around [u]int32 edges (zeros done earlier)", "subject": "18000000136400010000800000000000000000000040B000", "string": "-2147483649" }, { "description": "[decq822] values around [u]int32 edges (zeros done earlier)", "subject": "18000000136400000000800000000000000000000040B000", "string": "-2147483648" }, { "description": "[decq821] values around [u]int32 edges (zeros done earlier)", "subject": "18000000136400FFFFFF7F0000000000000000000040B000", "string": "-2147483647" }, { "description": "[decq820] values around [u]int32 edges (zeros done earlier)", "subject": "18000000136400FEFFFF7F0000000000000000000040B000", "string": "-2147483646" }, { "description": "[decq152] fold-downs (more below)", "subject": "18000000136400393000000000000000000000000040B000", "string": "-12345" }, { "description": "[decq154] fold-downs (more below)", "subject": "18000000136400D20400000000000000000000000040B000", "string": "-1234" }, { "description": "[decq006] derivative canonical plain strings", "subject": "18000000136400EE0200000000000000000000000040B000", "string": "-750" }, { "description": "[decq164] fold-downs (more below)", "subject": "1800000013640039300000000000000000000000003CB000", "string": "-123.45" }, { "description": "[decq156] fold-downs (more below)", "subject": "180000001364007B0000000000000000000000000040B000", "string": "-123" }, { "description": "[decq008] derivative canonical plain strings", "subject": "18000000136400EE020000000000000000000000003EB000", "string": "-75.0" }, { "description": "[decq158] fold-downs (more below)", "subject": "180000001364000C0000000000000000000000000040B000", "string": "-12" }, { "description": "[decq122] Nmax and similar", "subject": "18000000136400FFFFFFFF638E8D37C087ADBE09EDFFDF00", "string": "-9.999999999999999999999999999999999E+6144" }, { "description": "[decq002] (mostly derived from the Strawman 4 document and examples)", "subject": "18000000136400EE020000000000000000000000003CB000", "string": "-7.50" }, { "description": "[decq004] derivative canonical plain strings", "subject": "18000000136400EE0200000000000000000000000042B000", "string": "-7.50E+3" }, { "description": "[decq018] derivative canonical plain strings", "subject": "18000000136400EE020000000000000000000000002EB000", "string": "-7.50E-7" }, { "description": "[decq125] Nmax and similar", "subject": "18000000136400F2AF967ED05C82DE3297FF6FDE3CFEDF00", "string": "-1.234567890123456789012345678901234E+6144" }, { "description": "[decq131] fold-downs (more below)", "subject": "18000000136400000000807F1BCF85B27059C8A43CFEDF00", "string": "-1.230000000000000000000000000000000E+6144" }, { "description": "[decq162] fold-downs (more below)", "subject": "180000001364007B000000000000000000000000003CB000", "string": "-1.23" }, { "description": "[decq176] Nmin and below", "subject": "18000000136400010000000A5BC138938D44C64D31008000", "string": "-1.000000000000000000000000000000001E-6143" }, { "description": "[decq174] Nmin and below", "subject": "18000000136400000000000A5BC138938D44C64D31008000", "string": "-1.000000000000000000000000000000000E-6143" }, { "description": "[decq133] fold-downs (more below)", "subject": "18000000136400000000000A5BC138938D44C64D31FEDF00", "string": "-1.000000000000000000000000000000000E+6144" }, { "description": "[decq160] fold-downs (more below)", "subject": "18000000136400010000000000000000000000000040B000", "string": "-1" }, { "description": "[decq172] Nmin and below", "subject": "180000001364000100000000000000000000000000428000", "string": "-1E-6143" }, { "description": "[decq010] derivative canonical plain strings", "subject": "18000000136400EE020000000000000000000000003AB000", "string": "-0.750" }, { "description": "[decq012] derivative canonical plain strings", "subject": "18000000136400EE0200000000000000000000000038B000", "string": "-0.0750" }, { "description": "[decq014] derivative canonical plain strings", "subject": "18000000136400EE0200000000000000000000000034B000", "string": "-0.000750" }, { "description": "[decq016] derivative canonical plain strings", "subject": "18000000136400EE0200000000000000000000000030B000", "string": "-0.00000750" }, { "description": "[decq404] zeros", "subject": "180000001364000000000000000000000000000000000000", "string": "0E-6176" }, { "description": "[decq424] negative zeros", "subject": "180000001364000000000000000000000000000000008000", "string": "-0E-6176" }, { "description": "[decq407] zeros", "subject": "1800000013640000000000000000000000000000003C3000", "string": "0.00" }, { "description": "[decq427] negative zeros", "subject": "1800000013640000000000000000000000000000003CB000", "string": "-0.00" }, { "description": "[decq409] zeros", "subject": "180000001364000000000000000000000000000000403000", "string": "0" }, { "description": "[decq428] negative zeros", "subject": "18000000136400000000000000000000000000000040B000", "string": "-0" }, { "description": "[decq700] Selected DPD codes", "subject": "180000001364000000000000000000000000000000403000", "string": "0" }, { "description": "[decq406] zeros", "subject": "1800000013640000000000000000000000000000003C3000", "string": "0.00" }, { "description": "[decq426] negative zeros", "subject": "1800000013640000000000000000000000000000003CB000", "string": "-0.00" }, { "description": "[decq410] zeros", "subject": "180000001364000000000000000000000000000000463000", "string": "0E+3" }, { "description": "[decq431] negative zeros", "subject": "18000000136400000000000000000000000000000046B000", "string": "-0E+3" }, { "description": "[decq419] clamped zeros...", "subject": "180000001364000000000000000000000000000000FE5F00", "string": "0E+6111" }, { "description": "[decq432] negative zeros", "subject": "180000001364000000000000000000000000000000FEDF00", "string": "-0E+6111" }, { "description": "[decq405] zeros", "subject": "180000001364000000000000000000000000000000000000", "string": "0E-6176" }, { "description": "[decq425] negative zeros", "subject": "180000001364000000000000000000000000000000008000", "string": "-0E-6176" }, { "description": "[decq508] Specials", "subject": "180000001364000000000000000000000000000000007800", "string": "Infinity" }, { "description": "[decq528] Specials", "subject": "18000000136400000000000000000000000000000000F800", "string": "-Infinity" }, { "description": "[decq541] Specials", "subject": "180000001364000000000000000000000000000000007C00", "string": "NaN" }, { "description": "[decq074] Nmin and below", "subject": "18000000136400000000000A5BC138938D44C64D31000000", "string": "1.000000000000000000000000000000000E-6143" }, { "description": "[decq602] fold-down full sequence", "subject": "18000000136400000000000A5BC138938D44C64D31FE5F00", "string": "1.000000000000000000000000000000000E+6144" }, { "description": "[decq604] fold-down full sequence", "subject": "180000001364000000000081EFAC855B416D2DEE04FE5F00", "string": "1.00000000000000000000000000000000E+6143" }, { "description": "[decq606] fold-down full sequence", "subject": "1800000013640000000080264B91C02220BE377E00FE5F00", "string": "1.0000000000000000000000000000000E+6142" }, { "description": "[decq608] fold-down full sequence", "subject": "1800000013640000000040EAED7446D09C2C9F0C00FE5F00", "string": "1.000000000000000000000000000000E+6141" }, { "description": "[decq610] fold-down full sequence", "subject": "18000000136400000000A0CA17726DAE0F1E430100FE5F00", "string": "1.00000000000000000000000000000E+6140" }, { "description": "[decq612] fold-down full sequence", "subject": "18000000136400000000106102253E5ECE4F200000FE5F00", "string": "1.0000000000000000000000000000E+6139" }, { "description": "[decq614] fold-down full sequence", "subject": "18000000136400000000E83C80D09F3C2E3B030000FE5F00", "string": "1.000000000000000000000000000E+6138" }, { "description": "[decq616] fold-down full sequence", "subject": "18000000136400000000E4D20CC8DCD2B752000000FE5F00", "string": "1.00000000000000000000000000E+6137" }, { "description": "[decq618] fold-down full sequence", "subject": "180000001364000000004A48011416954508000000FE5F00", "string": "1.0000000000000000000000000E+6136" }, { "description": "[decq620] fold-down full sequence", "subject": "18000000136400000000A1EDCCCE1BC2D300000000FE5F00", "string": "1.000000000000000000000000E+6135" }, { "description": "[decq622] fold-down full sequence", "subject": "18000000136400000080F64AE1C7022D1500000000FE5F00", "string": "1.00000000000000000000000E+6134" }, { "description": "[decq624] fold-down full sequence", "subject": "18000000136400000040B2BAC9E0191E0200000000FE5F00", "string": "1.0000000000000000000000E+6133" }, { "description": "[decq626] fold-down full sequence", "subject": "180000001364000000A0DEC5ADC935360000000000FE5F00", "string": "1.000000000000000000000E+6132" }, { "description": "[decq628] fold-down full sequence", "subject": "18000000136400000010632D5EC76B050000000000FE5F00", "string": "1.00000000000000000000E+6131" }, { "description": "[decq630] fold-down full sequence", "subject": "180000001364000000E8890423C78A000000000000FE5F00", "string": "1.0000000000000000000E+6130" }, { "description": "[decq632] fold-down full sequence", "subject": "18000000136400000064A7B3B6E00D000000000000FE5F00", "string": "1.000000000000000000E+6129" }, { "description": "[decq634] fold-down full sequence", "subject": "1800000013640000008A5D78456301000000000000FE5F00", "string": "1.00000000000000000E+6128" }, { "description": "[decq636] fold-down full sequence", "subject": "180000001364000000C16FF2862300000000000000FE5F00", "string": "1.0000000000000000E+6127" }, { "description": "[decq638] fold-down full sequence", "subject": "180000001364000080C6A47E8D0300000000000000FE5F00", "string": "1.000000000000000E+6126" }, { "description": "[decq640] fold-down full sequence", "subject": "1800000013640000407A10F35A0000000000000000FE5F00", "string": "1.00000000000000E+6125" }, { "description": "[decq642] fold-down full sequence", "subject": "1800000013640000A0724E18090000000000000000FE5F00", "string": "1.0000000000000E+6124" }, { "description": "[decq644] fold-down full sequence", "subject": "180000001364000010A5D4E8000000000000000000FE5F00", "string": "1.000000000000E+6123" }, { "description": "[decq646] fold-down full sequence", "subject": "1800000013640000E8764817000000000000000000FE5F00", "string": "1.00000000000E+6122" }, { "description": "[decq648] fold-down full sequence", "subject": "1800000013640000E40B5402000000000000000000FE5F00", "string": "1.0000000000E+6121" }, { "description": "[decq650] fold-down full sequence", "subject": "1800000013640000CA9A3B00000000000000000000FE5F00", "string": "1.000000000E+6120" }, { "description": "[decq652] fold-down full sequence", "subject": "1800000013640000E1F50500000000000000000000FE5F00", "string": "1.00000000E+6119" }, { "description": "[decq654] fold-down full sequence", "subject": "180000001364008096980000000000000000000000FE5F00", "string": "1.0000000E+6118" }, { "description": "[decq656] fold-down full sequence", "subject": "1800000013640040420F0000000000000000000000FE5F00", "string": "1.000000E+6117" }, { "description": "[decq658] fold-down full sequence", "subject": "18000000136400A086010000000000000000000000FE5F00", "string": "1.00000E+6116" }, { "description": "[decq660] fold-down full sequence", "subject": "180000001364001027000000000000000000000000FE5F00", "string": "1.0000E+6115" }, { "description": "[decq662] fold-down full sequence", "subject": "18000000136400E803000000000000000000000000FE5F00", "string": "1.000E+6114" }, { "description": "[decq664] fold-down full sequence", "subject": "180000001364006400000000000000000000000000FE5F00", "string": "1.00E+6113" }, { "description": "[decq666] fold-down full sequence", "subject": "180000001364000A00000000000000000000000000FE5F00", "string": "1.0E+6112" }, { "description": "[decq060] fold-downs (more below)", "subject": "180000001364000100000000000000000000000000403000", "string": "1" }, { "description": "[decq670] fold-down full sequence", "subject": "180000001364000100000000000000000000000000FC5F00", "string": "1E+6110" }, { "description": "[decq668] fold-down full sequence", "subject": "180000001364000100000000000000000000000000FE5F00", "string": "1E+6111" }, { "description": "[decq072] Nmin and below", "subject": "180000001364000100000000000000000000000000420000", "string": "1E-6143" }, { "description": "[decq076] Nmin and below", "subject": "18000000136400010000000A5BC138938D44C64D31000000", "string": "1.000000000000000000000000000000001E-6143" }, { "description": "[decq036] fold-downs (more below)", "subject": "18000000136400000000807F1BCF85B27059C8A43CFE5F00", "string": "1.230000000000000000000000000000000E+6144" }, { "description": "[decq062] fold-downs (more below)", "subject": "180000001364007B000000000000000000000000003C3000", "string": "1.23" }, { "description": "[decq034] Nmax and similar", "subject": "18000000136400F2AF967ED05C82DE3297FF6FDE3CFE5F00", "string": "1.234567890123456789012345678901234E+6144" }, { "description": "[decq441] exponent lengths", "subject": "180000001364000700000000000000000000000000403000", "string": "7" }, { "description": "[decq449] exponent lengths", "subject": "1800000013640007000000000000000000000000001E5F00", "string": "7E+5999" }, { "description": "[decq447] exponent lengths", "subject": "1800000013640007000000000000000000000000000E3800", "string": "7E+999" }, { "description": "[decq445] exponent lengths", "subject": "180000001364000700000000000000000000000000063100", "string": "7E+99" }, { "description": "[decq443] exponent lengths", "subject": "180000001364000700000000000000000000000000523000", "string": "7E+9" }, { "description": "[decq842] VG testcase", "subject": "180000001364000000FED83F4E7C9FE4E269E38A5BCD1700", "string": "7.049000000000010795488000000000000E-3097" }, { "description": "[decq841] VG testcase", "subject": "180000001364000000203B9DB5056F000000000000002400", "string": "8.000000000000000000E-1550" }, { "description": "[decq840] VG testcase", "subject": "180000001364003C17258419D710C42F0000000000002400", "string": "8.81125000000001349436E-1548" }, { "description": "[decq701] Selected DPD codes", "subject": "180000001364000900000000000000000000000000403000", "string": "9" }, { "description": "[decq032] Nmax and similar", "subject": "18000000136400FFFFFFFF638E8D37C087ADBE09EDFF5F00", "string": "9.999999999999999999999999999999999E+6144" }, { "description": "[decq702] Selected DPD codes", "subject": "180000001364000A00000000000000000000000000403000", "string": "10" }, { "description": "[decq057] fold-downs (more below)", "subject": "180000001364000C00000000000000000000000000403000", "string": "12" }, { "description": "[decq703] Selected DPD codes", "subject": "180000001364001300000000000000000000000000403000", "string": "19" }, { "description": "[decq704] Selected DPD codes", "subject": "180000001364001400000000000000000000000000403000", "string": "20" }, { "description": "[decq705] Selected DPD codes", "subject": "180000001364001D00000000000000000000000000403000", "string": "29" }, { "description": "[decq706] Selected DPD codes", "subject": "180000001364001E00000000000000000000000000403000", "string": "30" }, { "description": "[decq707] Selected DPD codes", "subject": "180000001364002700000000000000000000000000403000", "string": "39" }, { "description": "[decq708] Selected DPD codes", "subject": "180000001364002800000000000000000000000000403000", "string": "40" }, { "description": "[decq709] Selected DPD codes", "subject": "180000001364003100000000000000000000000000403000", "string": "49" }, { "description": "[decq710] Selected DPD codes", "subject": "180000001364003200000000000000000000000000403000", "string": "50" }, { "description": "[decq711] Selected DPD codes", "subject": "180000001364003B00000000000000000000000000403000", "string": "59" }, { "description": "[decq712] Selected DPD codes", "subject": "180000001364003C00000000000000000000000000403000", "string": "60" }, { "description": "[decq713] Selected DPD codes", "subject": "180000001364004500000000000000000000000000403000", "string": "69" }, { "description": "[decq714] Selected DPD codes", "subject": "180000001364004600000000000000000000000000403000", "string": "70" }, { "description": "[decq715] Selected DPD codes", "subject": "180000001364004700000000000000000000000000403000", "string": "71" }, { "description": "[decq716] Selected DPD codes", "subject": "180000001364004800000000000000000000000000403000", "string": "72" }, { "description": "[decq717] Selected DPD codes", "subject": "180000001364004900000000000000000000000000403000", "string": "73" }, { "description": "[decq718] Selected DPD codes", "subject": "180000001364004A00000000000000000000000000403000", "string": "74" }, { "description": "[decq719] Selected DPD codes", "subject": "180000001364004B00000000000000000000000000403000", "string": "75" }, { "description": "[decq720] Selected DPD codes", "subject": "180000001364004C00000000000000000000000000403000", "string": "76" }, { "description": "[decq721] Selected DPD codes", "subject": "180000001364004D00000000000000000000000000403000", "string": "77" }, { "description": "[decq722] Selected DPD codes", "subject": "180000001364004E00000000000000000000000000403000", "string": "78" }, { "description": "[decq723] Selected DPD codes", "subject": "180000001364004F00000000000000000000000000403000", "string": "79" }, { "description": "[decq056] fold-downs (more below)", "subject": "180000001364007B00000000000000000000000000403000", "string": "123" }, { "description": "[decq064] fold-downs (more below)", "subject": "1800000013640039300000000000000000000000003C3000", "string": "123.45" }, { "description": "[decq732] Selected DPD codes", "subject": "180000001364000802000000000000000000000000403000", "string": "520" }, { "description": "[decq733] Selected DPD codes", "subject": "180000001364000902000000000000000000000000403000", "string": "521" }, { "description": "[decq740] DPD: one of each of the huffman groups", "subject": "180000001364000903000000000000000000000000403000", "string": "777" }, { "description": "[decq741] DPD: one of each of the huffman groups", "subject": "180000001364000A03000000000000000000000000403000", "string": "778" }, { "description": "[decq742] DPD: one of each of the huffman groups", "subject": "180000001364001303000000000000000000000000403000", "string": "787" }, { "description": "[decq746] DPD: one of each of the huffman groups", "subject": "180000001364001F03000000000000000000000000403000", "string": "799" }, { "description": "[decq743] DPD: one of each of the huffman groups", "subject": "180000001364006D03000000000000000000000000403000", "string": "877" }, { "description": "[decq753] DPD all-highs cases (includes the 24 redundant codes)", "subject": "180000001364007803000000000000000000000000403000", "string": "888" }, { "description": "[decq754] DPD all-highs cases (includes the 24 redundant codes)", "subject": "180000001364007903000000000000000000000000403000", "string": "889" }, { "description": "[decq760] DPD all-highs cases (includes the 24 redundant codes)", "subject": "180000001364008203000000000000000000000000403000", "string": "898" }, { "description": "[decq764] DPD all-highs cases (includes the 24 redundant codes)", "subject": "180000001364008303000000000000000000000000403000", "string": "899" }, { "description": "[decq745] DPD: one of each of the huffman groups", "subject": "18000000136400D303000000000000000000000000403000", "string": "979" }, { "description": "[decq770] DPD all-highs cases (includes the 24 redundant codes)", "subject": "18000000136400DC03000000000000000000000000403000", "string": "988" }, { "description": "[decq774] DPD all-highs cases (includes the 24 redundant codes)", "subject": "18000000136400DD03000000000000000000000000403000", "string": "989" }, { "description": "[decq730] Selected DPD codes", "subject": "18000000136400E203000000000000000000000000403000", "string": "994" }, { "description": "[decq731] Selected DPD codes", "subject": "18000000136400E303000000000000000000000000403000", "string": "995" }, { "description": "[decq744] DPD: one of each of the huffman groups", "subject": "18000000136400E503000000000000000000000000403000", "string": "997" }, { "description": "[decq780] DPD all-highs cases (includes the 24 redundant codes)", "subject": "18000000136400E603000000000000000000000000403000", "string": "998" }, { "description": "[decq787] DPD all-highs cases (includes the 24 redundant codes)", "subject": "18000000136400E703000000000000000000000000403000", "string": "999" }, { "description": "[decq053] fold-downs (more below)", "subject": "18000000136400D204000000000000000000000000403000", "string": "1234" }, { "description": "[decq052] fold-downs (more below)", "subject": "180000001364003930000000000000000000000000403000", "string": "12345" }, { "description": "[decq792] Miscellaneous (testers' queries, etc.)", "subject": "180000001364003075000000000000000000000000403000", "string": "30000" }, { "description": "[decq793] Miscellaneous (testers' queries, etc.)", "subject": "1800000013640090940D0000000000000000000000403000", "string": "890000" }, { "description": "[decq824] values around [u]int32 edges (zeros done earlier)", "subject": "18000000136400FEFFFF7F00000000000000000000403000", "string": "2147483646" }, { "description": "[decq825] values around [u]int32 edges (zeros done earlier)", "subject": "18000000136400FFFFFF7F00000000000000000000403000", "string": "2147483647" }, { "description": "[decq826] values around [u]int32 edges (zeros done earlier)", "subject": "180000001364000000008000000000000000000000403000", "string": "2147483648" }, { "description": "[decq827] values around [u]int32 edges (zeros done earlier)", "subject": "180000001364000100008000000000000000000000403000", "string": "2147483649" }, { "description": "[decq828] values around [u]int32 edges (zeros done earlier)", "subject": "18000000136400FEFFFFFF00000000000000000000403000", "string": "4294967294" }, { "description": "[decq829] values around [u]int32 edges (zeros done earlier)", "subject": "18000000136400FFFFFFFF00000000000000000000403000", "string": "4294967295" }, { "description": "[decq830] values around [u]int32 edges (zeros done earlier)", "subject": "180000001364000000000001000000000000000000403000", "string": "4294967296" }, { "description": "[decq831] values around [u]int32 edges (zeros done earlier)", "subject": "180000001364000100000001000000000000000000403000", "string": "4294967297" }, { "description": "[decq022] Normality", "subject": "18000000136400C7711CC7B548F377DC80A131C836403000", "string": "1111111111111111111111111111111111" }, { "description": "[decq020] Normality", "subject": "18000000136400F2AF967ED05C82DE3297FF6FDE3C403000", "string": "1234567890123456789012345678901234" }, { "description": "[decq550] Specials", "subject": "18000000136400FFFFFFFF638E8D37C087ADBE09ED413000", "string": "9999999999999999999999999999999999" } ] } bson-4.3.0/spec/support/driver-spec-tests/decimal128/decimal128-6.json0000644000004100000410000000605013236361476025274 0ustar www-datawww-data{ "description": "Decimal128", "bson_type": "0x13", "test_key": "d", "parseErrors": [ { "description": "Incomplete Exponent", "subject": "1e" }, { "description": "Exponent at the beginning", "subject": "E01" }, { "description": "Just a decimal place", "subject": "." }, { "description": "2 decimal places", "subject": "..3" }, { "description": "2 decimal places", "subject": ".13.3" }, { "description": "2 decimal places", "subject": "1..3" }, { "description": "2 decimal places", "subject": "1.3.4" }, { "description": "2 decimal places", "subject": "1.34." }, { "description": "Decimal with no digits", "subject": ".e" }, { "description": "2 signs", "subject": "+-32.4" }, { "description": "2 signs", "subject": "-+32.4" }, { "description": "2 negative signs", "subject": "--32.4" }, { "description": "2 negative signs", "subject": "-32.-4" }, { "description": "End in negative sign", "subject": "32.0-" }, { "description": "2 negative signs", "subject": "32.4E--21" }, { "description": "2 negative signs", "subject": "32.4E-2-1" }, { "description": "2 signs", "subject": "32.4E+-21" }, { "description": "Empty string", "subject": "" }, { "description": "leading white space positive number", "subject": " 1" }, { "description": "leading white space negative number", "subject": " -1" }, { "description": "trailing white space", "subject": "1 " }, { "description": "Invalid", "subject": "E" }, { "description": "Invalid", "subject": "invalid" }, { "description": "Invalid", "subject": "i" }, { "description": "Invalid", "subject": "in" }, { "description": "Invalid", "subject": "-in" }, { "description": "Invalid", "subject": "Na" }, { "description": "Invalid", "subject": "-Na" }, { "description": "Invalid", "subject": "1.23abc" }, { "description": "Invalid", "subject": "1.23abcE+02" }, { "description": "Invalid", "subject": "1.23E+0aabs2" } ] } bson-4.3.0/spec/support/driver-spec-tests/decimal128/decimal128-5.json0000644000004100000410000004133713236361476025302 0ustar www-datawww-data{ "description": "Decimal128", "bson_type": "0x13", "test_key": "d", "valid": [ { "description": "[decq035] fold-downs (more below) (Clamped)", "subject": "18000000136400000000807F1BCF85B27059C8A43CFE5F00", "string": "1.23E+6144", "match_string": "1.230000000000000000000000000000000E+6144" }, { "description": "[decq037] fold-downs (more below) (Clamped)", "subject": "18000000136400000000000A5BC138938D44C64D31FE5F00", "string": "1E+6144", "match_string": "1.000000000000000000000000000000000E+6144" }, { "description": "[decq077] Nmin and below (Subnormal)", "subject": "180000001364000000000081EFAC855B416D2DEE04000000", "string": "0.100000000000000000000000000000000E-6143", "match_string": "1.00000000000000000000000000000000E-6144" }, { "description": "[decq078] Nmin and below (Subnormal)", "subject": "180000001364000000000081EFAC855B416D2DEE04000000", "string": "1.00000000000000000000000000000000E-6144" }, { "description": "[decq079] Nmin and below (Subnormal)", "subject": "180000001364000A00000000000000000000000000000000", "string": "0.000000000000000000000000000000010E-6143", "match_string": "1.0E-6175" }, { "description": "[decq080] Nmin and below (Subnormal)", "subject": "180000001364000A00000000000000000000000000000000", "string": "1.0E-6175" }, { "description": "[decq081] Nmin and below (Subnormal)", "subject": "180000001364000100000000000000000000000000020000", "string": "0.00000000000000000000000000000001E-6143", "match_string": "1E-6175" }, { "description": "[decq082] Nmin and below (Subnormal)", "subject": "180000001364000100000000000000000000000000020000", "string": "1E-6175" }, { "description": "[decq083] Nmin and below (Subnormal)", "subject": "180000001364000100000000000000000000000000000000", "string": "0.000000000000000000000000000000001E-6143", "match_string": "1E-6176" }, { "description": "[decq084] Nmin and below (Subnormal)", "subject": "180000001364000100000000000000000000000000000000", "string": "1E-6176" }, { "description": "[decq090] underflows cannot be tested for simple copies, check edge cases (Subnormal)", "subject": "180000001364000100000000000000000000000000000000", "string": "1e-6176", "match_string": "1E-6176" }, { "description": "[decq100] underflows cannot be tested for simple copies, check edge cases (Subnormal)", "subject": "18000000136400FFFFFFFF095BC138938D44C64D31000000", "string": "999999999999999999999999999999999e-6176", "match_string": "9.99999999999999999999999999999999E-6144" }, { "description": "[decq130] fold-downs (more below) (Clamped)", "subject": "18000000136400000000807F1BCF85B27059C8A43CFEDF00", "string": "-1.23E+6144", "match_string": "-1.230000000000000000000000000000000E+6144" }, { "description": "[decq132] fold-downs (more below) (Clamped)", "subject": "18000000136400000000000A5BC138938D44C64D31FEDF00", "string": "-1E+6144", "match_string": "-1.000000000000000000000000000000000E+6144" }, { "description": "[decq177] Nmin and below (Subnormal)", "subject": "180000001364000000000081EFAC855B416D2DEE04008000", "string": "-0.100000000000000000000000000000000E-6143", "match_string": "-1.00000000000000000000000000000000E-6144" }, { "description": "[decq178] Nmin and below (Subnormal)", "subject": "180000001364000000000081EFAC855B416D2DEE04008000", "string": "-1.00000000000000000000000000000000E-6144" }, { "description": "[decq179] Nmin and below (Subnormal)", "subject": "180000001364000A00000000000000000000000000008000", "string": "-0.000000000000000000000000000000010E-6143", "match_string": "-1.0E-6175" }, { "description": "[decq180] Nmin and below (Subnormal)", "subject": "180000001364000A00000000000000000000000000008000", "string": "-1.0E-6175" }, { "description": "[decq181] Nmin and below (Subnormal)", "subject": "180000001364000100000000000000000000000000028000", "string": "-0.00000000000000000000000000000001E-6143", "match_string": "-1E-6175" }, { "description": "[decq182] Nmin and below (Subnormal)", "subject": "180000001364000100000000000000000000000000028000", "string": "-1E-6175" }, { "description": "[decq183] Nmin and below (Subnormal)", "subject": "180000001364000100000000000000000000000000008000", "string": "-0.000000000000000000000000000000001E-6143", "match_string": "-1E-6176" }, { "description": "[decq184] Nmin and below (Subnormal)", "subject": "180000001364000100000000000000000000000000008000", "string": "-1E-6176" }, { "description": "[decq190] underflow edge cases (Subnormal)", "subject": "180000001364000100000000000000000000000000008000", "string": "-1e-6176", "match_string": "-1E-6176" }, { "description": "[decq200] underflow edge cases (Subnormal)", "subject": "18000000136400FFFFFFFF095BC138938D44C64D31008000", "string": "-999999999999999999999999999999999e-6176", "match_string": "-9.99999999999999999999999999999999E-6144" }, { "description": "[decq400] zeros (Clamped)", "subject": "180000001364000000000000000000000000000000000000", "string": "0E-8000", "match_string": "0E-6176" }, { "description": "[decq401] zeros (Clamped)", "subject": "180000001364000000000000000000000000000000000000", "string": "0E-6177", "match_string": "0E-6176" }, { "description": "[decq414] clamped zeros... (Clamped)", "subject": "180000001364000000000000000000000000000000FE5F00", "string": "0E+6112", "match_string": "0E+6111" }, { "description": "[decq416] clamped zeros... (Clamped)", "subject": "180000001364000000000000000000000000000000FE5F00", "string": "0E+6144", "match_string": "0E+6111" }, { "description": "[decq418] clamped zeros... (Clamped)", "subject": "180000001364000000000000000000000000000000FE5F00", "string": "0E+8000", "match_string": "0E+6111" }, { "description": "[decq420] negative zeros (Clamped)", "subject": "180000001364000000000000000000000000000000008000", "string": "-0E-8000", "match_string": "-0E-6176" }, { "description": "[decq421] negative zeros (Clamped)", "subject": "180000001364000000000000000000000000000000008000", "string": "-0E-6177", "match_string": "-0E-6176" }, { "description": "[decq434] clamped zeros... (Clamped)", "subject": "180000001364000000000000000000000000000000FEDF00", "string": "-0E+6112", "match_string": "-0E+6111" }, { "description": "[decq436] clamped zeros... (Clamped)", "subject": "180000001364000000000000000000000000000000FEDF00", "string": "-0E+6144", "match_string": "-0E+6111" }, { "description": "[decq438] clamped zeros... (Clamped)", "subject": "180000001364000000000000000000000000000000FEDF00", "string": "-0E+8000", "match_string": "-0E+6111" }, { "description": "[decq601] fold-down full sequence (Clamped)", "subject": "18000000136400000000000A5BC138938D44C64D31FE5F00", "string": "1E+6144", "match_string": "1.000000000000000000000000000000000E+6144" }, { "description": "[decq603] fold-down full sequence (Clamped)", "subject": "180000001364000000000081EFAC855B416D2DEE04FE5F00", "string": "1E+6143", "match_string": "1.00000000000000000000000000000000E+6143" }, { "description": "[decq605] fold-down full sequence (Clamped)", "subject": "1800000013640000000080264B91C02220BE377E00FE5F00", "string": "1E+6142", "match_string": "1.0000000000000000000000000000000E+6142" }, { "description": "[decq607] fold-down full sequence (Clamped)", "subject": "1800000013640000000040EAED7446D09C2C9F0C00FE5F00", "string": "1E+6141", "match_string": "1.000000000000000000000000000000E+6141" }, { "description": "[decq609] fold-down full sequence (Clamped)", "subject": "18000000136400000000A0CA17726DAE0F1E430100FE5F00", "string": "1E+6140", "match_string": "1.00000000000000000000000000000E+6140" }, { "description": "[decq611] fold-down full sequence (Clamped)", "subject": "18000000136400000000106102253E5ECE4F200000FE5F00", "string": "1E+6139", "match_string": "1.0000000000000000000000000000E+6139" }, { "description": "[decq613] fold-down full sequence (Clamped)", "subject": "18000000136400000000E83C80D09F3C2E3B030000FE5F00", "string": "1E+6138", "match_string": "1.000000000000000000000000000E+6138" }, { "description": "[decq615] fold-down full sequence (Clamped)", "subject": "18000000136400000000E4D20CC8DCD2B752000000FE5F00", "string": "1E+6137", "match_string": "1.00000000000000000000000000E+6137" }, { "description": "[decq617] fold-down full sequence (Clamped)", "subject": "180000001364000000004A48011416954508000000FE5F00", "string": "1E+6136", "match_string": "1.0000000000000000000000000E+6136" }, { "description": "[decq619] fold-down full sequence (Clamped)", "subject": "18000000136400000000A1EDCCCE1BC2D300000000FE5F00", "string": "1E+6135", "match_string": "1.000000000000000000000000E+6135" }, { "description": "[decq621] fold-down full sequence (Clamped)", "subject": "18000000136400000080F64AE1C7022D1500000000FE5F00", "string": "1E+6134", "match_string": "1.00000000000000000000000E+6134" }, { "description": "[decq623] fold-down full sequence (Clamped)", "subject": "18000000136400000040B2BAC9E0191E0200000000FE5F00", "string": "1E+6133", "match_string": "1.0000000000000000000000E+6133" }, { "description": "[decq625] fold-down full sequence (Clamped)", "subject": "180000001364000000A0DEC5ADC935360000000000FE5F00", "string": "1E+6132", "match_string": "1.000000000000000000000E+6132" }, { "description": "[decq627] fold-down full sequence (Clamped)", "subject": "18000000136400000010632D5EC76B050000000000FE5F00", "string": "1E+6131", "match_string": "1.00000000000000000000E+6131" }, { "description": "[decq629] fold-down full sequence (Clamped)", "subject": "180000001364000000E8890423C78A000000000000FE5F00", "string": "1E+6130", "match_string": "1.0000000000000000000E+6130" }, { "description": "[decq631] fold-down full sequence (Clamped)", "subject": "18000000136400000064A7B3B6E00D000000000000FE5F00", "string": "1E+6129", "match_string": "1.000000000000000000E+6129" }, { "description": "[decq633] fold-down full sequence (Clamped)", "subject": "1800000013640000008A5D78456301000000000000FE5F00", "string": "1E+6128", "match_string": "1.00000000000000000E+6128" }, { "description": "[decq635] fold-down full sequence (Clamped)", "subject": "180000001364000000C16FF2862300000000000000FE5F00", "string": "1E+6127", "match_string": "1.0000000000000000E+6127" }, { "description": "[decq637] fold-down full sequence (Clamped)", "subject": "180000001364000080C6A47E8D0300000000000000FE5F00", "string": "1E+6126", "match_string": "1.000000000000000E+6126" }, { "description": "[decq639] fold-down full sequence (Clamped)", "subject": "1800000013640000407A10F35A0000000000000000FE5F00", "string": "1E+6125", "match_string": "1.00000000000000E+6125" }, { "description": "[decq641] fold-down full sequence (Clamped)", "subject": "1800000013640000A0724E18090000000000000000FE5F00", "string": "1E+6124", "match_string": "1.0000000000000E+6124" }, { "description": "[decq643] fold-down full sequence (Clamped)", "subject": "180000001364000010A5D4E8000000000000000000FE5F00", "string": "1E+6123", "match_string": "1.000000000000E+6123" }, { "description": "[decq645] fold-down full sequence (Clamped)", "subject": "1800000013640000E8764817000000000000000000FE5F00", "string": "1E+6122", "match_string": "1.00000000000E+6122" }, { "description": "[decq647] fold-down full sequence (Clamped)", "subject": "1800000013640000E40B5402000000000000000000FE5F00", "string": "1E+6121", "match_string": "1.0000000000E+6121" }, { "description": "[decq649] fold-down full sequence (Clamped)", "subject": "1800000013640000CA9A3B00000000000000000000FE5F00", "string": "1E+6120", "match_string": "1.000000000E+6120" }, { "description": "[decq651] fold-down full sequence (Clamped)", "subject": "1800000013640000E1F50500000000000000000000FE5F00", "string": "1E+6119", "match_string": "1.00000000E+6119" }, { "description": "[decq653] fold-down full sequence (Clamped)", "subject": "180000001364008096980000000000000000000000FE5F00", "string": "1E+6118", "match_string": "1.0000000E+6118" }, { "description": "[decq655] fold-down full sequence (Clamped)", "subject": "1800000013640040420F0000000000000000000000FE5F00", "string": "1E+6117", "match_string": "1.000000E+6117" }, { "description": "[decq657] fold-down full sequence (Clamped)", "subject": "18000000136400A086010000000000000000000000FE5F00", "string": "1E+6116", "match_string": "1.00000E+6116" }, { "description": "[decq659] fold-down full sequence (Clamped)", "subject": "180000001364001027000000000000000000000000FE5F00", "string": "1E+6115", "match_string": "1.0000E+6115" }, { "description": "[decq661] fold-down full sequence (Clamped)", "subject": "18000000136400E803000000000000000000000000FE5F00", "string": "1E+6114", "match_string": "1.000E+6114" }, { "description": "[decq663] fold-down full sequence (Clamped)", "subject": "180000001364006400000000000000000000000000FE5F00", "string": "1E+6113", "match_string": "1.00E+6113" }, { "description": "[decq665] fold-down full sequence (Clamped)", "subject": "180000001364000A00000000000000000000000000FE5F00", "string": "1E+6112", "match_string": "1.0E+6112" } ] } bson-4.3.0/spec/support/driver-spec-tests/decimal128/decimal128-1.json0000644000004100000410000004223313236361476025272 0ustar www-datawww-data{ "description": "Decimal128", "bson_type": "0x13", "test_key": "d", "valid": [ { "description": "Special - Canonical NaN", "subject": "180000001364000000000000000000000000000000007C00", "string": "NaN", "extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}" }, { "description": "Special - Negative NaN", "subject": "18000000136400000000000000000000000000000000FC00", "string": "NaN", "from_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}" }, { "description": "Special - Canonical SNaN", "subject": "180000001364000000000000000000000000000000007E00", "string": "NaN", "from_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}" }, { "description": "Special - Negative SNaN", "subject": "18000000136400000000000000000000000000000000FE00", "string": "NaN", "from_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}" }, { "description": "Special - NaN with a payload", "subject": "180000001364001200000000000000000000000000007E00", "string": "NaN", "from_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"NaN\"}}" }, { "description": "Special - Canonical Positive Infinity", "subject": "180000001364000000000000000000000000000000007800", "string": "Infinity", "extjson": "{\"d\" : {\"$numberDecimal\" : \"Infinity\"}}" }, { "description": "Special - Canonical Negative Infinity", "subject": "18000000136400000000000000000000000000000000F800", "string": "-Infinity", "extjson": "{\"d\" : {\"$numberDecimal\" : \"-Infinity\"}}" }, { "description": "Special - Invalid representation treated as 0", "subject": "180000001364000000000000000000000000000000106C00", "string": "0", "from_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}" }, { "description": "Special - Invalid representation treated as -0", "subject": "18000000136400DCBA9876543210DEADBEEF00000010EC00", "string": "-0", "from_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0\"}}" }, { "description": "Special - Invalid representation treated as 0E3", "subject": "18000000136400FFFFFFFFFFFFFFFFFFFFFFFFFFFF116C00", "string": "0E+3", "from_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+3\"}}" }, { "description": "Regular - Adjusted Exponent Limit", "subject": "18000000136400F2AF967ED05C82DE3297FF6FDE3CF22F00", "string": "0.000001234567890123456789012345678901234", "extjson": "{\"d\": { \"$numberDecimal\": \"0.000001234567890123456789012345678901234\" }}" }, { "description": "Regular - Smallest", "subject": "18000000136400D204000000000000000000000000343000", "string": "0.001234", "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.001234\"}}" }, { "description": "Regular - Smallest with Trailing Zeros", "subject": "1800000013640040EF5A07000000000000000000002A3000", "string": "0.00123400000", "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.00123400000\"}}" }, { "description": "Regular - 0.1", "subject": "1800000013640001000000000000000000000000003E3000", "string": "0.1", "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1\"}}" }, { "description": "Regular - 0.1234567890123456789012345678901234", "subject": "18000000136400F2AF967ED05C82DE3297FF6FDE3CFC2F00", "string": "0.1234567890123456789012345678901234", "extjson": "{\"d\" : {\"$numberDecimal\" : \"0.1234567890123456789012345678901234\"}}" }, { "description": "Regular - 0", "subject": "180000001364000000000000000000000000000000403000", "string": "0", "extjson": "{\"d\" : {\"$numberDecimal\" : \"0\"}}" }, { "description": "Regular - -0", "subject": "18000000136400000000000000000000000000000040B000", "string": "-0", "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0\"}}" }, { "description": "Regular - -0.0", "subject": "1800000013640000000000000000000000000000003EB000", "string": "-0.0", "extjson": "{\"d\" : {\"$numberDecimal\" : \"-0.0\"}}" }, { "description": "Regular - 2", "subject": "180000001364000200000000000000000000000000403000", "string": "2", "extjson": "{\"d\" : {\"$numberDecimal\" : \"2\"}}" }, { "description": "Regular - 2.000", "subject": "18000000136400D0070000000000000000000000003A3000", "string": "2.000", "extjson": "{\"d\" : {\"$numberDecimal\" : \"2.000\"}}" }, { "description": "Regular - Largest", "subject": "18000000136400F2AF967ED05C82DE3297FF6FDE3C403000", "string": "1234567890123456789012345678901234", "extjson": "{\"d\" : {\"$numberDecimal\" : \"1234567890123456789012345678901234\"}}" }, { "description": "Scientific - Tiniest", "subject": "18000000136400FFFFFFFF638E8D37C087ADBE09ED010000", "string": "9.999999999999999999999999999999999E-6143", "extjson": "{\"d\" : {\"$numberDecimal\" : \"9.999999999999999999999999999999999E-6143\"}}" }, { "description": "Scientific - Tiny", "subject": "180000001364000100000000000000000000000000000000", "string": "1E-6176", "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E-6176\"}}" }, { "description": "Scientific - Negative Tiny", "subject": "180000001364000100000000000000000000000000008000", "string": "-1E-6176", "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1E-6176\"}}" }, { "description": "Scientific - Adjusted Exponent Limit", "subject": "18000000136400F2AF967ED05C82DE3297FF6FDE3CF02F00", "string": "1.234567890123456789012345678901234E-7", "extjson": "{\"d\": { \"$numberDecimal\": \"1.234567890123456789012345678901234E-7\" }}" }, { "description": "Scientific - Fractional", "subject": "1800000013640064000000000000000000000000002CB000", "string": "-1.00E-8", "extjson": "{\"d\" : {\"$numberDecimal\" : \"-1.00E-8\"}}" }, { "description": "Scientific - 0 with Exponent", "subject": "180000001364000000000000000000000000000000205F00", "string": "0E+6000", "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E+6000\"}}" }, { "description": "Scientific - 0 with Negative Exponent", "subject": "1800000013640000000000000000000000000000007A2B00", "string": "0E-611", "extjson": "{\"d\" : {\"$numberDecimal\" : \"0E-611\"}}" }, { "description": "Scientific - No Decimal with Signed Exponent", "subject": "180000001364000100000000000000000000000000463000", "string": "1E+3", "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E+3\"}}" }, { "description": "Scientific - Trailing Zero", "subject": "180000001364001A04000000000000000000000000423000", "string": "1.050E+4", "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.050E+4\"}}" }, { "description": "Scientific - With Decimal", "subject": "180000001364006900000000000000000000000000423000", "string": "1.05E+3", "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.05E+3\"}}" }, { "description": "Scientific - Full", "subject": "18000000136400FFFFFFFFFFFFFFFFFFFFFFFFFFFF403000", "string": "5192296858534827628530496329220095", "extjson": "{\"d\" : {\"$numberDecimal\" : \"5192296858534827628530496329220095\"}}" }, { "description": "Scientific - Large", "subject": "18000000136400000000000A5BC138938D44C64D31FE5F00", "string": "1.000000000000000000000000000000000E+6144", "extjson": "{\"d\" : {\"$numberDecimal\" : \"1.000000000000000000000000000000000E+6144\"}}" }, { "description": "Scientific - Largest", "subject": "18000000136400FFFFFFFF638E8D37C087ADBE09EDFF5F00", "string": "9.999999999999999999999999999999999E+6144", "extjson": "{\"d\" : {\"$numberDecimal\" : \"9.999999999999999999999999999999999E+6144\"}}" }, { "description": "Non-Canonical Parsing - Exponent Normalization", "subject": "1800000013640064000000000000000000000000002CB000", "string": "-1.00E-8", "to_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"-100E-10\"}}" }, { "description": "Non-Canonical Parsing - Unsigned Positive Exponent", "subject": "180000001364000100000000000000000000000000463000", "string": "1E+3", "to_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"1E3\"}}" }, { "description": "Non-Canonical Parsing - Lowercase Exponent Identifier", "subject": "180000001364000100000000000000000000000000463000", "string": "1E+3", "to_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"1e+3\"}}" }, { "description": "Non-Canonical Parsing - Long Significand with Exponent", "subject": "1800000013640079D9E0F9763ADA429D0200000000583000", "string": "1.2345689012345789012345E+34", "to_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"12345689012345789012345E+12\"}}" }, { "description": "Non-Canonical Parsing - Positive Sign", "subject": "18000000136400F2AF967ED05C82DE3297FF6FDE3C403000", "string": "1234567890123456789012345678901234", "to_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"+1234567890123456789012345678901234\"}}" }, { "description": "Non-Canonical Parsing - Long Decimal String", "subject": "180000001364000100000000000000000000000000722800", "string": "1E-999", "to_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \".000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001\"}}" }, { "description": "Non-Canonical Parsing - nan", "subject": "180000001364000000000000000000000000000000007C00", "string": "NaN", "to_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"nan\"}}" }, { "description": "Non-Canonical Parsing - nAn", "subject": "180000001364000000000000000000000000000000007C00", "string": "NaN", "to_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"nAn\"}}" }, { "description": "Non-Canonical Parsing - +infinity", "subject": "180000001364000000000000000000000000000000007800", "string": "Infinity", "to_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"+infinity\"}}" }, { "description": "Non-Canonical Parsing - infinity", "subject": "180000001364000000000000000000000000000000007800", "string": "Infinity", "to_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"infinity\"}}" }, { "description": "Non-Canonical Parsing - infiniTY", "subject": "180000001364000000000000000000000000000000007800", "string": "Infinity", "to_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"infiniTY\"}}" }, { "description": "Non-Canonical Parsing - inf", "subject": "180000001364000000000000000000000000000000007800", "string": "Infinity", "to_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"inf\"}}" }, { "description": "Non-Canonical Parsing - inF", "subject": "180000001364000000000000000000000000000000007800", "string": "Infinity", "to_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"inF\"}}" }, { "description": "Non-Canonical Parsing - -infinity", "subject": "18000000136400000000000000000000000000000000F800", "string": "-Infinity", "to_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"-infinity\"}}" }, { "description": "Non-Canonical Parsing - -infiniTy", "subject": "18000000136400000000000000000000000000000000F800", "string": "-Infinity", "to_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"-infiniTy\"}}" }, { "description": "Non-Canonical Parsing - -Inf", "subject": "18000000136400000000000000000000000000000000F800", "string": "-Infinity", "to_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"-Infinity\"}}" }, { "description": "Non-Canonical Parsing - -inf", "subject": "18000000136400000000000000000000000000000000F800", "string": "-Infinity", "to_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"-inf\"}}" }, { "description": "Non-Canonical Parsing - -inF", "subject": "18000000136400000000000000000000000000000000F800", "string": "-Infinity", "to_extjson": false, "extjson": "{\"d\" : {\"$numberDecimal\" : \"-inF\"}}" }, { "description": "Rounded Subnormal number", "subject": "180000001364000100000000000000000000000000000000", "string": "10E-6177", "match_string": "1E-6176" }, { "description": "Clamped", "subject": "180000001364000a00000000000000000000000000fe5f00", "string": "1E6112", "match_string": "1.0E+6112" }, { "description": "Exact rounding", "subject": "18000000136400000000000a5bc138938d44c64d31cc3700", "string": "1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "match_string": "1.000000000000000000000000000000000E+999" } ] } bson-4.3.0/spec/support/driver-spec-tests/decimal128/decimal128-7.json0000644000004100000410000003113713236361476025301 0ustar www-datawww-data{ "description": "Decimal128", "bson_type": "0x13", "test_key": "d", "parseErrors": [ { "description": "[basx572] Near-specials (Conversion_syntax)", "subject": "-9Inf" }, { "description": "[basx516] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "-1-" }, { "description": "[basx533] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "0000.." }, { "description": "[basx534] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": ".0000." }, { "description": "[basx535] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "00..00" }, { "description": "[basx569] Near-specials (Conversion_syntax)", "subject": "0Inf" }, { "description": "[basx571] Near-specials (Conversion_syntax)", "subject": "-0Inf" }, { "description": "[basx575] Near-specials (Conversion_syntax)", "subject": "0sNaN" }, { "description": "[basx503] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "++1" }, { "description": "[basx504] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "--1" }, { "description": "[basx505] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "-+1" }, { "description": "[basx506] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "+-1" }, { "description": "[basx510] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": " +1" }, { "description": "[basx513] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": " + 1" }, { "description": "[basx514] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": " - 1" }, { "description": "[basx501] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "." }, { "description": "[basx502] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": ".." }, { "description": "[basx519] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "" }, { "description": "[basx525] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "e100" }, { "description": "[basx549] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "e+1" }, { "description": "[basx577] some baddies with dots and Es and dots and specials (Conversion_syntax)", "subject": ".e+1" }, { "description": "[basx578] some baddies with dots and Es and dots and specials (Conversion_syntax)", "subject": "+.e+1" }, { "description": "[basx581] some baddies with dots and Es and dots and specials (Conversion_syntax)", "subject": "E+1" }, { "description": "[basx582] some baddies with dots and Es and dots and specials (Conversion_syntax)", "subject": ".E+1" }, { "description": "[basx583] some baddies with dots and Es and dots and specials (Conversion_syntax)", "subject": "+.E+1" }, { "description": "[basx579] some baddies with dots and Es and dots and specials (Conversion_syntax)", "subject": "-.e+" }, { "description": "[basx580] some baddies with dots and Es and dots and specials (Conversion_syntax)", "subject": "-.e" }, { "description": "[basx584] some baddies with dots and Es and dots and specials (Conversion_syntax)", "subject": "-.E+" }, { "description": "[basx585] some baddies with dots and Es and dots and specials (Conversion_syntax)", "subject": "-.E" }, { "description": "[basx589] some baddies with dots and Es and dots and specials (Conversion_syntax)", "subject": "+.Inf" }, { "description": "[basx586] some baddies with dots and Es and dots and specials (Conversion_syntax)", "subject": ".NaN" }, { "description": "[basx587] some baddies with dots and Es and dots and specials (Conversion_syntax)", "subject": "-.NaN" }, { "description": "[basx545] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "ONE" }, { "description": "[basx561] Near-specials (Conversion_syntax)", "subject": "qNaN" }, { "description": "[basx573] Near-specials (Conversion_syntax)", "subject": "-sNa" }, { "description": "[basx588] some baddies with dots and Es and dots and specials (Conversion_syntax)", "subject": "+.sNaN" }, { "description": "[basx544] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "ten" }, { "description": "[basx527] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "u0b65" }, { "description": "[basx526] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "u0e5a" }, { "description": "[basx515] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "x" }, { "description": "[basx574] Near-specials (Conversion_syntax)", "subject": "xNaN" }, { "description": "[basx530] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": ".123.5" }, { "description": "[basx500] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "1..2" }, { "description": "[basx542] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "1e1.0" }, { "description": "[basx553] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "1E+1.2.3" }, { "description": "[basx543] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "1e123e" }, { "description": "[basx552] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "1E+1.2" }, { "description": "[basx546] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "1e.1" }, { "description": "[basx547] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "1e1." }, { "description": "[basx554] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "1E++1" }, { "description": "[basx555] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "1E--1" }, { "description": "[basx556] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "1E+-1" }, { "description": "[basx557] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "1E-+1" }, { "description": "[basx558] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "1E'1" }, { "description": "[basx559] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "1E\"1" }, { "description": "[basx520] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "1e-" }, { "description": "[basx560] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "1E" }, { "description": "[basx548] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "1ee" }, { "description": "[basx551] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "1.2.1" }, { "description": "[basx550] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "1.23.4" }, { "description": "[basx529] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "1.34.5" }, { "description": "[basx531] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "01.35." }, { "description": "[basx532] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "01.35-" }, { "description": "[basx518] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "3+" }, { "description": "[basx521] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "7e99999a" }, { "description": "[basx570] Near-specials (Conversion_syntax)", "subject": "9Inf" }, { "description": "[basx512] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "12 " }, { "description": "[basx517] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "12-" }, { "description": "[basx507] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "12e" }, { "description": "[basx508] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "12e++" }, { "description": "[basx509] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "12f4" }, { "description": "[basx536] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "111e*123" }, { "description": "[basx537] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "111e123-" }, { "description": "[basx540] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "111e1*23" }, { "description": "[basx538] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "111e+12+" }, { "description": "[basx539] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "111e1-3-" }, { "description": "[basx541] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "111E1e+3" }, { "description": "[basx528] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "123,65" }, { "description": "[basx523] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "7e12356789012x" }, { "description": "[basx522] The 'baddies' tests from DiagBigDecimal, plus some new ones (Conversion_syntax)", "subject": "7e123567890x" } ] } bson-4.3.0/spec/support/driver-spec-tests/decimal128/decimal128-3.json0000644000004100000410000017541613236361476025306 0ustar www-datawww-data{ "description": "Decimal128", "bson_type": "0x13", "test_key": "d", "valid": [ { "description": "[basx066] strings without E cannot generate E in result", "subject": "18000000136400185C0ACE0000000000000000000038B000", "string": "-00345678.5432", "match_string": "-345678.5432" }, { "description": "[basx065] strings without E cannot generate E in result", "subject": "18000000136400185C0ACE0000000000000000000038B000", "string": "-0345678.5432", "match_string": "-345678.5432" }, { "description": "[basx064] strings without E cannot generate E in result", "subject": "18000000136400185C0ACE0000000000000000000038B000", "string": "-345678.5432" }, { "description": "[basx041] strings without E cannot generate E in result", "subject": "180000001364004C0000000000000000000000000040B000", "string": "-76" }, { "description": "[basx027] conform to rules and exponent will be in permitted range).", "subject": "180000001364000F270000000000000000000000003AB000", "string": "-9.999" }, { "description": "[basx026] conform to rules and exponent will be in permitted range).", "subject": "180000001364009F230000000000000000000000003AB000", "string": "-9.119" }, { "description": "[basx025] conform to rules and exponent will be in permitted range).", "subject": "180000001364008F030000000000000000000000003CB000", "string": "-9.11" }, { "description": "[basx024] conform to rules and exponent will be in permitted range).", "subject": "180000001364005B000000000000000000000000003EB000", "string": "-9.1" }, { "description": "[dqbsr531] negatives (Rounded)", "subject": "1800000013640099761CC7B548F377DC80A131C836FEAF00", "string": "-1.1111111111111111111111111111123450", "match_string": "-1.111111111111111111111111111112345" }, { "description": "[basx022] conform to rules and exponent will be in permitted range).", "subject": "180000001364000A000000000000000000000000003EB000", "string": "-1.0" }, { "description": "[basx021] conform to rules and exponent will be in permitted range).", "subject": "18000000136400010000000000000000000000000040B000", "string": "-1" }, { "description": "[basx601] Zeros", "subject": "1800000013640000000000000000000000000000002E3000", "string": "0.000000000", "match_string": "0E-9" }, { "description": "[basx622] Zeros", "subject": "1800000013640000000000000000000000000000002EB000", "string": "-0.000000000", "match_string": "-0E-9" }, { "description": "[basx602] Zeros", "subject": "180000001364000000000000000000000000000000303000", "string": "0.00000000", "match_string": "0E-8" }, { "description": "[basx621] Zeros", "subject": "18000000136400000000000000000000000000000030B000", "string": "-0.00000000", "match_string": "-0E-8" }, { "description": "[basx603] Zeros", "subject": "180000001364000000000000000000000000000000323000", "string": "0.0000000", "match_string": "0E-7" }, { "description": "[basx620] Zeros", "subject": "18000000136400000000000000000000000000000032B000", "string": "-0.0000000", "match_string": "-0E-7" }, { "description": "[basx604] Zeros", "subject": "180000001364000000000000000000000000000000343000", "string": "0.000000" }, { "description": "[basx619] Zeros", "subject": "18000000136400000000000000000000000000000034B000", "string": "-0.000000" }, { "description": "[basx605] Zeros", "subject": "180000001364000000000000000000000000000000363000", "string": "0.00000" }, { "description": "[basx618] Zeros", "subject": "18000000136400000000000000000000000000000036B000", "string": "-0.00000" }, { "description": "[basx680] Zeros", "subject": "180000001364000000000000000000000000000000403000", "string": "000000.", "match_string": "0" }, { "description": "[basx606] Zeros", "subject": "180000001364000000000000000000000000000000383000", "string": "0.0000" }, { "description": "[basx617] Zeros", "subject": "18000000136400000000000000000000000000000038B000", "string": "-0.0000" }, { "description": "[basx681] Zeros", "subject": "180000001364000000000000000000000000000000403000", "string": "00000.", "match_string": "0" }, { "description": "[basx686] Zeros", "subject": "180000001364000000000000000000000000000000403000", "string": "+00000.", "match_string": "0" }, { "description": "[basx687] Zeros", "subject": "18000000136400000000000000000000000000000040B000", "string": "-00000.", "match_string": "-0" }, { "description": "[basx019] conform to rules and exponent will be in permitted range).", "subject": "1800000013640000000000000000000000000000003CB000", "string": "-00.00", "match_string": "-0.00" }, { "description": "[basx607] Zeros", "subject": "1800000013640000000000000000000000000000003A3000", "string": "0.000" }, { "description": "[basx616] Zeros", "subject": "1800000013640000000000000000000000000000003AB000", "string": "-0.000" }, { "description": "[basx682] Zeros", "subject": "180000001364000000000000000000000000000000403000", "string": "0000.", "match_string": "0" }, { "description": "[basx155] Numbers with E", "subject": "1800000013640000000000000000000000000000003A3000", "string": "0.000e+0", "match_string": "0.000" }, { "description": "[basx130] Numbers with E", "subject": "180000001364000000000000000000000000000000383000", "string": "0.000E-1", "match_string": "0.0000" }, { "description": "[basx290] some more negative zeros [systematic tests below]", "subject": "18000000136400000000000000000000000000000038B000", "string": "-0.000E-1", "match_string": "-0.0000" }, { "description": "[basx131] Numbers with E", "subject": "180000001364000000000000000000000000000000363000", "string": "0.000E-2", "match_string": "0.00000" }, { "description": "[basx291] some more negative zeros [systematic tests below]", "subject": "18000000136400000000000000000000000000000036B000", "string": "-0.000E-2", "match_string": "-0.00000" }, { "description": "[basx132] Numbers with E", "subject": "180000001364000000000000000000000000000000343000", "string": "0.000E-3", "match_string": "0.000000" }, { "description": "[basx292] some more negative zeros [systematic tests below]", "subject": "18000000136400000000000000000000000000000034B000", "string": "-0.000E-3", "match_string": "-0.000000" }, { "description": "[basx133] Numbers with E", "subject": "180000001364000000000000000000000000000000323000", "string": "0.000E-4", "match_string": "0E-7" }, { "description": "[basx293] some more negative zeros [systematic tests below]", "subject": "18000000136400000000000000000000000000000032B000", "string": "-0.000E-4", "match_string": "-0E-7" }, { "description": "[basx608] Zeros", "subject": "1800000013640000000000000000000000000000003C3000", "string": "0.00" }, { "description": "[basx615] Zeros", "subject": "1800000013640000000000000000000000000000003CB000", "string": "-0.00" }, { "description": "[basx683] Zeros", "subject": "180000001364000000000000000000000000000000403000", "string": "000.", "match_string": "0" }, { "description": "[basx630] Zeros", "subject": "1800000013640000000000000000000000000000003C3000", "string": "0.00E+0", "match_string": "0.00" }, { "description": "[basx670] Zeros", "subject": "1800000013640000000000000000000000000000003C3000", "string": "0.00E-0", "match_string": "0.00" }, { "description": "[basx631] Zeros", "subject": "1800000013640000000000000000000000000000003E3000", "string": "0.00E+1", "match_string": "0.0" }, { "description": "[basx671] Zeros", "subject": "1800000013640000000000000000000000000000003A3000", "string": "0.00E-1", "match_string": "0.000" }, { "description": "[basx134] Numbers with E", "subject": "180000001364000000000000000000000000000000383000", "string": "0.00E-2", "match_string": "0.0000" }, { "description": "[basx294] some more negative zeros [systematic tests below]", "subject": "18000000136400000000000000000000000000000038B000", "string": "-0.00E-2", "match_string": "-0.0000" }, { "description": "[basx632] Zeros", "subject": "180000001364000000000000000000000000000000403000", "string": "0.00E+2", "match_string": "0" }, { "description": "[basx672] Zeros", "subject": "180000001364000000000000000000000000000000383000", "string": "0.00E-2", "match_string": "0.0000" }, { "description": "[basx135] Numbers with E", "subject": "180000001364000000000000000000000000000000363000", "string": "0.00E-3", "match_string": "0.00000" }, { "description": "[basx295] some more negative zeros [systematic tests below]", "subject": "18000000136400000000000000000000000000000036B000", "string": "-0.00E-3", "match_string": "-0.00000" }, { "description": "[basx633] Zeros", "subject": "180000001364000000000000000000000000000000423000", "string": "0.00E+3", "match_string": "0E+1" }, { "description": "[basx673] Zeros", "subject": "180000001364000000000000000000000000000000363000", "string": "0.00E-3", "match_string": "0.00000" }, { "description": "[basx136] Numbers with E", "subject": "180000001364000000000000000000000000000000343000", "string": "0.00E-4", "match_string": "0.000000" }, { "description": "[basx674] Zeros", "subject": "180000001364000000000000000000000000000000343000", "string": "0.00E-4", "match_string": "0.000000" }, { "description": "[basx634] Zeros", "subject": "180000001364000000000000000000000000000000443000", "string": "0.00E+4", "match_string": "0E+2" }, { "description": "[basx137] Numbers with E", "subject": "180000001364000000000000000000000000000000323000", "string": "0.00E-5", "match_string": "0E-7" }, { "description": "[basx635] Zeros", "subject": "180000001364000000000000000000000000000000463000", "string": "0.00E+5", "match_string": "0E+3" }, { "description": "[basx675] Zeros", "subject": "180000001364000000000000000000000000000000323000", "string": "0.00E-5", "match_string": "0E-7" }, { "description": "[basx636] Zeros", "subject": "180000001364000000000000000000000000000000483000", "string": "0.00E+6", "match_string": "0E+4" }, { "description": "[basx676] Zeros", "subject": "180000001364000000000000000000000000000000303000", "string": "0.00E-6", "match_string": "0E-8" }, { "description": "[basx637] Zeros", "subject": "1800000013640000000000000000000000000000004A3000", "string": "0.00E+7", "match_string": "0E+5" }, { "description": "[basx677] Zeros", "subject": "1800000013640000000000000000000000000000002E3000", "string": "0.00E-7", "match_string": "0E-9" }, { "description": "[basx638] Zeros", "subject": "1800000013640000000000000000000000000000004C3000", "string": "0.00E+8", "match_string": "0E+6" }, { "description": "[basx678] Zeros", "subject": "1800000013640000000000000000000000000000002C3000", "string": "0.00E-8", "match_string": "0E-10" }, { "description": "[basx149] Numbers with E", "subject": "180000001364000000000000000000000000000000523000", "string": "000E+9", "match_string": "0E+9" }, { "description": "[basx639] Zeros", "subject": "1800000013640000000000000000000000000000004E3000", "string": "0.00E+9", "match_string": "0E+7" }, { "description": "[basx679] Zeros", "subject": "1800000013640000000000000000000000000000002A3000", "string": "0.00E-9", "match_string": "0E-11" }, { "description": "[basx063] strings without E cannot generate E in result", "subject": "18000000136400185C0ACE00000000000000000000383000", "string": "+00345678.5432", "match_string": "345678.5432" }, { "description": "[basx018] conform to rules and exponent will be in permitted range).", "subject": "1800000013640000000000000000000000000000003EB000", "string": "-0.0" }, { "description": "[basx609] Zeros", "subject": "1800000013640000000000000000000000000000003E3000", "string": "0.0" }, { "description": "[basx614] Zeros", "subject": "1800000013640000000000000000000000000000003EB000", "string": "-0.0" }, { "description": "[basx684] Zeros", "subject": "180000001364000000000000000000000000000000403000", "string": "00.", "match_string": "0" }, { "description": "[basx640] Zeros", "subject": "1800000013640000000000000000000000000000003E3000", "string": "0.0E+0", "match_string": "0.0" }, { "description": "[basx660] Zeros", "subject": "1800000013640000000000000000000000000000003E3000", "string": "0.0E-0", "match_string": "0.0" }, { "description": "[basx641] Zeros", "subject": "180000001364000000000000000000000000000000403000", "string": "0.0E+1", "match_string": "0" }, { "description": "[basx661] Zeros", "subject": "1800000013640000000000000000000000000000003C3000", "string": "0.0E-1", "match_string": "0.00" }, { "description": "[basx296] some more negative zeros [systematic tests below]", "subject": "1800000013640000000000000000000000000000003AB000", "string": "-0.0E-2", "match_string": "-0.000" }, { "description": "[basx642] Zeros", "subject": "180000001364000000000000000000000000000000423000", "string": "0.0E+2", "match_string": "0E+1" }, { "description": "[basx662] Zeros", "subject": "1800000013640000000000000000000000000000003A3000", "string": "0.0E-2", "match_string": "0.000" }, { "description": "[basx297] some more negative zeros [systematic tests below]", "subject": "18000000136400000000000000000000000000000038B000", "string": "-0.0E-3", "match_string": "-0.0000" }, { "description": "[basx643] Zeros", "subject": "180000001364000000000000000000000000000000443000", "string": "0.0E+3", "match_string": "0E+2" }, { "description": "[basx663] Zeros", "subject": "180000001364000000000000000000000000000000383000", "string": "0.0E-3", "match_string": "0.0000" }, { "description": "[basx644] Zeros", "subject": "180000001364000000000000000000000000000000463000", "string": "0.0E+4", "match_string": "0E+3" }, { "description": "[basx664] Zeros", "subject": "180000001364000000000000000000000000000000363000", "string": "0.0E-4", "match_string": "0.00000" }, { "description": "[basx645] Zeros", "subject": "180000001364000000000000000000000000000000483000", "string": "0.0E+5", "match_string": "0E+4" }, { "description": "[basx665] Zeros", "subject": "180000001364000000000000000000000000000000343000", "string": "0.0E-5", "match_string": "0.000000" }, { "description": "[basx646] Zeros", "subject": "1800000013640000000000000000000000000000004A3000", "string": "0.0E+6", "match_string": "0E+5" }, { "description": "[basx666] Zeros", "subject": "180000001364000000000000000000000000000000323000", "string": "0.0E-6", "match_string": "0E-7" }, { "description": "[basx647] Zeros", "subject": "1800000013640000000000000000000000000000004C3000", "string": "0.0E+7", "match_string": "0E+6" }, { "description": "[basx667] Zeros", "subject": "180000001364000000000000000000000000000000303000", "string": "0.0E-7", "match_string": "0E-8" }, { "description": "[basx648] Zeros", "subject": "1800000013640000000000000000000000000000004E3000", "string": "0.0E+8", "match_string": "0E+7" }, { "description": "[basx668] Zeros", "subject": "1800000013640000000000000000000000000000002E3000", "string": "0.0E-8", "match_string": "0E-9" }, { "description": "[basx160] Numbers with E", "subject": "180000001364000000000000000000000000000000523000", "string": "00E+9", "match_string": "0E+9" }, { "description": "[basx161] Numbers with E", "subject": "1800000013640000000000000000000000000000002E3000", "string": "00E-9", "match_string": "0E-9" }, { "description": "[basx649] Zeros", "subject": "180000001364000000000000000000000000000000503000", "string": "0.0E+9", "match_string": "0E+8" }, { "description": "[basx669] Zeros", "subject": "1800000013640000000000000000000000000000002C3000", "string": "0.0E-9", "match_string": "0E-10" }, { "description": "[basx062] strings without E cannot generate E in result", "subject": "18000000136400185C0ACE00000000000000000000383000", "string": "+0345678.5432", "match_string": "345678.5432" }, { "description": "[basx001] conform to rules and exponent will be in permitted range).", "subject": "180000001364000000000000000000000000000000403000", "string": "0" }, { "description": "[basx017] conform to rules and exponent will be in permitted range).", "subject": "18000000136400000000000000000000000000000040B000", "string": "-0" }, { "description": "[basx611] Zeros", "subject": "180000001364000000000000000000000000000000403000", "string": "0.", "match_string": "0" }, { "description": "[basx613] Zeros", "subject": "18000000136400000000000000000000000000000040B000", "string": "-0.", "match_string": "-0" }, { "description": "[basx685] Zeros", "subject": "180000001364000000000000000000000000000000403000", "string": "0.", "match_string": "0" }, { "description": "[basx688] Zeros", "subject": "180000001364000000000000000000000000000000403000", "string": "+0.", "match_string": "0" }, { "description": "[basx689] Zeros", "subject": "18000000136400000000000000000000000000000040B000", "string": "-0.", "match_string": "-0" }, { "description": "[basx650] Zeros", "subject": "180000001364000000000000000000000000000000403000", "string": "0E+0", "match_string": "0" }, { "description": "[basx651] Zeros", "subject": "180000001364000000000000000000000000000000423000", "string": "0E+1" }, { "description": "[basx298] some more negative zeros [systematic tests below]", "subject": "1800000013640000000000000000000000000000003CB000", "string": "-0E-2", "match_string": "-0.00" }, { "description": "[basx652] Zeros", "subject": "180000001364000000000000000000000000000000443000", "string": "0E+2" }, { "description": "[basx299] some more negative zeros [systematic tests below]", "subject": "1800000013640000000000000000000000000000003AB000", "string": "-0E-3", "match_string": "-0.000" }, { "description": "[basx653] Zeros", "subject": "180000001364000000000000000000000000000000463000", "string": "0E+3" }, { "description": "[basx654] Zeros", "subject": "180000001364000000000000000000000000000000483000", "string": "0E+4" }, { "description": "[basx655] Zeros", "subject": "1800000013640000000000000000000000000000004A3000", "string": "0E+5" }, { "description": "[basx656] Zeros", "subject": "1800000013640000000000000000000000000000004C3000", "string": "0E+6" }, { "description": "[basx657] Zeros", "subject": "1800000013640000000000000000000000000000004E3000", "string": "0E+7" }, { "description": "[basx658] Zeros", "subject": "180000001364000000000000000000000000000000503000", "string": "0E+8" }, { "description": "[basx138] Numbers with E", "subject": "180000001364000000000000000000000000000000523000", "string": "+0E+9", "match_string": "0E+9" }, { "description": "[basx139] Numbers with E", "subject": "18000000136400000000000000000000000000000052B000", "string": "-0E+9" }, { "description": "[basx144] Numbers with E", "subject": "180000001364000000000000000000000000000000523000", "string": "0E+9" }, { "description": "[basx154] Numbers with E", "subject": "180000001364000000000000000000000000000000523000", "string": "0E9", "match_string": "0E+9" }, { "description": "[basx659] Zeros", "subject": "180000001364000000000000000000000000000000523000", "string": "0E+9" }, { "description": "[basx042] strings without E cannot generate E in result", "subject": "18000000136400FC040000000000000000000000003C3000", "string": "+12.76", "match_string": "12.76" }, { "description": "[basx143] Numbers with E", "subject": "180000001364000100000000000000000000000000523000", "string": "+1E+009", "match_string": "1E+9" }, { "description": "[basx061] strings without E cannot generate E in result", "subject": "18000000136400185C0ACE00000000000000000000383000", "string": "+345678.5432", "match_string": "345678.5432" }, { "description": "[basx036] conform to rules and exponent will be in permitted range).", "subject": "1800000013640015CD5B0700000000000000000000203000", "string": "0.0000000123456789", "match_string": "1.23456789E-8" }, { "description": "[basx035] conform to rules and exponent will be in permitted range).", "subject": "1800000013640015CD5B0700000000000000000000223000", "string": "0.000000123456789", "match_string": "1.23456789E-7" }, { "description": "[basx034] conform to rules and exponent will be in permitted range).", "subject": "1800000013640015CD5B0700000000000000000000243000", "string": "0.00000123456789" }, { "description": "[basx053] strings without E cannot generate E in result", "subject": "180000001364003200000000000000000000000000323000", "string": "0.0000050" }, { "description": "[basx033] conform to rules and exponent will be in permitted range).", "subject": "1800000013640015CD5B0700000000000000000000263000", "string": "0.0000123456789" }, { "description": "[basx016] conform to rules and exponent will be in permitted range).", "subject": "180000001364000C000000000000000000000000003A3000", "string": "0.012" }, { "description": "[basx015] conform to rules and exponent will be in permitted range).", "subject": "180000001364007B000000000000000000000000003A3000", "string": "0.123" }, { "description": "[basx037] conform to rules and exponent will be in permitted range).", "subject": "1800000013640078DF0D8648700000000000000000223000", "string": "0.123456789012344" }, { "description": "[basx038] conform to rules and exponent will be in permitted range).", "subject": "1800000013640079DF0D8648700000000000000000223000", "string": "0.123456789012345" }, { "description": "[basx250] Numbers with E", "subject": "18000000136400F104000000000000000000000000383000", "string": "0.1265" }, { "description": "[basx257] Numbers with E", "subject": "18000000136400F104000000000000000000000000383000", "string": "0.1265E-0", "match_string": "0.1265" }, { "description": "[basx256] Numbers with E", "subject": "18000000136400F104000000000000000000000000363000", "string": "0.1265E-1", "match_string": "0.01265" }, { "description": "[basx258] Numbers with E", "subject": "18000000136400F1040000000000000000000000003A3000", "string": "0.1265E+1", "match_string": "1.265" }, { "description": "[basx251] Numbers with E", "subject": "18000000136400F104000000000000000000000000103000", "string": "0.1265E-20", "match_string": "1.265E-21" }, { "description": "[basx263] Numbers with E", "subject": "18000000136400F104000000000000000000000000603000", "string": "0.1265E+20", "match_string": "1.265E+19" }, { "description": "[basx255] Numbers with E", "subject": "18000000136400F104000000000000000000000000343000", "string": "0.1265E-2", "match_string": "0.001265" }, { "description": "[basx259] Numbers with E", "subject": "18000000136400F1040000000000000000000000003C3000", "string": "0.1265E+2", "match_string": "12.65" }, { "description": "[basx254] Numbers with E", "subject": "18000000136400F104000000000000000000000000323000", "string": "0.1265E-3", "match_string": "0.0001265" }, { "description": "[basx260] Numbers with E", "subject": "18000000136400F1040000000000000000000000003E3000", "string": "0.1265E+3", "match_string": "126.5" }, { "description": "[basx253] Numbers with E", "subject": "18000000136400F104000000000000000000000000303000", "string": "0.1265E-4", "match_string": "0.00001265" }, { "description": "[basx261] Numbers with E", "subject": "18000000136400F104000000000000000000000000403000", "string": "0.1265E+4", "match_string": "1265" }, { "description": "[basx252] Numbers with E", "subject": "18000000136400F104000000000000000000000000283000", "string": "0.1265E-8", "match_string": "1.265E-9" }, { "description": "[basx262] Numbers with E", "subject": "18000000136400F104000000000000000000000000483000", "string": "0.1265E+8", "match_string": "1.265E+7" }, { "description": "[basx159] Numbers with E", "subject": "1800000013640049000000000000000000000000002E3000", "string": "0.73e-7", "match_string": "7.3E-8" }, { "description": "[basx004] conform to rules and exponent will be in permitted range).", "subject": "1800000013640064000000000000000000000000003C3000", "string": "1.00" }, { "description": "[basx003] conform to rules and exponent will be in permitted range).", "subject": "180000001364000A000000000000000000000000003E3000", "string": "1.0" }, { "description": "[basx002] conform to rules and exponent will be in permitted range).", "subject": "180000001364000100000000000000000000000000403000", "string": "1" }, { "description": "[basx148] Numbers with E", "subject": "180000001364000100000000000000000000000000523000", "string": "1E+009", "match_string": "1E+9" }, { "description": "[basx153] Numbers with E", "subject": "180000001364000100000000000000000000000000523000", "string": "1E009", "match_string": "1E+9" }, { "description": "[basx141] Numbers with E", "subject": "180000001364000100000000000000000000000000523000", "string": "1e+09", "match_string": "1E+9" }, { "description": "[basx146] Numbers with E", "subject": "180000001364000100000000000000000000000000523000", "string": "1E+09", "match_string": "1E+9" }, { "description": "[basx151] Numbers with E", "subject": "180000001364000100000000000000000000000000523000", "string": "1e09", "match_string": "1E+9" }, { "description": "[basx142] Numbers with E", "subject": "180000001364000100000000000000000000000000F43000", "string": "1E+90" }, { "description": "[basx147] Numbers with E", "subject": "180000001364000100000000000000000000000000F43000", "string": "1e+90", "match_string": "1E+90" }, { "description": "[basx152] Numbers with E", "subject": "180000001364000100000000000000000000000000F43000", "string": "1E90", "match_string": "1E+90" }, { "description": "[basx140] Numbers with E", "subject": "180000001364000100000000000000000000000000523000", "string": "1E+9" }, { "description": "[basx150] Numbers with E", "subject": "180000001364000100000000000000000000000000523000", "string": "1E9", "match_string": "1E+9" }, { "description": "[basx014] conform to rules and exponent will be in permitted range).", "subject": "18000000136400D2040000000000000000000000003A3000", "string": "1.234" }, { "description": "[basx170] Numbers with E", "subject": "18000000136400F1040000000000000000000000003A3000", "string": "1.265" }, { "description": "[basx177] Numbers with E", "subject": "18000000136400F1040000000000000000000000003A3000", "string": "1.265E-0", "match_string": "1.265" }, { "description": "[basx176] Numbers with E", "subject": "18000000136400F104000000000000000000000000383000", "string": "1.265E-1", "match_string": "0.1265" }, { "description": "[basx178] Numbers with E", "subject": "18000000136400F1040000000000000000000000003C3000", "string": "1.265E+1", "match_string": "12.65" }, { "description": "[basx171] Numbers with E", "subject": "18000000136400F104000000000000000000000000123000", "string": "1.265E-20" }, { "description": "[basx183] Numbers with E", "subject": "18000000136400F104000000000000000000000000623000", "string": "1.265E+20" }, { "description": "[basx175] Numbers with E", "subject": "18000000136400F104000000000000000000000000363000", "string": "1.265E-2", "match_string": "0.01265" }, { "description": "[basx179] Numbers with E", "subject": "18000000136400F1040000000000000000000000003E3000", "string": "1.265E+2", "match_string": "126.5" }, { "description": "[basx174] Numbers with E", "subject": "18000000136400F104000000000000000000000000343000", "string": "1.265E-3", "match_string": "0.001265" }, { "description": "[basx180] Numbers with E", "subject": "18000000136400F104000000000000000000000000403000", "string": "1.265E+3", "match_string": "1265" }, { "description": "[basx173] Numbers with E", "subject": "18000000136400F104000000000000000000000000323000", "string": "1.265E-4", "match_string": "0.0001265" }, { "description": "[basx181] Numbers with E", "subject": "18000000136400F104000000000000000000000000423000", "string": "1.265E+4" }, { "description": "[basx172] Numbers with E", "subject": "18000000136400F1040000000000000000000000002A3000", "string": "1.265E-8" }, { "description": "[basx182] Numbers with E", "subject": "18000000136400F1040000000000000000000000004A3000", "string": "1.265E+8" }, { "description": "[basx157] Numbers with E", "subject": "180000001364000400000000000000000000000000523000", "string": "4E+9" }, { "description": "[basx067] examples", "subject": "180000001364000500000000000000000000000000343000", "string": "5E-6", "match_string": "0.000005" }, { "description": "[basx069] examples", "subject": "180000001364000500000000000000000000000000323000", "string": "5E-7" }, { "description": "[basx385] Engineering notation tests", "subject": "180000001364000700000000000000000000000000403000", "string": "7E0", "match_string": "7" }, { "description": "[basx365] Engineering notation tests", "subject": "180000001364000700000000000000000000000000543000", "string": "7E10", "match_string": "7E+10" }, { "description": "[basx405] Engineering notation tests", "subject": "1800000013640007000000000000000000000000002C3000", "string": "7E-10" }, { "description": "[basx363] Engineering notation tests", "subject": "180000001364000700000000000000000000000000563000", "string": "7E11", "match_string": "7E+11" }, { "description": "[basx407] Engineering notation tests", "subject": "1800000013640007000000000000000000000000002A3000", "string": "7E-11" }, { "description": "[basx361] Engineering notation tests", "subject": "180000001364000700000000000000000000000000583000", "string": "7E12", "match_string": "7E+12" }, { "description": "[basx409] Engineering notation tests", "subject": "180000001364000700000000000000000000000000283000", "string": "7E-12" }, { "description": "[basx411] Engineering notation tests", "subject": "180000001364000700000000000000000000000000263000", "string": "7E-13" }, { "description": "[basx383] Engineering notation tests", "subject": "180000001364000700000000000000000000000000423000", "string": "7E1", "match_string": "7E+1" }, { "description": "[basx387] Engineering notation tests", "subject": "1800000013640007000000000000000000000000003E3000", "string": "7E-1", "match_string": "0.7" }, { "description": "[basx381] Engineering notation tests", "subject": "180000001364000700000000000000000000000000443000", "string": "7E2", "match_string": "7E+2" }, { "description": "[basx389] Engineering notation tests", "subject": "1800000013640007000000000000000000000000003C3000", "string": "7E-2", "match_string": "0.07" }, { "description": "[basx379] Engineering notation tests", "subject": "180000001364000700000000000000000000000000463000", "string": "7E3", "match_string": "7E+3" }, { "description": "[basx391] Engineering notation tests", "subject": "1800000013640007000000000000000000000000003A3000", "string": "7E-3", "match_string": "0.007" }, { "description": "[basx377] Engineering notation tests", "subject": "180000001364000700000000000000000000000000483000", "string": "7E4", "match_string": "7E+4" }, { "description": "[basx393] Engineering notation tests", "subject": "180000001364000700000000000000000000000000383000", "string": "7E-4", "match_string": "0.0007" }, { "description": "[basx375] Engineering notation tests", "subject": "1800000013640007000000000000000000000000004A3000", "string": "7E5", "match_string": "7E+5" }, { "description": "[basx395] Engineering notation tests", "subject": "180000001364000700000000000000000000000000363000", "string": "7E-5", "match_string": "0.00007" }, { "description": "[basx373] Engineering notation tests", "subject": "1800000013640007000000000000000000000000004C3000", "string": "7E6", "match_string": "7E+6" }, { "description": "[basx397] Engineering notation tests", "subject": "180000001364000700000000000000000000000000343000", "string": "7E-6", "match_string": "0.000007" }, { "description": "[basx371] Engineering notation tests", "subject": "1800000013640007000000000000000000000000004E3000", "string": "7E7", "match_string": "7E+7" }, { "description": "[basx399] Engineering notation tests", "subject": "180000001364000700000000000000000000000000323000", "string": "7E-7" }, { "description": "[basx369] Engineering notation tests", "subject": "180000001364000700000000000000000000000000503000", "string": "7E8", "match_string": "7E+8" }, { "description": "[basx401] Engineering notation tests", "subject": "180000001364000700000000000000000000000000303000", "string": "7E-8" }, { "description": "[basx367] Engineering notation tests", "subject": "180000001364000700000000000000000000000000523000", "string": "7E9", "match_string": "7E+9" }, { "description": "[basx403] Engineering notation tests", "subject": "1800000013640007000000000000000000000000002E3000", "string": "7E-9" }, { "description": "[basx007] conform to rules and exponent will be in permitted range).", "subject": "1800000013640064000000000000000000000000003E3000", "string": "10.0" }, { "description": "[basx005] conform to rules and exponent will be in permitted range).", "subject": "180000001364000A00000000000000000000000000403000", "string": "10" }, { "description": "[basx165] Numbers with E", "subject": "180000001364000A00000000000000000000000000523000", "string": "10E+009", "match_string": "1.0E+10" }, { "description": "[basx163] Numbers with E", "subject": "180000001364000A00000000000000000000000000523000", "string": "10E+09", "match_string": "1.0E+10" }, { "description": "[basx325] Engineering notation tests", "subject": "180000001364000A00000000000000000000000000403000", "string": "10e0", "match_string": "10" }, { "description": "[basx305] Engineering notation tests", "subject": "180000001364000A00000000000000000000000000543000", "string": "10e10", "match_string": "1.0E+11" }, { "description": "[basx345] Engineering notation tests", "subject": "180000001364000A000000000000000000000000002C3000", "string": "10e-10", "match_string": "1.0E-9" }, { "description": "[basx303] Engineering notation tests", "subject": "180000001364000A00000000000000000000000000563000", "string": "10e11", "match_string": "1.0E+12" }, { "description": "[basx347] Engineering notation tests", "subject": "180000001364000A000000000000000000000000002A3000", "string": "10e-11", "match_string": "1.0E-10" }, { "description": "[basx301] Engineering notation tests", "subject": "180000001364000A00000000000000000000000000583000", "string": "10e12", "match_string": "1.0E+13" }, { "description": "[basx349] Engineering notation tests", "subject": "180000001364000A00000000000000000000000000283000", "string": "10e-12", "match_string": "1.0E-11" }, { "description": "[basx351] Engineering notation tests", "subject": "180000001364000A00000000000000000000000000263000", "string": "10e-13", "match_string": "1.0E-12" }, { "description": "[basx323] Engineering notation tests", "subject": "180000001364000A00000000000000000000000000423000", "string": "10e1", "match_string": "1.0E+2" }, { "description": "[basx327] Engineering notation tests", "subject": "180000001364000A000000000000000000000000003E3000", "string": "10e-1", "match_string": "1.0" }, { "description": "[basx321] Engineering notation tests", "subject": "180000001364000A00000000000000000000000000443000", "string": "10e2", "match_string": "1.0E+3" }, { "description": "[basx329] Engineering notation tests", "subject": "180000001364000A000000000000000000000000003C3000", "string": "10e-2", "match_string": "0.10" }, { "description": "[basx319] Engineering notation tests", "subject": "180000001364000A00000000000000000000000000463000", "string": "10e3", "match_string": "1.0E+4" }, { "description": "[basx331] Engineering notation tests", "subject": "180000001364000A000000000000000000000000003A3000", "string": "10e-3", "match_string": "0.010" }, { "description": "[basx317] Engineering notation tests", "subject": "180000001364000A00000000000000000000000000483000", "string": "10e4", "match_string": "1.0E+5" }, { "description": "[basx333] Engineering notation tests", "subject": "180000001364000A00000000000000000000000000383000", "string": "10e-4", "match_string": "0.0010" }, { "description": "[basx315] Engineering notation tests", "subject": "180000001364000A000000000000000000000000004A3000", "string": "10e5", "match_string": "1.0E+6" }, { "description": "[basx335] Engineering notation tests", "subject": "180000001364000A00000000000000000000000000363000", "string": "10e-5", "match_string": "0.00010" }, { "description": "[basx313] Engineering notation tests", "subject": "180000001364000A000000000000000000000000004C3000", "string": "10e6", "match_string": "1.0E+7" }, { "description": "[basx337] Engineering notation tests", "subject": "180000001364000A00000000000000000000000000343000", "string": "10e-6", "match_string": "0.000010" }, { "description": "[basx311] Engineering notation tests", "subject": "180000001364000A000000000000000000000000004E3000", "string": "10e7", "match_string": "1.0E+8" }, { "description": "[basx339] Engineering notation tests", "subject": "180000001364000A00000000000000000000000000323000", "string": "10e-7", "match_string": "0.0000010" }, { "description": "[basx309] Engineering notation tests", "subject": "180000001364000A00000000000000000000000000503000", "string": "10e8", "match_string": "1.0E+9" }, { "description": "[basx341] Engineering notation tests", "subject": "180000001364000A00000000000000000000000000303000", "string": "10e-8", "match_string": "1.0E-7" }, { "description": "[basx164] Numbers with E", "subject": "180000001364000A00000000000000000000000000F43000", "string": "10e+90", "match_string": "1.0E+91" }, { "description": "[basx162] Numbers with E", "subject": "180000001364000A00000000000000000000000000523000", "string": "10E+9", "match_string": "1.0E+10" }, { "description": "[basx307] Engineering notation tests", "subject": "180000001364000A00000000000000000000000000523000", "string": "10e9", "match_string": "1.0E+10" }, { "description": "[basx343] Engineering notation tests", "subject": "180000001364000A000000000000000000000000002E3000", "string": "10e-9", "match_string": "1.0E-8" }, { "description": "[basx008] conform to rules and exponent will be in permitted range).", "subject": "1800000013640065000000000000000000000000003E3000", "string": "10.1" }, { "description": "[basx009] conform to rules and exponent will be in permitted range).", "subject": "1800000013640068000000000000000000000000003E3000", "string": "10.4" }, { "description": "[basx010] conform to rules and exponent will be in permitted range).", "subject": "1800000013640069000000000000000000000000003E3000", "string": "10.5" }, { "description": "[basx011] conform to rules and exponent will be in permitted range).", "subject": "180000001364006A000000000000000000000000003E3000", "string": "10.6" }, { "description": "[basx012] conform to rules and exponent will be in permitted range).", "subject": "180000001364006D000000000000000000000000003E3000", "string": "10.9" }, { "description": "[basx013] conform to rules and exponent will be in permitted range).", "subject": "180000001364006E000000000000000000000000003E3000", "string": "11.0" }, { "description": "[basx040] strings without E cannot generate E in result", "subject": "180000001364000C00000000000000000000000000403000", "string": "12" }, { "description": "[basx190] Numbers with E", "subject": "18000000136400F1040000000000000000000000003C3000", "string": "12.65" }, { "description": "[basx197] Numbers with E", "subject": "18000000136400F1040000000000000000000000003C3000", "string": "12.65E-0", "match_string": "12.65" }, { "description": "[basx196] Numbers with E", "subject": "18000000136400F1040000000000000000000000003A3000", "string": "12.65E-1", "match_string": "1.265" }, { "description": "[basx198] Numbers with E", "subject": "18000000136400F1040000000000000000000000003E3000", "string": "12.65E+1", "match_string": "126.5" }, { "description": "[basx191] Numbers with E", "subject": "18000000136400F104000000000000000000000000143000", "string": "12.65E-20", "match_string": "1.265E-19" }, { "description": "[basx203] Numbers with E", "subject": "18000000136400F104000000000000000000000000643000", "string": "12.65E+20", "match_string": "1.265E+21" }, { "description": "[basx195] Numbers with E", "subject": "18000000136400F104000000000000000000000000383000", "string": "12.65E-2", "match_string": "0.1265" }, { "description": "[basx199] Numbers with E", "subject": "18000000136400F104000000000000000000000000403000", "string": "12.65E+2", "match_string": "1265" }, { "description": "[basx194] Numbers with E", "subject": "18000000136400F104000000000000000000000000363000", "string": "12.65E-3", "match_string": "0.01265" }, { "description": "[basx200] Numbers with E", "subject": "18000000136400F104000000000000000000000000423000", "string": "12.65E+3", "match_string": "1.265E+4" }, { "description": "[basx193] Numbers with E", "subject": "18000000136400F104000000000000000000000000343000", "string": "12.65E-4", "match_string": "0.001265" }, { "description": "[basx201] Numbers with E", "subject": "18000000136400F104000000000000000000000000443000", "string": "12.65E+4", "match_string": "1.265E+5" }, { "description": "[basx192] Numbers with E", "subject": "18000000136400F1040000000000000000000000002C3000", "string": "12.65E-8", "match_string": "1.265E-7" }, { "description": "[basx202] Numbers with E", "subject": "18000000136400F1040000000000000000000000004C3000", "string": "12.65E+8", "match_string": "1.265E+9" }, { "description": "[basx044] strings without E cannot generate E in result", "subject": "18000000136400FC040000000000000000000000003C3000", "string": "012.76", "match_string": "12.76" }, { "description": "[basx042] strings without E cannot generate E in result", "subject": "18000000136400FC040000000000000000000000003C3000", "string": "12.76" }, { "description": "[basx046] strings without E cannot generate E in result", "subject": "180000001364001100000000000000000000000000403000", "string": "17.", "match_string": "17" }, { "description": "[basx049] strings without E cannot generate E in result", "subject": "180000001364002C00000000000000000000000000403000", "string": "0044", "match_string": "44" }, { "description": "[basx048] strings without E cannot generate E in result", "subject": "180000001364002C00000000000000000000000000403000", "string": "044", "match_string": "44" }, { "description": "[basx158] Numbers with E", "subject": "180000001364002C00000000000000000000000000523000", "string": "44E+9", "match_string": "4.4E+10" }, { "description": "[basx068] examples", "subject": "180000001364003200000000000000000000000000323000", "string": "50E-7", "match_string": "0.0000050" }, { "description": "[basx169] Numbers with E", "subject": "180000001364006400000000000000000000000000523000", "string": "100e+009", "match_string": "1.00E+11" }, { "description": "[basx167] Numbers with E", "subject": "180000001364006400000000000000000000000000523000", "string": "100e+09", "match_string": "1.00E+11" }, { "description": "[basx168] Numbers with E", "subject": "180000001364006400000000000000000000000000F43000", "string": "100E+90", "match_string": "1.00E+92" }, { "description": "[basx166] Numbers with E", "subject": "180000001364006400000000000000000000000000523000", "string": "100e+9", "match_string": "1.00E+11" }, { "description": "[basx210] Numbers with E", "subject": "18000000136400F1040000000000000000000000003E3000", "string": "126.5" }, { "description": "[basx217] Numbers with E", "subject": "18000000136400F1040000000000000000000000003E3000", "string": "126.5E-0", "match_string": "126.5" }, { "description": "[basx216] Numbers with E", "subject": "18000000136400F1040000000000000000000000003C3000", "string": "126.5E-1", "match_string": "12.65" }, { "description": "[basx218] Numbers with E", "subject": "18000000136400F104000000000000000000000000403000", "string": "126.5E+1", "match_string": "1265" }, { "description": "[basx211] Numbers with E", "subject": "18000000136400F104000000000000000000000000163000", "string": "126.5E-20", "match_string": "1.265E-18" }, { "description": "[basx223] Numbers with E", "subject": "18000000136400F104000000000000000000000000663000", "string": "126.5E+20", "match_string": "1.265E+22" }, { "description": "[basx215] Numbers with E", "subject": "18000000136400F1040000000000000000000000003A3000", "string": "126.5E-2", "match_string": "1.265" }, { "description": "[basx219] Numbers with E", "subject": "18000000136400F104000000000000000000000000423000", "string": "126.5E+2", "match_string": "1.265E+4" }, { "description": "[basx214] Numbers with E", "subject": "18000000136400F104000000000000000000000000383000", "string": "126.5E-3", "match_string": "0.1265" }, { "description": "[basx220] Numbers with E", "subject": "18000000136400F104000000000000000000000000443000", "string": "126.5E+3", "match_string": "1.265E+5" }, { "description": "[basx213] Numbers with E", "subject": "18000000136400F104000000000000000000000000363000", "string": "126.5E-4", "match_string": "0.01265" }, { "description": "[basx221] Numbers with E", "subject": "18000000136400F104000000000000000000000000463000", "string": "126.5E+4", "match_string": "1.265E+6" }, { "description": "[basx212] Numbers with E", "subject": "18000000136400F1040000000000000000000000002E3000", "string": "126.5E-8", "match_string": "0.000001265" }, { "description": "[basx222] Numbers with E", "subject": "18000000136400F1040000000000000000000000004E3000", "string": "126.5E+8", "match_string": "1.265E+10" }, { "description": "[basx006] conform to rules and exponent will be in permitted range).", "subject": "18000000136400E803000000000000000000000000403000", "string": "1000" }, { "description": "[basx230] Numbers with E", "subject": "18000000136400F104000000000000000000000000403000", "string": "1265" }, { "description": "[basx237] Numbers with E", "subject": "18000000136400F104000000000000000000000000403000", "string": "1265E-0", "match_string": "1265" }, { "description": "[basx236] Numbers with E", "subject": "18000000136400F1040000000000000000000000003E3000", "string": "1265E-1", "match_string": "126.5" }, { "description": "[basx238] Numbers with E", "subject": "18000000136400F104000000000000000000000000423000", "string": "1265E+1", "match_string": "1.265E+4" }, { "description": "[basx231] Numbers with E", "subject": "18000000136400F104000000000000000000000000183000", "string": "1265E-20", "match_string": "1.265E-17" }, { "description": "[basx243] Numbers with E", "subject": "18000000136400F104000000000000000000000000683000", "string": "1265E+20", "match_string": "1.265E+23" }, { "description": "[basx235] Numbers with E", "subject": "18000000136400F1040000000000000000000000003C3000", "string": "1265E-2", "match_string": "12.65" }, { "description": "[basx239] Numbers with E", "subject": "18000000136400F104000000000000000000000000443000", "string": "1265E+2", "match_string": "1.265E+5" }, { "description": "[basx234] Numbers with E", "subject": "18000000136400F1040000000000000000000000003A3000", "string": "1265E-3", "match_string": "1.265" }, { "description": "[basx240] Numbers with E", "subject": "18000000136400F104000000000000000000000000463000", "string": "1265E+3", "match_string": "1.265E+6" }, { "description": "[basx233] Numbers with E", "subject": "18000000136400F104000000000000000000000000383000", "string": "1265E-4", "match_string": "0.1265" }, { "description": "[basx241] Numbers with E", "subject": "18000000136400F104000000000000000000000000483000", "string": "1265E+4", "match_string": "1.265E+7" }, { "description": "[basx232] Numbers with E", "subject": "18000000136400F104000000000000000000000000303000", "string": "1265E-8", "match_string": "0.00001265" }, { "description": "[basx242] Numbers with E", "subject": "18000000136400F104000000000000000000000000503000", "string": "1265E+8", "match_string": "1.265E+11" }, { "description": "[basx060] strings without E cannot generate E in result", "subject": "18000000136400185C0ACE00000000000000000000383000", "string": "345678.5432" }, { "description": "[basx059] strings without E cannot generate E in result", "subject": "18000000136400F198670C08000000000000000000363000", "string": "0345678.54321", "match_string": "345678.54321" }, { "description": "[basx058] strings without E cannot generate E in result", "subject": "180000001364006AF90B7C50000000000000000000343000", "string": "345678.543210" }, { "description": "[basx057] strings without E cannot generate E in result", "subject": "180000001364006A19562522020000000000000000343000", "string": "2345678.543210" }, { "description": "[basx056] strings without E cannot generate E in result", "subject": "180000001364006AB9C8733A0B0000000000000000343000", "string": "12345678.543210" }, { "description": "[basx031] conform to rules and exponent will be in permitted range).", "subject": "1800000013640040AF0D8648700000000000000000343000", "string": "123456789.000000" }, { "description": "[basx030] conform to rules and exponent will be in permitted range).", "subject": "1800000013640080910F8648700000000000000000343000", "string": "123456789.123456" }, { "description": "[basx032] conform to rules and exponent will be in permitted range).", "subject": "1800000013640080910F8648700000000000000000403000", "string": "123456789123456" } ] } bson-4.3.0/spec/support/shared_examples.rb0000644000004100000410000000637513236361476020674 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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. shared_examples_for "a binary encoded string" do let(:binary_encoding) do Encoding.find(BSON::BINARY) end unless RUBY_VERSION < "1.9" it "returns the string with binary encoding" do expect(encoded.encoding).to eq(binary_encoding) end end end shared_examples_for "a bson element" do let(:element) do defined?(obj) ? obj : described_class.new end it "has the correct single byte BSON type" do expect(element.bson_type).to eq(type) end end shared_examples_for "a serializable bson element" do it "serializes to bson" do expect(obj.to_bson.to_s).to eq(bson) end end shared_examples_for "a deserializable bson element" do let(:io) do BSON::ByteBuffer.new(bson) end let(:result) do (defined?(klass) ? klass : described_class).from_bson(io) end it "deserializes from bson" do expect(result).to eq(obj) end end shared_examples_for "a JSON serializable object" do it "serializes the JSON from #as_json" do expect(object.to_json).to eq(object.as_json.to_json) end end shared_examples_for "immutable when frozen" do |block| context "when the document is frozen" do before do doc.freeze end it "raises a runtime error" do expect { block.call(doc) }.to raise_error(RuntimeError) end end end shared_examples_for "a document able to handle utf-8" do it "serializes and deserializes properly" do expect( BSON::Document.from_bson(BSON::ByteBuffer.new(document.to_bson.to_s)) ).to eq(document) end end shared_examples_for "a class which converts to Time" do it "shares BSON type with Time" do expect(described_class.new.bson_type).to eq(Time::BSON_TYPE) end end shared_examples_for "a validated BSON key" do context "when the string is valid" do context "when the string has no invalid characters" do let(:string) do "testing" end it "returns the key" do expect(validated).to eq(string) end end context "when the string contains a $" do let(:string) do "te$ting" end it "returns the key" do expect(validated).to eq(string) end end end context "when the string is invalid" do context "when the string starts with $" do let(:string) do "$testing" end it "raises an exception" do expect { validated }.to raise_error(BSON::String::IllegalKey) end end context "when the string contains a ." do let(:string) do "testing.testing" end it "raises an exception" do expect { validated }.to raise_error(BSON::String::IllegalKey) end end end end bson-4.3.0/spec/support/corpus.rb0000644000004100000410000001707213236361476017037 0ustar www-datawww-data# Copyright (C) 2016 MongoDB, 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 'json' module BSON module Corpus # Represents a test from the driver BSON Corpus. # # @since 4.2.0 class Spec # The spec description. # # @return [ String ] The spec description. # # @since 4.2.0 attr_reader :description # The document key of the object to test. # # @return [ String ] The document key. # # @since 4.2.0 attr_reader :test_key # Instantiate the new spec. # # @example Create the spec. # Spec.new(file) # # @param [ String ] file The name of the json file. # # @since 4.2.0 def initialize(file) @spec = ::JSON.parse(File.read(file)) @valid = @spec['valid'] || [] @invalid = @spec['decodeErrors'] || [] @description = @spec['description'] @test_key = @spec['test_key'] end # Get a list of tests that are expected to pass. # # @example Get the list of valid tests. # spec.valid_tests # # @return [ Array ] The list of valid Tests. # # @since 4.2.0 def valid_tests @valid_tests ||= @valid.collect do |test| BSON::Corpus::Test.new(self, test) end end # Get a list of tests that raise exceptions. # # @example Get the list of invalid tests. # spec.invalid_tests # # @return [ Array ] The list of invalid Tests. # # @since 4.2.0 def invalid_tests @invalid_tests ||= @invalid.collect do |test| BSON::Corpus::Test.new(self, test) end end # The class of the bson object to test. # # @example Get the class of the object to test. # spec.klass # # @return [ Class ] The object class. # # @since 4.2.0 def klass @klass ||= BSON.const_get(description) end end # Represents a single BSON Corpus test. # # @since 4.2.0 class Test # The test description. # # @return [ String ] The test description. # # @since 4.2.0 attr_reader :description # Name of a field in a valid test case extjson document that should be # checked against the case's string field. # # @return [ String ] The json representation of the object. # # @since 4.2.0 attr_reader :test_key # Instantiate the new Test. # # @example Create the test. # Test.new(test) # # @param [ Corpus::Spec ] spec The test specification. # @param [ Hash ] test The test specification. # # @since 4.2.0 def initialize(spec, test) @spec = spec @description = test['description'] @canonical_bson = test['canonical_bson'] @extjson = ::JSON.parse(test['extjson']) if test['extjson'] @bson = test['bson'] @test_key = spec.test_key end # The correct representation of the subject as bson. # # @example Get the correct representation of the subject as bson. # test.correct_bson # # @return [ String ] The correct bson bytes. # # @since 4.2.0 def correct_bson @correct_bson ||= decode_hex(@canonical_bson || @bson) end # Given the hex representation of bson, decode it into a Document, # then reencoded it to bson. # # @example Decoded the bson hex representation, then reencode. # test.reencoded_bson # # @return [ String ] The reencoded bson bytes. # # @since 4.2.0 def reencoded_bson bson_bytes = decode_hex(@bson) buffer = BSON::ByteBuffer.new(bson_bytes) BSON::Document.from_bson(buffer).to_bson.to_s end # Given the hex representation of the canonical bson, decode it into a Document, # then reencoded it to bson. # # @example Decoded the canonical bson hex representation, then reencode. # test.reencoded_canonical_bson # # @return [ String ] The reencoded canonical bson bytes. # # @since 4.2.0 def reencoded_canonical_bson bson_bytes = decode_hex(@canonical_bson) buffer = BSON::ByteBuffer.new(bson_bytes) BSON::Document.from_bson(buffer).to_bson.to_s end # Whether the canonical bson should be tested. # # @example Determine if the canonical bson should be tested. # test.test_canonical_bson? # # @return [ true, false ] Whether the canonical bson should be tested. # # @since 4.2.0 def test_canonical_bson? @canonical_bson && (@bson != @canonical_bson) end # The correct representation of the subject as extended json. # # @example Get the correct representation of the subject as extended json. # test.correct_extjson # # @return [ String ] The correct extended json representation. # # @since 4.2.0 def correct_extjson @canonical_extjson || @extjson end # Whether the extended json should be tested. # # @example Determine if the extended json should be tested. # test.test_extjson? # # @return [ true, false ] Whether the extended json should be tested. # # @since 4.2.0 def test_extjson? !!@extjson end # Get the extended json representation of the decoded doc from the provided # bson hex representation. # # @example Get the extended json representation of the decoded doc. # test.extjson_from_encoded_bson # # @return [ Hash ] The extended json representation. # # @since 4.2.0 def extjson_from_bson subject = decode_hex(@bson) buffer = BSON::ByteBuffer.new(subject) ::JSON.parse(BSON::Document.from_bson(buffer).to_json) end # Get the extended json representation of the decoded doc from the provided # canonical bson hex representation. # # @example Get the extended json representation of the canonical decoded doc. # test.extjson_from_canonical_bson # # @return [ Hash ] The extended json representation. # # @since 4.2.0 def extjson_from_canonical_bson subject = decode_hex(@canonical_bson) buffer = BSON::ByteBuffer.new(subject) ::JSON.parse(BSON::Document.from_bson(buffer).to_json) end # Get the extended json representation of the decoded doc from the provided # extended json representation. (Verifies roundtrip) # # @example Get the extended json representation of the canonical decoded doc. # test.extjson_from_encoded_extjson # # @return [ Hash ] The extended json representation. # # @since 4.2.0 def extjson_from_encoded_extjson doc = BSON::Document.new(@extjson) ::JSON.parse(doc.to_json) end private def decode_hex(obj) [ obj ].pack('H*') end end end end bson-4.3.0/lib/0000755000004100000410000000000013236361476013270 5ustar www-datawww-databson-4.3.0/lib/bson.rb0000644000004100000410000000526113236361476014562 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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/environment" # The core namespace for all BSON related behaviour. # # @since 0.0.0 module BSON # Create a new object id from a string using ObjectId.from_string # # @example Create an object id from the string. # BSON::ObjectId(id) # # @param [ String ] string The string to create the id from. # # @raise [ BSON::ObjectId::Invalid ] If the provided string is invalid. # # @return [ BSON::ObjectId ] The new object id. # # @see ObjectId.from_string def self.ObjectId(string) self::ObjectId.from_string(string) end # Constant for binary string encoding. # # @since 2.0.0 BINARY = "BINARY".freeze # Constant for bson types that don't actually serialize a value. # # @since 2.0.0 NO_VALUE = "".force_encoding(BINARY).freeze # Constant for a null byte (0x00). # # @since 2.0.0 NULL_BYTE = 0.chr.force_encoding(BINARY).freeze # Constant for UTF-8 string encoding. # # @since 2.0.0 UTF8 = "UTF-8".freeze end require "bson/config" require "bson/registry" require "bson/specialized" require "bson/json" require "bson/int32" require "bson/int64" require "bson/integer" require "bson/array" require "bson/binary" require "bson/boolean" require "bson/code" require "bson/code_with_scope" require "bson/date" require "bson/date_time" require "bson/decimal128" require "bson/document" require "bson/false_class" require "bson/float" require "bson/hash" require "bson/open_struct" require "bson/max_key" require "bson/min_key" require "bson/nil_class" require "bson/object" require "bson/object_id" require "bson/regexp" require "bson/string" require "bson/symbol" require "bson/time" require "bson/timestamp" require "bson/true_class" require "bson/undefined" require "bson/version" # If we are using JRuby, attempt to load the Java extensions, if we are using # MRI or Rubinius, attempt to load the C extensions. # # @since 2.0.0 begin if BSON::Environment.jruby? require "bson-ruby.jar" org.bson.NativeService.new.basicLoad(JRuby.runtime) else require "bson_native" end rescue LoadError $stderr.puts("Failed to load the necessary extensions.") raise end bson-4.3.0/lib/bson/0000755000004100000410000000000013236361476014231 5ustar www-datawww-databson-4.3.0/lib/bson/string.rb0000644000004100000410000000767113236361476016077 0ustar www-datawww-data# -*- coding: utf-8 -*- # Copyright (C) 2009-2014 MongoDB 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 # Injects behaviour for encoding and decoding string values to and from # raw bytes as specified by the BSON spec. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 module String # A string is type 0x02 in the BSON spec. # # @since 2.0.0 BSON_TYPE = 2.chr.force_encoding(BINARY).freeze # Regex for matching illegal BSON keys. # # @since 4.1.0 ILLEGAL_KEY = /(\A[$])|(\.)/.freeze # Get the string as encoded BSON. # # @example Get the string as encoded BSON. # "test".to_bson # # @raise [ EncodingError ] If the string is not UTF-8. # # @return [ BSON::ByteBuffer ] The buffer with the encoded object. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?) buffer.put_string(self) end # Get the string as a BSON key name encoded C string with checking for special characters. # # @example Get the string as key name. # "test".to_bson_key # # @raise [ EncodingError ] If the string is not UTF-8. # # @raise [ IllegalKey ] If validating keys and it contains a '.' or starts # with '$'. # # @return [ String ] The encoded string. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def to_bson_key(validating_keys = Config.validating_keys?) if validating_keys raise IllegalKey.new(self) if ILLEGAL_KEY =~ self end self end # Convert the string to an object id. This will only work for strings of size # 12. # # @example Convert the string to an object id. # string.to_bson_object_id # # @note This is used for repairing legacy bson data. # # @raise [ BSON::ObjectId::Invalid ] If the string is not 12 elements. # # @return [ String ] The raw object id bytes. # # @since 2.0.0 def to_bson_object_id ObjectId.repair(self) end # Convert the string to a hexidecimal representation. # # @example Convert the string to hex. # "\x01".to_hex_string # # @return [ String ] The string as hex. # # @since 2.0.0 def to_hex_string unpack("H*")[0] end # Raised when validating keys and a key is illegal in MongoDB # # @since 4.1.0 class IllegalKey < RuntimeError # Instantiate the exception. # # @example Instantiate the exception. # BSON::Object::IllegalKey.new(string) # # @param [ String ] string The illegal string. # # @since 4.1.0 def initialize(string) super("'#{string}' is an illegal key in MongoDB. Keys may not start with '$' or contain a '.'.") end end module ClassMethods # Deserialize a string from BSON. # # @param [ ByteBuffer ] buffer The byte buffer. # # @return [ Regexp ] The decoded string. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def from_bson(buffer) buffer.get_string end end # Register this type when the module is loaded. # # @since 2.0.0 Registry.register(BSON_TYPE, ::String) end # Enrich the core String class with this module. # # @since 2.0.0 ::String.send(:include, String) ::String.send(:extend, String::ClassMethods) end bson-4.3.0/lib/bson/max_key.rb0000644000004100000410000000342513236361476016217 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 # Represents a $maxKey type, which compares less than any other value in the # specification. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 class MaxKey include Comparable include JSON include Specialized # A $maxKey is type 0x7F in the BSON spec. # # @since 2.0.0 BSON_TYPE = 127.chr.force_encoding(BINARY).freeze # Constant for always evaluating greater in a comparison. # # @since 2.0.0 GREATER = 1.freeze # When comparing a max key with any other object, the max key will always # be greater. # # @example Compare with another object. # max_key <=> 1000 # # @param [ Object ] other The object to compare against. # # @return [ Integer ] Always 1. # # @since 2.0.0 def <=>(other) GREATER end # Get the max key as JSON hash data. # # @example Get the max key as a JSON hash. # max_key.as_json # # @return [ Hash ] The max key as a JSON hash. # # @since 2.0.0 def as_json(*args) { "$maxKey" => 1 } end # Register this type when the module is loaded. # # @since 2.0.0 Registry.register(BSON_TYPE, self) end end bson-4.3.0/lib/bson/hash.rb0000644000004100000410000000576413236361476015515 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 # Injects behaviour for encoding and decoding hashes to # and from raw bytes as specified by the BSON spec. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 module Hash # An hash (embedded document) is type 0x03 in the BSON spec. # # @since 2.0.0 BSON_TYPE = 3.chr.force_encoding(BINARY).freeze # Get the hash as encoded BSON. # # @example Get the hash as encoded BSON. # { "field" => "value" }.to_bson # # @return [ BSON::ByteBuffer ] The buffer with the encoded object. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?) if buffer.respond_to?(:put_hash) buffer.put_hash(self, validating_keys) else position = buffer.length buffer.put_int32(0) each do |field, value| buffer.put_byte(value.bson_type) buffer.put_cstring(field.to_bson_key(validating_keys)) value.to_bson(buffer, validating_keys) end buffer.put_byte(NULL_BYTE) buffer.replace_int32(position, buffer.length - position) end end # Converts the hash to a normalized value in a BSON document. # # @example Convert the hash to a normalized value. # hash.to_bson_normalized_value # # @return [ BSON::Document ] The normazlied hash. # # @since 3.0.0 def to_bson_normalized_value Document.new(self) end module ClassMethods # Deserialize the hash from BSON. # # @param [ ByteBuffer ] buffer The byte buffer. # # @return [ Array ] The decoded hash. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def from_bson(buffer) if buffer.respond_to?(:get_hash) buffer.get_hash else hash = Document.allocate buffer.get_int32 # Throw away the size. while (type = buffer.get_byte) != NULL_BYTE field = buffer.get_cstring hash.store(field, BSON::Registry.get(type, field).from_bson(buffer)) end hash end end end # Register this type when the module is loaded. # # @since 2.0.0 Registry.register(BSON_TYPE, ::Hash) end # Enrich the core Hash class with this module. # # @since 2.0.0 ::Hash.send(:include, Hash) ::Hash.send(:extend, Hash::ClassMethods) end bson-4.3.0/lib/bson/date_time.rb0000644000004100000410000000251613236361476016515 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "time" module BSON # Injects behaviour for encoding date time values to raw bytes as specified by # the BSON spec for time. # # @see http://bsonspec.org/#/specification # # @since 2.1.0 module DateTime # Get the date time as encoded BSON. # # @example Get the date time as encoded BSON. # DateTime.new(2012, 1, 1, 0, 0, 0).to_bson # # @return [ BSON::ByteBuffer ] The buffer with the encoded object. # # @see http://bsonspec.org/#/specification # # @since 2.1.0 def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?) to_time.to_bson(buffer) end end # Enrich the core DateTime class with this module. # # @since 2.1.0 ::DateTime.send(:include, DateTime) end bson-4.3.0/lib/bson/code_with_scope.rb0000644000004100000410000000657113236361476017725 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 # Represents a code with scope, which is a wrapper around javascript code # with variable scope provided. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 class CodeWithScope include JSON # A code with scope is type 0x0F in the BSON spec. # # @since 2.0.0 BSON_TYPE = 15.chr.force_encoding(BINARY).freeze # @!attribute javascript # @return [ String ] The javascript code. # @since 2.0.0 # @!attribute scope # @return [ Hash ] The variable scope. # @since 2.0.0 attr_reader :javascript, :scope # Determine if this code with scope object is equal to another object. # # @example Check the code with scope equality. # code_with_scope == other # # @param [ Object ] other The object to compare against. # # @return [ true, false ] If the objects are equal. # # @since 2.0.0 def ==(other) return false unless other.is_a?(CodeWithScope) javascript == other.javascript && scope == other.scope end # Get the code with scope as JSON hash data. # # @example Get the code with scope as a JSON hash. # code_with_scope.as_json # # @return [ Hash ] The code with scope as a JSON hash. # # @since 2.0.0 def as_json(*args) { "$code" => javascript, "$scope" => scope } end # Instantiate the new code with scope. # # @example Instantiate the code with scope. # BSON::CodeWithScope.new("this.value = name", name: "sid") # # @param [ String ] javascript The javascript code. # @param [ Hash ] scope The variable scope. # # @since 2.0.0 def initialize(javascript = "", scope = {}) @javascript = javascript @scope = scope end # Encode the javascript code with scope. # # @example Encode the code with scope. # code_with_scope.to_bson # # @return [ BSON::ByteBuffer ] The buffer with the encoded object. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?) position = buffer.length buffer.put_int32(0) buffer.put_string(javascript) scope.to_bson(buffer) buffer.replace_int32(position, buffer.length - position) end # Deserialize a code with scope from BSON. # # @param [ ByteBuffer ] buffer The byte buffer. # # @return [ TrueClass, FalseClass ] The decoded code with scope. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def self.from_bson(buffer) buffer.get_int32 # Throw away the total length. new(buffer.get_string, ::Hash.from_bson(buffer)) end # Register this type when the module is loaded. # # @since 2.0.0 Registry.register(BSON_TYPE, self) end end bson-4.3.0/lib/bson/binary.rb0000644000004100000410000001274513236361476016053 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 'base64' module BSON # Represents binary data. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 class Binary include JSON # A binary is type 0x05 in the BSON spec. # # @since 2.0.0 BSON_TYPE = 5.chr.force_encoding(BINARY).freeze # The mappings of subtypes to their single byte identifiers. # # @since 2.0.0 SUBTYPES = { :generic => 0.chr, :function => 1.chr, :old => 2.chr, :uuid_old => 3.chr, :uuid => 4.chr, :md5 => 5.chr, :user => 128.chr }.freeze # The mappings of single byte subtypes to their symbol counterparts. # # @since 2.0.0 TYPES = SUBTYPES.invert.freeze # @!attribute data # @return [ Object ] The raw binary data. # @since 2.0.0 # @!attribute type # @return [ Symbol ] The binary type. # @since 2.0.0 attr_reader :data, :type # Determine if this binary object is equal to another object. # # @example Check the binary equality. # binary == other # # @param [ Object ] other The object to compare against. # # @return [ true, false ] If the objects are equal. # # @since 2.0.0 def ==(other) return false unless other.is_a?(Binary) type == other.type && data == other.data end alias eql? == # Generates a Fixnum hash value for this object. # # Allows using Binary as hash keys. # # @return [ Fixnum ] # # @since 2.3.1 def hash data.hash + type.hash end # Get the binary as JSON hash data. # # @example Get the binary as a JSON hash. # binary.as_json # # @return [ Hash ] The binary as a JSON hash. # # @since 2.0.0 def as_json(*args) { "$binary" => Base64.encode64(data), "$type" => type } end # Instantiate the new binary object. # # @example Instantiate a binary. # BSON::Binary.new(data, :md5) # # @param [ Object ] data The raw binary data. # @param [ Symbol ] type The binary type. # # @since 2.0.0 def initialize(data = "", type = :generic) validate_type!(type) @data = data @type = type end # Get a nice string for use with object inspection. # # @example Inspect the binary. # object_id.inspect # # @return [ String ] The binary in form BSON::Binary:object_id # # @since 2.3.0 def inspect "" end # Encode the binary type # # @example Encode the binary. # binary.to_bson # # @return [ BSON::ByteBuffer ] The buffer with the encoded object. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?) position = buffer.length buffer.put_int32(0) buffer.put_byte(SUBTYPES[type]) buffer.put_int32(data.bytesize) if type == :old buffer.put_bytes(data.force_encoding(BINARY)) buffer.replace_int32(position, buffer.length - position - 5) end # Deserialize the binary data from BSON. # # @param [ ByteBuffer ] buffer The byte buffer. # # @return [ Binary ] The decoded binary data. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def self.from_bson(buffer) length = buffer.get_int32 type = TYPES[buffer.get_byte] length = buffer.get_int32 if type == :old data = buffer.get_bytes(length) new(data, type) end # Raised when providing an invalid type to the Binary. # # @since 2.0.0 class InvalidType < RuntimeError # @!attribute type # @return [ Object ] The invalid type. # @since 2.0.0 attr_reader :type # Instantiate the new error. # # @example Instantiate the error. # InvalidType.new(:error) # # @param [ Object ] type The invalid type. # # @since 2.0.0 def initialize(type) @type = type end # Get the custom error message for the exception. # # @example Get the message. # error.message # # @return [ String ] The error message. # # @since 2.0.0 def message "#{type.inspect} is not a valid binary type. " + "Please use one of #{SUBTYPES.keys.map(&:inspect).join(", ")}." end end private # Validate the provided type is a valid type. # # @api private # # @example Validate the type. # binary.validate_type!(:user) # # @param [ Object ] type The provided type. # # @raise [ InvalidType ] The the type is invalid. # # @since 2.0.0 def validate_type!(type) raise InvalidType.new(type) unless SUBTYPES.has_key?(type) end # Register this type when the module is loaded. # # @since 2.0.0 Registry.register(BSON_TYPE, self) end end bson-4.3.0/lib/bson/float.rb0000644000004100000410000000406213236361476015665 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 # Injects behaviour for encoding and decoding floating point values # to and from # raw bytes as specified by the BSON spec. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 module Float # A floating point is type 0x01 in the BSON spec. # # @since 2.0.0 BSON_TYPE = 1.chr.force_encoding(BINARY).freeze # The pack directive is for 8 byte floating points. # # @since 2.0.0 PACK = "E".freeze # Get the floating point as encoded BSON. # # @example Get the floating point as encoded BSON. # 1.221311.to_bson # # @return [ BSON::ByteBuffer ] The buffer with the encoded object. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?) buffer.put_double(self) end module ClassMethods # Deserialize an instance of a Float from a BSON double. # # @param [ ByteBuffer ] buffer The byte buffer. # # @return [ Float ] The decoded Float. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def from_bson(buffer) buffer.get_double end end # Register this type when the module is loaded. # # @since 2.0.0 Registry.register(BSON_TYPE, ::Float) end # Enrich the core Float class with this module. # # @since 2.0.0 ::Float.send(:include, Float) ::Float.send(:extend, Float::ClassMethods) end bson-4.3.0/lib/bson/json.rb0000644000004100000410000000210013236361476015520 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 # Provides common behaviour for JSON serialization of objects. # # @since 2.0.0 module JSON # Converting an object to JSON simply gets it's hash representation via # as_json, then converts it to a string. # # @example Convert the object to JSON # object.to_json # # @note All types must implement as_json. # # @return [ String ] The object as JSON. # # @since 2.0.0 def to_json(*args) as_json.to_json(*args) end end end bson-4.3.0/lib/bson/time.rb0000644000004100000410000000401113236361476015510 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 # Injects behaviour for encoding and decoding time values to # and from raw bytes as specified by the BSON spec. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 module Time # A time is type 0x09 in the BSON spec. # # @since 2.0.0 BSON_TYPE = 9.chr.force_encoding(BINARY).freeze # Get the time as encoded BSON. # # @example Get the time as encoded BSON. # Time.new(2012, 1, 1, 0, 0, 0).to_bson # # @return [ BSON::ByteBuffer ] The buffer with the encoded object. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?) buffer.put_int64((to_i * 1000) + (usec / 1000)) end module ClassMethods # Deserialize UTC datetime from BSON. # # @param [ ByteBuffer ] buffer The byte buffer. # # @return [ Time ] The decoded UTC datetime. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def from_bson(buffer) seconds, fragment = Int64.from_bson(buffer).divmod(1000) at(seconds, fragment * 1000).utc end end # Register this type when the module is loaded. # # @since 2.0.0 Registry.register(BSON_TYPE, ::Time) end # Enrich the core Time class with this module. # # @since 2.0.0 ::Time.send(:include, Time) ::Time.send(:extend, Time::ClassMethods) end bson-4.3.0/lib/bson/false_class.rb0000644000004100000410000000330613236361476017037 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 # Injects behaviour for encoding and decoding false values to and from # raw bytes as specified by the BSON spec. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 module FalseClass # A false value in the BSON spec is 0x00. # # @since 2.0.0 FALSE_BYTE = 0.chr.force_encoding(BINARY).freeze # The BSON type for false values is the general boolean type of 0x08. # # @example Get the bson type. # false.bson_type # # @return [ String ] The character 0x08. # # @since 2.0.0 def bson_type Boolean::BSON_TYPE end # Get the false boolean as encoded BSON. # # @example Get the false boolean as encoded BSON. # false.to_bson # # @return [ BSON::ByteBuffer ] The buffer with the encoded object. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?) buffer.put_byte(FALSE_BYTE) end end # Enrich the core FalseClass class with this module. # # @since 2.0.0 ::FalseClass.send(:include, FalseClass) end bson-4.3.0/lib/bson/document.rb0000644000004100000410000001354513236361476016404 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "yaml" # Since we have a custom bsondoc type for yaml serialization, we need # to ensure that it's properly deserialized when parsed. # # @since 2.0.0 YAML.add_builtin_type("bsondoc") do |type, value| BSON::Document[value.map{ |val| val.to_a.first }] end module BSON # This module provides behaviour for serializing and deserializing entire # BSON documents, according to the BSON specification. # # @note The specification is: document ::= int32 e_list "\x00" # # @see http://bsonspec.org/#/specification # # @since 2.0.0 class Document < ::Hash # Get a value from the document for the provided key. Can use string or # symbol access, but the fastest will be to always provide a key that is of # the same type as the stored keys. # # @example Get an element for the key. # document["field"] # # @example Get an element for the key by symbol. # document[:field] # # @param [ String, Symbol ] key The key to lookup. # # @return [ Object ] The found value, or nil if none found. # # @since 2.0.0 def [](key) super(convert_key(key)) end # Set a value on the document. Will normalize symbol keys into strings. # # @example Set a value on the document. # document[:test] = "value" # # @param [ String, Symbol ] key The key to update. # @param [ Object ] value The value to update. # # @return [ Object ] The updated value. # # @since 3.0.0 def []=(key, value) super(convert_key(key), convert_value(value)) end # Returns true if the given key is present in the document. Will normalize # symbol keys into strings. # # @example Test if a key exists using a symbol # document.has_key?(:test) # # @param [ Object ] key The key to check for. # # @return [ true, false] # # @since 4.0.0 def has_key?(key) super(convert_key(key)) end alias :include? :has_key? alias :key? :has_key? alias :member? :has_key? # Returns true if the given value is present in the document. Will normalize # symbols into strings. # # @example Test if a key exists using a symbol # document.has_value?(:test) # # @param [ Object ] value THe value to check for. # # @return [ true, false] # # @since 4.0.0 def has_value?(value) super(convert_value(value)) end alias :value :has_value? # Deletes the key-value pair and returns the value from the document # whose key is equal to key. # If the key is not found, returns the default value. If the optional code # block is given and the key is not found, pass in the key and return the # result of block. # # @example Delete a key-value pair # document.delete(:test) # # @param [ Object ] key The key of the key-value pair to delete. # # @return [ Object ] # # @since 4.0.0 def delete(key, &block) super(convert_key(key), &block) end # Instantiate a new Document. Valid parameters for instantiation is a hash # only or nothing. # # @example Create the new Document. # BSON::Document.new(name: "Joe", age: 33) # # @param [ Hash ] elements The elements of the document. # # @since 3.0.0 def initialize(elements = nil) super() (elements || {}).each_pair{ |key, value| self[key] = value } end # Merge this document with another document, returning a new document in # the process. # # @example Merge with another document. # document.merge(name: "Bob") # # @param [ BSON::Document, Hash ] other The document/hash to merge with. # # @return [ BSON::Document ] The result of the merge. # # @since 3.0.0 def merge(other, &block) dup.merge!(other, &block) end # Merge this document with another document, returning the same document in # the process. # # @example Merge with another document. # document.merge(name: "Bob") # # @param [ BSON::Document, Hash ] other The document/hash to merge with. # # @return [ BSON::Document ] The result of the merge. # # @since 3.0.0 def merge!(other) other.each_pair do |key, value| value = yield(convert_key(key), self[key], convert_value(value)) if block_given? && self[key] self[key] = value end self end alias :update :merge! if instance_methods.include?(:dig) # Retrieves the value object corresponding to the each key objects repeatedly. # Will normalize symbol keys into strings. # # @example Get value from nested sub-documents, handling missing levels. # document # => { :key1 => { "key2" => "value"}} # document.dig(:key1, :key2) # => "value" # document.dig("key1", "key2") # => "value" # document.dig("foo", "key2") # => nil # # @param [ Array ] *keys Keys, which constitute a "path" to the nested value. # # @return [ Object, NilClass ] The requested value or nil. # # @since 3.0.0 def dig(*keys) super(*keys.map{|key| convert_key(key)}) end end private def convert_key(key) key.to_bson_normalized_key end def convert_value(value) value.to_bson_normalized_value end end end bson-4.3.0/lib/bson/decimal128.rb0000644000004100000410000002016013236361476016406 0ustar www-datawww-data# Copyright (C) 2016 MongoDB 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 'bigdecimal' require 'bson/decimal128/builder' module BSON class Decimal128 include JSON # A Decimal128 is type 0x13 in the BSON spec. # # @since 4.2.0 BSON_TYPE = 19.chr.force_encoding(BINARY).freeze # Exponent offset. # # @since 4.2.0 EXPONENT_OFFSET = 6176.freeze # Minimum exponent. # # @since 4.2.0 MIN_EXPONENT = -6176.freeze # Maximum exponent. # # @since 4.2.0 MAX_EXPONENT = 6111.freeze # Maximum digits of precision. # # @since 4.2.0 MAX_DIGITS_OF_PRECISION = 34.freeze # Key for this type when converted to extended json. # # @since 4.2.0 EXTENDED_JSON_KEY = "$numberDecimal".freeze # The native type to which this object can be converted. # # @since 4.2.0 NATIVE_TYPE = BigDecimal # Get the Decimal128 as JSON hash data. # # @example Get the Decimal128 as a JSON hash. # decimal.as_json # # @return [ Hash ] The number as a JSON hash. # # @since 4.2.0 def as_json(*args) { EXTENDED_JSON_KEY => to_s } end # Check equality of the decimal128 object with another object. # # @example Check if the decimal128 object is equal to the other. # decimal == other # # @param [ Object ] other The object to check against. # # @return [ true, false ] If the objects are equal. # # @since 4.2.0 def ==(other) return false unless other.is_a?(Decimal128) @high == other.instance_variable_get(:@high) && @low == other.instance_variable_get(:@low) end alias :eql? :== # Create a new Decimal128 from a BigDecimal. # # @example Create a Decimal128 from a BigDecimal. # Decimal128.new(big_decimal) # # @param [ String, BigDecimal ] object The BigDecimal or String to use for # instantiating a Decimal128. # # @raise [ InvalidBigDecimal ] Raise error unless object argument is a BigDecimal. # # @since 4.2.0 def initialize(object) if object.is_a?(String) set_bits(*Builder::FromString.new(object).bits) elsif object.is_a?(BigDecimal) set_bits(*Builder::FromBigDecimal.new(object).bits) else raise InvalidArgument.new end end # Get the decimal128 as its raw BSON data. # # @example Get the raw bson bytes in a buffer. # decimal.to_bson # # @return [ BSON::ByteBuffer ] The buffer with the encoded object. # # @see http://bsonspec.org/#/specification # # @since 4.2.0 def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?) buffer.put_decimal128(@low, @high) end # Get the hash value for the decimal128. # # @example Get the hash value. # decimal.hash # # @return [ Integer ] The hash value. # # @since 4.2.0 def hash num = @high << 64 num |= @low num.hash end # Get a nice string for use with object inspection. # # @example Inspect the decimal128 object. # decimal128.inspect # # @return [ String ] The decimal as a string. # # @since 4.2.0 def inspect "BSON::Decimal128('#{to_s}')" end # Get the string representation of the decimal128. # # @example Get the decimal128 as a string. # decimal128.to_s # # @return [ String ] The decimal128 as a string. # # @since 4.2.0 def to_s @string ||= Builder::ToString.new(self).string end alias :to_str :to_s # Get a Ruby BigDecimal object corresponding to this Decimal128. # Note that, when converting to a Ruby BigDecimal, non-zero significant digits # are preserved but trailing zeroes may be lost. # See the following example: # # @example # decimal128 = BSON::Decimal128.new("0.200") # => BSON::Decimal128('0.200') # big_decimal = decimal128.to_big_decimal # => # # big_decimal.to_s # => "0.2E0" # # Note that the the BSON::Decimal128 object can represent -NaN, sNaN, # and -sNaN while Ruby's BigDecimal cannot. # # @return [ BigDecimal ] The decimal as a BigDecimal. # # @since 4.2.0 def to_big_decimal @big_decimal ||= BigDecimal.new(to_s) end private def set_bits(low, high) @low = low @high = high end class << self # Deserialize the decimal128 from raw BSON bytes. # # @example Get the decimal128 from BSON. # Decimal128.from_bson(bson) # # @param [ ByteBuffer ] buffer The byte buffer. # # @return [ BSON::Decimal128 ] The decimal object. # # @since 4.2.0 def from_bson(buffer) from_bits(*buffer.get_decimal128_bytes.unpack('Q<*')) end # Instantiate a Decimal128 from a string. # # @example Create a Decimal128 from a string. # BSON::Decimal128.from_string("1.05E+3") # # @param [ String ] string The string to parse. # # @raise [ BSON::Decimal128::InvalidString ] If the provided string is invalid. # # @return [ BSON::Decimal128 ] The new decimal128. # # @since 4.2.0 def from_string(string) from_bits(*Builder::FromString.new(string).bits) end # Instantiate a Decimal128 from high and low bits. # # @example Create a Decimal128 from high and low bits. # BSON::Decimal128.from_bits(high, low) # # @param [ Integer ] high The high order bits. # @param [ Integer ] low The low order bits. # # @return [ BSON::Decimal128 ] The new decimal128. # # @since 4.2.0 def from_bits(low, high) decimal = allocate decimal.send(:set_bits, low, high) decimal end end # Raised when trying to create a Decimal128 from an object that is neither a String nor a BigDecimal. # # @api private # # @since 4.2.0 class InvalidArgument < ArgumentError # The custom error message for this error. # # @since 4.2.0 MESSAGE = 'A Decimal128 can only be created from a String or BigDecimal.'.freeze # Get the custom error message for the exception. # # @example Get the message. # error.message # # @return [ String ] The error message. # # @since 4.2.0 def message MESSAGE end end # Raised when trying to create a Decimal128 from a string with # an invalid format. # # @api private # # @since 4.2.0 class InvalidString < RuntimeError # The custom error message for this error. # # @since 4.2.0 MESSAGE = 'Invalid string format for creating a Decimal128 object.'.freeze # Get the custom error message for the exception. # # @example Get the message. # error.message # # @return [ String ] The error message. # # @since 4.2.0 def message MESSAGE end end # Raised when the exponent or significand provided is outside the valid range. # # @api private # # @since 4.2.0 class InvalidRange < RuntimeError # The custom error message for this error. # # @since 4.2.0 MESSAGE = 'Value out of range for Decimal128 representation.'.freeze # Get the custom error message for the exception. # # @example Get the message. # error.message # # @return [ String ] The error message. # # @since 4.2.0 def message MESSAGE end end Registry.register(BSON_TYPE, self) end end bson-4.3.0/lib/bson/date.rb0000644000004100000410000000274513236361476015503 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 'date' module BSON # Injects behaviour for encoding date values to raw bytes as specified by # the BSON spec for time. # # @see http://bsonspec.org/#/specification # # @since 2.1.0 module Date # Get the date as encoded BSON. # # @example Get the date as encoded BSON. # Date.new(2012, 1, 1).to_bson # # @return [ BSON::ByteBuffer ] The buffer with the encoded object. # # @see http://bsonspec.org/#/specification # # @since 2.1.0 def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?) ::Time.utc(year, month, day).to_bson(buffer) end # Get the BSON type for the date. # # As the date is converted to a time, this returns the BSON type for time. def bson_type ::Time::BSON_TYPE end end # Enrich the core Date class with this module. # # @since 2.1.0 ::Date.send(:include, Date) end bson-4.3.0/lib/bson/open_struct.rb0000644000004100000410000000320513236361476017123 0ustar www-datawww-data# Copyright (C) 2016 MongoDB 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 # Injects behaviour for encoding OpenStruct objects using hashes # to raw bytes as specified by the BSON spec. # # @see http://bsonspec.org/#/specification # # @since 4.2.0 module OpenStruct # Get the OpenStruct as encoded BSON. # # @example Get the OpenStruct object as encoded BSON. # OpenStruct.new({ "field" => "value" }).to_bson # # @return [ BSON::ByteBuffer ] The buffer with the encoded object. # # @see http://bsonspec.org/#/specification # # @since 4.2.0 def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?) if Environment.ruby_1_9? marshal_dump.dup else to_h end.to_bson(buffer, validating_keys) end # The BSON type for OpenStruct objects is the Hash type of 0x03. # # @example Get the bson type. # struct.bson_type # # @return [ String ] The character 0x03. # # @since 4.2.0 def bson_type ::Hash::BSON_TYPE end end ::OpenStruct.send(:include, OpenStruct) if defined?(::OpenStruct) end bson-4.3.0/lib/bson/object.rb0000644000004100000410000000443213236361476016027 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 # Injects behaviour for all Ruby objects. # # @since 2.2.4 module Object # Objects that don't override this method will raise an error when trying # to use them as keys in a BSON document. This is only overridden in String # and Symbol. # # @example Convert the object to a BSON key. # object.to_bson_key # # @raise [ InvalidKey ] Always raises an exception. # # @see http://bsonspec.org/#/specification # # @since 2.2.4 def to_bson_key(validating_keys = Config.validating_keys?) raise InvalidKey.new(self) end # Converts the object to a normalized key in a BSON document. # # @example Convert the object to a normalized key. # object.to_bson_normalized_key # # @return [ Object ] self. # # @since 3.0.0 def to_bson_normalized_key self end # Converts the object to a normalized value in a BSON document. # # @example Convert the object to a normalized value. # object.to_bson_normalized_value # # @return [ Object ] self. # # @since 3.0.0 def to_bson_normalized_value self end end # Raised when trying to serialize an object into a key. # # @since 2.2.4 class InvalidKey < RuntimeError # Instantiate the exception. # # @example Instantiate the exception. # BSON::Object::InvalidKey.new(object) # # @param [ Object ] object The object that was meant for the key. # # @since 2.2.4 def initialize(object) super("#{object.class} instances are not allowed as keys in a BSON document.") end end # Enrich the core Object class with this module. # # @since 2.2.4 ::Object.send(:include, Object) end bson-4.3.0/lib/bson/true_class.rb0000644000004100000410000000327213236361476016726 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 # Injects behaviour for encoding and decoding true values to and from # raw bytes as specified by the BSON spec. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 module TrueClass # A true value in the BSON spec is 0x01. # # @since 2.0.0 TRUE_BYTE = 1.chr.force_encoding(BINARY).freeze # The BSON type for true values is the general boolean type of 0x08. # # @example Get the bson type. # false.bson_type # # @return [ String ] The character 0x08. # # @since 2.0.0 def bson_type Boolean::BSON_TYPE end # Get the true boolean as encoded BSON. # # @example Get the true boolean as encoded BSON. # true.to_bson # # @return [ BSON::ByteBuffer ] The buffer with the encoded object. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?) buffer.put_byte(TRUE_BYTE) end end # Enrich the core TrueClass class with this module. # # @since 2.0.0 ::TrueClass.send(:include, TrueClass) end bson-4.3.0/lib/bson/int32.rb0000644000004100000410000000527013236361476015521 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 # Represents a $maxKey type, which compares less than any other value in the # specification. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 class Int32 # A boolean is type 0x08 in the BSON spec. # # @since 2.0.0 BSON_TYPE = 16.chr.force_encoding(BINARY).freeze # The number of bytes constant. # # @since 4.0.0 BYTES_LENGTH = 4 # Constant for the int 32 pack directive. # # @since 2.0.0 PACK = "l<".freeze # Deserialize an Integer from BSON. # # @param [ ByteBuffer ] buffer The byte buffer. # # @return [ Integer ] The decoded Integer. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def self.from_bson(buffer) buffer.get_int32 end # Instantiate a BSON Int32. # # @param [ Integer ] integer The 32-bit integer. # # @see http://bsonspec.org/#/specification # # @since 4.2.0 def initialize(integer) out_of_range! unless integer.bson_int32? @integer = integer.freeze end # Append the integer as encoded BSON to a ByteBuffer. # # @example Encoded the integer and append to a ByteBuffer. # int32.to_bson # # @return [ BSON::ByteBuffer ] The buffer with the encoded integer. # # @see http://bsonspec.org/#/specification # # @since 4.2.0 def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?) buffer.put_int32(@integer) end # Convert the integer to a BSON string key. # # @example Convert the integer to a BSON key string. # int.to_bson_key # # @param [ true, false ] validating_keys If BSON should validate the key. # # @return [ String ] The string key. # # @since 4.2.0 def to_bson_key(validating_keys = Config.validating_keys?) @integer.to_bson_key(validating_keys) end private def out_of_range! raise RangeError.new("#{self} is not a valid 4 byte integer value.") end # Register this type when the module is loaded. # # @since 2.0.0 Registry.register(BSON_TYPE, self) end end bson-4.3.0/lib/bson/boolean.rb0000644000004100000410000000252113236361476016175 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 # Represents a boolean type, which compares less than any other value in the # specification. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 class Boolean # A boolean is type 0x08 in the BSON spec. # # @since 2.0.0 BSON_TYPE = 8.chr.force_encoding(BINARY).freeze # Deserialize a boolean from BSON. # # @param [ ByteBuffer ] buffer The byte buffer. # # @return [ TrueClass, FalseClass ] The decoded boolean. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def self.from_bson(buffer) buffer.get_byte == TrueClass::TRUE_BYTE end # Register this type when the module is loaded. # # @since 2.0.0 Registry.register(BSON_TYPE, self) end end bson-4.3.0/lib/bson/version.rb0000644000004100000410000000116313236361476016244 0ustar www-datawww-data# Copyright (C) 2009-2016 MongoDB 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 VERSION = "4.3.0".freeze end bson-4.3.0/lib/bson/code.rb0000644000004100000410000000534713236361476015501 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 # Represents a code type, which is a wrapper around javascript code. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 class Code include JSON # A code is type 0x0D in the BSON spec. # # @since 2.0.0 BSON_TYPE = 13.chr.force_encoding(BINARY).freeze # @!attribute javascript # @return [ String ] The javascript code. # @since 2.0.0 attr_reader :javascript # Determine if this code object is equal to another object. # # @example Check the code equality. # code == other # # @param [ Object ] other The object to compare against. # # @return [ true, false ] If the objects are equal. # # @since 2.0.0 def ==(other) return false unless other.is_a?(Code) javascript == other.javascript end # Get the code as JSON hash data. # # @example Get the code as a JSON hash. # code.as_json # # @return [ Hash ] The code as a JSON hash. # # @since 2.0.0 def as_json(*args) { "$code" => javascript } end # Instantiate the new code. # # @example Instantiate the new code. # BSON::Code.new("this.value = 5") # # @param [ String ] javascript The javascript code. # # @since 2.0.0 def initialize(javascript = "") @javascript = javascript end # Encode the javascript code. # # @example Encode the code. # code.to_bson # # @return [ BSON::ByteBuffer ] The buffer with the encoded object. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?) buffer.put_string(javascript) # @todo: was formerly to_bson_string end # Deserialize code from BSON. # # @param [ ByteBuffer ] buffer The byte buffer. # # @return [ TrueClass, FalseClass ] The decoded code. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def self.from_bson(buffer) new(buffer.get_string) end # Register this type when the module is loaded. # # @since 2.0.0 Registry.register(BSON_TYPE, self) end end bson-4.3.0/lib/bson/config.rb0000644000004100000410000000274313236361476016031 0ustar www-datawww-data# Copyright (C) 2016 MongoDB 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 # Provides configuration options for the BSON library. # # @since 4.1.0 module Config extend self # Set the configuration option for BSON to validate keys or not. # # @example Set the config option. # BSON::Config.validating_keys = true # # @param [ true, false ] value The value to set. # # @return [ true, false ] The value. # # @since 4.1.0 def validating_keys=(value) @validating_keys = value end # Returns true if BSON will validate the document keys on serialization to # determine if they contain invalid MongoDB values. Invalid keys start with # '$' or contain a '.' in them. # # @example Is BSON validating keys? # BSON::Config.validating_keys? # # @return [ true, false ] If BSON is validating keys? # # @since 4.1.0 def validating_keys? !!(@validating_keys||=nil) end end end bson-4.3.0/lib/bson/array.rb0000644000004100000410000000710613236361476015700 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 # Injects behaviour for encoding and decoding arrays to # and from raw bytes as specified by the BSON spec. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 module Array # An array is type 0x04 in the BSON spec. # # @since 2.0.0 BSON_TYPE = 4.chr.force_encoding(BINARY).freeze # Get the array as encoded BSON. # # @example Get the array as encoded BSON. # [ 1, 2, 3 ].to_bson # # @note Arrays are encoded as documents, where the index of the value in # the array is the actual key. # # @return [ BSON::ByteBuffer ] The buffer with the encoded object. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?) if buffer.respond_to?(:put_array) buffer.put_array(self, validating_keys) else position = buffer.length buffer.put_int32(0) each_with_index do |value, index| buffer.put_byte(value.bson_type) buffer.put_cstring(index.to_s) value.to_bson(buffer, validating_keys) end buffer.put_byte(NULL_BYTE) buffer.replace_int32(position, buffer.length - position) end end # Convert the array to an object id. This will only work for arrays of size # 12 where the elements are all strings. # # @example Convert the array to an object id. # array.to_bson_object_id # # @note This is used for repairing legacy bson data. # # @raise [ BSON::ObjectId::Invalid ] If the array is not 12 elements. # # @return [ String ] The raw object id bytes. # # @since 2.0.0 def to_bson_object_id ObjectId.repair(self) { pack("C*") } end # Converts the array to a normalized value in a BSON document. # # @example Convert the array to a normalized value. # array.to_bson_normalized_value # # @return [ Array ] The normalized array. # # @since 3.0.0 def to_bson_normalized_value map { |value| value.to_bson_normalized_value } end module ClassMethods # Deserialize the array from BSON. # # @param [ ByteBuffer ] buffer The byte buffer. # # @return [ Array ] The decoded array. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def from_bson(buffer) if buffer.respond_to?(:get_array) buffer.get_array else array = new buffer.get_int32 # throw away the length while (type = buffer.get_byte) != NULL_BYTE buffer.get_cstring array << BSON::Registry.get(type).from_bson(buffer) end array end end end # Register this type when the module is loaded. # # @since 2.0.0 Registry.register(BSON_TYPE, ::Array) end # Enrich the core Array class with this module. # # @since 2.0.0 ::Array.send(:include, Array) ::Array.send(:extend, Array::ClassMethods) end bson-4.3.0/lib/bson/min_key.rb0000644000004100000410000000342313236361476016213 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 # Represents a $minKey type, which compares less than any other value in the # specification. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 class MinKey include Comparable include JSON include Specialized # A $minKey is type 0xFF in the BSON spec. # # @since 2.0.0 BSON_TYPE = 255.chr.force_encoding(BINARY).freeze # Constant for always evaluating lesser in a comparison. # # @since 2.0.0 LESSER = -1.freeze # When comparing a min key with any other object, the min key will always # be lesser. # # @example Compare with another object. # min_key <=> 1000 # # @param [ Object ] other The object to compare against. # # @return [ Integer ] Always -1. # # @since 2.0.0 def <=>(other) LESSER end # Get the min key as JSON hash data. # # @example Get the min key as a JSON hash. # min_key.as_json # # @return [ Hash ] The min key as a JSON hash. # # @since 2.0.0 def as_json(*args) { "$minKey" => 1 } end # Register this type when the module is loaded. # # @since 2.0.0 Registry.register(BSON_TYPE, self) end end bson-4.3.0/lib/bson/decimal128/0000755000004100000410000000000013236361476016062 5ustar www-datawww-databson-4.3.0/lib/bson/decimal128/builder.rb0000644000004100000410000003263213236361476020043 0ustar www-datawww-data# Copyright (C) 2016 MongoDB 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 Decimal128 # Helper module for parsing String, Integer, Float, BigDecimal, and Decimal128 # objects into other objects. # # @api private # # @since 4.2.0 module Builder # Infinity mask. # # @since 4.2.0 INFINITY_MASK = 0x7800000000000000.freeze # NaN mask. # # @since 4.2.0 NAN_MASK = 0x7c00000000000000.freeze # SNaN mask. # # @since 4.2.0 SNAN_MASK = (1 << 57).freeze # Signed bit mask. # # @since 4.2.0 SIGN_BIT_MASK = (1 << 63).freeze # The two highest bits of the 64 high order bits. # # @since 4.2.0 TWO_HIGHEST_BITS_SET = (3 << 61).freeze extend self # Convert parts representing a Decimal128 into the corresponding bits. # # @param [ Integer ] significand The significand. # @param [ Integer ] exponent The exponent. # @param [ true, false ] is_negative Whether the value is negative. # # @return [ Array ] Tuple of the low and high bits. # # @since 4.2.0 def parts_to_bits(significand, exponent, is_negative) validate_range!(exponent, significand) exponent = exponent + Decimal128::EXPONENT_OFFSET high = significand >> 64 low = (high << 64) ^ significand if high >> 49 == 1 high = high & 0x7fffffffffff high |= TWO_HIGHEST_BITS_SET high |= (exponent & 0x3fff) << 47 else high |= exponent << 49 end if is_negative high |= SIGN_BIT_MASK end [ low, high ] end private def validate_range!(exponent, significand) unless valid_significand?(significand) && valid_exponent?(exponent) raise Decimal128::InvalidRange.new end end def valid_significand?(significand) significand.to_s.length <= Decimal128::MAX_DIGITS_OF_PRECISION end def valid_exponent?(exponent) exponent <= Decimal128::MAX_EXPONENT && exponent >= Decimal128::MIN_EXPONENT end # Helper class for parsing a String into Decimal128 high and low bits. # # @api private # # @since 4.2.0 class FromString # Regex matching a string representing NaN. # # @return [ Regex ] A regex matching a NaN string. # # @since 4.2.0 NAN_REGEX = /^(\-)?(S)?NaN$/i.freeze # Regex matching a string representing positive or negative Infinity. # # @return [ Regex ] A regex matching a positive or negative Infinity string. # # @since 4.2.0 INFINITY_REGEX = /^(\+|\-)?Inf(inity)?$/i.freeze # Regex for the fraction, including leading zeros. # # @return [ Regex ] The regex for matching the fraction, # including leading zeros. # # @since 4.2.0 SIGNIFICAND_WITH_LEADING_ZEROS_REGEX = /(0*)(\d+)/.freeze # Regex for separating a negative sign from the significands. # # @return [ Regex ] The regex for separating a sign from significands. # # @since 4.2.0 SIGN_AND_DIGITS_REGEX = /^(\-)?(\S+)/.freeze # Regex matching a scientific exponent. # # @return [ Regex ] A regex matching E, e, E+, e+. # # @since 4.2.0 SCIENTIFIC_EXPONENT_REGEX = /E\+?/i.freeze # Regex for capturing trailing zeros. # # @since 4.2.0 TRAILING_ZEROS_REGEX = /[1-9]*(0+)$/.freeze # Regex for a valid decimal128 string format. # # @return [ Regex ] The regex for a valid decimal128 string. # # @since 4.2.0 VALID_DECIMAL128_STRING_REGEX = /^[\-\+]?(\d+(\.\d*)?|\.\d+)(E[\-\+]?\d+)?$/i.freeze # Initialize the FromString Builder object. # # @example Create the FromString builder. # Builder::FromString.new(string) # # @param [ String ] string The string to create a Decimal128 from. # # @since 4.2.0 def initialize(string) @string = string end # Get the bits representing the Decimal128 that the string corresponds to. # # @example Get the bits for the Decimal128 object created from the string. # builder.bits # # @return [ Array ] Tuple of the low and high bits. # # @since 4.2.0 def bits if special? to_special_bits else validate_format! to_bits end end private def to_bits original, sign, digits_str = SIGN_AND_DIGITS_REGEX.match(@string).to_a digits, e, scientific_exp = digits_str.partition(SCIENTIFIC_EXPONENT_REGEX) before_decimal, decimal, after_decimal = digits.partition('.') significand_str = before_decimal << after_decimal significand_str = SIGNIFICAND_WITH_LEADING_ZEROS_REGEX.match(significand_str).to_a[2] exponent = -(after_decimal.length) exponent = exponent + scientific_exp.to_i exponent, significand_str = round_exact(exponent, significand_str) exponent, significand_str = clamp(exponent, significand_str) Builder.parts_to_bits(significand_str.to_i, exponent, sign == '-') end def round_exact(exponent, significand) if exponent < Decimal128::MIN_EXPONENT if significand.to_i == 0 round = Decimal128::MIN_EXPONENT - exponent exponent += round elsif trailing_zeros = TRAILING_ZEROS_REGEX.match(significand) round = [ (Decimal128::MIN_EXPONENT - exponent), trailing_zeros[1].size ].min significand = significand[0...-round] exponent += round end elsif significand.length > Decimal128::MAX_DIGITS_OF_PRECISION trailing_zeros = TRAILING_ZEROS_REGEX.match(significand) if trailing_zeros round = [ trailing_zeros[1].size, (significand.length - Decimal128::MAX_DIGITS_OF_PRECISION), (Decimal128::MAX_EXPONENT - exponent)].min significand = significand[0...-round] exponent += round end end [ exponent, significand ] end def clamp(exponent, significand) if exponent > Decimal128::MAX_EXPONENT if significand.to_i == 0 adjust = exponent - Decimal128::MAX_EXPONENT significand = '0' else adjust = [ (exponent - Decimal128::MAX_EXPONENT), Decimal128::MAX_DIGITS_OF_PRECISION - significand.length ].min significand << '0'* adjust end exponent -= adjust end [ exponent, significand ] end def to_special_bits high = 0 if match = NAN_REGEX.match(@string) high = NAN_MASK high = high | SIGN_BIT_MASK if match[1] high = high | SNAN_MASK if match[2] elsif match = INFINITY_REGEX.match(@string) high = INFINITY_MASK high = high | SIGN_BIT_MASK if match[1] == '-' end [ 0, high ] end def special? @string =~ NAN_REGEX || @string =~ INFINITY_REGEX end def validate_format! raise BSON::Decimal128::InvalidString.new unless @string =~ VALID_DECIMAL128_STRING_REGEX end end # Helper class for parsing a BigDecimal into Decimal128 high and low bits. # # @api private # # @since 4.2.0 class FromBigDecimal # Initialize the FromBigDecimal Builder object. # # @example Create the FromBigDecimal builder. # Builder::FromBigDecimal.new(big_decimal) # # @param [ BigDecimal ] big_decimal The big decimal object to # create a Decimal128 from. # # @since 4.2.0 def initialize(big_decimal) @big_decimal = big_decimal end # Get the bits representing the Decimal128 that the big decimal corresponds to. # # @example Get the bits for the Decimal128 object created from the big decimal. # builder.bits # # @return [ Array ] Tuple of the low and high bits. # # @since 4.2.0 def bits if special? to_special_bits else to_bits end end private def to_special_bits case @big_decimal.sign when BigDecimal::SIGN_POSITIVE_INFINITE high = INFINITY_MASK when BigDecimal::SIGN_NEGATIVE_INFINITE high = INFINITY_MASK | SIGN_BIT_MASK when BigDecimal::SIGN_NaN high = NAN_MASK end [ 0, high ] end def to_bits sign, significand_str, base, exp = @big_decimal.split exponent = @big_decimal.zero? ? 0 : exp - significand_str.length is_negative = (sign == BigDecimal::SIGN_NEGATIVE_FINITE || sign == BigDecimal::SIGN_NEGATIVE_ZERO) Builder.parts_to_bits(significand_str.to_i, exponent, is_negative) end def special? @big_decimal.infinite? || @big_decimal.nan? end end # Helper class for getting a String representation of a Decimal128 object. # # @api private # # @since 4.2.0 class ToString # String representing a NaN value. # # @return [ String ] The string representing NaN. # # @since 4.2.0 NAN_STRING = 'NaN'.freeze # String representing an Infinity value. # # @return [ String ] The string representing Infinity. # # @since 4.2.0 INFINITY_STRING = 'Infinity'.freeze # Initialize the FromBigDecimal Builder object. # # @example Create the ToString builder. # Builder::ToString.new(big_decimal) # # @param [ Decimal128 ] decimal128 The decimal128 object to # create a String from. # # @since 4.2.0 def initialize(decimal128) @decimal128 = decimal128 end # Get the string representing the Decimal128 object. # # @example Get a string representing the decimal128. # builder.string # # @return [ String ] The string representing the decimal128 object. # # @since 4.2.0 def string return NAN_STRING if nan? str = infinity? ? INFINITY_STRING : create_string negative? ? '-' << str : str end private def create_string if use_scientific_notation? exp_pos_sign = exponent < 0 ? '' : '+' if significand.length > 1 str = "#{significand[0]}.#{significand[1..-1]}E#{exp_pos_sign}#{scientific_exponent}" else str = "#{significand}E#{exp_pos_sign}#{scientific_exponent}" end elsif exponent < 0 if significand.length > exponent.abs decimal_point_index = significand.length - exponent.abs str = "#{significand[0..decimal_point_index-1]}.#{significand[decimal_point_index..-1]}" else left_zero_pad = (exponent + significand.length).abs str = "0.#{'0' * left_zero_pad}#{significand}" end end str || significand end def scientific_exponent @scientific_exponent ||= (significand.length - 1) + exponent end def use_scientific_notation? exponent > 0 || scientific_exponent < -6 end def exponent @exponent ||= two_highest_bits_set? ? ((high_bits & 0x1fffe00000000000) >> 47) - Decimal128::EXPONENT_OFFSET : ((high_bits & 0x7fff800000000000) >> 49) - Decimal128::EXPONENT_OFFSET end def significand @significand ||= two_highest_bits_set? ? '0' : bits_to_significand.to_s end def bits_to_significand significand = high_bits & 0x1ffffffffffff significand = significand << 64 significand |= low_bits end def two_highest_bits_set? high_bits & TWO_HIGHEST_BITS_SET == TWO_HIGHEST_BITS_SET end def nan? high_bits & NAN_MASK == NAN_MASK end def negative? high_bits & SIGN_BIT_MASK == SIGN_BIT_MASK end def infinity? high_bits & INFINITY_MASK == INFINITY_MASK end def high_bits @decimal128.instance_variable_get(:@high) end def low_bits @decimal128.instance_variable_get(:@low) end end end end endbson-4.3.0/lib/bson/integer.rb0000644000004100000410000001120113236361476016206 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 # Injects behaviour for encoding and decoding integer values to and from # raw bytes as specified by the BSON spec. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 module Integer # The maximum 32 bit integer value. # # @since 2.0.0 MAX_32BIT = (1 << 31) - 1 # The maximum 64 bit integer value. # # @since 2.0.0 MAX_64BIT = (1 << 63) - 1 # The minimum 32 bit integer value. # # @since 2.0.0 MIN_32BIT = -(1 << 31) # The minimum 64 bit integer value. # # @since 2.0.0 MIN_64BIT = -(1 << 63) # The BSON index size. # # @since 2.0.0 BSON_INDEX_SIZE = 1024.freeze # A hash of index values for array optimization. # # @since 2.0.0 BSON_ARRAY_INDEXES = ::Array.new(BSON_INDEX_SIZE) do |i| (i.to_s.force_encoding(BINARY) << NULL_BYTE).freeze end.freeze # Is this integer a valid BSON 32 bit value? # # @example Is the integer a valid 32 bit value? # 1024.bson_int32? # # @return [ true, false ] If the integer is 32 bit. # # @since 2.0.0 def bson_int32? (MIN_32BIT <= self) && (self <= MAX_32BIT) end # Is this integer a valid BSON 64 bit value? # # @example Is the integer a valid 64 bit value? # 1024.bson_int64? # # @return [ true, false ] If the integer is 64 bit. # # @since 2.0.0 def bson_int64? (MIN_64BIT <= self) && (self <= MAX_64BIT) end # Get the BSON type for this integer. Will depend on whether the integer # is 32 bit or 64 bit. # # @example Get the BSON type for the integer. # 1024.bson_type # # @return [ String ] The single byte BSON type. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def bson_type bson_int32? ? Int32::BSON_TYPE : (bson_int64? ? Int64::BSON_TYPE : out_of_range!) end # Get the integer as encoded BSON. # # @example Get the integer as encoded BSON. # 1024.to_bson # # @return [ BSON::ByteBuffer ] The buffer with the encoded object. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?) if bson_int32? buffer.put_int32(self) elsif bson_int64? buffer.put_int64(self) else out_of_range! end end # Convert the integer to a 32 bit (4 bytes) raw bytes string. # # @example Convert the integer to it's 32 bit bytes. # 1024.to_bson_int32 # # @param [ String ] encoded The string to encode to. # # @return [ String ] The encoded string. # # @since 2.0.0 def to_bson_int32(encoded) append_bson_int32(encoded) end # Convert the integer to a 64 bit (8 bytes) raw bytes string. # # @example Convert the integer to it's 64 bit bytes. # 1024.to_bson_int64 # # @param [ String ] encoded The string to encode to. # # @return [ String ] The encoded string. # # @since 2.0.0 def to_bson_int64(encoded) append_bson_int32(encoded) encoded << ((self >> 32) & 255) encoded << ((self >> 40) & 255) encoded << ((self >> 48) & 255) encoded << ((self >> 56) & 255) end # Convert the integer to a BSON string key. # # @example Convert the integer to a BSON key string. # 1.to_bson_key # # @param [ true, false ] validating_keys If BSON should validate the key. # # @return [ String ] The string key. # # @since 2.0.0 def to_bson_key(validating_keys = Config.validating_keys?) to_s.to_bson_key(validating_keys) end private def append_bson_int32(encoded) encoded << (self & 255) encoded << ((self >> 8) & 255) encoded << ((self >> 16) & 255) encoded << ((self >> 24) & 255) end def out_of_range! raise RangeError.new("#{self} is not a valid 8 byte integer value.") end end # Enrich the core Integer class with this module. # # @since 2.0.0 ::Integer.send(:include, Integer) end bson-4.3.0/lib/bson/registry.rb0000644000004100000410000000464613236361476016440 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 # Provides constant values for each to the BSON types and mappings from raw # bytes back to these types. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 module Registry extend self # A Mapping of all the BSON types to their corresponding Ruby classes. # # @since 2.0.0 MAPPINGS = {} # Get the class for the single byte identifier for the type in the BSON # specification. # # @example Get the type for the byte. # BSON::Registry.get("\x01") # # @return [ Class ] The corresponding Ruby class for the type. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def get(byte, field = nil) if type = MAPPINGS[byte] || (byte.is_a?(String) && type = MAPPINGS[byte.ord]) type else handle_unsupported_type!(byte, field) end end # Register the Ruby type for the corresponding single byte. # # @example Register the type. # BSON::Registry.register("\x01", Float) # # @param [ String ] byte The single byte. # @param [ Class ] type The class the byte maps to. # # @return [ Class ] The class. # # @since 2.0.0 def register(byte, type) MAPPINGS[byte.ord] = type define_type_reader(type) end # Raised when trying to get a type from the registry that doesn't exist. # # @since 4.1.0 class UnsupportedType < RuntimeError; end private def define_type_reader(type) type.module_eval <<-MOD def bson_type; BSON_TYPE; end MOD end def handle_unsupported_type!(byte, field) message = "Detected unknown BSON type #{byte.inspect} " message += (field ? "for fieldname \"#{field}\". " : "in array. ") message +="Are you using the latest BSON version?" raise UnsupportedType.new(message) end end end bson-4.3.0/lib/bson/int64.rb0000644000004100000410000000514513236361476015527 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 # Represents a $maxKey type, which compares less than any other value in the # specification. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 class Int64 # A boolean is type 0x08 in the BSON spec. # # @since 2.0.0 BSON_TYPE = 18.chr.force_encoding(BINARY).freeze # Constant for the int 64 pack directive. # # @since 2.0.0 PACK = "q<".freeze # Deserialize an Integer from BSON. # # @param [ ByteBuffer ] buffer The byte buffer. # # @return [ Integer ] The decoded Integer. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def self.from_bson(buffer) buffer.get_int64 end # Instantiate a BSON Int64. # # @param [ Integer ] integer The 64-bit integer. # # @see http://bsonspec.org/#/specification # # @since 4.2.0 def initialize(integer) out_of_range! unless integer.bson_int64? @integer = integer.freeze end # Append the integer as encoded BSON to a ByteBuffer. # # @example Encoded the integer and append to a ByteBuffer. # int64.to_bson # # @return [ BSON::ByteBuffer ] The buffer with the encoded integer. # # @see http://bsonspec.org/#/specification # # @since 4.2.0 def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?) buffer.put_int64(@integer) end # Convert the integer to a BSON string key. # # @example Convert the integer to a BSON key string. # int.to_bson_key # # @param [ true, false ] validating_keys If BSON should validate the key. # # @return [ String ] The string key. # # @since 4.2.0 def to_bson_key(validating_keys = Config.validating_keys?) @integer.to_bson_key(validating_keys) end private def out_of_range! raise RangeError.new("#{self} is not a valid 8 byte integer value.") end # Register this type when the module is loaded. # # @since 2.0.0 Registry.register(BSON_TYPE, self) end end bson-4.3.0/lib/bson/environment.rb0000644000004100000410000000251413236361476017124 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 # Provides static helper methods around determining what environment is # running without polluting the global namespace. # # @since 2.0.0 module Environment extend self # Determine if we are using JRuby or not. # # @example Are we running with JRuby? # Environment.jruby? # # @return [ true, false ] If JRuby is our vm. # # @since 2.0.0 def jruby? @jruby ||= defined?(JRUBY_VERSION) end # Determine if we are using Ruby version 1.9. # # @example Are we running with Ruby version 1.9? # Environment.ruby_1_9? # # @return [ true, false ] If the Ruby version is 1.9. # # @since 4.2.0 def ruby_1_9? @ruby_1_9 ||= RUBY_VERSION < '2.0.0' end end end bson-4.3.0/lib/bson/timestamp.rb0000644000004100000410000000761413236361476016571 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 # Represents a timestamp type, which is predominately used for sharding. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 class Timestamp include JSON include Comparable # A timestamp is type 0x11 in the BSON spec. # # @since 2.0.0 BSON_TYPE = 17.chr.force_encoding(BINARY).freeze # Error message if an object other than a Timestamp is compared with this object. # # @since 4.3.0 COMPARISON_ERROR_MESSAGE = 'comparison of %s with Timestamp failed'.freeze # @!attribute seconds # @return [ Integer ] The number of seconds. # @since 2.0.0 # # @!attribute increment # @return [ Integer ] The incrementing value. # @since 2.0.0 # attr_reader :seconds, :increment # Determine if this timestamp is equal to another object. # # @example Check the timestamp equality. # timestamp == other # # @param [ Object ] other The object to compare against. # # @return [ true, false ] If the objects are equal. # # @since 2.0.0 def ==(other) return false unless other.is_a?(Timestamp) seconds == other.seconds && increment == other.increment end # Determine if this timestamp is greater or less than another object. # # @example Compare the timestamp. # timestamp < other # # @param [ Object ] other The object to compare against. # # @return [ true, false ] The result of the comparison. # # @since 4.3.0 def <=>(other) raise ArgumentError.new(COMPARISON_ERROR_MESSAGE % other.class) unless other.is_a?(Timestamp) return 0 if self == other a = [ seconds, increment ] b = [ other.seconds, other.increment ] [ a, b ].sort[0] == a ? -1 : 1 end # Get the timestamp as JSON hash data. # # @example Get the timestamp as a JSON hash. # timestamp.as_json # # @return [ Hash ] The timestamp as a JSON hash. # # @since 2.0.0 def as_json(*args) { "$timestamp" => { "t" => seconds, "i" => increment } } end # Instantiate the new timestamp. # # @example Instantiate the timestamp. # BSON::Timestamp.new(5, 30) # # @param [ Integer ] seconds The number of seconds. # @param [ Integer ] increment The increment value. # # @since 2.0.0 def initialize(seconds, increment) @seconds, @increment = seconds, increment end # Get the timestamp as its encoded raw BSON bytes. # # @example Get the timestamp as BSON. # timestamp.to_bson # # @return [ BSON::ByteBuffer ] The buffer with the encoded object. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?) buffer.put_int32(increment) buffer.put_int32(seconds) end # Deserialize timestamp from BSON. # # @param [ ByteBuffer ] buffer The byte buffer. # # @return [ Timestamp ] The decoded timestamp. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def self.from_bson(buffer) increment = buffer.get_int32 seconds = buffer.get_int32 new(seconds, increment) end # Register this type when the module is loaded. # # @since 2.0.0 Registry.register(BSON_TYPE, self) end end bson-4.3.0/lib/bson/nil_class.rb0000644000004100000410000000304313236361476016525 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 # Injects behaviour for encoding and decoding nil values to and from # raw bytes as specified by the BSON spec. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 module NilClass include Specialized # A nil is type 0x0A in the BSON spec. # # @since 2.0.0 BSON_TYPE = 10.chr.force_encoding(BINARY).freeze module ClassMethods # Deserialize NilClass from BSON. # # @param [ ByteBuffer ] buffer The byte buffer. # # @return [ nil ] The decoded nil value. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def from_bson(buffer) nil end end # Register this type when the module is loaded. # # @since 2.0.0 Registry.register(BSON_TYPE, ::NilClass) end # Enrich the core NilClass class with this module. # # @since 2.0.0 ::NilClass.send(:include, NilClass) ::NilClass.send(:extend, NilClass::ClassMethods) end bson-4.3.0/lib/bson/symbol.rb0000644000004100000410000000622313236361476016066 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 # Injects behaviour for encoding and decoding symbol values to and from # raw bytes as specified by the BSON spec. # # @note Symbols are deprecated in the BSON spec, but they are still # currently supported here for backwards compatibility. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 module Symbol # A symbol is type 0x0E in the BSON spec. # # @since 2.0.0 BSON_TYPE = 14.chr.force_encoding(BINARY).freeze # Symbols are serialized as strings as symbols are now removed from the # BSON specification. Therefore the bson_type when serializing must be a # string. # # @example Get the BSON type for the symbol. # :test.bson_type # # @return [ String ] The single byte BSON type. # # @see http://bsonspec.org/#/specification # # @since 4.0.0 def bson_type String::BSON_TYPE end # Get the symbol as encoded BSON. # # @example Get the symbol as encoded BSON. # :test.to_bson # # @return [ BSON::ByteBuffer ] The buffer with the encoded object. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?) to_s.to_bson(buffer) end # Get the symbol as a BSON key name encoded C symbol. # # @example Get the symbol as a key name. # :test.to_bson_key # # @return [ String ] The encoded symbol as a BSON key. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def to_bson_key(validating_keys = Config.validating_keys?) to_s.to_bson_key(validating_keys) end # Converts the symbol to a normalized key in a BSON document. # # @example Convert the symbol to a normalized key. # :test.to_bson_normalized_key # # @return [ String ] The symbol as a non interned string. # # @since 3.0.0 def to_bson_normalized_key to_s end module ClassMethods # Deserialize a symbol from BSON. # # @param [ ByteBuffer ] buffer The byte buffer. # # @return [ Regexp ] The decoded symbol. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def from_bson(buffer) buffer.get_string.intern end end # Register this type when the module is loaded. # # @since 2.0.0 Registry::MAPPINGS[BSON_TYPE.ord] = ::Symbol end # Enrich the core Symbol class with this module. # # @since 2.0.0 ::Symbol.send(:include, Symbol) ::Symbol.send(:extend, Symbol::ClassMethods) end bson-4.3.0/lib/bson/object_id.rb0000644000004100000410000002533413236361476016507 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 "digest/md5" require "socket" require "thread" module BSON # Represents object_id data. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 class ObjectId include Comparable include JSON # A object_id is type 0x07 in the BSON spec. # # @since 2.0.0 BSON_TYPE = 7.chr.force_encoding(BINARY).freeze # Check equality of the object id with another object. # # @example Check if the object id is equal to the other. # object_id == other # # @param [ Object ] other The object to check against. # # @return [ true, false ] If the objects are equal. # # @since 2.0.0 def ==(other) return false unless other.is_a?(ObjectId) generate_data == other.send(:generate_data) end alias :eql? :== # Check case equality on the object id. # # @example Check case equality. # object_id === other # # @param [ Object ] other The object to check against. # # @return [ true, false ] If the objects are equal in a case. # # @since 2.0.0 def ===(other) return to_str === other.to_str if other.respond_to?(:to_str) super end # Return the object id as a JSON hash representation. # # @example Get the object id as JSON. # object_id.as_json # # @return [ Hash ] The object id as a JSON hash. # # @since 2.0.0 def as_json(*args) { "$oid" => to_s } end # Compare this object id with another object for use in sorting. # # @example Compare the object id with the other object. # object <=> other # # @param [ Object ] other The object to compare to. # # @return [ Integer ] The result of the comparison. # # @since 2.0.0 def <=>(other) generate_data <=> other.to_bson.to_s end # Return the UTC time at which this ObjectId was generated. This may # be used instread of a created_at timestamp since this information # is always encoded in the object id. # # @example Get the generation time. # object_id.generation_time # # @return [ Time ] The time the id was generated. # # @since 2.0.0 def generation_time ::Time.at(generate_data.unpack("N")[0]).utc end alias :to_time :generation_time # Get the hash value for the object id. # # @example Get the hash value. # object_id.hash # # @return [ Integer ] The hash value. # # @since 2.0.0 def hash generate_data.hash end # Get a nice string for use with object inspection. # # @example Inspect the object id. # object_id.inspect # # @return [ String ] The object id in form BSON::ObjectId('id') # # @since 2.0.0 def inspect "BSON::ObjectId('#{to_s}')" end # Dump the raw bson when calling Marshal.dump. # # @example Dump the raw bson. # Marshal.dump(object_id) # # @return [ String ] The raw bson bytes. # # @since 2.0.0 def marshal_dump generate_data end # Unmarshal the data into an object id. # # @example Unmarshal the data. # Marshal.load(data) # # @param [ String ] data The raw bson bytes. # # @return [ String ] The raw bson bytes. # # @since 2.0.0 def marshal_load(data) @raw_data = data end # Get the object id as it's raw BSON data. # # @example Get the raw bson bytes. # object_id.to_bson # # @note Since Moped's BSON and MongoDB BSON before 2.0.0 have different # internal representations, we will attempt to repair the data for cases # where the object was instantiated in a non-standard way. (Like a # Marshal.load) # # @return [ BSON::ByteBuffer ] The buffer with the encoded object. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?) buffer.put_bytes(generate_data) end # Get the string representation of the object id. # # @example Get the object id as a string. # object_id.to_s # # @return [ String ] The object id as a string. # # @since 2.0.0 def to_s generate_data.to_hex_string.force_encoding(UTF8) end alias :to_str :to_s # Raised when trying to create an object id with invalid data. # # @since 2.0.0 class Invalid < RuntimeError; end private def initialize_copy(other) generate_data other.instance_variable_set(:@raw_data, @raw_data) end def generate_data repair if defined?(@data) @raw_data ||= @@generator.next_object_id end def repair @raw_data = @data.to_bson_object_id remove_instance_variable(:@data) end class << self # Deserialize the object id from raw BSON bytes. # # @example Get the object id from BSON. # ObjectId.from_bson(bson) # # @param [ ByteBuffer ] buffer The byte buffer. # # @return [ BSON::ObjectId ] The object id. # # @since 2.0.0 def from_bson(buffer) from_data(buffer.get_bytes(12)) end # Create a new object id from raw bytes. # # @example Create an object id from raw bytes. # BSON::ObjectId.from_data(data) # # @param [ String ] data The raw bytes. # # @return [ ObjectId ] The new object id. # # @since 2.0.0 def from_data(data) object_id = allocate object_id.instance_variable_set(:@raw_data, data) object_id end # Create a new object id from a string. # # @example Create an object id from the string. # BSON::ObjectId.from_string(id) # # @param [ String ] string The string to create the id from. # # @raise [ BSON::ObjectId::Invalid ] If the provided string is invalid. # # @return [ BSON::ObjectId ] The new object id. # # @since 2.0.0 def from_string(string) unless legal?(string) raise Invalid.new("'#{string}' is an invalid ObjectId.") end from_data([ string ].pack("H*")) end # Create a new object id from a time. # # @example Create an object id from a time. # BSON::ObjectId.from_time(time) # # @example Create an object id from a time, ensuring uniqueness. # BSON::ObjectId.from_time(time, unique: true) # # @param [ Time ] time The time to generate from. # @param [ Hash ] options The options. # # @option options [ true, false ] :unique Whether the id should be # unique. # # @return [ ObjectId ] The new object id. # # @since 2.0.0 def from_time(time, options = {}) from_data(options[:unique] ? @@generator.next_object_id(time.to_i) : [ time.to_i ].pack("Nx8")) end # Determine if the provided string is a legal object id. # # @example Is the string a legal object id? # BSON::ObjectId.legal?(string) # # @param [ String ] string The string to check. # # @return [ true, false ] If the string is legal. # # @since 2.0.0 def legal?(string) string.to_s =~ /\A[0-9a-f]{24}\z/i ? true : false end # Executes the provided block only if the size of the provided object is # 12. Used in legacy id repairs. # # @example Execute in a repairing block. # BSON::ObjectId.repair("test") { obj } # # @param [ String, Array ] object The object to repair. # # @raise [ Invalid ] If the array is not 12 elements. # # @return [ String ] The result of the block. # # @since 2.0.0 def repair(object) if object.size == 12 block_given? ? yield(object) : object else raise Invalid.new("#{object.inspect} is not a valid object id.") end end end # Inner class that encapsulates the behaviour of actually generating each # part of the ObjectId. # # @api private # # @since 2.0.0 class Generator # @!attribute machine_id # @return [ String ] The unique machine id. # @since 2.0.0 attr_reader :machine_id # Instantiate the new object id generator. Will set the machine id once # on the initial instantiation. # # @example Instantiate the generator. # BSON::ObjectId::Generator.new # # @since 2.0.0 def initialize @counter = rand(0x1000000) @machine_id = Digest::MD5.digest(Socket.gethostname).unpack("N")[0] @mutex = Mutex.new end # Return object id data based on the current time, incrementing the # object id counter. Will use the provided time if not nil. # # @example Get the next object id data. # generator.next_object_id # # @param [ Time ] time The optional time to generate with. # # @return [ String ] The raw object id bytes. # # @since 2.0.0 def next_object_id(time = nil) @mutex.lock begin count = @counter = (@counter + 1) % 0xFFFFFF ensure @mutex.unlock rescue nil end generate(time || ::Time.new.to_i, count) end # Generate object id data for a given time using the provided counter. # # @example Generate the object id bytes. # generator.generate(time) # # @param [ Integer ] time The time since epoch in seconds. # @param [ Integer ] counter The optional counter. # # @return [ String ] The raw object id bytes. # # @since 2.0.0 def generate(time, counter = 0) [ time, machine_id, process_id, counter << 8 ].pack("N NX lXX NX") end private if Environment.jruby? def process_id "#{Process.pid}#{Thread.current.object_id}".hash % 0xFFFF end else def process_id Process.pid % 0xFFFF end end end # We keep one global generator for object ids. # # @since 2.0.0 @@generator = Generator.new # Register this type when the module is loaded. # # @since 2.0.0 Registry.register(BSON_TYPE, self) end end bson-4.3.0/lib/bson/undefined.rb0000644000004100000410000000251113236361476016516 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 # Represents the Undefined BSON type # # @see http://bsonspec.org/#/specification # # @since 2.0.0 class Undefined include Specialized # Undefined is type 0x06 in the BSON spec. # # @since 2.0.0 BSON_TYPE = 6.chr.force_encoding(BINARY).freeze # Determine if undefined is equal to another object. # # @example Check undefined equality. # BSON::Undefined.new == object # # @param [ Object ] other The object to check against. # # @return [ true, false ] If the objects are equal. # # @since 2.0.0 def ==(other) self.class == other.class end # Register this type when the module is loaded. # # @since 2.0.0 Registry.register(BSON_TYPE, self) end end bson-4.3.0/lib/bson/specialized.rb0000644000004100000410000000370113236361476017053 0ustar www-datawww-data# Copyright (C) 2009-2014 MongoDB 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 # Provides behaviour to special values that exist in the BSON spec that don't # have a native type, like $minKey and $maxKey. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 module Specialized # Determine if the min key is equal to another object. # # @example Check min key equality. # BSON::MinKey.new == object # # @param [ Object ] other The object to check against. # # @return [ true, false ] If the objects are equal. # # @since 2.0.0 def ==(other) self.class == other.class end # Encode the min key - has no value since it only needs the type and field # name when being encoded. # # @example Encode the min key value. # min_key.to_bson # # @return [ BSON::ByteBuffer ] The buffer with the encoded object. # # @since 2.0.0 def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?) buffer end private def self.included(klass) klass.extend(ClassMethods) end module ClassMethods # Deserialize from BSON. # # @param [ ByteBuffer ] buffer The byte buffer. # # @return [ Specialized ] The decoded specialized class. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def from_bson(buffer) new end end end end bson-4.3.0/lib/bson/regexp.rb0000644000004100000410000002011513236361476016047 0ustar www-datawww-data# Copyright (C) 2009-2016 MongoDB 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 # Injects behaviour for encoding and decoding regular expression values to # and from raw bytes as specified by the BSON spec. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 module Regexp include JSON # A regular expression is type 0x0B in the BSON spec. # # @since 2.0.0 BSON_TYPE = 11.chr.force_encoding(BINARY).freeze # Extended value constant. # # @since 3.2.6 EXTENDED_VALUE = 'x'.freeze # Ignore case constant. # # @since 3.2.6 IGNORECASE_VALUE = 'i'.freeze # Multiline constant. # # @since 3.2.6 MULTILINE_VALUE = 'm'.freeze # Newline constant. # # @since 3.2.6 NEWLINE_VALUE = 's'.freeze # Ruby multiline constant. # # @since 3.2.6 # # @deprecated Will be removed in 5.0 RUBY_MULTILINE_VALUE = 'ms'.freeze # Get the regexp as JSON hash data. # # @example Get the regexp as a JSON hash. # regexp.as_json # # @return [ Hash ] The regexp as a JSON hash. # # @since 2.0.0 def as_json(*args) { "$regex" => source, "$options" => bson_options } end # Get the regular expression as encoded BSON. # # @example Get the regular expression as encoded BSON. # %r{\d+}.to_bson # # @note From the BSON spec: The first cstring is the regex pattern, # the second is the regex options string. Options are identified # by characters, which must be stored in alphabetical order. # Valid options are 'i' for case insensitive matching, # 'm' for multiline matching, 'x' for verbose mode, # 'l' to make \w, \W, etc. locale dependent, # 's' for dotall mode ('.' matches everything), # and 'u' to make \w, \W, etc. match unicode. # # @param [ BSON::ByteBuffer ] buffer The byte buffer to append to. # @param [ true, false ] validating_keys # # @return [ BSON::ByteBuffer ] The buffer with the encoded object. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?) buffer.put_cstring(source) buffer.put_cstring(bson_options) end private def bson_options # Ruby's Regexp always has BSON's equivalent of 'm' on, so always add it bson_ignorecase + MULTILINE_VALUE + bson_dotall + bson_extended end def bson_extended (options & ::Regexp::EXTENDED != 0) ? EXTENDED_VALUE : NO_VALUE end def bson_ignorecase (options & ::Regexp::IGNORECASE != 0) ? IGNORECASE_VALUE : NO_VALUE end def bson_dotall # Ruby Regexp's MULTILINE is equivalent to BSON's dotall value (options & ::Regexp::MULTILINE != 0) ? NEWLINE_VALUE : NO_VALUE end # Represents the raw values for the regular expression. # # @see https://jira.mongodb.org/browse/RUBY-698 # # @since 3.0.0 class Raw include JSON # @return [ String ] pattern The regex pattern. attr_reader :pattern # @return [ Integer ] options The options. attr_reader :options # Compile the Regular expression into the native type. # # @example Compile the regular expression. # raw.compile # # @return [ ::Regexp ] The compiled regular expression. # # @since 3.0.0 def compile @compiled ||= ::Regexp.new(pattern, options_to_int) end # Initialize the new raw regular expression. # # @example Initialize the raw regexp. # Raw.new(pattern, options) # # @param [ String ] pattern The regular expression pattern. # @param [ String, Integer ] options The options. # # @note The ability to specify options as an Integer is deprecated. # Please specify options as a String. The ability to pass options as # as Integer will be removed in version 5.0.0. # # @since 3.0.0 def initialize(pattern, options = '') @pattern = pattern @options = options end # Allow automatic delegation of methods to the Regexp object # returned by +compile+. # # @param [ String] method The name of a method. # # @since 3.1.0 def respond_to?(method, include_private = false) compile.respond_to?(method, include_private) || super end # Encode the Raw Regexp object to BSON. # # @example Get the raw regular expression as encoded BSON. # raw_regexp.to_bson # # @note From the BSON spec: The first cstring is the regex pattern, # the second is the regex options string. Options are identified # by characters, which must be stored in alphabetical order. # Valid options are 'i' for case insensitive matching, # 'm' for multiline matching, 'x' for verbose mode, # 'l' to make \w, \W, etc. locale dependent, # 's' for dotall mode ('.' matches everything), # and 'u' to make \w, \W, etc. match unicode. # # @param [ BSON::ByteBuffer ] buffer The byte buffer to append to. # @param [ true, false ] validating_keys # # @return [ BSON::ByteBuffer ] The buffer with the encoded object. # # @see http://bsonspec.org/#/specification # # @since 4.2.0 def to_bson(buffer = ByteBuffer.new, validating_keys = Config.validating_keys?) return compile.to_bson(buffer, validating_keys) if options.is_a?(Integer) buffer.put_cstring(source) buffer.put_cstring(options.chars.sort.join) end # Get the raw BSON regexp as JSON hash data. # # @example Get the raw regexp as a JSON hash. # raw_regexp.as_json # # @return [ Hash ] The raw regexp as a JSON hash. # # @since 4.2.0 def as_json(*args) { "$regex" => source, "$options" => options } end # Check equality of the raw bson regexp against another. # # @example Check if the raw bson regexp is equal to the other. # raw_regexp == other # # @param [ Object ] other The object to check against. # # @return [ true, false ] If the objects are equal. # # @since 4.2.0 def ==(other) return false unless other.is_a?(::Regexp::Raw) pattern == other.pattern && options == other.options end alias :eql? :== private def method_missing(method, *arguments) return super unless respond_to?(method) compile.send(method, *arguments) end def options_to_int return options if options.is_a?(Integer) opts = 0 opts |= ::Regexp::IGNORECASE if options.include?(IGNORECASE_VALUE) opts |= ::Regexp::MULTILINE if options.include?(NEWLINE_VALUE) opts |= ::Regexp::EXTENDED if options.include?(EXTENDED_VALUE) opts end end module ClassMethods # Deserialize the regular expression from BSON. # # @param [ ByteBuffer ] buffer The byte buffer. # # @return [ Regexp ] The decoded regular expression. # # @see http://bsonspec.org/#/specification # # @since 2.0.0 def from_bson(buffer) pattern = buffer.get_cstring options = buffer.get_cstring Raw.new(pattern, options) end end # Register this type when the module is loaded. # # @since 2.0.0 Registry.register(BSON_TYPE, ::Regexp) end # Enrich the core Regexp class with this module. # # @since 2.0.0 ::Regexp.send(:include, Regexp) ::Regexp.send(:extend, Regexp::ClassMethods) end bson-4.3.0/checksums.yaml.gz.sig0000444000004100000410000000040013236361476016563 0ustar www-datawww-data9 q‡Q ^)Ḛ inՎ9&+XQyS#qݨ?o_ LtM1zMAR*A@A ㈥~>w,/U5l[&']CU ,,h!aCo8Y>w0{)X9O1q\bМQI .I xō} 2֊]eDwcEn({(T&îx7bson-4.3.0/NOTICE0000644000004100000410000000006013236361476013422 0ustar www-datawww-dataRuby BSON Copyright (C) 2009-2013 MongoDB, Inc. bson-4.3.0/CONTRIBUTING.md0000644000004100000410000000236413236361476014760 0ustar www-datawww-dataContributing ============ Code Conventions ---------------- Code style should fall in line with the style guide outlined by [Github](https://github.com/styleguide/ruby) Testing ------- Bug fixes and new features should always have the appropriate specs, and the specs should follow the following guidelines: - Prefer `let` and `let!` over the use of instance variables and `subject`. - Prefer `expect(...).to eq(...) syntax over `...should eq(...)`. - Use shared examples to reduce duplication. - Use `describe "#method"` for instance method specs. - Use `describe ".method"` for class method specs. - Use `context` blocks to set up conditions. - Always provide descriptive specifications via `it`. Specs can be automatically run with Guard, via `bundle exec guard` Before commiting, run `rake` to ensure all specs pass with both pure Ruby and the native extensions. Git Etiquette ------------- Please follow the commit message guidelines as outlined [in this blog post](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html). If the commit fixes a bug, please add the JIRA number on the last line: ``` [ close RUBY-492 ] ``` Please ensure that only one feature/bug fix is in each pull request, and that it is squashed into a single commit. bson-4.3.0/LICENSE0000644000004100000410000002501713236361476013534 0ustar www-datawww-data 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 MongoDB, 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. bson-4.3.0/CHANGELOG.md0000644000004100000410000001577313236361476014350 0ustar www-datawww-dataBSON Changelog ============== ## 3.2.6 ### Bug Fixes * [#44](https://github.com/mongodb/bson-ruby/pull/44) Fixed regexp deserialization in conjunction with SSL io. (Niels Ganser) ## 3.2.5 ### Bug Fixes * [RUBY-1024](https://jira.mongodb.org/browse/RUBY-1024) Fixed Hash#merge only to yield when keys exist in both hashes. (Agis Anastasopoulos) ## 3.2.4 ### Bug Fixes * [RUBY-1019](https://jira.mongodb.org/browse/RUBY-1019) Performace improvements on deserialization. ## 3.2.3 ### Bug Fixes * [#41](https://github.com/mongodb/bson-ruby/pull/41) Normalizing arrays does not mutate. (Agis Anastasopoulos) * [#40](https://github.com/mongodb/bson-ruby/pull/40) Added big endian support. (Jeff Blight) ## 3.2.1 ### Bug Fixes [#39](https://github.com/mongodb/bson-ruby/pull/39) Fixed MD5 hashing of hostname in c extension. (James Hudon) ## 3.2.0 ### Bug Fixes * [RUBY-950](https://jira.mongodb.org/browse/RUBY-950) Don't encode to UTF-8 in Binary#to_bson, only force BINARY encoding. ### New features * Add `BSON.ObjectId` constructor for instantiating an ObjectId from a String. Update ObjectId#inspect to print out a string that can be evaluated into the corresponding ObjectId. (Tony Ta) ## 3.1.2 ### Bug Fixes * [RUBY-950](https://jira.mongodb.org/browse/RUBY-950) Encode to UTF-8 then force BINARY encoding in Binary#to_bson. ## 3.1.1 ### Bug Fixes * Fixed argument errors when delegating to regex objects. (Tom Scott) ## 3.1.0 ### New Features * `BSON::Regexp::Raw` now behaves like a regular `Regexp` by delegating to the compiled and wrapped regex. (Tom Scott) ### Bug Fixes * Fixed `inspect` on `BSON::Binary` to handle ASCII characters. (Jérémy Carlier) ## 3.0.4 ### Bug Fixes * Fixed `BSON::ObjectId.legal?` regular expression to properly check beginning and end of strings. ## 3.0.3 ### Bug Fixes * [#31](https://github.com/mongodb/bson-ruby/pull/31) Fix Int64 decode from strings. (Nobuyoshi Nakada) ## 3.0.2 ### Bug Fixes * [RUBY-898](https://jira.mongodb.org/browse/RUBY-898) Compensated for different return values of Socket#readbyte and OpenSSL::SSL::SSLSocket#readbyte. ## 3.0.1 ### Bug Fixes * Fixed installation on latest Rubygems which requires `'date'` to be required. ## 3.0.0 ### Backwards Incompatible Changes * [RUBY-852](https://jira.mongodb.org/browse/RUBY-852) Regular expressions that are deserialized now return a `BSON::Regexp::Raw` instead of a `Regexp` object. In order to get the regular expression compiled, call `#compile` on the returned object. raw.compile ### New Features * `BSON::Binary` now implements `#inspect` with a truncated view of the data for better readability. ### Bug Fixes * The native object id generation was fixed to match the raw Ruby. (Conrad Irwin) * [#23](http://github.com/mongodb/bson-ruby/pull/23): `BSON::Binary` types can be now used as hash keys. (Adam Wróbel) ## 2.2.3 ### Bug Fixes * Fixed native C encoding of strings and performace on Rubinius. ## 2.2.2 ### Bug Fixes * [#17](http://github.com/mongodb/bson-ruby/pull/17): Fixed `BSON::ObjectId` counter increment on Ruby 2.1.0 since method names can no longer override Ruby keywords. * [#16](http://github.com/mongodb/bson-ruby/pull/16): Fixed serialization of times when microseconds are causing `to_f` on time to be 1 microsecond inaccurate. (Francois Bernier) ## 2.2.1 ### Bug Fixes * [#15](http://github.com/mongodb/bson-ruby/pull/15): `Date` and `DateTime` instances now return the `Time` value for the BSON type, so that they can be serialized inside hashes and arrays. (Michael Sell) ## 2.2.0 ### Dependency Changes * Ruby 1.8 interpreters are no longer supported. ## 2.1.2 ### Bug Fixes * [#14](http://github.com/mongodb/bson-ruby/pull/14): Fixed all 1.8 errors related to `DateTime` serialization. ## 2.1.1 ### Bug Fixes * [#13](http://github.com/mongodb/bson-ruby/pull/13) / [RUBY-714](http://jira.mongodb.org/browse/RUBY-714): Require time in `DateTime` modules when using outside of environments that don't already have time included. ## 2.1.0 ### New Features * `Date` and `DateTime` objects in Ruby can now be serialized into BSON. `Date` is converted to a UTC `Time` at midnight and serialized, while `DateTime` is simply converted to the identical `Time` before serialization. Note that these objects will be deserialized into `Time` objects. ## 2.0.0 ### Backwards Incompatible Changes * `BSON::DEFAULT_MAX_BSON_SIZE` has been removed, as the BSON specification does not provide an upper limit on how large BSON documents can be. * `BSON.serialize` is no longer the entry point to serialize a BSON document into its raw bytes. For Ruby runtimes that support ordered hashes, you may simply call `to_bson` on the hash instance (Alternatively a `BSON::Document` is also a hash: { key: "value" }.to_bson BSON::Document[:key, "value"].to_bson For Ruby runtimes that do not support ordered hashes, then you must instantiate an instance of a `BSON::Document` (which is a subclass of hash) and call `to_bson` on that, since the BSON specification guarantees order of the fields: BSON::Document[:key, "value"].to_bson * `BSON.deserialize` is no longer the entry point for raw byte deserialization into a document. For Ruby runtimes that support ordered hashes, you may simply call `from_bson` on the `Hash` class if you want a `Hash` instance, or on `BSON::Document` if you want an instance of that. The input must be a `StringIO` object: Hash.from_bson(stringio) BSON::Document.from_bson(stringio) For Ruby runtimes that do not support ordered hashes, then `from_bson` must be called on `BSON::Document` in order to guarantee order: BSON::Document.from_bson(stringio) * Calling `to_json` on custom BSON objects now outputs different results from before, and conforms the BSON specification: - `BSON::Binary`: `{ "$binary" : "\x01", "$type" : "md5" }` - `BSON::Code`: `{ "$code" : "this.v = 5 }` - `BSON::CodeWithScope`: `{ "$code" : "this.v = value", "$scope" : { v => 5 }}` - `BSON::MaxKey`: `{ "$maxKey" : 1 }` - `BSON::MinKey`: `{ "$minKey" : 1 }` - `BSON::ObjectId`: `{ "$oid" : "4e4d66343b39b68407000001" }` - `BSON::Timestamp`: `{ "t" : 5, "i" : 30 }` - `Regexp`: `{ "$regex" : "[abc]", "$options" : "i" }` ### New Features * All Ruby objects that have a corresponding object defined in the BSON specification can now have `to_bson` called on them to get the raw BSON bytes. These objects include: - `Array` - `FalseClass` - `Float` - `Hash` - `Integer` - `NilClass` - `Regexp` - `String` - `Symbol` (deprecated) - `Time` - `TrueClass` * Custom types specific to the BSON specification that have Ruby objects defined for them may also have `to_bson` called on them to get the raw bytes. These types are: - `BSON::Binary` - `BSON::Code` - `BSON::CodeWithScope` - `BSON::MaxKey` - `BSON::MinKey` - `BSON::ObjectId` - `BSON::Timestamp` - `BSON::Undefined` bson-4.3.0/metadata.gz.sig0000444000004100000410000000040013236361476015415 0ustar www-datawww-data'ɱmyRuWGN< dK n[Rv@|f\N1RZRav'mmc{]O\{3Ӵi53k%K` 'xL@$NCDiRmdӢMfK -y@ɧ_ #else # include # include #endif #define BSON_BIG_ENDIAN 4321 #define BSON_LITTLE_ENDIAN 1234 #if defined(__sun) # include # if defined(_LITTLE_ENDIAN) # define BSON_BYTE_ORDER 1234 # else # define BSON_BYTE_ORDER 4321 # endif #endif /* See a similar check in ruby's sha2.h */ # ifndef BSON_BYTE_ORDER # ifdef WORDS_BIGENDIAN # define BSON_BYTE_ORDER BSON_BIG_ENDIAN # else # define BSON_BYTE_ORDER BSON_LITTLE_ENDIAN # endif # endif /* BSON_BYTE_ORDER */ #if defined(__sun) # define BSON_UINT16_SWAP_LE_BE(v) __bson_uint16_swap_slow((uint16_t)v) # define BSON_UINT32_SWAP_LE_BE(v) __bson_uint32_swap_slow((uint32_t)v) # define BSON_UINT64_SWAP_LE_BE(v) __bson_uint64_swap_slow((uint64_t)v) #elif defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__) && \ (__clang_major__ >= 3) && (__clang_minor__ >= 1) # if __has_builtin(__builtin_bswap16) # define BSON_UINT16_SWAP_LE_BE(v) __builtin_bswap16(v) # endif # if __has_builtin(__builtin_bswap32) # define BSON_UINT32_SWAP_LE_BE(v) __builtin_bswap32(v) # endif # if __has_builtin(__builtin_bswap64) # define BSON_UINT64_SWAP_LE_BE(v) __builtin_bswap64(v) # endif #elif defined(__GNUC__) && (__GNUC__ >= 4) # if __GNUC__ > 4 || (defined (__GNUC_MINOR__) && __GNUC_MINOR__ >= 3) # define BSON_UINT32_SWAP_LE_BE(v) __builtin_bswap32 ((uint32_t)v) # define BSON_UINT64_SWAP_LE_BE(v) __builtin_bswap64 ((uint64_t)v) # endif #endif #ifndef BSON_UINT16_SWAP_LE_BE # define BSON_UINT16_SWAP_LE_BE(v) __bson_uint16_swap_slow((uint16_t)v) #endif #ifndef BSON_UINT32_SWAP_LE_BE # define BSON_UINT32_SWAP_LE_BE(v) __bson_uint32_swap_slow((uint32_t)v) #endif #ifndef BSON_UINT64_SWAP_LE_BE # define BSON_UINT64_SWAP_LE_BE(v) __bson_uint64_swap_slow((uint64_t)v) #endif #if BSON_BYTE_ORDER == BSON_LITTLE_ENDIAN # define BSON_UINT16_TO_BE(v) BSON_UINT16_SWAP_LE_BE(v) # define BSON_UINT32_FROM_LE(v) ((uint32_t)v) # define BSON_UINT32_TO_LE(v) ((uint32_t)v) # define BSON_UINT32_FROM_BE(v) BSON_UINT32_SWAP_LE_BE(v) # define BSON_UINT32_TO_BE(v) BSON_UINT32_SWAP_LE_BE(v) # define BSON_UINT64_FROM_LE(v) ((uint64_t)v) # define BSON_UINT64_TO_LE(v) ((uint64_t)v) # define BSON_UINT64_FROM_BE(v) BSON_UINT64_SWAP_LE_BE(v) # define BSON_UINT64_TO_BE(v) BSON_UINT64_SWAP_LE_BE(v) # define BSON_DOUBLE_FROM_LE(v) ((double)v) # define BSON_DOUBLE_TO_LE(v) ((double)v) #elif BSON_BYTE_ORDER == BSON_BIG_ENDIAN # define BSON_UINT16_TO_BE(v) ((uint16_t)v) # define BSON_UINT32_FROM_LE(v) BSON_UINT32_SWAP_LE_BE(v) # define BSON_UINT32_TO_LE(v) BSON_UINT32_SWAP_LE_BE(v) # define BSON_UINT32_FROM_BE(v) ((uint32_t)v) # define BSON_UINT32_TO_BE(v) ((uint32_t)v) # define BSON_UINT64_FROM_LE(v) BSON_UINT64_SWAP_LE_BE(v) # define BSON_UINT64_TO_LE(v) BSON_UINT64_SWAP_LE_BE(v) # define BSON_UINT64_FROM_BE(v) ((uint64_t)v) # define BSON_UINT64_TO_BE(v) ((uint64_t)v) # define BSON_DOUBLE_FROM_LE(v) (__bson_double_swap_slow(v)) # define BSON_DOUBLE_TO_LE(v) (__bson_double_swap_slow(v)) #else # error "The endianness of target architecture is unknown." #endif /* *-------------------------------------------------------------------------- * * __bson_uint16_swap_slow -- * * Fallback endianness conversion for 16-bit integers. * * Returns: * The endian swapped version. * * Side effects: * None. * *-------------------------------------------------------------------------- */ static uint16_t __bson_uint16_swap_slow(uint16_t v) { return ((v & 0x00FF) << 8) | ((v & 0xFF00) >> 8); } /* *-------------------------------------------------------------------------- * * __bson_uint32_swap_slow -- * * Fallback endianness conversion for 32-bit integers. * * Returns: * The endian swapped version. * * Side effects: * None. * *-------------------------------------------------------------------------- */ static uint32_t __bson_uint32_swap_slow(uint32_t v) { return ((v & 0x000000FFU) << 24) | ((v & 0x0000FF00U) << 8) | ((v & 0x00FF0000U) >> 8) | ((v & 0xFF000000U) >> 24); } /* *-------------------------------------------------------------------------- * * __bson_uint64_swap_slow -- * * Fallback endianness conversion for 64-bit integers. * * Returns: * The endian swapped version. * * Side effects: * None. * *-------------------------------------------------------------------------- */ static uint64_t __bson_uint64_swap_slow(uint64_t v) { return ((v & 0x00000000000000FFULL) << 56) | ((v & 0x000000000000FF00ULL) << 40) | ((v & 0x0000000000FF0000ULL) << 24) | ((v & 0x00000000FF000000ULL) << 8) | ((v & 0x000000FF00000000ULL) >> 8) | ((v & 0x0000FF0000000000ULL) >> 24) | ((v & 0x00FF000000000000ULL) >> 40) | ((v & 0xFF00000000000000ULL) >> 56); } /* *-------------------------------------------------------------------------- * * __bson_double_swap_slow -- * * Fallback endianness conversion for double floating point. * * Returns: * The endian swapped version. * * Side effects: * None. * *-------------------------------------------------------------------------- */ static double __bson_double_swap_slow(double v) { uint64_t uv; memcpy(&uv, &v, sizeof(v)); uv = BSON_UINT64_SWAP_LE_BE(uv); memcpy(&v, &uv, sizeof(v)); return v; } bson-4.3.0/ext/bson/bson_native.c0000644000004100000410000011643013236361476016743 0ustar www-datawww-data/* * Copyright (C) 2009-2016 MongoDB 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. */ #include #include #include #include #include #include "native-endian.h" #define BSON_BYTE_BUFFER_SIZE 1024 #ifndef HOST_NAME_HASH_MAX #define HOST_NAME_HASH_MAX 256 #endif #define BSON_TYPE_DOUBLE 1 #define BSON_TYPE_STRING 2 #define BSON_TYPE_OBJECT 3 #define BSON_TYPE_ARRAY 4 #define BSON_TYPE_INT32 16 #define BSON_TYPE_INT64 18 #define BSON_TYPE_BOOLEAN 8 typedef struct { size_t size; size_t write_position; size_t read_position; char buffer[BSON_BYTE_BUFFER_SIZE]; char *b_ptr; } byte_buffer_t; #define READ_PTR(byte_buffer_ptr) \ (byte_buffer_ptr->b_ptr + byte_buffer_ptr->read_position) #define READ_SIZE(byte_buffer_ptr) \ (byte_buffer_ptr->write_position - byte_buffer_ptr->read_position) #define WRITE_PTR(byte_buffer_ptr) \ (byte_buffer_ptr->b_ptr + byte_buffer_ptr->write_position) #define ENSURE_BSON_WRITE(buffer_ptr, length) \ { if (buffer_ptr->write_position + length > buffer_ptr->size) rb_bson_expand_buffer(buffer_ptr, length); } #define ENSURE_BSON_READ(buffer_ptr, length) \ { if (buffer_ptr->read_position + length > buffer_ptr->write_position) \ rb_raise(rb_eRangeError, "Attempted to read %zu bytes, but only %zu bytes remain", (size_t)length, READ_SIZE(buffer_ptr)); } static VALUE rb_bson_byte_buffer_allocate(VALUE klass); static VALUE rb_bson_byte_buffer_initialize(int argc, VALUE *argv, VALUE self); static VALUE rb_bson_byte_buffer_length(VALUE self); static VALUE rb_bson_byte_buffer_get_byte(VALUE self); static VALUE rb_bson_byte_buffer_get_bytes(VALUE self, VALUE i); static VALUE rb_bson_byte_buffer_get_cstring(VALUE self); static VALUE rb_bson_byte_buffer_get_decimal128_bytes(VALUE self); static VALUE rb_bson_byte_buffer_get_double(VALUE self); static VALUE rb_bson_byte_buffer_get_int32(VALUE self); static VALUE rb_bson_byte_buffer_get_int64(VALUE self); static VALUE rb_bson_byte_buffer_get_string(VALUE self); static VALUE rb_bson_byte_buffer_get_hash(VALUE self); static VALUE rb_bson_byte_buffer_get_array(VALUE self); static VALUE rb_bson_byte_buffer_put_byte(VALUE self, VALUE byte); static VALUE rb_bson_byte_buffer_put_bytes(VALUE self, VALUE bytes); static VALUE rb_bson_byte_buffer_put_cstring(VALUE self, VALUE string); static VALUE rb_bson_byte_buffer_put_decimal128(VALUE self, VALUE low, VALUE high); static VALUE rb_bson_byte_buffer_put_double(VALUE self, VALUE f); static VALUE rb_bson_byte_buffer_put_int32(VALUE self, VALUE i); static VALUE rb_bson_byte_buffer_put_int64(VALUE self, VALUE i); static VALUE rb_bson_byte_buffer_put_string(VALUE self, VALUE string); static VALUE rb_bson_byte_buffer_put_hash(VALUE self, VALUE hash, VALUE validating_keys); static VALUE rb_bson_byte_buffer_put_array(VALUE self, VALUE array, VALUE validating_keys); static VALUE rb_bson_byte_buffer_read_position(VALUE self); static VALUE rb_bson_byte_buffer_replace_int32(VALUE self, VALUE index, VALUE i); static VALUE rb_bson_byte_buffer_rewind(VALUE self); static VALUE rb_bson_byte_buffer_write_position(VALUE self); static VALUE rb_bson_byte_buffer_to_s(VALUE self); static VALUE rb_bson_object_id_generator_next(int argc, VALUE* args, VALUE self); static size_t rb_bson_byte_buffer_memsize(const void *ptr); static void rb_bson_byte_buffer_free(void *ptr); static void rb_bson_expand_buffer(byte_buffer_t* buffer_ptr, size_t length); static void rb_bson_generate_machine_id(VALUE rb_md5_class, char *rb_bson_machine_id); static bool rb_bson_utf8_validate(const char *utf8, size_t utf8_len, bool allow_null); static const rb_data_type_t rb_byte_buffer_data_type = { "bson/byte_buffer", { NULL, rb_bson_byte_buffer_free, rb_bson_byte_buffer_memsize } }; static uint8_t pvt_get_type_byte(byte_buffer_t *b); static VALUE pvt_get_int32(byte_buffer_t *b); static VALUE pvt_get_int64(byte_buffer_t *b); static VALUE pvt_get_double(byte_buffer_t *b); static VALUE pvt_get_string(byte_buffer_t *b); static VALUE pvt_get_boolean(byte_buffer_t *b); static VALUE pvt_read_field(byte_buffer_t *b, VALUE rb_buffer, uint8_t type); static void pvt_replace_int32(byte_buffer_t *b, int32_t position, int32_t newval); static void pvt_skip_cstring(byte_buffer_t *b); static void pvt_validate_length(byte_buffer_t *b); static void pvt_put_field(byte_buffer_t *b, VALUE rb_buffer, VALUE val, VALUE validating_keys); static void pvt_put_byte(byte_buffer_t *b, const char byte); static void pvt_put_int32(byte_buffer_t *b, const int32_t i32); static void pvt_put_int64(byte_buffer_t *b, const int64_t i); static void pvt_put_double(byte_buffer_t *b, double f); static void pvt_put_cstring(byte_buffer_t *b, VALUE string); static void pvt_put_bson_key(byte_buffer_t *b, VALUE string, VALUE validating_keys); /** * Holds the machine id hash for object id generation. */ static char rb_bson_machine_id_hash[HOST_NAME_HASH_MAX]; /** * The counter for incrementing object ids. */ static uint32_t rb_bson_object_id_counter; static VALUE rb_bson_registry; static VALUE rb_bson_illegal_key; /** * Initialize the bson_native extension. */ void Init_bson_native() { char rb_bson_machine_id[256]; VALUE rb_bson_module = rb_define_module("BSON"); VALUE rb_byte_buffer_class = rb_define_class_under(rb_bson_module, "ByteBuffer", rb_cObject); VALUE rb_bson_object_id_class = rb_const_get(rb_bson_module, rb_intern("ObjectId")); VALUE rb_bson_object_id_generator_class = rb_const_get(rb_bson_object_id_class, rb_intern("Generator")); VALUE rb_digest_class = rb_const_get(rb_cObject, rb_intern("Digest")); VALUE rb_md5_class = rb_const_get(rb_digest_class, rb_intern("MD5")); rb_bson_illegal_key = rb_const_get(rb_const_get(rb_bson_module, rb_intern("String")),rb_intern("IllegalKey")); rb_define_alloc_func(rb_byte_buffer_class, rb_bson_byte_buffer_allocate); rb_define_method(rb_byte_buffer_class, "initialize", rb_bson_byte_buffer_initialize, -1); rb_define_method(rb_byte_buffer_class, "length", rb_bson_byte_buffer_length, 0); rb_define_method(rb_byte_buffer_class, "get_byte", rb_bson_byte_buffer_get_byte, 0); rb_define_method(rb_byte_buffer_class, "get_bytes", rb_bson_byte_buffer_get_bytes, 1); rb_define_method(rb_byte_buffer_class, "get_cstring", rb_bson_byte_buffer_get_cstring, 0); rb_define_method(rb_byte_buffer_class, "get_decimal128_bytes", rb_bson_byte_buffer_get_decimal128_bytes, 0); rb_define_method(rb_byte_buffer_class, "get_double", rb_bson_byte_buffer_get_double, 0); rb_define_method(rb_byte_buffer_class, "get_hash", rb_bson_byte_buffer_get_hash, 0); rb_define_method(rb_byte_buffer_class, "get_array", rb_bson_byte_buffer_get_array, 0); rb_define_method(rb_byte_buffer_class, "get_int32", rb_bson_byte_buffer_get_int32, 0); rb_define_method(rb_byte_buffer_class, "get_int64", rb_bson_byte_buffer_get_int64, 0); rb_define_method(rb_byte_buffer_class, "get_string", rb_bson_byte_buffer_get_string, 0); rb_define_method(rb_byte_buffer_class, "put_byte", rb_bson_byte_buffer_put_byte, 1); rb_define_method(rb_byte_buffer_class, "put_bytes", rb_bson_byte_buffer_put_bytes, 1); rb_define_method(rb_byte_buffer_class, "put_cstring", rb_bson_byte_buffer_put_cstring, 1); rb_define_method(rb_byte_buffer_class, "put_decimal128", rb_bson_byte_buffer_put_decimal128, 2); rb_define_method(rb_byte_buffer_class, "put_double", rb_bson_byte_buffer_put_double, 1); rb_define_method(rb_byte_buffer_class, "put_int32", rb_bson_byte_buffer_put_int32, 1); rb_define_method(rb_byte_buffer_class, "put_int64", rb_bson_byte_buffer_put_int64, 1); rb_define_method(rb_byte_buffer_class, "put_string", rb_bson_byte_buffer_put_string, 1); rb_define_method(rb_byte_buffer_class, "read_position", rb_bson_byte_buffer_read_position, 0); rb_define_method(rb_byte_buffer_class, "replace_int32", rb_bson_byte_buffer_replace_int32, 2); rb_define_method(rb_byte_buffer_class, "rewind!", rb_bson_byte_buffer_rewind, 0); rb_define_method(rb_byte_buffer_class, "write_position", rb_bson_byte_buffer_write_position, 0); rb_define_method(rb_byte_buffer_class, "to_s", rb_bson_byte_buffer_to_s, 0); rb_define_method(rb_bson_object_id_generator_class, "next_object_id", rb_bson_object_id_generator_next, -1); rb_define_method(rb_byte_buffer_class, "put_hash", rb_bson_byte_buffer_put_hash, 2); rb_define_method(rb_byte_buffer_class, "put_array", rb_bson_byte_buffer_put_array, 2); // Get the object id machine id and hash it. rb_require("digest/md5"); gethostname(rb_bson_machine_id, sizeof(rb_bson_machine_id)); rb_bson_machine_id[255] = '\0'; rb_bson_generate_machine_id(rb_md5_class, rb_bson_machine_id); // Set the object id counter to a random number rb_bson_object_id_counter = FIX2INT(rb_funcall(rb_mKernel, rb_intern("rand"), 1, INT2FIX(0x1000000))); rb_bson_registry = rb_const_get(rb_bson_module, rb_intern("Registry")); } void rb_bson_generate_machine_id(VALUE rb_md5_class, char *rb_bson_machine_id) { VALUE digest = rb_funcall(rb_md5_class, rb_intern("digest"), 1, rb_str_new2(rb_bson_machine_id)); memcpy(rb_bson_machine_id_hash, RSTRING_PTR(digest), RSTRING_LEN(digest)); } /** * Allocates a bson byte buffer that wraps a byte_buffer_t. */ VALUE rb_bson_byte_buffer_allocate(VALUE klass) { byte_buffer_t *b; VALUE obj = TypedData_Make_Struct(klass, byte_buffer_t, &rb_byte_buffer_data_type, b); b->b_ptr = b->buffer; b->size = BSON_BYTE_BUFFER_SIZE; return obj; } /** * Initialize a byte buffer. */ VALUE rb_bson_byte_buffer_initialize(int argc, VALUE *argv, VALUE self) { VALUE bytes; rb_scan_args(argc, argv, "01", &bytes); if (!NIL_P(bytes)) { rb_bson_byte_buffer_put_bytes(self, bytes); } return self; } static int fits_int32(int64_t i64){ return i64 >= INT32_MIN && i64 <= INT32_MAX; } /* write the byte denoting the BSON type for the passed object*/ void pvt_put_type_byte(byte_buffer_t *b, VALUE val){ switch(TYPE(val)){ case T_BIGNUM: case T_FIXNUM: if(fits_int32(NUM2LL(val))){ pvt_put_byte(b, BSON_TYPE_INT32); }else{ pvt_put_byte(b, BSON_TYPE_INT64); } break; case T_STRING: pvt_put_byte(b, BSON_TYPE_STRING); break; case T_ARRAY: pvt_put_byte(b, BSON_TYPE_ARRAY); break; case T_TRUE: case T_FALSE: pvt_put_byte(b, BSON_TYPE_BOOLEAN); break; case T_HASH: pvt_put_byte(b, BSON_TYPE_OBJECT); break; case T_FLOAT: pvt_put_byte(b, BSON_TYPE_DOUBLE); break; default:{ VALUE type = rb_funcall(val, rb_intern("bson_type"),0); pvt_put_byte(b, *RSTRING_PTR(type)); break; } } } void pvt_put_field(byte_buffer_t *b, VALUE rb_buffer, VALUE val, VALUE validating_keys){ switch(TYPE(val)){ case T_BIGNUM: case T_FIXNUM:{ int64_t i64= NUM2LL(val); if(fits_int32(i64)){ pvt_put_int32(b, (int32_t)i64); }else{ pvt_put_int64(b, i64); } break; } case T_FLOAT: pvt_put_double(b, NUM2DBL(val)); break; case T_ARRAY: rb_bson_byte_buffer_put_array(rb_buffer, val, validating_keys); break; case T_TRUE: pvt_put_byte(b, 1); break; case T_FALSE: pvt_put_byte(b, 0); break; case T_HASH: rb_bson_byte_buffer_put_hash(rb_buffer, val, validating_keys); break; default:{ rb_funcall(val, rb_intern("to_bson"), 2, rb_buffer, validating_keys); break; } } } typedef struct{ byte_buffer_t *b; VALUE buffer; VALUE validating_keys; } put_hash_context; static int put_hash_callback(VALUE key, VALUE val, VALUE context){ VALUE buffer = ((put_hash_context*)context)->buffer; VALUE validating_keys = ((put_hash_context*)context)->validating_keys; byte_buffer_t *b = ((put_hash_context*)context)->b; pvt_put_type_byte(b, val); switch(TYPE(key)){ case T_STRING: pvt_put_bson_key(b, key, validating_keys); break; case T_SYMBOL: pvt_put_bson_key(b, rb_sym_to_s(key), validating_keys); break; default: rb_bson_byte_buffer_put_cstring(buffer, rb_funcall(key, rb_intern("to_bson_key"), 1, validating_keys)); } pvt_put_field(b, buffer, val, validating_keys); return ST_CONTINUE; } /** * serializes a hash into the byte buffer */ VALUE rb_bson_byte_buffer_put_hash(VALUE self, VALUE hash, VALUE validating_keys){ byte_buffer_t *b = NULL; put_hash_context context = {0}; size_t position = 0; size_t new_position = 0; int32_t new_length = 0; TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); Check_Type(hash, T_HASH); position = READ_SIZE(b); /* insert length placeholder */ pvt_put_int32(b, 0); context.buffer = self; context.validating_keys = validating_keys; context.b = b; rb_hash_foreach(hash, put_hash_callback, (VALUE)&context); pvt_put_byte(b, 0); /* update length placeholder with actual value */ new_position = READ_SIZE(b); new_length = new_position - position; pvt_replace_int32(b, position, new_length); return self; } static const char *index_strings[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "100", "101", "102", "103", "104", "105", "106", "107", "108", "109", "110", "111", "112", "113", "114", "115", "116", "117", "118", "119", "120", "121", "122", "123", "124", "125", "126", "127", "128", "129", "130", "131", "132", "133", "134", "135", "136", "137", "138", "139", "140", "141", "142", "143", "144", "145", "146", "147", "148", "149", "150", "151", "152", "153", "154", "155", "156", "157", "158", "159", "160", "161", "162", "163", "164", "165", "166", "167", "168", "169", "170", "171", "172", "173", "174", "175", "176", "177", "178", "179", "180", "181", "182", "183", "184", "185", "186", "187", "188", "189", "190", "191", "192", "193", "194", "195", "196", "197", "198", "199", "200", "201", "202", "203", "204", "205", "206", "207", "208", "209", "210", "211", "212", "213", "214", "215", "216", "217", "218", "219", "220", "221", "222", "223", "224", "225", "226", "227", "228", "229", "230", "231", "232", "233", "234", "235", "236", "237", "238", "239", "240", "241", "242", "243", "244", "245", "246", "247", "248", "249", "250", "251", "252", "253", "254", "255", "256", "257", "258", "259", "260", "261", "262", "263", "264", "265", "266", "267", "268", "269", "270", "271", "272", "273", "274", "275", "276", "277", "278", "279", "280", "281", "282", "283", "284", "285", "286", "287", "288", "289", "290", "291", "292", "293", "294", "295", "296", "297", "298", "299", "300", "301", "302", "303", "304", "305", "306", "307", "308", "309", "310", "311", "312", "313", "314", "315", "316", "317", "318", "319", "320", "321", "322", "323", "324", "325", "326", "327", "328", "329", "330", "331", "332", "333", "334", "335", "336", "337", "338", "339", "340", "341", "342", "343", "344", "345", "346", "347", "348", "349", "350", "351", "352", "353", "354", "355", "356", "357", "358", "359", "360", "361", "362", "363", "364", "365", "366", "367", "368", "369", "370", "371", "372", "373", "374", "375", "376", "377", "378", "379", "380", "381", "382", "383", "384", "385", "386", "387", "388", "389", "390", "391", "392", "393", "394", "395", "396", "397", "398", "399", "400", "401", "402", "403", "404", "405", "406", "407", "408", "409", "410", "411", "412", "413", "414", "415", "416", "417", "418", "419", "420", "421", "422", "423", "424", "425", "426", "427", "428", "429", "430", "431", "432", "433", "434", "435", "436", "437", "438", "439", "440", "441", "442", "443", "444", "445", "446", "447", "448", "449", "450", "451", "452", "453", "454", "455", "456", "457", "458", "459", "460", "461", "462", "463", "464", "465", "466", "467", "468", "469", "470", "471", "472", "473", "474", "475", "476", "477", "478", "479", "480", "481", "482", "483", "484", "485", "486", "487", "488", "489", "490", "491", "492", "493", "494", "495", "496", "497", "498", "499", "500", "501", "502", "503", "504", "505", "506", "507", "508", "509", "510", "511", "512", "513", "514", "515", "516", "517", "518", "519", "520", "521", "522", "523", "524", "525", "526", "527", "528", "529", "530", "531", "532", "533", "534", "535", "536", "537", "538", "539", "540", "541", "542", "543", "544", "545", "546", "547", "548", "549", "550", "551", "552", "553", "554", "555", "556", "557", "558", "559", "560", "561", "562", "563", "564", "565", "566", "567", "568", "569", "570", "571", "572", "573", "574", "575", "576", "577", "578", "579", "580", "581", "582", "583", "584", "585", "586", "587", "588", "589", "590", "591", "592", "593", "594", "595", "596", "597", "598", "599", "600", "601", "602", "603", "604", "605", "606", "607", "608", "609", "610", "611", "612", "613", "614", "615", "616", "617", "618", "619", "620", "621", "622", "623", "624", "625", "626", "627", "628", "629", "630", "631", "632", "633", "634", "635", "636", "637", "638", "639", "640", "641", "642", "643", "644", "645", "646", "647", "648", "649", "650", "651", "652", "653", "654", "655", "656", "657", "658", "659", "660", "661", "662", "663", "664", "665", "666", "667", "668", "669", "670", "671", "672", "673", "674", "675", "676", "677", "678", "679", "680", "681", "682", "683", "684", "685", "686", "687", "688", "689", "690", "691", "692", "693", "694", "695", "696", "697", "698", "699", "700", "701", "702", "703", "704", "705", "706", "707", "708", "709", "710", "711", "712", "713", "714", "715", "716", "717", "718", "719", "720", "721", "722", "723", "724", "725", "726", "727", "728", "729", "730", "731", "732", "733", "734", "735", "736", "737", "738", "739", "740", "741", "742", "743", "744", "745", "746", "747", "748", "749", "750", "751", "752", "753", "754", "755", "756", "757", "758", "759", "760", "761", "762", "763", "764", "765", "766", "767", "768", "769", "770", "771", "772", "773", "774", "775", "776", "777", "778", "779", "780", "781", "782", "783", "784", "785", "786", "787", "788", "789", "790", "791", "792", "793", "794", "795", "796", "797", "798", "799", "800", "801", "802", "803", "804", "805", "806", "807", "808", "809", "810", "811", "812", "813", "814", "815", "816", "817", "818", "819", "820", "821", "822", "823", "824", "825", "826", "827", "828", "829", "830", "831", "832", "833", "834", "835", "836", "837", "838", "839", "840", "841", "842", "843", "844", "845", "846", "847", "848", "849", "850", "851", "852", "853", "854", "855", "856", "857", "858", "859", "860", "861", "862", "863", "864", "865", "866", "867", "868", "869", "870", "871", "872", "873", "874", "875", "876", "877", "878", "879", "880", "881", "882", "883", "884", "885", "886", "887", "888", "889", "890", "891", "892", "893", "894", "895", "896", "897", "898", "899", "900", "901", "902", "903", "904", "905", "906", "907", "908", "909", "910", "911", "912", "913", "914", "915", "916", "917", "918", "919", "920", "921", "922", "923", "924", "925", "926", "927", "928", "929", "930", "931", "932", "933", "934", "935", "936", "937", "938", "939", "940", "941", "942", "943", "944", "945", "946", "947", "948", "949", "950", "951", "952", "953", "954", "955", "956", "957", "958", "959", "960", "961", "962", "963", "964", "965", "966", "967", "968", "969", "970", "971", "972", "973", "974", "975", "976", "977", "978", "979", "980", "981", "982", "983", "984", "985", "986", "987", "988", "989", "990", "991", "992", "993", "994", "995", "996", "997", "998", "999"}; /** * Writes an array index to the byte buffer. */ void pvt_put_array_index(byte_buffer_t *b, int32_t index) { char buffer[16]; const char *c_str = NULL; if (index < 1000) { c_str = index_strings[index]; } else { c_str = buffer; snprintf(buffer, sizeof(buffer), "%d", index); } size_t length = strlen(c_str) + 1; ENSURE_BSON_WRITE(b, length); memcpy(WRITE_PTR(b), c_str, length); b->write_position += length; } /** * serializes an array into the byte buffer */ VALUE rb_bson_byte_buffer_put_array(VALUE self, VALUE array, VALUE validating_keys){ byte_buffer_t *b = NULL; size_t new_position = 0; int32_t new_length = 0; size_t position = 0; VALUE *array_element = NULL; TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); Check_Type(array, T_ARRAY); position = READ_SIZE(b); /* insert length placeholder */ pvt_put_int32(b, 0); array_element = RARRAY_PTR(array); for(int32_t index=0; index < RARRAY_LEN(array); index++, array_element++){ pvt_put_type_byte(b, *array_element); pvt_put_array_index(b,index); pvt_put_field(b, self, *array_element, validating_keys); } pvt_put_byte(b, 0); /* update length placeholder */ new_position = READ_SIZE(b); new_length = new_position - position; pvt_replace_int32(b, position, new_length); return self; } /** * Get the length of the buffer. */ VALUE rb_bson_byte_buffer_length(VALUE self) { byte_buffer_t *b; TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); return UINT2NUM(READ_SIZE(b)); } /** * Get a single byte from the buffer. */ VALUE rb_bson_byte_buffer_get_byte(VALUE self) { byte_buffer_t *b; VALUE byte; TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); ENSURE_BSON_READ(b, 1); byte = rb_str_new(READ_PTR(b), 1); b->read_position += 1; return byte; } uint8_t pvt_get_type_byte(byte_buffer_t *b){ ENSURE_BSON_READ(b, 1); int8_t byte = *READ_PTR(b); b->read_position += 1; return (uint8_t)byte; } /** * Get bytes from the buffer. */ VALUE rb_bson_byte_buffer_get_bytes(VALUE self, VALUE i) { byte_buffer_t *b; VALUE bytes; const uint32_t length = FIX2LONG(i); TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); ENSURE_BSON_READ(b, length); bytes = rb_str_new(READ_PTR(b), length); b->read_position += length; return bytes; } VALUE pvt_get_boolean(byte_buffer_t *b){ VALUE result = Qnil; ENSURE_BSON_READ(b, 1); result = *READ_PTR(b) == 1 ? Qtrue: Qfalse; b->read_position += 1; return result; } /** * Get a cstring from the buffer. */ VALUE rb_bson_byte_buffer_get_cstring(VALUE self) { byte_buffer_t *b; VALUE string; int length; TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); length = (int)strlen(READ_PTR(b)); ENSURE_BSON_READ(b, length); string = rb_enc_str_new(READ_PTR(b), length, rb_utf8_encoding()); b->read_position += length + 1; return string; } /** * Reads but does not return a cstring from the buffer. */ void pvt_skip_cstring(byte_buffer_t *b) { int length; length = (int)strlen(READ_PTR(b)); ENSURE_BSON_READ(b, length); b->read_position += length + 1; } /** * Get the 16 bytes representing the decimal128 from the buffer. */ VALUE rb_bson_byte_buffer_get_decimal128_bytes(VALUE self) { byte_buffer_t *b; VALUE bytes; TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); ENSURE_BSON_READ(b, 16); bytes = rb_str_new(READ_PTR(b), 16); b->read_position += 16; return bytes; } /** * Get a double from the buffer. */ VALUE rb_bson_byte_buffer_get_double(VALUE self) { byte_buffer_t *b; TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); return pvt_get_double(b); } VALUE pvt_get_double(byte_buffer_t *b) { double d; ENSURE_BSON_READ(b, 8); memcpy(&d, READ_PTR(b), 8); b->read_position += 8; return DBL2NUM(BSON_DOUBLE_FROM_LE(d)); } /** * Get a int32 from the buffer. */ VALUE rb_bson_byte_buffer_get_int32(VALUE self) { byte_buffer_t *b; TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); return pvt_get_int32(b); } VALUE pvt_get_int32(byte_buffer_t *b) { int32_t i32; ENSURE_BSON_READ(b, 4); memcpy(&i32, READ_PTR(b), 4); b->read_position += 4; return INT2NUM(BSON_UINT32_FROM_LE(i32)); } /** * Get a int64 from the buffer. */ VALUE rb_bson_byte_buffer_get_int64(VALUE self) { byte_buffer_t *b; TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); return pvt_get_int64(b); } VALUE pvt_get_int64(byte_buffer_t *b) { int64_t i64; ENSURE_BSON_READ(b, 8); memcpy(&i64, READ_PTR(b), 8); b->read_position += 8; return LL2NUM(BSON_UINT64_FROM_LE(i64)); } /** * Get a string from the buffer. */ VALUE rb_bson_byte_buffer_get_string(VALUE self) { byte_buffer_t *b; TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); return pvt_get_string(b); } VALUE pvt_get_string(byte_buffer_t *b) { int32_t length; int32_t length_le; VALUE string; ENSURE_BSON_READ(b, 4); memcpy(&length, READ_PTR(b), 4); length_le = BSON_UINT32_FROM_LE(length); b->read_position += 4; ENSURE_BSON_READ(b, length_le); string = rb_enc_str_new(READ_PTR(b), length_le - 1, rb_utf8_encoding()); b->read_position += length_le; return string; } VALUE rb_bson_byte_buffer_get_hash(VALUE self){ VALUE doc = Qnil; byte_buffer_t *b=NULL; uint8_t type; VALUE cDocument = rb_const_get(rb_const_get(rb_cObject, rb_intern("BSON")), rb_intern("Document")); TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); pvt_validate_length(b); doc = rb_funcall(cDocument, rb_intern("allocate"),0); while((type = pvt_get_type_byte(b)) != 0){ VALUE field = rb_bson_byte_buffer_get_cstring(self); rb_hash_aset(doc, field, pvt_read_field(b, self, type)); } return doc; } VALUE rb_bson_byte_buffer_get_array(VALUE self){ byte_buffer_t *b; VALUE array = Qnil; uint8_t type; TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); pvt_validate_length(b); array = rb_ary_new(); while((type = pvt_get_type_byte(b)) != 0){ pvt_skip_cstring(b); rb_ary_push(array, pvt_read_field(b, self, type)); } return array; } /** * Read a single field from a hash or array */ VALUE pvt_read_field(byte_buffer_t *b, VALUE rb_buffer, uint8_t type){ switch(type) { case BSON_TYPE_INT32: return pvt_get_int32(b); case BSON_TYPE_INT64: return pvt_get_int64(b); case BSON_TYPE_DOUBLE: return pvt_get_double(b); case BSON_TYPE_STRING: return pvt_get_string(b); case BSON_TYPE_ARRAY: return rb_bson_byte_buffer_get_array(rb_buffer); case BSON_TYPE_OBJECT: return rb_bson_byte_buffer_get_hash(rb_buffer); case BSON_TYPE_BOOLEAN: return pvt_get_boolean(b); default: { VALUE klass = rb_funcall(rb_bson_registry,rb_intern("get"),1, INT2FIX(type)); VALUE value = rb_funcall(klass, rb_intern("from_bson"),1, rb_buffer); return value; } } } /** * Writes a byte to the byte buffer. */ VALUE rb_bson_byte_buffer_put_byte(VALUE self, VALUE byte) { byte_buffer_t *b; const char *str = RSTRING_PTR(byte); TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); ENSURE_BSON_WRITE(b, 1); memcpy(WRITE_PTR(b), str, 1); b->write_position += 1; return self; } void pvt_put_byte( byte_buffer_t *b, const char byte) { ENSURE_BSON_WRITE(b, 1); *WRITE_PTR(b) = byte; b->write_position += 1; } /** * Writes bytes to the byte buffer. */ VALUE rb_bson_byte_buffer_put_bytes(VALUE self, VALUE bytes) { byte_buffer_t *b; const char *str = RSTRING_PTR(bytes); const size_t length = RSTRING_LEN(bytes); TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); ENSURE_BSON_WRITE(b, length); memcpy(WRITE_PTR(b), str, length); b->write_position += length; return self; } /** * Writes a cstring to the byte buffer. */ VALUE rb_bson_byte_buffer_put_cstring(VALUE self, VALUE string) { byte_buffer_t *b; TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); pvt_put_cstring(b, string); return self; } void pvt_put_cstring(byte_buffer_t *b, VALUE string) { char *c_str = RSTRING_PTR(string); size_t length = RSTRING_LEN(string) + 1; if (!rb_bson_utf8_validate(c_str, length - 1, false)) { rb_raise(rb_eArgError, "String %s is not a valid UTF-8 CString.", c_str); } ENSURE_BSON_WRITE(b, length); memcpy(WRITE_PTR(b), c_str, length); b->write_position += length; } /** * Write a hash key to the byte buffer, validating it if requested */ void pvt_put_bson_key(byte_buffer_t *b, VALUE string, VALUE validating_keys){ if(RTEST(validating_keys)){ char *c_str = RSTRING_PTR(string); size_t length = RSTRING_LEN(string); if(length > 0 && (c_str[0] == '$' || memchr(c_str, '.', length))){ rb_exc_raise(rb_funcall(rb_bson_illegal_key, rb_intern("new"),1, string)); } } pvt_put_cstring(b, string); } /** * Writes a 128 bit decimal to the byte buffer. */ VALUE rb_bson_byte_buffer_put_decimal128(VALUE self, VALUE low, VALUE high) { byte_buffer_t *b; const int64_t low64 = BSON_UINT64_TO_LE(NUM2ULL(low)); const int64_t high64 = BSON_UINT64_TO_LE(NUM2ULL(high)); TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); ENSURE_BSON_WRITE(b, 8); memcpy(WRITE_PTR(b), &low64, 8); b->write_position += 8; ENSURE_BSON_WRITE(b, 8); memcpy(WRITE_PTR(b), &high64, 8); b->write_position += 8; return self; } /** * Writes a 64 bit double to the buffer. */ VALUE rb_bson_byte_buffer_put_double(VALUE self, VALUE f) { byte_buffer_t *b; TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); pvt_put_double(b,NUM2DBL(f)); return self; } void pvt_put_double(byte_buffer_t *b, double f) { const double d = BSON_DOUBLE_TO_LE(f); ENSURE_BSON_WRITE(b, 8); memcpy(WRITE_PTR(b), &d, 8); b->write_position += 8; } /** * Writes a 32 bit integer to the byte buffer. */ VALUE rb_bson_byte_buffer_put_int32(VALUE self, VALUE i) { byte_buffer_t *b; const int32_t i32 = NUM2INT(i); TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); pvt_put_int32(b, i32); return self; } void pvt_put_int32(byte_buffer_t *b, const int32_t i) { const int32_t i32 = BSON_UINT32_TO_LE(i); ENSURE_BSON_WRITE(b, 4); memcpy(WRITE_PTR(b), &i32, 4); b->write_position += 4; } /** * Writes a 64 bit integer to the byte buffer. */ VALUE rb_bson_byte_buffer_put_int64(VALUE self, VALUE i) { byte_buffer_t *b; const int64_t i64 = NUM2LL(i); TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); pvt_put_int64(b, i64); return self; } void pvt_put_int64(byte_buffer_t *b, const int64_t i) { const int64_t i64 = BSON_UINT64_TO_LE(i); ENSURE_BSON_WRITE(b, 8); memcpy(WRITE_PTR(b), &i64, 8); b->write_position += 8; } /** * validate the buffer contains the amount of bytes the array / hash claimns * and that it is null terminated */ void pvt_validate_length(byte_buffer_t *b) { int32_t length; ENSURE_BSON_READ(b, 4); memcpy(&length, READ_PTR(b), 4); length = BSON_UINT32_TO_LE(length); /* minimum valid length is 4 (byte count) + 1 (terminating byte) */ if(length >= 5){ ENSURE_BSON_READ(b, length); /* The last byte should be a null byte: it should be at length - 1 */ if( *(READ_PTR(b) + length - 1) != 0 ){ rb_raise(rb_eRangeError, "Buffer should have contained null terminator at %zu but contained %d", b->read_position + (size_t)length, (int)*(READ_PTR(b) + length)); } b->read_position += 4; } else{ rb_raise(rb_eRangeError, "Buffer contained invalid length %d at %zu", length, b->read_position); } } /** * Writes a string to the byte buffer. */ VALUE rb_bson_byte_buffer_put_string(VALUE self, VALUE string) { byte_buffer_t *b; int32_t length_le; char *str = RSTRING_PTR(string); const int32_t length = RSTRING_LEN(string) + 1; length_le = BSON_UINT32_TO_LE(length); if (!rb_bson_utf8_validate(str, length - 1, true)) { rb_raise(rb_eArgError, "String %s is not valid UTF-8.", str); } TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); ENSURE_BSON_WRITE(b, length + 4); memcpy(WRITE_PTR(b), &length_le, 4); b->write_position += 4; memcpy(WRITE_PTR(b), str, length); b->write_position += length; return self; } /** * Get the read position. */ VALUE rb_bson_byte_buffer_read_position(VALUE self) { byte_buffer_t *b; TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); return INT2NUM(b->read_position); } /** * Replace a 32 bit integer int the byte buffer. */ VALUE rb_bson_byte_buffer_replace_int32(VALUE self, VALUE index, VALUE i) { byte_buffer_t *b; TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); pvt_replace_int32(b, NUM2LONG(index), NUM2LONG(i)); return self; } void pvt_replace_int32(byte_buffer_t *b, int32_t position, int32_t newval) { const int32_t i32 = BSON_UINT32_TO_LE(newval); memcpy(READ_PTR(b) + position, &i32, 4); } /** * Reset the read position to the beginning of the byte buffer. */ VALUE rb_bson_byte_buffer_rewind(VALUE self) { byte_buffer_t *b; TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); b->read_position = 0; return self; } /** * Get the write position. */ VALUE rb_bson_byte_buffer_write_position(VALUE self) { byte_buffer_t *b; TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); return INT2NUM(b->write_position); } /** * Convert the buffer to a string. */ VALUE rb_bson_byte_buffer_to_s(VALUE self) { byte_buffer_t *b; TypedData_Get_Struct(self, byte_buffer_t, &rb_byte_buffer_data_type, b); return rb_str_new(READ_PTR(b), READ_SIZE(b)); } /** * Get the size of the byte_buffer_t in memory. */ size_t rb_bson_byte_buffer_memsize(const void *ptr) { return ptr ? sizeof(byte_buffer_t) : 0; } /** * Free the memory for the byte buffer. */ void rb_bson_byte_buffer_free(void *ptr) { byte_buffer_t *b = ptr; if (b->b_ptr != b->buffer) { xfree(b->b_ptr); } xfree(b); } /** * Expand the byte buffer linearly. */ void rb_bson_expand_buffer(byte_buffer_t* buffer_ptr, size_t length) { const size_t required_size = buffer_ptr->write_position - buffer_ptr->read_position + length; if (required_size <= buffer_ptr->size) { memmove(buffer_ptr->b_ptr, READ_PTR(buffer_ptr), READ_SIZE(buffer_ptr)); buffer_ptr->write_position -= buffer_ptr->read_position; buffer_ptr->read_position = 0; } else { char *new_b_ptr; const size_t new_size = required_size * 2; new_b_ptr = ALLOC_N(char, new_size); memcpy(new_b_ptr, READ_PTR(buffer_ptr), READ_SIZE(buffer_ptr)); if (buffer_ptr->b_ptr != buffer_ptr->buffer) { xfree(buffer_ptr->b_ptr); } buffer_ptr->b_ptr = new_b_ptr; buffer_ptr->size = new_size; buffer_ptr->write_position -= buffer_ptr->read_position; buffer_ptr->read_position = 0; } } /** * Generate the next object id. */ VALUE rb_bson_object_id_generator_next(int argc, VALUE* args, VALUE self) { char bytes[12]; uint32_t t; uint32_t c; uint16_t pid = BSON_UINT16_TO_BE(getpid()); if (argc == 0 || (argc == 1 && *args == Qnil)) { t = BSON_UINT32_TO_BE((int) time(NULL)); } else { t = BSON_UINT32_TO_BE(NUM2ULONG(rb_funcall(*args, rb_intern("to_i"), 0))); } c = BSON_UINT32_TO_BE(rb_bson_object_id_counter << 8); memcpy(&bytes, &t, 4); memcpy(&bytes[4], rb_bson_machine_id_hash, 3); memcpy(&bytes[7], &pid, 2); memcpy(&bytes[9], &c, 3); rb_bson_object_id_counter++; return rb_str_new(bytes, 12); } /** * Taken from libbson. */ static void _bson_utf8_get_sequence(const char *utf8, uint8_t *seq_length, uint8_t *first_mask) { unsigned char c = *(const unsigned char *)utf8; uint8_t m; uint8_t n; /* * See the following[1] for a description of what the given multi-byte * sequences will be based on the bits set of the first byte. We also need * to mask the first byte based on that. All subsequent bytes are masked * against 0x3F. * * [1] http://www.joelonsoftware.com/articles/Unicode.html */ if ((c & 0x80) == 0) { n = 1; m = 0x7F; } else if ((c & 0xE0) == 0xC0) { n = 2; m = 0x1F; } else if ((c & 0xF0) == 0xE0) { n = 3; m = 0x0F; } else if ((c & 0xF8) == 0xF0) { n = 4; m = 0x07; } else if ((c & 0xFC) == 0xF8) { n = 5; m = 0x03; } else if ((c & 0xFE) == 0xFC) { n = 6; m = 0x01; } else { n = 0; m = 0; } *seq_length = n; *first_mask = m; } /** * Taken from libbson. */ bool rb_bson_utf8_validate(const char *utf8, size_t utf8_len, bool allow_null) { uint32_t c; uint8_t first_mask; uint8_t seq_length; unsigned i; unsigned j; if (!utf8) { return false; } for (i = 0; i < utf8_len; i += seq_length) { _bson_utf8_get_sequence(&utf8[i], &seq_length, &first_mask); /* * Ensure we have a valid multi-byte sequence length. */ if (!seq_length) { return false; } /* * Ensure we have enough bytes left. */ if ((utf8_len - i) < seq_length) { return false; } /* * Also calculate the next char as a unichar so we can * check code ranges for non-shortest form. */ c = utf8 [i] & first_mask; /* * Check the high-bits for each additional sequence byte. */ for (j = i + 1; j < (i + seq_length); j++) { c = (c << 6) | (utf8 [j] & 0x3F); if ((utf8[j] & 0xC0) != 0x80) { return false; } } /* * Check for NULL bytes afterwards. * * Hint: if you want to optimize this function, starting here to do * this in the same pass as the data above would probably be a good * idea. You would add a branch into the inner loop, but save possibly * on cache-line bouncing on larger strings. Just a thought. */ if (!allow_null) { for (j = 0; j < seq_length; j++) { if (((i + j) > utf8_len) || !utf8[i + j]) { return false; } } } /* * Code point wont fit in utf-16, not allowed. */ if (c > 0x0010FFFF) { return false; } /* * Byte is in reserved range for UTF-16 high-marks * for surrogate pairs. */ if ((c & 0xFFFFF800) == 0xD800) { return false; } /* * Check non-shortest form unicode. */ switch (seq_length) { case 1: if (c <= 0x007F) { continue; } return false; case 2: if ((c >= 0x0080) && (c <= 0x07FF)) { continue; } else if (c == 0) { /* Two-byte representation for NULL. */ continue; } return false; case 3: if (((c >= 0x0800) && (c <= 0x0FFF)) || ((c >= 0x1000) && (c <= 0xFFFF))) { continue; } return false; case 4: if (((c >= 0x10000) && (c <= 0x3FFFF)) || ((c >= 0x40000) && (c <= 0xFFFFF)) || ((c >= 0x100000) && (c <= 0x10FFFF))) { continue; } return false; default: return false; } } return true; } bson-4.3.0/README.md0000644000004100000410000000340413236361476014002 0ustar www-datawww-dataBSON [![Build Status](https://secure.travis-ci.org/mongodb/bson-ruby.png?branch=master&.png)](http://travis-ci.org/mongodb/bson-ruby) [![Code Climate](https://codeclimate.com/github/mongodb/bson-ruby.png)](https://codeclimate.com/github/mongodb/bson-ruby) [![Coverage Status](https://coveralls.io/repos/mongodb/bson-ruby/badge.png?branch=master)](https://coveralls.io/r/mongodb/bson-ruby?branch=master) [![Inline docs](http://inch-ci.org/github/mongodb/bson-ruby.svg?branch=master)](http://inch-ci.org/github/mongodb/bson-ruby) ==== An implementation of the BSON specification in Ruby. Compatibility ------------- BSON is tested against MRI (1.9.2+), JRuby (1.7.0+) and Rubinius (2.0.0+). Documentation ------------- Current documentation can be found [here](http://docs.mongodb.org/ecosystem/tutorial/ruby-bson-tutorial/#ruby-bson-tutorial) API Documentation ----------------- The [API Documentation](http://rdoc.info/github/mongodb/bson-ruby/master/frames) is located at rdoc.info. BSON Specification ------------------ The [BSON specification](http://bsonspec.org) is at bsonspec.org. Versioning ---------- As of 2.0.0, this project adheres to the [Semantic Versioning Specification](http://semver.org/). License ------- Copyright (C) 2009-2016 MongoDB 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.