encoded_id 0.2.0 → 0.4.0
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.
- checksums.yaml +4 -4
- data/README.md +229 -43
- data/lib/encoded_id/alphabet.rb +39 -0
- data/lib/encoded_id/reversible_id.rb +33 -15
- data/lib/encoded_id/version.rb +1 -1
- data/lib/encoded_id.rb +4 -1
- data/sig/encoded_id.rbs +13 -7
- data/sig/hash_ids.rbs +0 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5cc2ba3de20b77f871eacb0820fb0ab151281bf6ff6281c992f9e47dc8657138
|
4
|
+
data.tar.gz: 22e9cc3a0dcaecaf34aea73b25681651efe8a4528b4cb70d01ea0aa5fdb73b57
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 04f9083352c9559df93ef8418397f43b9360b070025ba75e1ad4ba116fced9635f479939ca9cc55f9b9e594d380e8c4fa503834c85e1ef1994c187de0f5ce3a0
|
7
|
+
data.tar.gz: b2527e2301ad455b22d8ce1a5c652a6814485a703b032af635834ba145b904050ea3b15f3cb9d189b0e3a3a1361e5dce4c4fdbf662f819c56bbbcd212c8f7008
|
data/README.md
CHANGED
@@ -1,65 +1,77 @@
|
|
1
1
|
# EncodedId
|
2
2
|
|
3
|
-
Encode
|
3
|
+
Encode numerical or hex IDs into obfuscated strings that can be used in URLs.
|
4
4
|
|
5
|
-
|
5
|
+
```ruby
|
6
|
+
coder = ::EncodedId::ReversibleId.new(salt: my_salt)
|
7
|
+
coder.encode(123)
|
8
|
+
# => "p5w9-z27j"
|
9
|
+
coder.encode_hex("10f8c")
|
10
|
+
# => "w72a-y0az"
|
11
|
+
```
|
6
12
|
|
7
|
-
The obfuscated strings are reversible
|
8
|
-
encoding multiple IDs at once.
|
13
|
+
The obfuscated strings are reversible (they decode them back into the original IDs).
|
9
14
|
|
10
|
-
|
11
|
-
reversibles = ::EncodedId::ReversibleId.new(salt: my_salt)
|
12
|
-
reversibles.encode([78, 45]) # "7aq6-0zqw"
|
13
|
-
reversibles.decode("7aq6-0zqw") # [78, 45]
|
14
|
-
```
|
15
|
+
Also supports encoding multiple IDs at once.
|
15
16
|
|
16
|
-
|
17
|
+
```ruby
|
18
|
+
my_salt = "salt!"
|
19
|
+
coder = ::EncodedId::ReversibleId.new(salt: my_salt)
|
17
20
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
+
# One of more values can be encoded
|
22
|
+
coder.encode([78, 45])
|
23
|
+
# => "z2j7-0dmw"
|
21
24
|
|
22
|
-
|
25
|
+
# The encoded string can then be reversed back into the original IDs
|
26
|
+
coder.decode("z2j7-0dmw")
|
27
|
+
# => [78, 45]
|
23
28
|
|
24
|
-
|
25
|
-
|
26
|
-
=>
|
29
|
+
# The decoder can be resilient to easily confused characters
|
30
|
+
coder.decode("z2j7-Odmw") # (note the capital 'o' instead of zero)
|
31
|
+
# => [78, 45]
|
27
32
|
```
|
28
33
|
|
29
34
|
## Features
|
30
35
|
|
31
|
-
|
36
|
+
* encoded IDs are reversible (uses with https://hashids.org)
|
37
|
+
* supports slugged IDs (eg `beef-tenderloins-prime--p5w9-z27j`)
|
38
|
+
* supports multiple IDs encoded in one encoded string (eg `7aq6-0zqw` decodes to `[78, 45]`)
|
39
|
+
* supports encoding of hex strings (eg UUIDs), including multiple IDs encoded in one string **(experimental)**
|
40
|
+
* supports custom alphabets for the encoded string (at least 16 characters needed)
|
41
|
+
- by default uses a variation of the Crockford reduced character set (https://www.crockford.com/base32.html)
|
42
|
+
- easily confused characters (eg `i` and `j`, `0` and `O`, `1` and `I` etc) are mapped to counterpart characters, to help
|
43
|
+
avoid common readability mistakes when reading/sharing
|
44
|
+
- build in profanity limitation
|
45
|
+
* encoded string can be split into groups of letters to improve human-readability
|
46
|
+
- eg `nft9hr834htu` as `nft9-hr83-4htu`
|
32
47
|
|
33
|
-
|
34
|
-
* supports slugged IDs (eg 'beef-tenderloins-prime--p5w9-z27j')
|
35
|
-
* supports multiple IDs encoded in one `EncodedId` (eg '7aq6-0zqw' decodes to `[78, 45]`)
|
36
|
-
* supports encoding of hex strings (eg UUIDs), including mutliple IDs encoded in one `EncodedId`
|
37
|
-
* uses a reduced character set (Crockford alphabet) & ids split into groups of letters, ie 'human-readability'
|
38
|
-
* profanity limitation
|
48
|
+
### Rails support `encoded_id-rails`
|
39
49
|
|
40
|
-
To use with **Rails** check out the `encoded_id-rails` gem.
|
50
|
+
To use with **Rails** check out the [`encoded_id-rails`](https://github.com/stevegeek/encoded_id-rails) gem.
|
41
51
|
|
42
|
-
|
52
|
+
```ruby
|
53
|
+
class User < ApplicationRecord
|
54
|
+
include EncodedId::WithEncodedId
|
55
|
+
end
|
56
|
+
|
57
|
+
User.find_by_encoded_id("p5w9-z27j")
|
58
|
+
# => #<User id: 78>
|
59
|
+
```
|
60
|
+
|
61
|
+
### Note on security of encoded IDs (hashids)
|
43
62
|
|
44
63
|
**Encoded IDs are not secure**. It maybe possible to reverse them via brute-force. They are meant to be used in URLs as
|
45
64
|
an obfuscation. The algorithm is not an encryption.
|
46
65
|
|
47
66
|
Please read more on https://hashids.org/
|
48
67
|
|
49
|
-
|
50
|
-
## Compared to alternate Gems
|
68
|
+
## Compare to alternate Gems
|
51
69
|
|
52
70
|
- https://github.com/excid3/prefixed_ids
|
53
71
|
- https://github.com/namick/obfuscate_id
|
54
72
|
- https://github.com/norman/friendly_id
|
55
73
|
- https://github.com/SPBTV/with_uid
|
56
74
|
|
57
|
-
## See also
|
58
|
-
|
59
|
-
- https://hashids.org
|
60
|
-
- https://www.crockford.com/wrmg/base32.html
|
61
|
-
|
62
|
-
|
63
75
|
## Installation
|
64
76
|
|
65
77
|
Install the gem and add to the application's Gemfile by executing:
|
@@ -70,20 +82,189 @@ If bundler is not being used to manage dependencies, install the gem by executin
|
|
70
82
|
|
71
83
|
$ gem install encoded_id
|
72
84
|
|
73
|
-
##
|
85
|
+
## `EncodedId::ReversibleId.new`
|
86
|
+
|
87
|
+
To create an instance of the encoder/decoder use `.new` with the `salt` option:
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
coder = EncodedId::ReversibleId.new(
|
91
|
+
# The salt is required
|
92
|
+
salt: ...,
|
93
|
+
# And then the following options are optional
|
94
|
+
length: 8,
|
95
|
+
split_at: 4,
|
96
|
+
split_with: "-",
|
97
|
+
alphabet: EncodedId::Alphabet.modified_crockford,
|
98
|
+
hex_digit_encoding_group_size: 4 # Experimental
|
99
|
+
)
|
100
|
+
```
|
101
|
+
|
102
|
+
Note the `salt` value is required and should be a string of some length (greater than 3 characters). This is used to generate the encoded string.
|
103
|
+
|
104
|
+
It will need to be the same value when decoding the string back into the original ID. If the salt is changed, the encoded
|
105
|
+
strings will be different and possibly decode to different IDs.
|
106
|
+
|
107
|
+
### Options
|
74
108
|
|
75
|
-
|
109
|
+
The encoded ID is configurable. The following can be changed:
|
76
110
|
|
77
|
-
|
111
|
+
- the length, eg 8 characters for `p5w9-z27j`
|
112
|
+
- the alphabet used in it (min 16 characters)
|
113
|
+
- and the number of characters to split the output into and the separator
|
78
114
|
|
79
|
-
|
115
|
+
### `length`
|
116
|
+
|
117
|
+
`length`: the minimum length of the encoded string. The default is 8 characters.
|
118
|
+
|
119
|
+
The actual length of the encoded string can be longer if the inputs cannot be represented in the minimum length.
|
120
|
+
|
121
|
+
### `alphabet`
|
122
|
+
|
123
|
+
`alphabet`: the alphabet used in the encoded string. By default it uses a variation of the Crockford reduced character set (https://www.crockford.com/base32.html).
|
124
|
+
|
125
|
+
`alphabet` must be an instance of `EncodedId::Alphabet`.
|
126
|
+
|
127
|
+
The default alphabet is `EncodedId::Alphabet.modified_crockford`.
|
128
|
+
|
129
|
+
To create a new alphabet, use `EncodedId::Alphabet.new`:
|
80
130
|
|
81
131
|
```ruby
|
82
|
-
|
83
|
-
|
84
|
-
|
132
|
+
alphabet = EncodedId::Alphabet.new("0123456789abcdef")
|
133
|
+
```
|
134
|
+
|
135
|
+
`EncodedId::Alphabet.new(characters, equivalences)`
|
136
|
+
|
137
|
+
**characters**
|
138
|
+
|
139
|
+
`characters`: the characters of the alphabet. Can be a string or array of strings.
|
140
|
+
|
141
|
+
Note that the `characters` of the alphabet must be at least 16 _unique_ characters long.
|
85
142
|
|
86
|
-
|
143
|
+
|
144
|
+
```ruby
|
145
|
+
alphabet = EncodedId::Alphabet.new("ςερτυθιοπλκξηγφδσαζχψωβνμ")
|
146
|
+
coder = ::EncodedId::ReversibleId.new(salt: my_salt, alphabet: alphabet)
|
147
|
+
coder.encode(123)
|
148
|
+
# => "πφλχ-ψησω"
|
149
|
+
```
|
150
|
+
|
151
|
+
Note that larger alphabets can result in shorter encoded strings (but remember that `length` specifies the minimum length
|
152
|
+
of the encoded string).
|
153
|
+
|
154
|
+
**equivalences**
|
155
|
+
|
156
|
+
You can optionally pass an appropriate character `equivalences` mapping. This is used to map easily confused characters
|
157
|
+
to their counterpart.
|
158
|
+
|
159
|
+
`equivalences`: a hash of characters keys, with their equivalent alphabet character mapped to in the values.
|
160
|
+
|
161
|
+
Note that the characters to be mapped:
|
162
|
+
- must not be in the alphabet,
|
163
|
+
- must map to a character that is in the alphabet.
|
164
|
+
|
165
|
+
`nil` is the default value which means no equivalences are used.
|
166
|
+
|
167
|
+
```ruby
|
168
|
+
alphabet = EncodedId::Alphabet.new("!@#$%^&*()+-={}", {"_" => "-"})
|
169
|
+
coder = ::EncodedId::ReversibleId.new(salt: my_salt, alphabet: alphabet)
|
170
|
+
coder.encode(123)
|
171
|
+
# => "}*^(-^}*="
|
172
|
+
```
|
173
|
+
|
174
|
+
### `split_at` and `split_with`
|
175
|
+
|
176
|
+
For readability, the encoded string can be split into groups of characters.
|
177
|
+
|
178
|
+
`split_at`: specifies the number of characters to split the encoded string into. Defaults to 4.
|
179
|
+
|
180
|
+
`split_with`: specifies the separator to use between the groups. Default is `-`.
|
181
|
+
|
182
|
+
### `hex_digit_encoding_group_size`
|
183
|
+
|
184
|
+
**Experimental**
|
185
|
+
|
186
|
+
`hex_digit_encoding_group_size`: specifies the number of hex digits to encode in a group. Defaults to 4. Can be
|
187
|
+
between 1 and 32.
|
188
|
+
|
189
|
+
Can be used to control the size of the encoded string when encoding hex strings. Larger values will result in shorter
|
190
|
+
encoded strings for long inputs, and shorter values will result in shorter encoded strings for smaller inputs.
|
191
|
+
|
192
|
+
But note that bigger values will also result in larger markers that separate the groups so could end up increasing
|
193
|
+
the encoded string length undesirably.
|
194
|
+
|
195
|
+
See below section `Using with hex strings` for more details.
|
196
|
+
|
197
|
+
## `EncodedId::ReversibleId#encode`
|
198
|
+
|
199
|
+
`#encode(id)`: where `id` is an integer or array of integers to encode.
|
200
|
+
|
201
|
+
```ruby
|
202
|
+
coder.encode(123)
|
203
|
+
# => "p5w9-z27j"
|
204
|
+
|
205
|
+
# One of more values can be encoded
|
206
|
+
coder.encode([78, 45])
|
207
|
+
# => "z2j7-0dmw"
|
208
|
+
```
|
209
|
+
|
210
|
+
## `EncodedId::ReversibleId#decode`
|
211
|
+
|
212
|
+
`#decode(encoded_id)`: where `encoded_id` is a string to decode.
|
213
|
+
|
214
|
+
```ruby
|
215
|
+
# The encoded string can then be reversed back into the original IDs
|
216
|
+
coder.decode("z2j7-0dmw")
|
217
|
+
# => [78, 45]
|
218
|
+
```
|
219
|
+
|
220
|
+
## Using with hex strings
|
221
|
+
|
222
|
+
**Experimental** (subject to incompatible changes in future versions)
|
223
|
+
|
224
|
+
```ruby
|
225
|
+
# Hex input strings are also supported
|
226
|
+
coder.encode_hex("10f8c")
|
227
|
+
# => "w72a-y0az"
|
228
|
+
```
|
229
|
+
|
230
|
+
When encoding hex strings, the input is split into groups of hex digits, and each group is encoded separately as its
|
231
|
+
integer equivalent. In other words the input is converted into an array of integers and encoded as normal with the
|
232
|
+
`encode` method.
|
233
|
+
|
234
|
+
eg with `hex_digit_encoding_group_size=1` and inpu `f1`, is split into `f` and `1`, and then encoded as `15` and `1`
|
235
|
+
respectively, ie `encode` is called with `[15, 1]`.
|
236
|
+
|
237
|
+
To encode multiple hex inputs the encoded string contains markers to indicate the start of a new hex input. This
|
238
|
+
marker is equal to an integer value which is 1 larger than the maximum value the hex digit encoding group size can
|
239
|
+
represent (ie it is `2^(hex_digit_encoding_group_size * 4)`).
|
240
|
+
|
241
|
+
So for a hex digit encoding group size of 4 (ie group max value is `0xFFFF`), the marker is `65536`
|
242
|
+
|
243
|
+
For example with `hex_digit_encoding_group_size=1` for the inputs `f1` and `e2` encoded together, the
|
244
|
+
actual encoded integer array is `[15, 1, 16, 14, 2]`.
|
245
|
+
|
246
|
+
### `EncodedId::ReversibleId#encode_hex`
|
247
|
+
|
248
|
+
`encode_hex(hex_string)` , where `hex_string` is a string of hex digits or an array of hex strings.
|
249
|
+
|
250
|
+
```ruby
|
251
|
+
# UUIDs will result in long output strings...
|
252
|
+
coder.encode_hex("9a566b8b-8618-42ab-8db7-a5a0276401fd")
|
253
|
+
# => "5jjy-c8d9-hxp2-qsve-rgh9-rxnt-7nb5-tve7-bf84-vr"
|
254
|
+
#
|
255
|
+
# but there is an option to help reduce this...
|
256
|
+
coder = ::EncodedId::ReversibleId.new(salt: my_salt, hex_digit_encoding_group_size: 32)
|
257
|
+
coder.encode_hex("9a566b8b-8618-42ab-8db7-a5a0276401fd")
|
258
|
+
# => "vr7m-qra8-m5y6-dkgj-5rqr-q44e-gp4a-52"
|
259
|
+
```
|
260
|
+
|
261
|
+
### `EncodedId::ReversibleId#decode_hex`
|
262
|
+
|
263
|
+
`decode_hex(encoded_id)` , where the output is an array of hex strings.
|
264
|
+
|
265
|
+
```ruby
|
266
|
+
coder.decode_hex("5jjy-c8d9-hxp2-qsve-rgh9-rxnt-7nb5-tve7-bf84-vr")
|
267
|
+
# => ["9a566b8b-8618-42ab-8db7-a5a0276401fd"]
|
87
268
|
```
|
88
269
|
|
89
270
|
## Development
|
@@ -95,9 +276,14 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
95
276
|
number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git
|
96
277
|
commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
97
278
|
|
279
|
+
## See also
|
280
|
+
|
281
|
+
- https://hashids.org
|
282
|
+
- https://www.crockford.com/base32.html
|
283
|
+
|
98
284
|
## Contributing
|
99
285
|
|
100
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
286
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/stevegeek/encoded_id.
|
101
287
|
|
102
288
|
## License
|
103
289
|
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EncodedId
|
4
|
+
class Alphabet
|
5
|
+
def initialize(characters, equivalences = nil)
|
6
|
+
unless (characters.is_a?(Array) || characters.is_a?(String)) && characters.size > 0
|
7
|
+
raise InvalidAlphabetError, "Alphabet must be a string or array"
|
8
|
+
end
|
9
|
+
unique_alphabet = (characters.is_a?(Array) ? characters : characters.chars).uniq
|
10
|
+
raise InvalidAlphabetError, "Alphabet must be at least 16 unique characters" if unique_alphabet.size < 16
|
11
|
+
@characters = unique_alphabet.join
|
12
|
+
|
13
|
+
# Equivalences is a hash of characters to their equivalent character.
|
14
|
+
# Characters to be mapped must not be in the alphabet, and must map to a character that is in the alphabet.
|
15
|
+
raise InvalidConfigurationError, "Character equivalences must be a hash or nil" unless equivalences.nil? || equivalences.is_a?(Hash)
|
16
|
+
valid_equivalences = equivalences.nil? || (unique_alphabet & equivalences.keys).empty? && (equivalences.values - unique_alphabet).empty?
|
17
|
+
raise InvalidConfigurationError unless valid_equivalences
|
18
|
+
@equivalences = equivalences
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :characters, :equivalences
|
22
|
+
|
23
|
+
class << self
|
24
|
+
def modified_crockford
|
25
|
+
# Note we downcase first, so mappings are only for lower case. Also Crockford suggests i==1,
|
26
|
+
# but here i==j is used.
|
27
|
+
|
28
|
+
new(
|
29
|
+
"0123456789abcdefghjkmnpqrstuvwxyz",
|
30
|
+
{
|
31
|
+
"o" => "0",
|
32
|
+
"i" => "j",
|
33
|
+
"l" => "1"
|
34
|
+
}
|
35
|
+
)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -8,18 +8,29 @@ require "hashids"
|
|
8
8
|
# Note hashIds already has a built in profanity limitation algorithm
|
9
9
|
module EncodedId
|
10
10
|
class ReversibleId
|
11
|
-
|
11
|
+
def initialize(salt:, length: 8, split_at: 4, split_with: "-", alphabet: Alphabet.modified_crockford, hex_digit_encoding_group_size: 4)
|
12
|
+
raise InvalidAlphabetError, "alphabet must be an instance of Alphabet" unless alphabet.is_a?(Alphabet)
|
13
|
+
@alphabet = alphabet
|
12
14
|
|
13
|
-
|
14
|
-
unique_alphabet = alphabet.chars.uniq
|
15
|
-
raise InvalidAlphabetError, "Alphabet must be at least 16 characters" if unique_alphabet.size < 16
|
16
|
-
|
17
|
-
@human_friendly_alphabet = unique_alphabet.join
|
15
|
+
raise InvalidConfigurationError, "Salt must be a string and longer that 3 characters" unless salt.is_a?(String) && salt.size > 3
|
18
16
|
@salt = salt
|
17
|
+
# Target length of the encoded string (the minimum but not maximum length)
|
18
|
+
raise InvalidConfigurationError, "Length must be an integer greater than 0" unless length.is_a?(Integer) && length > 0
|
19
19
|
@length = length
|
20
|
+
# Split the encoded string into groups of this size
|
21
|
+
unless (split_at.is_a?(Integer) && split_at > 0) || split_at.nil?
|
22
|
+
raise InvalidConfigurationError, "Split at must be an integer greater than 0 or nil"
|
23
|
+
end
|
20
24
|
@split_at = split_at
|
25
|
+
unless split_with.is_a?(String) && !alphabet.characters.include?(split_with)
|
26
|
+
raise InvalidConfigurationError, "Split with must be a string and not part of the alphabet"
|
27
|
+
end
|
28
|
+
@split_with = split_with
|
21
29
|
# Number of hex digits to encode in each group, larger values will result in shorter hashes for longer inputs.
|
22
30
|
# Vice versa for smaller values, ie a smaller value will result in smaller hashes for small inputs.
|
31
|
+
if hex_digit_encoding_group_size < 1 || hex_digit_encoding_group_size > 32
|
32
|
+
raise InvalidConfigurationError, "hex_digit_encoding_group_size must be > 0 and <= 32"
|
33
|
+
end
|
23
34
|
@hex_digit_encoding_group_size = hex_digit_encoding_group_size
|
24
35
|
end
|
25
36
|
|
@@ -51,7 +62,12 @@ module EncodedId
|
|
51
62
|
|
52
63
|
private
|
53
64
|
|
54
|
-
attr_reader :salt,
|
65
|
+
attr_reader :salt,
|
66
|
+
:length,
|
67
|
+
:alphabet,
|
68
|
+
:split_at,
|
69
|
+
:split_with,
|
70
|
+
:hex_digit_encoding_group_size
|
55
71
|
|
56
72
|
def prepare_input(value)
|
57
73
|
inputs = value.is_a?(Array) ? value.map(&:to_i) : [value.to_i]
|
@@ -61,7 +77,7 @@ module EncodedId
|
|
61
77
|
end
|
62
78
|
|
63
79
|
def encoded_id_generator
|
64
|
-
@encoded_id_generator ||= ::Hashids.new(salt, length,
|
80
|
+
@encoded_id_generator ||= ::Hashids.new(salt, length, alphabet.characters)
|
65
81
|
end
|
66
82
|
|
67
83
|
def split_regex
|
@@ -69,17 +85,19 @@ module EncodedId
|
|
69
85
|
end
|
70
86
|
|
71
87
|
def humanize_length(hash)
|
72
|
-
hash.gsub(split_regex,
|
88
|
+
hash.gsub(split_regex, "\\0#{split_with}")
|
73
89
|
end
|
74
90
|
|
75
91
|
def convert_to_hash(str)
|
76
|
-
|
92
|
+
clean = str.delete(split_with).downcase
|
93
|
+
alphabet.equivalences.nil? ? clean : map_equivalent_characters(clean)
|
77
94
|
end
|
78
95
|
|
79
|
-
def
|
80
|
-
|
81
|
-
|
82
|
-
|
96
|
+
def map_equivalent_characters(str)
|
97
|
+
alphabet.equivalences.reduce(str) do |cleaned, ceq|
|
98
|
+
from, to = ceq
|
99
|
+
cleaned.tr(from, to)
|
100
|
+
end
|
83
101
|
end
|
84
102
|
|
85
103
|
# TODO: optimize this
|
@@ -107,7 +125,7 @@ module EncodedId
|
|
107
125
|
|
108
126
|
# Marker to separate hex strings, must be greater than largest value encoded
|
109
127
|
def hex_string_separator
|
110
|
-
@hex_string_separator ||= 2.pow(hex_digit_encoding_group_size * 4)
|
128
|
+
@hex_string_separator ||= 2.pow(hex_digit_encoding_group_size * 4)
|
111
129
|
end
|
112
130
|
|
113
131
|
# TODO: optimize this
|
data/lib/encoded_id/version.rb
CHANGED
data/lib/encoded_id.rb
CHANGED
@@ -1,12 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "encoded_id/version"
|
4
|
+
require_relative "encoded_id/alphabet"
|
4
5
|
require_relative "encoded_id/reversible_id"
|
5
6
|
|
6
7
|
module EncodedId
|
7
|
-
class
|
8
|
+
class InvalidConfigurationError < StandardError; end
|
8
9
|
|
9
10
|
class InvalidAlphabetError < ArgumentError; end
|
10
11
|
|
12
|
+
class EncodedIdFormatError < ArgumentError; end
|
13
|
+
|
11
14
|
class InvalidInputError < ArgumentError; end
|
12
15
|
end
|
data/sig/encoded_id.rbs
CHANGED
@@ -1,14 +1,19 @@
|
|
1
1
|
module EncodedId
|
2
|
-
VERSION: ::String
|
3
|
-
|
4
2
|
EncodedIdFormatError: ::ArgumentError
|
5
3
|
InvalidAlphabetError: ::ArgumentError
|
6
4
|
InvalidInputError: ::ArgumentError
|
7
5
|
|
8
|
-
class
|
9
|
-
|
6
|
+
class Alphabet
|
7
|
+
def initialize: (String, ?::Hash[::String, ::String]) -> void
|
8
|
+
|
9
|
+
attr_reader alphabet: String
|
10
|
+
attr_reader equivalences: ::Hash[::String, ::String]
|
10
11
|
|
11
|
-
def
|
12
|
+
def self.modified_crockford: () -> Alphabet
|
13
|
+
end
|
14
|
+
|
15
|
+
class ReversibleId
|
16
|
+
def initialize: (salt: ::String, ?length: ::Integer, ?split_at: ::Integer, ?split_with: ::String, ?alphabet: Alphabet, ?hex_digit_encoding_group_size: ::Integer) -> void
|
12
17
|
|
13
18
|
# Encode the input values into a hash
|
14
19
|
def encode: (untyped values) -> ::String
|
@@ -32,9 +37,10 @@ module EncodedId
|
|
32
37
|
|
33
38
|
attr_reader length: ::Integer
|
34
39
|
|
35
|
-
attr_reader
|
40
|
+
attr_reader alphabet: Alphabet
|
36
41
|
|
37
42
|
attr_reader split_at: ::Integer | nil
|
43
|
+
attr_reader split_with: ::String
|
38
44
|
|
39
45
|
attr_reader hex_digit_encoding_group_size: ::Integer
|
40
46
|
|
@@ -48,7 +54,7 @@ module EncodedId
|
|
48
54
|
|
49
55
|
def convert_to_hash: (::String str) -> ::String
|
50
56
|
|
51
|
-
def
|
57
|
+
def map_equivalent_characters: (::String str) -> ::String
|
52
58
|
|
53
59
|
def integer_representation: (untyped hexs) -> ::Array[::Integer]
|
54
60
|
|
data/sig/hash_ids.rbs
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: encoded_id
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen Ierodiaconou
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-12-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: hashids
|
@@ -42,6 +42,7 @@ files:
|
|
42
42
|
- Rakefile
|
43
43
|
- Steepfile
|
44
44
|
- lib/encoded_id.rb
|
45
|
+
- lib/encoded_id/alphabet.rb
|
45
46
|
- lib/encoded_id/reversible_id.rb
|
46
47
|
- lib/encoded_id/version.rb
|
47
48
|
- rbs_collection.yaml
|