hashids 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
1
  *.gem
2
+ Gemfile.lock
2
3
  *.rbc
3
4
  .bundle
4
5
  .config
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ bundler_args: --without documentation
3
+ rvm:
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - jruby-19mode # JRuby in 1.9 mode
7
+ - rbx-19mode
8
+ - ruby-head
data/Gemfile CHANGED
@@ -2,3 +2,8 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in hashids.gemspec
4
4
  gemspec
5
+
6
+ group :development do
7
+ gem "rake"
8
+ gem "minitest" if RUBY_VERSION < '1.9.3'
9
+ end
data/README.md CHANGED
@@ -5,10 +5,15 @@ Use hashids when you do not want to expose your database ids to the user.
5
5
 
6
6
  [http://www.hashids.org/ruby/](http://www.hashids.org/ruby/)
7
7
 
8
+ [![Build Status](https://secure.travis-ci.org/peterhellberg/hashids.rb.png)](http://travis-ci.org/peterhellberg/hashids.rb)
9
+ (1.9.2, 1.9.3, jruby-19mode, rbx-19mode and ruby-head)
10
+
8
11
  ## What is it?
9
12
 
10
13
  hashids (Hash ID's) creates short, unique, decryptable hashes from unsigned integers.
11
14
 
15
+ _(NOTE: This is **NOT** a true cryptographic hash, since it is reversible)_
16
+
12
17
  It was designed for websites to use in URL shortening, tracking stuff, or
13
18
  making pages private (or at least unguessable).
14
19
 
@@ -12,6 +12,8 @@ Gem::Specification.new do |gem|
12
12
  gem.description = %q{Use hashids when you do not want to expose your database ids to the user.}
13
13
  gem.homepage = "https://github.com/peterhellberg/hashids.rb"
14
14
 
15
+ gem.required_ruby_version = '>= 1.9.2'
16
+
15
17
  gem.files = `git ls-files`.split($/)
16
18
  gem.test_files = gem.files.grep(%r{^(spec)/})
17
19
  gem.require_paths = ["lib"]
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  class Hashids
4
- VERSION = "0.0.1"
4
+ VERSION = "0.0.2"
5
5
  DEFAULT_ALPHABET = "xcS4F6h89aUbideAI7tkynuopqrXCgTE5GBKHLMjfRsz"
6
6
  PRIMES = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43]
7
7
 
@@ -10,22 +10,22 @@ class Hashids
10
10
  class AlphabetError < ArgumentError; end
11
11
 
12
12
  def initialize(salt = "", min_length = 0, alphabet = DEFAULT_ALPHABET)
13
- @salt = salt
14
- @min_length = min_length
15
- @alphabet = alphabet
13
+ @salt = salt
14
+ @min_length = min_length
15
+ @alphabet = alphabet
16
+
17
+ @chars_regex = /./
16
18
 
17
19
  validate_attributes
18
20
  setup_alphabet
19
21
  end
20
22
 
21
23
  def encrypt(*numbers)
22
- return "" unless numbers.any?
23
-
24
- numbers.each do |number|
25
- return "" if !number.kind_of?(Fixnum) || number < 0
24
+ if numbers.empty? || numbers.reject { |n| Integer(n) && n > 0 }.any?
25
+ ""
26
+ else
27
+ encode(numbers, @alphabet, @salt, @min_length)
26
28
  end
27
-
28
- encode(numbers, @alphabet, @salt, @min_length)
29
29
  end
30
30
 
31
31
  def decrypt(hash)
@@ -52,7 +52,7 @@ class Hashids
52
52
  @seps = []
53
53
  @guards = []
54
54
 
55
- @alphabet = @alphabet.split('').uniq.join
55
+ @alphabet = @alphabet.scan(@chars_regex).uniq.join('')
56
56
 
57
57
  if @alphabet.length < 4
58
58
  raise AlphabetError, "Alphabet must contain at least 4 unique characters."
@@ -63,7 +63,7 @@ class Hashids
63
63
 
64
64
  break if char.nil?
65
65
 
66
- @seps.push char
66
+ @seps << char
67
67
  @alphabet.gsub!(char, ' ')
68
68
  end
69
69
 
@@ -71,7 +71,7 @@ class Hashids
71
71
  separator = @seps[index]
72
72
 
73
73
  unless separator.nil?
74
- @guards.push(separator)
74
+ @guards << separator
75
75
  @seps.delete_at(index)
76
76
  end
77
77
  end
@@ -83,13 +83,13 @@ class Hashids
83
83
  def encode(numbers, alphabet, salt, min_length = 0)
84
84
  ret = ""
85
85
 
86
- seps = consistent_shuffle(@seps, numbers).split("")
86
+ seps = consistent_shuffle(@seps, numbers).scan(@chars_regex)
87
87
  lottery_char = ""
88
88
 
89
89
  numbers.each_with_index do |number, i|
90
90
  if i == 0
91
91
  lottery_salt = numbers.join('-')
92
- numbers.each { |n| lottery_salt += "-" + ((n.to_i + 1) * 2).to_s }
92
+ numbers.each { |n| lottery_salt += "-#{(n + 1) * 2}" }
93
93
 
94
94
  lottery = consistent_shuffle(alphabet, lottery_salt)
95
95
 
@@ -172,8 +172,8 @@ class Hashids
172
172
  end
173
173
 
174
174
  if alphabet.length > 0 && lottery_char.length > 0
175
- alphabet = consistent_shuffle(alphabet, (lottery_char.ord & 12345).to_s + "" + @salt)
176
- ret.push unhash(sub_hash, alphabet)
175
+ alphabet = consistent_shuffle(alphabet, (lottery_char.ord & 12345).to_s + @salt)
176
+ ret << unhash(sub_hash, alphabet)
177
177
  end
178
178
  end
179
179
  end
@@ -187,24 +187,21 @@ class Hashids
187
187
  def consistent_shuffle(alphabet, salt)
188
188
  ret = ""
189
189
 
190
- alphabet = alphabet.join "" if alphabet.respond_to? :join
191
- salt = salt.join "" if salt.respond_to? :join
190
+ alphabet = alphabet.join("") if alphabet.respond_to? :join
191
+ salt = salt.join("") if salt.respond_to? :join
192
192
 
193
- alphabet_array = alphabet.split('')
194
- salt_array = salt.split('')
195
- sorting_array = []
193
+ alphabet_array = alphabet.scan(@chars_regex)
194
+ salt_array = salt.scan(@chars_regex)
195
+ sorting_array = []
196
196
 
197
- salt_array.push "" unless salt_array.any?
198
-
199
- salt_array.each do |salt_char|
200
- sorting_array.push salt_char.ord || 0
201
- end
197
+ salt_array << "" if salt_array.empty?
198
+ salt_array.each { |char| sorting_array << char.ord }
202
199
 
203
200
  sorting_array.each_with_index do |int,i|
204
201
  add = true
205
202
  k = i
206
203
 
207
- while k != (sorting_array.length + i - 1)
204
+ while k != sorting_array.length + i - 1
208
205
  next_index = (k + 1) % sorting_array.length
209
206
 
210
207
  if add
@@ -223,9 +220,8 @@ class Hashids
223
220
  i = 0
224
221
 
225
222
  while alphabet_array.length > 0
226
- alphabet_size = alphabet_array.length
227
223
  pos = sorting_array[i]
228
- pos %= alphabet_size if pos >= alphabet_size
224
+ pos %= alphabet_array.length if pos >= alphabet_array.length
229
225
  ret += alphabet_array[pos]
230
226
 
231
227
  alphabet_array.delete_at(pos)
@@ -237,11 +233,10 @@ class Hashids
237
233
 
238
234
  def hash(number, alphabet)
239
235
  hash = ""
240
- alphabet_length = alphabet.length
241
236
 
242
237
  while number > 0
243
- hash = alphabet[number % alphabet_length] + hash
244
- number = number / alphabet_length
238
+ hash = alphabet[number % alphabet.length] + hash
239
+ number = number / alphabet.length
245
240
  end
246
241
 
247
242
  hash
@@ -250,15 +245,12 @@ class Hashids
250
245
  def unhash(hash, alphabet)
251
246
  number = 0
252
247
 
253
- hash.split('').each_with_index { |char, i|
254
- pos = alphabet.index char
255
-
256
- return if pos.nil?
257
-
258
- number += pos * alphabet.length ** (hash.length - i - 1)
259
- }
248
+ hash.split('').each_with_index do |char, i|
249
+ if pos = alphabet.index(char)
250
+ number += pos * alphabet.length ** (hash.length - i - 1)
251
+ end
252
+ end
260
253
 
261
254
  number
262
255
  end
263
-
264
256
  end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ # Profile with perftools.rb
4
+ #
5
+ # CPUPROFILE=/tmp/hashids_profile \
6
+ # RUBYOPT="-r`gem which 'perftools.rb' | tail -1`" \
7
+ # ruby spec/hashids_profile.rb
8
+ #
9
+ # Generate diagram
10
+ #
11
+ # pprof.rb --gif /tmp/hashids_profile > /tmp/hashids_profile.gif && \
12
+ # open /tmp/hashids_profile.gif
13
+ #
14
+
15
+ require_relative "../lib/hashids"
16
+
17
+ h = Hashids.new('this is my salt')
18
+
19
+ 10_000.times do |n|
20
+ h.decrypt(h.encrypt(n))
21
+ end
@@ -89,15 +89,15 @@ describe Hashids do
89
89
  h.encrypt(1,2,3,4,5).must_equal 'adcdacddcdaacdad'
90
90
  end
91
91
 
92
- it "doesn’t produce repeating patterns for identical numbers" do
92
+ it "does not produce repeating patterns for identical numbers" do
93
93
  hashids.encrypt(5,5,5,5).must_equal 'GLh5SMs9'
94
94
  end
95
95
 
96
- it "doesn’t produce repeating patterns for incremented numbers" do
96
+ it "does not produce repeating patterns for incremented numbers" do
97
97
  hashids.encrypt(*(1..10).to_a).must_equal 'zEUzfySGIpuyhpF6HaC7'
98
98
  end
99
99
 
100
- it "doesn’t produce similarities between incrementing number hashes" do
100
+ it "does not produce similarities between incrementing number hashes" do
101
101
  hashids.encrypt(1).must_equal 'LX'
102
102
  hashids.encrypt(2).must_equal 'ed'
103
103
  hashids.encrypt(3).must_equal 'o9'
@@ -126,7 +126,7 @@ describe Hashids do
126
126
  }
127
127
  end
128
128
 
129
- it "doesn’t decrypt with a different salt" do
129
+ it "does not decrypt with a different salt" do
130
130
  peppers = Hashids.new('this is my pepper')
131
131
  hashids.decrypt('ryBo').must_equal [12345]
132
132
  peppers.decrypt('ryBo').must_equal []
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hashids
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -19,12 +19,14 @@ extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
21
  - .gitignore
22
+ - .travis.yml
22
23
  - Gemfile
23
24
  - LICENSE.txt
24
25
  - README.md
25
26
  - Rakefile
26
27
  - hashids.gemspec
27
28
  - lib/hashids.rb
29
+ - spec/hashids_profile.rb
28
30
  - spec/hashids_spec.rb
29
31
  homepage: https://github.com/peterhellberg/hashids.rb
30
32
  licenses: []
@@ -37,13 +39,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
37
39
  requirements:
38
40
  - - ! '>='
39
41
  - !ruby/object:Gem::Version
40
- version: '0'
42
+ version: 1.9.2
41
43
  required_rubygems_version: !ruby/object:Gem::Requirement
42
44
  none: false
43
45
  requirements:
44
46
  - - ! '>='
45
47
  - !ruby/object:Gem::Version
46
48
  version: '0'
49
+ segments:
50
+ - 0
51
+ hash: 2124593182474944467
47
52
  requirements: []
48
53
  rubyforge_project:
49
54
  rubygems_version: 1.8.24
@@ -51,5 +56,5 @@ signing_key:
51
56
  specification_version: 3
52
57
  summary: Generate YouTube-like hashes from one or many numbers.
53
58
  test_files:
59
+ - spec/hashids_profile.rb
54
60
  - spec/hashids_spec.rb
55
- has_rdoc: