encoded_id 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 -5
- 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
@@ -3,10 +3,17 @@ module EncodedId
|
|
3
3
|
InvalidAlphabetError: ::ArgumentError
|
4
4
|
InvalidInputError: ::ArgumentError
|
5
5
|
|
6
|
-
class
|
7
|
-
|
6
|
+
class Alphabet
|
7
|
+
def initialize: (String, ?::Hash[::String, ::String]) -> void
|
8
|
+
|
9
|
+
attr_reader alphabet: String
|
10
|
+
attr_reader equivalences: ::Hash[::String, ::String]
|
8
11
|
|
9
|
-
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
|
10
17
|
|
11
18
|
# Encode the input values into a hash
|
12
19
|
def encode: (untyped values) -> ::String
|
@@ -30,9 +37,10 @@ module EncodedId
|
|
30
37
|
|
31
38
|
attr_reader length: ::Integer
|
32
39
|
|
33
|
-
attr_reader
|
40
|
+
attr_reader alphabet: Alphabet
|
34
41
|
|
35
42
|
attr_reader split_at: ::Integer | nil
|
43
|
+
attr_reader split_with: ::String
|
36
44
|
|
37
45
|
attr_reader hex_digit_encoding_group_size: ::Integer
|
38
46
|
|
@@ -46,7 +54,7 @@ module EncodedId
|
|
46
54
|
|
47
55
|
def convert_to_hash: (::String str) -> ::String
|
48
56
|
|
49
|
-
def
|
57
|
+
def map_equivalent_characters: (::String str) -> ::String
|
50
58
|
|
51
59
|
def integer_representation: (untyped hexs) -> ::Array[::Integer]
|
52
60
|
|
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
|