encoded_id 1.0.0.rc4 → 1.0.0.rc5

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.
@@ -0,0 +1,139 @@
1
+ // https://github.com/tzvetkoff/hashids.c
2
+ /*
3
+ Copyright (C) 2014 Latchezar Tzvetkoff
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10
+ */
11
+
12
+
13
+ #ifndef HASHIDS_H
14
+ #define HASHIDS_H 1
15
+
16
+ #include <stdlib.h>
17
+
18
+ /* version constants */
19
+ #define HASHIDS_VERSION "1.2.1"
20
+ #define HASHIDS_VERSION_MAJOR 1
21
+ #define HASHIDS_VERSION_MINOR 2
22
+ #define HASHIDS_VERSION_PATCH 1
23
+
24
+ /* minimal alphabet length */
25
+ #define HASHIDS_MIN_ALPHABET_LENGTH 16u
26
+
27
+ /* separator divisor */
28
+ #define HASHIDS_SEPARATOR_DIVISOR 3.5f
29
+
30
+ /* guard divisor */
31
+ #define HASHIDS_GUARD_DIVISOR 12u
32
+
33
+ /* default salt */
34
+ #define HASHIDS_DEFAULT_SALT ""
35
+
36
+ /* default minimal hash length */
37
+ #define HASHIDS_DEFAULT_MIN_HASH_LENGTH 0u
38
+
39
+ /* default alphabet */
40
+ #define HASHIDS_DEFAULT_ALPHABET "abcdefghijklmnopqrstuvwxyz" \
41
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
42
+ "1234567890"
43
+
44
+ /* default separators */
45
+ #define HASHIDS_DEFAULT_SEPARATORS "cfhistuCFHISTU"
46
+
47
+ /* error codes */
48
+ #define HASHIDS_ERROR_OK 0
49
+ #define HASHIDS_ERROR_ALLOC -1
50
+ #define HASHIDS_ERROR_ALPHABET_LENGTH -2
51
+ #define HASHIDS_ERROR_ALPHABET_SPACE -3
52
+ #define HASHIDS_ERROR_INVALID_HASH -4
53
+ #define HASHIDS_ERROR_INVALID_NUMBER -5
54
+
55
+ /* thread-safe hashids_errno indirection */
56
+ extern int *__hashids_errno_addr(void);
57
+ #define hashids_errno (*__hashids_errno_addr())
58
+
59
+ /* alloc & free */
60
+ extern void *(*_hashids_alloc)(size_t size);
61
+ extern void (*_hashids_free)(void *ptr);
62
+
63
+ /* the hashids "object" */
64
+ struct hashids_s {
65
+ char *alphabet;
66
+ char *alphabet_copy_1;
67
+ char *alphabet_copy_2;
68
+ size_t alphabet_length;
69
+
70
+ char *salt;
71
+ size_t salt_length;
72
+
73
+ char *separators;
74
+ size_t separators_count;
75
+
76
+ char *guards;
77
+ size_t guards_count;
78
+
79
+ size_t min_hash_length;
80
+ };
81
+ typedef struct hashids_s hashids_t;
82
+
83
+ /* exported function definitions */
84
+ void
85
+ hashids_shuffle(char *str, size_t str_length, char *salt, size_t salt_length);
86
+
87
+ void
88
+ hashids_free(hashids_t *hashids);
89
+
90
+ hashids_t *
91
+ hashids_init3(const char *salt, size_t min_hash_length,
92
+ const char *alphabet);
93
+
94
+ hashids_t *
95
+ hashids_init2(const char *salt, size_t min_hash_length);
96
+
97
+ hashids_t *
98
+ hashids_init(const char *salt);
99
+
100
+ size_t
101
+ hashids_estimate_encoded_size(hashids_t *hashids, size_t numbers_count,
102
+ unsigned long long *numbers);
103
+
104
+ size_t
105
+ hashids_estimate_encoded_size_v(hashids_t *hashids, size_t numbers_count, ...);
106
+
107
+ size_t
108
+ hashids_encode(hashids_t *hashids, char *buffer, size_t numbers_count,
109
+ unsigned long long *numbers);
110
+
111
+ size_t
112
+ hashids_encode_v(hashids_t *hashids, char *buffer, size_t numbers_count, ...);
113
+
114
+ size_t
115
+ hashids_encode_one(hashids_t *hashids, char *buffer,
116
+ unsigned long long number);
117
+
118
+ size_t
119
+ hashids_numbers_count(hashids_t *hashids, const char *str);
120
+
121
+ size_t
122
+ hashids_decode(hashids_t *hashids, const char *str,
123
+ unsigned long long *numbers, size_t numbers_max);
124
+
125
+ size_t
126
+ hashids_decode_unsafe(hashids_t *hashids, const char *str,
127
+ unsigned long long *numbers);
128
+
129
+ size_t
130
+ hashids_decode_safe(hashids_t *hashids, const char *str,
131
+ unsigned long long *numbers, size_t numbers_max);
132
+
133
+ size_t
134
+ hashids_encode_hex(hashids_t *hashids, char *buffer, const char *hex_str);
135
+
136
+ size_t
137
+ hashids_decode_hex(hashids_t *hashids, char *str, char *output);
138
+
139
+ #endif
@@ -15,6 +15,10 @@ module EncodedId
15
15
  }
16
16
  )
17
17
  end
18
+
19
+ def alphanum
20
+ new("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
21
+ end
18
22
  end
19
23
 
20
24
  def initialize(characters, equivalences = nil)
@@ -0,0 +1,227 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This implementation based on https://github.com/peterhellberg/hashids.rb
4
+ #
5
+ # Original Hashids implementation is MIT licensed:
6
+ #
7
+ # Copyright (c) 2013-2017 Peter Hellberg
8
+ #
9
+ # MIT License
10
+ #
11
+ # Permission is hereby granted, free of charge, to any person obtaining
12
+ # a copy of this software and associated documentation files (the
13
+ # "Software"), to deal in the Software without restriction, including
14
+ # without limitation the rights to use, copy, modify, merge, publish,
15
+ # distribute, sublicense, and/or sell copies of the Software, and to
16
+ # permit persons to whom the Software is furnished to do so, subject to
17
+ # the following conditions:
18
+ #
19
+ # The above copyright notice and this permission notice shall be
20
+ # included in all copies or substantial portions of the Software.
21
+ #
22
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
+ #
30
+ # This version also MIT licensed (Stephen Ierodiaconou): see LICENSE.txt file
31
+ module EncodedId
32
+ class HashId
33
+ def initialize(salt, min_hash_length = 0, alphabet = Alphabet.alphanum)
34
+ unless min_hash_length.is_a?(Integer) && min_hash_length >= 0
35
+ raise ArgumentError, "The min length must be a Integer and greater than or equal to 0"
36
+ end
37
+ @min_hash_length = min_hash_length
38
+
39
+ # TODO: move this class creation out of the constructor?
40
+ @separators_and_guards = OrdinalAlphabetSeparatorGuards.new(alphabet, salt)
41
+ @alphabet_ordinals = @separators_and_guards.alphabet
42
+ @separator_ordinals = @separators_and_guards.seps
43
+ @guard_ordinals = @separators_and_guards.guards
44
+ @salt_ordinals = @separators_and_guards.salt
45
+
46
+ @escaped_separator_selector = @separators_and_guards.seps_tr_selector
47
+ @escaped_guards_selector = @separators_and_guards.guards_tr_selector
48
+ end
49
+
50
+ attr_reader :alphabet_ordinals, :separator_ordinals, :guard_ordinals, :salt_ordinals
51
+
52
+ # We could get rid of calling with multiple arguments and just use an array as the argument always
53
+ def encode(numbers)
54
+ numbers.all? { |n| Integer(n) } # raises if conversion fails
55
+
56
+ return "" if numbers.empty? || numbers.any? { |n| n < 0 }
57
+
58
+ internal_encode(numbers)
59
+ end
60
+
61
+ def encode_hex(str)
62
+ return "" unless hex_string?(str)
63
+
64
+ numbers = str.scan(/[\w\W]{1,12}/).map do |num|
65
+ "1#{num}".to_i(16)
66
+ end
67
+
68
+ encode(numbers)
69
+ end
70
+
71
+ def decode(hash)
72
+ return [] if hash.nil? || hash.empty?
73
+
74
+ internal_decode(hash)
75
+ end
76
+
77
+ def decode_hex(hash)
78
+ numbers = decode(hash)
79
+
80
+ ret = numbers.map do |n|
81
+ n.to_s(16)[1..]
82
+ end
83
+
84
+ ret.join.upcase
85
+ end
86
+
87
+ protected
88
+
89
+ def internal_encode(numbers)
90
+ current_alphabet = @alphabet_ordinals.dup
91
+ separator_ordinals = @separator_ordinals
92
+ guard_ordinals = @guard_ordinals
93
+
94
+ alphabet_length = current_alphabet.length
95
+ length = numbers.length
96
+
97
+ hash_int = 0
98
+ # We dont use the iterator#sum to avoid the extra array allocation
99
+ i = 0
100
+ while i < length
101
+ hash_int += numbers[i] % (i + 100)
102
+ i += 1
103
+ end
104
+
105
+ lottery = current_alphabet[hash_int % alphabet_length]
106
+
107
+ # This is the final string form of the hash, as an array of ordinals
108
+ hashid_code = []
109
+ hashid_code << lottery
110
+ seasoning = [lottery].concat(@salt_ordinals)
111
+
112
+ i = 0
113
+ while i < length
114
+ num = numbers[i]
115
+ consistent_shuffle!(current_alphabet, seasoning, current_alphabet.dup, alphabet_length)
116
+ last_char_ord = hash_one_number(hashid_code, num, current_alphabet, alphabet_length)
117
+
118
+ if (i + 1) < length
119
+ num %= (last_char_ord + i)
120
+ hashid_code << separator_ordinals[num % separator_ordinals.length]
121
+ end
122
+
123
+ i += 1
124
+ end
125
+
126
+ if hashid_code.length < @min_hash_length
127
+ hashid_code.prepend(guard_ordinals[(hash_int + hashid_code[0]) % guard_ordinals.length])
128
+
129
+ if hashid_code.length < @min_hash_length
130
+ hashid_code << guard_ordinals[(hash_int + hashid_code[2]) % guard_ordinals.length]
131
+ end
132
+ end
133
+
134
+ half_length = current_alphabet.length.div(2)
135
+
136
+ while hashid_code.length < @min_hash_length
137
+ consistent_shuffle!(current_alphabet, current_alphabet.dup, nil, current_alphabet.length)
138
+ hashid_code.prepend(*current_alphabet[half_length..])
139
+ hashid_code.concat(current_alphabet[0, half_length])
140
+
141
+ excess = hashid_code.length - @min_hash_length
142
+ hashid_code = hashid_code[excess / 2, @min_hash_length] if excess > 0
143
+ end
144
+
145
+ # Convert the array of ordinals to a string
146
+ hashid_code.pack("U*")
147
+ end
148
+
149
+ def internal_decode(hash)
150
+ ret = []
151
+ current_alphabet = @alphabet_ordinals.dup
152
+ salt_ordinals = @salt_ordinals
153
+
154
+ breakdown = hash.tr(@escaped_guards_selector, " ")
155
+ array = breakdown.split(" ")
156
+
157
+ i = [3, 2].include?(array.length) ? 1 : 0
158
+
159
+ if (breakdown = array[i])
160
+ lottery, breakdown = breakdown[0], breakdown[1..]
161
+ breakdown.tr!(@escaped_separator_selector, " ")
162
+ sub_hashes = breakdown.split(" ")
163
+
164
+ seasoning = [lottery.ord].concat(salt_ordinals)
165
+
166
+ len = sub_hashes.length
167
+ time = 0
168
+ while time < len
169
+ sub_hash = sub_hashes[time]
170
+ consistent_shuffle!(current_alphabet, seasoning, current_alphabet.dup, current_alphabet.length)
171
+
172
+ ret.push unhash(sub_hash, current_alphabet)
173
+ time += 1
174
+ end
175
+
176
+ # Check if the result is consistent with the hash, this is important for safety since otherwise
177
+ # a random string could feasibly decode to a set of numbers
178
+ if encode(ret) != hash
179
+ ret = []
180
+ end
181
+ end
182
+
183
+ ret
184
+ end
185
+
186
+ def hash_one_number(hash_code, num, alphabet, alphabet_length)
187
+ char = nil
188
+ insert_at = 0
189
+ while true # standard:disable Style/InfiniteLoop
190
+ char = alphabet[num % alphabet_length]
191
+ insert_at -= 1
192
+ hash_code.insert(insert_at, char)
193
+ num /= alphabet_length
194
+ break unless num > 0
195
+ end
196
+
197
+ char
198
+ end
199
+
200
+ def unhash(input, alphabet)
201
+ num = 0
202
+ input_length = input.length
203
+ alphabet_length = alphabet.length
204
+ i = 0
205
+ while i < input_length
206
+ pos = alphabet.index(input[i].ord)
207
+
208
+ raise InvalidInputError, "unable to unhash" unless pos
209
+
210
+ num += pos * alphabet_length**(input_length - i - 1)
211
+ i += 1
212
+ end
213
+
214
+ num
215
+ end
216
+
217
+ private
218
+
219
+ def hex_string?(string)
220
+ string.to_s.match(/\A[0-9a-fA-F]+\Z/)
221
+ end
222
+
223
+ def consistent_shuffle!(collection_to_shuffle, salt_part_1, salt_part_2, max_salt_length)
224
+ HashIdConsistentShuffle.shuffle!(collection_to_shuffle, salt_part_1, salt_part_2, max_salt_length)
225
+ end
226
+ end
227
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EncodedId
4
+ class HashIdConsistentShuffle
5
+ def self.shuffle!(collection_to_shuffle, salt_part_1, salt_part_2, max_salt_length)
6
+ salt_part_1_length = salt_part_1.length
7
+ raise SaltError, "Salt is too short in shuffle" if salt_part_1_length < max_salt_length && salt_part_2.nil?
8
+
9
+ return collection_to_shuffle if collection_to_shuffle.empty? || max_salt_length == 0 || salt_part_1.nil? || salt_part_1_length == 0
10
+
11
+ idx = ord_total = 0
12
+ i = collection_to_shuffle.length - 1
13
+ while i >= 1
14
+ n = (idx >= salt_part_1_length) ? salt_part_2[idx - salt_part_1_length] : salt_part_1[idx]
15
+ ord_total += n
16
+ j = (n + idx + ord_total) % i
17
+
18
+ collection_to_shuffle[i], collection_to_shuffle[j] = collection_to_shuffle[j], collection_to_shuffle[i]
19
+
20
+ idx = (idx + 1) % max_salt_length
21
+ i -= 1
22
+ end
23
+
24
+ collection_to_shuffle
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EncodedId
4
+ class HashIdSalt
5
+ def initialize(salt)
6
+ unless salt.is_a?(String)
7
+ raise SaltError, "The salt must be a String"
8
+ end
9
+ @salt = salt.freeze
10
+ @chars = salt.chars.freeze
11
+ end
12
+
13
+ attr_reader :salt, :chars
14
+ end
15
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EncodedId
4
+ class OrdinalAlphabetSeparatorGuards
5
+ SEP_DIV = 3.5
6
+ DEFAULT_SEPS = "cfhistuCFHISTU".chars.map(&:ord).freeze
7
+ GUARD_DIV = 12.0
8
+ SPACE_CHAR = " ".ord
9
+
10
+ def initialize(alphabet, salt)
11
+ @alphabet = alphabet.characters.chars.map(&:ord)
12
+ @salt = salt.chars.map(&:ord)
13
+
14
+ setup_seps
15
+ setup_guards
16
+
17
+ @seps_tr_selector = escape_characters_string_for_tr(@seps.map(&:chr))
18
+ @guards_tr_selector = escape_characters_string_for_tr(@guards.map(&:chr))
19
+
20
+ @alphabet.freeze
21
+ @seps.freeze
22
+ @guards.freeze
23
+ end
24
+
25
+ attr_reader :salt, :alphabet, :seps, :guards, :seps_tr_selector, :guards_tr_selector
26
+
27
+ private
28
+
29
+ def escape_characters_string_for_tr(chars)
30
+ chars.join.gsub(/([-\\^])/) { "\\#{$1}" }
31
+ end
32
+
33
+ def setup_seps
34
+ @seps = DEFAULT_SEPS.dup
35
+
36
+ @seps.length.times do |i|
37
+ # Seps should only contain characters present in alphabet,
38
+ # and alphabet should not contains seps
39
+ if (j = @alphabet.index(@seps[i]))
40
+ @alphabet = pick_characters(@alphabet, j)
41
+ else
42
+ @seps = pick_characters(@seps, i)
43
+ end
44
+ end
45
+
46
+ @alphabet.delete(SPACE_CHAR)
47
+ @seps.delete(SPACE_CHAR)
48
+
49
+ consistent_shuffle!(@seps, @salt, nil, @salt.length)
50
+
51
+ if @seps.length == 0 || (@alphabet.length / @seps.length.to_f) > SEP_DIV
52
+ seps_length = (@alphabet.length / SEP_DIV).ceil
53
+ seps_length = 2 if seps_length == 1
54
+
55
+ if seps_length > @seps.length
56
+ diff = seps_length - @seps.length
57
+
58
+ @seps += @alphabet[0, diff]
59
+ @alphabet = @alphabet[diff..]
60
+ else
61
+ @seps = @seps[0, seps_length]
62
+ end
63
+ end
64
+
65
+ consistent_shuffle!(@alphabet, @salt, nil, @salt.length)
66
+ end
67
+
68
+ def setup_guards
69
+ gc = (@alphabet.length / GUARD_DIV).ceil
70
+
71
+ if @alphabet.length < 3
72
+ @guards = @seps[0, gc]
73
+ @seps = @seps[gc..]
74
+ else
75
+ @guards = @alphabet[0, gc]
76
+ @alphabet = @alphabet[gc..]
77
+ end
78
+ end
79
+
80
+ def pick_characters(array, index)
81
+ tail = array[index + 1..]
82
+ head = array[0, index] + [SPACE_CHAR] # This space seems pointless but the original code does it, and its needed to maintain the same result in shuffling
83
+ tail ? head + tail : head
84
+ end
85
+
86
+ def consistent_shuffle!(collection_to_shuffle, salt_part_1, salt_part_2, max_salt_length)
87
+ HashIdConsistentShuffle.shuffle!(collection_to_shuffle, salt_part_1, salt_part_2, max_salt_length)
88
+ end
89
+ end
90
+ end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "hashids"
4
-
5
3
  # Hashid with a reduced character set Crockford alphabet and split groups
6
4
  # See: https://www.crockford.com/wrmg/base32.html
7
5
  # Build with https://hashids.org
@@ -37,10 +35,10 @@ module EncodedId
37
35
 
38
36
  # Decode the hash to original array
39
37
  def decode(str, downcase: true)
40
- raise InvalidInputError if max_length_exceeded?(str)
38
+ raise EncodedIdFormatError, "Max length of input exceeded" if max_length_exceeded?(str)
41
39
 
42
40
  encoded_id_generator.decode(convert_to_hash(str, downcase))
43
- rescue ::Hashids::InputError => e
41
+ rescue InvalidInputError => e
44
42
  raise EncodedIdFormatError, e.message
45
43
  end
46
44
 
@@ -111,7 +109,7 @@ module EncodedId
111
109
  end
112
110
 
113
111
  def encoded_id_generator
114
- @encoded_id_generator ||= ::Hashids.new(salt, length, alphabet.characters)
112
+ @encoded_id_generator ||= HashId.new(salt, length, alphabet)
115
113
  end
116
114
 
117
115
  def split_regex
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EncodedId
4
- VERSION = "1.0.0.rc4"
4
+ VERSION = "1.0.0.rc5"
5
5
  end
data/lib/encoded_id.rb CHANGED
@@ -3,6 +3,12 @@
3
3
  require_relative "encoded_id/version"
4
4
  require_relative "encoded_id/alphabet"
5
5
  require_relative "encoded_id/hex_representation"
6
+
7
+ require_relative "encoded_id/hash_id_salt"
8
+ require_relative "encoded_id/hash_id_consistent_shuffle"
9
+ require_relative "encoded_id/ordinal_alphabet_separator_guards"
10
+ require_relative "encoded_id/hash_id"
11
+
6
12
  require_relative "encoded_id/reversible_id"
7
13
 
8
14
  module EncodedId
@@ -15,4 +21,6 @@ module EncodedId
15
21
  class EncodedIdLengthError < ArgumentError; end
16
22
 
17
23
  class InvalidInputError < ArgumentError; end
24
+
25
+ class SaltError < ArgumentError; end
18
26
  end
data/sig/encoded_id.rbs CHANGED
@@ -7,6 +7,78 @@ module EncodedId
7
7
  InvalidAlphabetError: ::ArgumentError
8
8
  InvalidInputError: ::ArgumentError
9
9
 
10
+ class HashId
11
+ MIN_ALPHABET_LENGTH: ::Integer
12
+
13
+ SEP_DIV: ::Float
14
+
15
+ GUARD_DIV: ::Float
16
+
17
+ DEFAULT_SEPS: ::String
18
+
19
+ DEFAULT_ALPHABET: ::String
20
+
21
+ attr_reader salt: ::String
22
+
23
+ attr_reader min_hash_length: ::Integer
24
+
25
+ @alphabet: ::String
26
+
27
+ attr_reader alphabet: ::String
28
+
29
+ attr_reader seps: ::String | ::Array[::String]
30
+
31
+ attr_reader guards: untyped
32
+
33
+ def initialize: (?::String salt, ?::Integer min_hash_length, ?untyped alphabet) -> void
34
+
35
+ def encode: (*(Array[::Integer] | ::Integer) numbers) -> ::String
36
+
37
+ def encode_hex: (::String str) -> ::String
38
+
39
+ def decode: (::String hash) -> ::Array[::Integer]
40
+
41
+ def decode_hex: (::String hash) -> ::Array[::Integer]
42
+
43
+ # protected
44
+
45
+ def internal_encode: (untyped numbers) -> untyped
46
+
47
+ def internal_decode: (untyped hash, untyped alphabet) -> untyped
48
+
49
+ def consistent_shuffle: (::Array[::String] chars, ::String salt1, ::String ?salt2, ::Integer salt1_length) -> untyped
50
+
51
+ def hash: (untyped input, untyped alphabet) -> untyped
52
+
53
+ def unhash: (untyped input, untyped alphabet) -> untyped
54
+
55
+ private
56
+
57
+ def setup_alphabet: () -> untyped
58
+
59
+ def setup_seps: () -> untyped
60
+
61
+ def setup_guards: () -> untyped
62
+
63
+ SaltError: ArgumentError
64
+
65
+ MinLengthError: ArgumentError
66
+
67
+ AlphabetError: ArgumentError
68
+
69
+ InputError: ArgumentError
70
+
71
+ def validate_attributes: () -> untyped
72
+
73
+ def validate_alphabet: () -> (untyped | nil)
74
+
75
+ def hex_string?: (untyped string) -> untyped
76
+
77
+ def pick_characters: (untyped array, untyped index) -> untyped
78
+
79
+ def uniq_characters: (untyped string) -> untyped
80
+ end
81
+
10
82
  class Alphabet
11
83
  MIN_UNIQUE_CHARACTERS: ::Integer
12
84
 
@@ -75,7 +147,7 @@ module EncodedId
75
147
 
76
148
  private
77
149
 
78
- @encoded_id_generator: ::Hashids
150
+ @encoded_id_generator: HashId
79
151
  @split_regex: ::Regexp
80
152
  @hex_string_separator: ::Integer
81
153
 
@@ -97,13 +169,13 @@ module EncodedId
97
169
  def validate_max_length: (::Integer | nil) -> (::Integer | nil)
98
170
  def validate_max_input: (::Integer) -> ::Integer
99
171
  def validate_split_at: (::Integer | nil) -> (::Integer | nil)
100
- def validate_split_with: (::String, Alphabet) -> ::String
172
+ def validate_split_with: (::String, Alphabet) -> (::String | nil)
101
173
  def validate_hex_digit_encoding_group_size: (::Integer) -> ::Integer
102
174
  def valid_integer_option?: (::Integer | nil) -> bool
103
175
 
104
176
  def prepare_input: (untyped value) -> ::Array[::Integer]
105
177
 
106
- def encoded_id_generator: () -> ::Hashids
178
+ def encoded_id_generator: () -> HashId
107
179
 
108
180
  def split_regex: () -> ::Regexp
109
181