Class: Base32::URL
- Inherits:
-
Object
- Object
- Base32::URL
- Defined in:
- lib/base32/url.rb
Overview
encode a value with the encoding defined by Douglas Crockford in <www.crockford.com/wrmg/base32.html>
this is not the same as the Base32 encoding defined in RFC 4648
The Base32 symbol set is a superset of the Base16 symbol set.
We chose a symbol set of 10 digits and 22 letters. We exclude 4 of the 26 letters: I L O U.
Excluded Letters
- I
-
Can be confused with 1
- L
-
Can be confused with 1
- O
-
Can be confused with 0
- U
-
Accidental obscenity
When decoding, upper and lower case letters are accepted, and i and l will be treated as 1 and o will be treated as 0. When encoding, lower upper case letters are used.
If the bit-length of the number to be encoded is not a multiple of 5 bits, then zero-extend the number to make its bit-length a multiple of 5.
Hyphens (-) can be inserted into symbol strings. This can partition a string into manageable pieces, improving readability by helping to prevent confusion. Hyphens are ignored during decoding. An application may look for hyphens to assure symbol string correctness.
Constant Summary collapse
- ENCODE_CHARS =
%w(0 1 2 3 4 5 6 7 8 9 a b c d e f g h j k m n p q r s t v w x y z ?)- DECODE_MAP =
ENCODE_CHARS.to_enum(:each_with_index).inject({}) do |h,(c,i)| h[c] = i; h end.merge({'i' => 1, 'l' => 1, 'o' => 0})
- CHECKSUM_CHARS =
%w(i l o u)- CHECKSUM_MAP =
{ "i" => 32, "l" => 33, "o" => 34, "u" => 35 }
Class Method Summary collapse
- .clean(string) ⇒ Object
-
.decode(string, opts = {}) ⇒ Object
decode a string to an integer using Douglas Crockfords Base32 Encoding.
-
.decode!(string, opts = {}) ⇒ Object
same as decode, but raises ArgumentError when the string can’t be decoded.
-
.encode(number, opts = {}) ⇒ Object
encodes an integer into a string.
-
.normalize(string, opts = {}) ⇒ Object
return the canonical encoding of a string.
-
.valid?(string, opts = {}) ⇒ Boolean
returns false if the string contains invalid characters and can’t be decoded.
Class Method Details
.clean(string) ⇒ Object
152 153 154 |
# File 'lib/base32/url.rb', line 152 def clean(string) string.gsub(/-/,'').downcase end |
.decode(string, opts = {}) ⇒ Object
decode a string to an integer using Douglas Crockfords Base32 Encoding
the string is converted to uppercase and hyphens are stripped before decoding
I,i,l,L decodes to 1
O,o decodes to 0
Base32::Crockford.decode("16J") # => 1234
Base32::Crockford.decode("OI") # => 1
Base32::Crockford.decode("3G923-0VQVS") # => 123456789012345
returns nil if the string contains invalid characters and can’t be decoded, or if checksum option is used and checksum is incorrect
106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/base32/url.rb', line 106 def self.decode(string, opts = {}) if opts[:checksum] checksum_char = string.slice!(-1) checksum_number = DECODE_MAP.merge(CHECKSUM_MAP)[checksum_char] end number = clean(string).split(//).map { |char| DECODE_MAP[char] or return nil }.inject(0) { |result,val| (result << 5) + val } return nil if opts[:checksum] && (number % 36 != checksum_number) number end |
.decode!(string, opts = {}) ⇒ Object
same as decode, but raises ArgumentError when the string can’t be decoded
123 124 125 |
# File 'lib/base32/url.rb', line 123 def self.decode!(string, opts = {}) decode(string) or raise ArgumentError end |
.encode(number, opts = {}) ⇒ Object
encodes an integer into a string
when checksum is given, a checksum is added at the end of the the string, calculated as modulo 36 of number. Four additional checksum symbols are used for symbol values 32-35
when split is given a hyphen is inserted every <n> characters to improve readability
when length is given, the resulting string is zero-padded to be exactly this number of characters long (hyphens are ignored)
Base32::URL.encode(1234) # => "16j"
Base32::URL.encode(123456789012345, :split=>5) # => "3g923-0vqvs"
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/base32/url.rb', line 70 def self.encode(number, opts = {}) # verify options raise ArgumentError unless (opts.keys - [:length, :split, :checksum] == []) str = number.to_s(2).reverse.scan(/.{1,5}/).map do |bits| ENCODE_CHARS[bits.reverse.to_i(2)] end.reverse.join str += (ENCODE_CHARS + CHECKSUM_CHARS)[number % 36] if opts[:checksum] str = str.rjust(opts[:length], '0') if opts[:length] if opts[:split] str = str.reverse str = str.scan(/.{1,#{opts[:split]}}/).map { |x| x.reverse } str = str.reverse.join("-") end str end |
.normalize(string, opts = {}) ⇒ Object
return the canonical encoding of a string. converts it to uppercase and removes hyphens
replaces invalid characters with a question mark (‘?’)
132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/base32/url.rb', line 132 def self.normalize(string, opts = {}) checksum_char = string.slice!(-1) if opts[:checksum] string = clean(string).split(//).map do |char| ENCODE_CHARS[DECODE_MAP[char] || 32] end.join string += checksum_char if opts[:checksum] string end |
.valid?(string, opts = {}) ⇒ Boolean
returns false if the string contains invalid characters and can’t be decoded
147 148 149 |
# File 'lib/base32/url.rb', line 147 def self.valid?(string, opts = {}) !(normalize(string, opts) =~ /\?/) end |