bson_minihash 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +17 -0
- data/.rspec +3 -0
- data/Gemfile +9 -0
- data/Guardfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +104 -0
- data/Rakefile +7 -0
- data/bson_minihash.gemspec +28 -0
- data/examples/mongo.rb +21 -0
- data/examples/moped.rb +21 -0
- data/lib/bson_minihash/hex.rb +40 -0
- data/lib/bson_minihash/version.rb +3 -0
- data/lib/bson_minihash.rb +73 -0
- data/spec/bson_minihash/bson_minihash_spec.rb +88 -0
- data/spec/bson_minihash/hex_spec.rb +57 -0
- data/spec/spec_helper.rb +19 -0
- metadata +148 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
OWY2OTRlM2MxODljZDQwNjQzNzAzODI4NDEyNGViZGVhYWY3OGMwYQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MWJhMWRiZDM5ZjlmNTA5Yzg4MTQ4ZjBjZTM2YjA0ZmM5MTc1MDU1Nw==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
MGNkODE3NWQ5ZWY4ZjU1MzM2NDk2OTdmZGQ1MDlhZjc2YTE1M2E1ZTIwYmZi
|
10
|
+
MmU3NDczNDEyMDRiYWI3NGRhMmExMDY5NjBlMjM5MjFlOGEzZmUxN2Q2MzEw
|
11
|
+
NDkxODUxMTg0YmQ2NWI2N2QzMWQ4YjJiODZkMjg3MmRmMjM5ZjM=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
Y2Y2NzY3ZmQ1Y2YyYThkOTVmMDI0NGJkYWFiYzkwMjNhN2I4NjIzOGEyZDg3
|
14
|
+
NzU4NzIxOTY1ZTcxNmMxYzAyNzgzZDlkOGJlZTdjMTc4ZTA3ODE2MmRjYzBh
|
15
|
+
NGJhMjIxNTY2NDI1MGRhZWU2YmU4MzgwNTU3NjBmNzU0NjgzY2U=
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Michael Shapiro
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
# BSON MiniHash
|
2
|
+
|
3
|
+
Compacts cryptographic hashes and other strings of limited charsets into blobs of BSON binary data, to reduce MongoDB storage and index size. Supports the vanilla Mongo driver, MongoMapper and Mongoid.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'bson_minihash'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install bson_minihash
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
You need to require either the 'bson' (Mongo driver/MongoMapper) or 'moped' (Mongoid) libraries before using MiniHash, so it knows which library's binary object type to give you. If you're using MongoMapper or Mongoid, one of those libraries has already been loaded for you.
|
22
|
+
|
23
|
+
### Digestion
|
24
|
+
|
25
|
+
If you've got some data you want to digest, then pack into a minihash, `BSONMiniHash#digest(data, hash_type)` provides a shortcut to do so.
|
26
|
+
|
27
|
+
require 'mongo'
|
28
|
+
require 'bson_minihash'
|
29
|
+
|
30
|
+
BSONMiniHash.digest("Geddy Lee", :md5)
|
31
|
+
#=> <BSON::Binary:70301078819340>
|
32
|
+
|
33
|
+
`hash_type` can be either `:md5` or `:sha1`
|
34
|
+
|
35
|
+
### Packing pre-existing hashes
|
36
|
+
|
37
|
+
If you've already got a hash as a string (e.g. passed as a parameter to your web app), you can pack it into a minihash that's suitable for a `#find` operation by using `BSONMiniHash.pack(string, hash_type)`.
|
38
|
+
|
39
|
+
require 'mongo'
|
40
|
+
require 'bson_minihash'
|
41
|
+
|
42
|
+
BSONMiniHash.pack('99f815bab7703b220c97feeca3ff9769', :md5)
|
43
|
+
#=> <BSON::Binary:70301087948100>
|
44
|
+
|
45
|
+
`hash_type` can be `:md5`, `:sha1` or `:hex`
|
46
|
+
|
47
|
+
It's best to pass the kind of hash you're using, minihash will do a little validation on the hash to make sure it fits the right character set and length. `:hex` just checks for the hex character range, without a length check, see the Caveats section below before using it.
|
48
|
+
|
49
|
+
### Examples
|
50
|
+
|
51
|
+
For examples of using minihashes in MongoDB, please see the `examples` direcotry.
|
52
|
+
|
53
|
+
## How does it work?
|
54
|
+
|
55
|
+
Have you ever wondered what the difference between `Digest::SHA1.digest` and `Digest::SHA1.hexdigest` is?
|
56
|
+
|
57
|
+
str = "Geddy Lee"
|
58
|
+
|
59
|
+
Digest::SHA1.digest(str).length
|
60
|
+
#=> 20
|
61
|
+
|
62
|
+
Digest::SHA1.hexdigest(str).length
|
63
|
+
#=> 40
|
64
|
+
|
65
|
+
They both contain the same information, except `#digest` uses only the space that it needs to represent the hash. SHA1 and MD5 both use different length combinations of only sixteen characters (hex) to represent their hashes. A nibble (half a byte, four bits), is enough room to store one of those character.
|
66
|
+
|
67
|
+
`#hexdigest` gives a UTF-8 string, which uses a byte per character when relegated to the ASCII range, double the amount needed.
|
68
|
+
|
69
|
+
So we convert each character in the hash to its actual hex value:
|
70
|
+
|
71
|
+
Digest::SHA1.hexdigest(str).split('').collect(&:hex)
|
72
|
+
#=> [3, 14, 10, 10, 12, 14, 9, 0, 14, 5, 5, 2, 6, 14, 5, 10, 12, 12, 9, 6, 15, 1, 13, 6, 13, 11, 1, 4, 6, 11, 0, 14, 13, 4, 0, 1, 12, 2, 15, 14]
|
73
|
+
|
74
|
+
Then pack them together into a new string, treating each number as a nibble:
|
75
|
+
|
76
|
+
Digest::SHA1.hexdigest(str).split('').collect(&:hex).in_groups_of(2).collect{|n| (n.first << 4) + n.last }.pack("C*")
|
77
|
+
#=> ">\xAA\xCE\x90\xE5RnZ\xCC\x96\xF1\xD6\xDB\x14k\x0E\xD4\x01\xC2\xFE"
|
78
|
+
|
79
|
+
That's a roundabout way of emulating `#digest` :)
|
80
|
+
|
81
|
+
Digest::SHA1.digest(str)
|
82
|
+
#=> ">\xAA\xCE\x90\xE5RnZ\xCC\x96\xF1\xD6\xDB\x14k\x0E\xD4\x01\xC2\xFE"
|
83
|
+
|
84
|
+
Or, we could use the handy "hex" format of `Array#pack`, which is what minihash does.
|
85
|
+
|
86
|
+
[Digest::SHA1.hexdigest(str)].pack('H*')
|
87
|
+
# => ">\xAA\xCE\x90\xE5RnZ\xCC\x96\xF1\xD6\xDB\x14k\x0E\xD4\x01\xC2\xFE"
|
88
|
+
|
89
|
+
## Efficiency
|
90
|
+
|
91
|
+
In MongoDB, you should see about a factor of two space saving for the minihash fields. Of course, you're spending some CPU power to pack the fields, but it's not much.
|
92
|
+
|
93
|
+
## Caveats
|
94
|
+
In MongoDB, it's not a great idea to use hashes as unique indexes, since there's always the possiblity of collisions.
|
95
|
+
|
96
|
+
If you choose to `#pack` a string with the `:hex` type, beware that an odd-length string will have an extra nibble at the end, since a byte is the smallest unit of allocation.
|
97
|
+
|
98
|
+
## Contributing
|
99
|
+
|
100
|
+
1. Fork it
|
101
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
102
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
103
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
104
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'bson_minihash/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "bson_minihash"
|
8
|
+
spec.version = BSONMiniHash::VERSION
|
9
|
+
spec.authors = ["Michael Shapiro"]
|
10
|
+
spec.email = ["koudelka@ryoukai.org"]
|
11
|
+
spec.summary = "Stores hashes in a BSON 'packed' format."
|
12
|
+
spec.description = "Saves space by storing strings with limited character sets as packed BSON BinData."
|
13
|
+
spec.homepage = 'https://github.com/koudelka/bson_minihash'
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
|
25
|
+
spec.add_development_dependency "mongo"
|
26
|
+
spec.add_development_dependency "bson_ext"
|
27
|
+
spec.add_development_dependency "moped"
|
28
|
+
end
|
data/examples/mongo.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'mongo'
|
2
|
+
require 'bson_minihash'
|
3
|
+
|
4
|
+
collection = Mongo::Connection.new('127.0.0.1', 27017).db('test').collection('artists')
|
5
|
+
|
6
|
+
# Digestion
|
7
|
+
mini_hash = BSONMiniHash.digest("Syd Vicious", :md5)
|
8
|
+
p mini_hash
|
9
|
+
collection.insert(name: "Syd Vicious", hash: mini_hash)
|
10
|
+
doc = collection.find_one(hash: mini_hash)
|
11
|
+
p doc
|
12
|
+
|
13
|
+
# Packing a hash you already have
|
14
|
+
mini_hash = BSONMiniHash.pack("3eaace90e5526e5acc96f1d6db146b0ed401c2fe", :sha1)
|
15
|
+
collection.insert(name: "Geddy Lee", hash: mini_hash)
|
16
|
+
doc = collection.find_one(hash: mini_hash)
|
17
|
+
p doc
|
18
|
+
|
19
|
+
|
20
|
+
# Unpacking a mini hash
|
21
|
+
p BSONMiniHash.unpack(doc['hash'])
|
data/examples/moped.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'moped'
|
2
|
+
require 'bson_minihash'
|
3
|
+
|
4
|
+
session = Moped::Session.new([ "127.0.0.1:27017" ])
|
5
|
+
session.use "test"
|
6
|
+
|
7
|
+
# Digestion
|
8
|
+
mini_hash = BSONMiniHash.digest("Syd Vicious", :md5)
|
9
|
+
session[:artists].insert(name: "Syd Vicious", hash: mini_hash)
|
10
|
+
doc = session[:artists].find(hash: mini_hash).first
|
11
|
+
p doc
|
12
|
+
|
13
|
+
# Packing a hash you already have
|
14
|
+
mini_hash = BSONMiniHash.pack("3eaace90e5526e5acc96f1d6db146b0ed401c2fe", :sha1)
|
15
|
+
session[:artists].insert(name: "Geddy Lee", hash: mini_hash)
|
16
|
+
doc = session[:artists].find(hash: mini_hash).first
|
17
|
+
p doc
|
18
|
+
|
19
|
+
|
20
|
+
# Unpacking a mini hash
|
21
|
+
p BSONMiniHash.unpack(doc['hash'])
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'digest'
|
2
|
+
|
3
|
+
module BSONMiniHash
|
4
|
+
module Hex
|
5
|
+
FORMAT = 'H*'.freeze
|
6
|
+
TYPES = [:md5, :sha1, :hex].freeze
|
7
|
+
|
8
|
+
def self.pack(str, type = :hex)
|
9
|
+
Hex.validate(str, type)
|
10
|
+
[str].pack(FORMAT)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.unpack(packed_str)
|
14
|
+
packed_str.unpack(FORMAT).first
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.validate(str, type)
|
18
|
+
raise ArgumentError, "Hex strings must comprise of characters between a-f and 0-9" unless str.match /^[a-f0-9]+$/i
|
19
|
+
|
20
|
+
case type
|
21
|
+
when :md5
|
22
|
+
raise ArgumentError, "MD5 strings must be 32 characters in length" unless str.length == 32
|
23
|
+
when :sha1
|
24
|
+
raise ArgumentError, "SHA1 strings must be 40 characters in length" unless str.length == 40
|
25
|
+
end
|
26
|
+
true
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.digest(data, type)
|
30
|
+
case type
|
31
|
+
when :md5
|
32
|
+
Digest::MD5.digest(data)
|
33
|
+
when :sha1
|
34
|
+
Digest::SHA1.digest(data)
|
35
|
+
else
|
36
|
+
raise ArgumentError, "type #{type} not supported"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module BSONMiniHash
|
2
|
+
|
3
|
+
def self.bson_lib
|
4
|
+
case
|
5
|
+
when Kernel.const_defined?(:Moped) # Mongoid
|
6
|
+
:moped
|
7
|
+
when Kernel.const_defined?(:BSON) # Mongo driver (incliding MongoMapper)
|
8
|
+
:bson
|
9
|
+
else
|
10
|
+
raise "In order to use BSONMiniHash, you need to have either the 'bson' or 'moped' gem loaded"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
#
|
15
|
+
# Beware, if you're not using SHA1, MD5 or any other hash with a length divisible by two,
|
16
|
+
# you'll get a zero padded string when doing a round trip as the packed string will have
|
17
|
+
# an extra nibble of space at the end.
|
18
|
+
#
|
19
|
+
def self.pack(str, type = :hex)
|
20
|
+
str = str.downcase.strip
|
21
|
+
|
22
|
+
packed_str = \
|
23
|
+
case
|
24
|
+
when Hex::TYPES.include?(type)
|
25
|
+
Hex.pack(str, type)
|
26
|
+
else
|
27
|
+
raise ArgumentError, "type #{type} not supported"
|
28
|
+
end
|
29
|
+
|
30
|
+
bson_obj(packed_str)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.digest(data, type)
|
34
|
+
packed_str = \
|
35
|
+
case
|
36
|
+
when Hex::TYPES.include?(type)
|
37
|
+
Hex.digest(data, type)
|
38
|
+
else
|
39
|
+
raise ArgumentError, "type #{type} not supported"
|
40
|
+
end
|
41
|
+
|
42
|
+
bson_obj(packed_str)
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.unpack(packed_obj, type = :hex)
|
46
|
+
#
|
47
|
+
# Both BSON and Moped give the right thing for to_s
|
48
|
+
#
|
49
|
+
packed_str = packed_obj.to_s
|
50
|
+
|
51
|
+
case
|
52
|
+
when Hex::TYPES.include?(type)
|
53
|
+
Hex.unpack(packed_str)
|
54
|
+
else
|
55
|
+
raise ArgumentError, "type #{type} not supported"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def self.bson_obj(packed_str)
|
62
|
+
case self.bson_lib
|
63
|
+
when :bson
|
64
|
+
BSON::Binary.new(packed_str)
|
65
|
+
when :moped
|
66
|
+
Moped::BSON::Binary.new(:user, packed_str)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
require "bson_minihash/version"
|
73
|
+
require "bson_minihash/hex"
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BSONMiniHash do
|
4
|
+
|
5
|
+
#
|
6
|
+
# These test only pass becauseof the order in which they're writting. It sucks.
|
7
|
+
#
|
8
|
+
# I don't see another way to do this, since there's no way to remove a module
|
9
|
+
# from the global namespace once it's been added.
|
10
|
+
#
|
11
|
+
|
12
|
+
context "No BSON Library" do
|
13
|
+
it "should throw an error" do
|
14
|
+
expect {
|
15
|
+
BSONMiniHash.pack('a')
|
16
|
+
}.to raise_error(RuntimeError)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "BSON" do
|
21
|
+
it "should detect when the BSON library (mongo driver / mongomapper) is in use" do
|
22
|
+
require 'bson'
|
23
|
+
BSONMiniHash.bson_lib.should == :bson
|
24
|
+
end
|
25
|
+
|
26
|
+
context "packing" do
|
27
|
+
it "should create a binary object of the right class" do
|
28
|
+
BSONMiniHash.pack('a').class.should == BSON::Binary
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should have the same value through a pack/unpack roundtrip" do
|
33
|
+
str = "abcdef1234567890"
|
34
|
+
BSONMiniHash.unpack(BSONMiniHash.pack(str)).should == str
|
35
|
+
end
|
36
|
+
|
37
|
+
context "digestion" do
|
38
|
+
it "should create a binary object of the right class" do
|
39
|
+
BSONMiniHash.digest('a', :md5).class.should == BSON::Binary
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should properly digest" do
|
43
|
+
str = 'abcdefghijklmnop1235'
|
44
|
+
BSONMiniHash.digest(str, :md5).to_s.should == Digest::MD5.digest(str)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should have the right value through a digest/unpack roundtrip" do
|
48
|
+
str = "abcdef1234567890"
|
49
|
+
BSONMiniHash.unpack(BSONMiniHash.digest(str, :sha1)).should == Digest::SHA1.hexdigest(str)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "Moped" do
|
55
|
+
it "should detect when the Moped library (mongoid) is in use" do
|
56
|
+
require 'moped'
|
57
|
+
BSONMiniHash.bson_lib.should == :moped
|
58
|
+
end
|
59
|
+
|
60
|
+
context "packing" do
|
61
|
+
it "should create a binary object of the right class" do
|
62
|
+
BSONMiniHash.pack('a').class.should == Moped::BSON::Binary
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should have the same value through a pack/unpack roundtrip" do
|
67
|
+
str = "abcdef1234567890"
|
68
|
+
BSONMiniHash.unpack(BSONMiniHash.pack(str)).should == str
|
69
|
+
end
|
70
|
+
|
71
|
+
context "digestion" do
|
72
|
+
it "should create a binary object of the right class" do
|
73
|
+
BSONMiniHash.digest('a', :md5).class.should == Moped::BSON::Binary
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should properly digest" do
|
77
|
+
str = 'abcdefghijklmnop1235'
|
78
|
+
BSONMiniHash.digest(str, :md5).to_s.should == Digest::MD5.digest(str)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should have the right value through a digest/unpack roundtrip" do
|
82
|
+
str = "abcdef1234567890"
|
83
|
+
BSONMiniHash.unpack(BSONMiniHash.digest(str, :sha1)).should == Digest::SHA1.hexdigest(str)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BSONMiniHash::Hex do
|
4
|
+
|
5
|
+
context "Packing" do
|
6
|
+
it "should correctly pack a hex string" do
|
7
|
+
str = "7e240de74fb1ed08fa08d38063f6a6a91462a815"
|
8
|
+
packed_str = "~$\r\xE7O\xB1\xED\b\xFA\b\xD3\x80c\xF6\xA6\xA9\x14b\xA8\x15"
|
9
|
+
BSONMiniHash::Hex.pack(str).should == packed_str
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should correctly unpack a hex string" do
|
13
|
+
str = "7e240de74fb1ed08fa08d38063f6a6a91462a815"
|
14
|
+
packed_str = "~$\r\xE7O\xB1\xED\b\xFA\b\xD3\x80c\xF6\xA6\xA9\x14b\xA8\x15"
|
15
|
+
BSONMiniHash::Hex.unpack(packed_str).should == str
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should correctly roundtrip a hex string" do
|
19
|
+
unpacked_str = "7e240de74fb1ed08fa08d38063f6a6a91462a815"
|
20
|
+
BSONMiniHash::Hex.unpack(BSONMiniHash::Hex.pack(unpacked_str)).should == unpacked_str
|
21
|
+
|
22
|
+
packed_str = "~$\r\xE7O\xB1\xED\b\xFA\b\xD3\x80c\xF6\xA6\xA9\x14b\xA8\x15"
|
23
|
+
BSONMiniHash::Hex.pack(BSONMiniHash::Hex.unpack(packed_str)).should == packed_str
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "Validation" do
|
28
|
+
it "should fail when the character set isn't in hex" do
|
29
|
+
str = Digest::MD5.hexdigest("a")
|
30
|
+
str[0] = 'g'
|
31
|
+
expect { BSONMiniHash::Hex.validate(str, :md5) }.to raise_error(ArgumentError)
|
32
|
+
end
|
33
|
+
|
34
|
+
context "MD5" do
|
35
|
+
it "should pass for a correctly formatted MD5" do
|
36
|
+
BSONMiniHash::Hex.validate(Digest::MD5.hexdigest("a"), :md5).should be_true
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should fail when the length is other than 32" do
|
40
|
+
str = Digest::MD5.hexdigest("a")
|
41
|
+
expect { BSONMiniHash::Hex.validate(str[1..-1], :md5) }.to raise_error(ArgumentError)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "SHA1" do
|
46
|
+
it "should pass for a correctly formatted SHA1" do
|
47
|
+
BSONMiniHash::Hex.validate(Digest::SHA1.hexdigest("a"), :sha1).should be_true
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should fail when the length is other than 40" do
|
51
|
+
str = Digest::SHA1.hexdigest("a")
|
52
|
+
expect { BSONMiniHash::Hex.validate(str[1..-1], :sha1) }.to raise_error(ArgumentError)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'bson_minihash'
|
2
|
+
|
3
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
4
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
5
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
6
|
+
# loaded once.
|
7
|
+
#
|
8
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
9
|
+
RSpec.configure do |config|
|
10
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
11
|
+
config.run_all_when_everything_filtered = true
|
12
|
+
config.filter_run :focus
|
13
|
+
|
14
|
+
# Run specs in random order to surface order dependencies. If you find an
|
15
|
+
# order dependency and want to debug it, you can fix the order by providing
|
16
|
+
# the seed, which is printed after each run.
|
17
|
+
# --seed 1234
|
18
|
+
#config.order = 'random'
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bson_minihash
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Michael Shapiro
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-05-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: mongo
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ! '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bson_ext
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ! '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: moped
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: Saves space by storing strings with limited character sets as packed
|
98
|
+
BSON BinData.
|
99
|
+
email:
|
100
|
+
- koudelka@ryoukai.org
|
101
|
+
executables: []
|
102
|
+
extensions: []
|
103
|
+
extra_rdoc_files: []
|
104
|
+
files:
|
105
|
+
- .gitignore
|
106
|
+
- .rspec
|
107
|
+
- Gemfile
|
108
|
+
- Guardfile
|
109
|
+
- LICENSE.txt
|
110
|
+
- README.md
|
111
|
+
- Rakefile
|
112
|
+
- bson_minihash.gemspec
|
113
|
+
- examples/mongo.rb
|
114
|
+
- examples/moped.rb
|
115
|
+
- lib/bson_minihash.rb
|
116
|
+
- lib/bson_minihash/hex.rb
|
117
|
+
- lib/bson_minihash/version.rb
|
118
|
+
- spec/bson_minihash/bson_minihash_spec.rb
|
119
|
+
- spec/bson_minihash/hex_spec.rb
|
120
|
+
- spec/spec_helper.rb
|
121
|
+
homepage: https://github.com/koudelka/bson_minihash
|
122
|
+
licenses:
|
123
|
+
- MIT
|
124
|
+
metadata: {}
|
125
|
+
post_install_message:
|
126
|
+
rdoc_options: []
|
127
|
+
require_paths:
|
128
|
+
- lib
|
129
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ! '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
requirements: []
|
140
|
+
rubyforge_project:
|
141
|
+
rubygems_version: 2.0.3
|
142
|
+
signing_key:
|
143
|
+
specification_version: 4
|
144
|
+
summary: Stores hashes in a BSON 'packed' format.
|
145
|
+
test_files:
|
146
|
+
- spec/bson_minihash/bson_minihash_spec.rb
|
147
|
+
- spec/bson_minihash/hex_spec.rb
|
148
|
+
- spec/spec_helper.rb
|