Class: EncodedId::Encoders::HashidOrdinalAlphabetSeparatorGuards
- Inherits:
-
Object
- Object
- EncodedId::Encoders::HashidOrdinalAlphabetSeparatorGuards
- Includes:
- HashidConsistentShuffle
- Defined in:
- lib/encoded_id/encoders/hashid_ordinal_alphabet_separator_guards.rb
Overview
Prepares and partitions the character sets for HashID encoding.
This class is responsible for splitting a single input alphabet into three disjoint sets:
-
Alphabet: Main characters used to encode numbers
-
**Separators (seps)**: Characters that separate encoded numbers in the hash
-
Guards: Characters added at boundaries to meet minimum length requirements
Initialization Process:
Step 1: Start with default separators (“cfhistuCFHISTU”) Step 2: Ensure separators and alphabet are disjoint (remove overlaps) Step 3: Shuffle separators using the salt Step 4: Balance alphabet-to-separator ratio (target ≈ 3.5:1) Step 5: Create guards from alphabet or separators (target ≈ 12:1 alphabet-to-guards) Step 6: Shuffle alphabet using the salt
Character Set Ratios:
The algorithm maintains specific ratios between the character sets:
-
Alphabet : Separators ≈ 3.5 : 1 (SEP_DIV)
-
Alphabet : Guards ≈ 12 : 1 (GUARD_DIV)
These ratios ensure:
-
Enough separators to avoid patterns in multi-number hashes
-
Guards are rare enough to not waste space but common enough to be useful
-
Alphabet is large enough for efficient encoding (shorter hashes)
Why Ordinals?
All characters are stored as integer ordinals (Unicode codepoints) rather than strings. This provides:
-
Faster comparisons and lookups
-
More efficient memory usage
-
Direct array indexing without string allocations
Constant Summary collapse
- SEP_DIV =
Target ratio of alphabet to separators (alphabet.length / seps.length ≈ 3.5)
3.5- DEFAULT_SEPS =
Default separator characters - chosen to be visually distinct and common in many fonts
"cfhistuCFHISTU".chars.map(&:ord).freeze
- GUARD_DIV =
Target ratio of alphabet to guards (alphabet.length / guards.length ≈ 12)
12.0- SPACE_CHAR =
Space character ordinal - used as a placeholder when removing characters
" ".ord
Instance Attribute Summary collapse
-
#alphabet ⇒ Object
readonly
: Array.
-
#guards ⇒ Object
readonly
: Array.
-
#guards_tr_selector ⇒ Object
readonly
: String.
-
#salt ⇒ Object
readonly
: Array.
-
#seps ⇒ Object
readonly
: Array.
-
#seps_tr_selector ⇒ Object
readonly
: String.
Instance Method Summary collapse
-
#initialize(alphabet, salt) ⇒ HashidOrdinalAlphabetSeparatorGuards
constructor
Initialize and partition the character sets.
Methods included from HashidConsistentShuffle
Constructor Details
#initialize(alphabet, salt) ⇒ HashidOrdinalAlphabetSeparatorGuards
Initialize and partition the character sets.
Takes an alphabet and salt, then:
-
Converts all characters to ordinals (integer codepoints)
-
Partitions the alphabet into separators, guards, and the remaining alphabet
-
Shuffles each set deterministically using the salt
-
Balances the ratios between the sets
-
Creates escaped versions for use with String#tr
All arrays are frozen after setup to prevent accidental modification.
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/encoded_id/encoders/hashid_ordinal_alphabet_separator_guards.rb', line 79 def initialize(alphabet, salt) @alphabet = alphabet.characters.chars.map(&:ord) @salt = salt.chars.map(&:ord) setup_seps setup_guards # Pre-compute escaped versions for String#tr operations during decode. # This escapes special characters like '-', '\\', and '^' that have # special meaning in tr() character ranges. @seps_tr_selector = escape_characters_string_for_tr(@seps.map(&:chr)) @guards_tr_selector = escape_characters_string_for_tr(@guards.map(&:chr)) @alphabet.freeze @seps.freeze @guards.freeze end |
Instance Attribute Details
#alphabet ⇒ Object (readonly)
: Array
98 99 100 |
# File 'lib/encoded_id/encoders/hashid_ordinal_alphabet_separator_guards.rb', line 98 def alphabet @alphabet end |
#guards ⇒ Object (readonly)
: Array
100 101 102 |
# File 'lib/encoded_id/encoders/hashid_ordinal_alphabet_separator_guards.rb', line 100 def guards @guards end |
#guards_tr_selector ⇒ Object (readonly)
: String
102 103 104 |
# File 'lib/encoded_id/encoders/hashid_ordinal_alphabet_separator_guards.rb', line 102 def guards_tr_selector @guards_tr_selector end |
#salt ⇒ Object (readonly)
: Array
97 98 99 |
# File 'lib/encoded_id/encoders/hashid_ordinal_alphabet_separator_guards.rb', line 97 def salt @salt end |
#seps ⇒ Object (readonly)
: Array
99 100 101 |
# File 'lib/encoded_id/encoders/hashid_ordinal_alphabet_separator_guards.rb', line 99 def seps @seps end |
#seps_tr_selector ⇒ Object (readonly)
: String
101 102 103 |
# File 'lib/encoded_id/encoders/hashid_ordinal_alphabet_separator_guards.rb', line 101 def seps_tr_selector @seps_tr_selector end |