Module: Base32H
Overview
This module provides Base32H encoding and decoding functions.
Constant Summary collapse
- VERSION =
"0.1.0"
Instance Method Summary collapse
-
#decode(str) ⇒ Object
:category: Decoding Numeric.
-
#decode_bin(str) ⇒ Object
:category: Decoding Binary.
-
#decode_digit(d) ⇒ Object
:category: Decoding Digit.
-
#digits ⇒ Object
The complete list of Base32H digits, as an array of strings; the index of the array is the numeric value of the digit(s) in the string at that index.
-
#encode(int) ⇒ Object
:category: Encoding Numeric.
-
#encode_bin(bin) ⇒ Object
:category: Encoding Binary.
-
#encode_digit(d) ⇒ Object
:category: Encoding Digit.
Instance Method Details
#decode(str) ⇒ Object
:category: Decoding Numeric
Decodes a Base32H number to its integer representation.
112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/base32h.rb', line 112 def decode(str) res = str.to_s.chars.reverse.reduce({acc: 0, exp: 0}) do |state, char| digit = decode_digit(char) if digit.nil? state else {acc: state[:acc] + (digit * 32**state[:exp]), exp: state[:exp] + 1} end end res[:acc] end |
#decode_bin(str) ⇒ Object
:category: Decoding Binary
Decodes a Base32H binary into a string of packed unsigned bytes.
129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/base32h.rb', line 129 def decode_bin(str) data = str.chars.reject {|c| decode_digit(c).nil?} extra = data.length % 8 data = (['0'] * (8 - extra)) + data if extra > 0 out = [] data.each_slice(8) do |s| chunk = u40_to_bytes decode(s.join '') out += chunk end out.pack('C*') end |
#decode_digit(d) ⇒ Object
:category: Decoding Digit
Decodes a single Base32H digit to its integer representation.
103 104 105 106 |
# File 'lib/base32h.rb', line 103 def decode_digit(d) d = d.to_s digits.find_index {|i| i.include? d} end |
#digits ⇒ Object
The complete list of Base32H digits, as an array of strings; the index of the array is the numeric value of the digit(s) in the string at that index. The first character in each string is the “canonical” digit (i.e. the one that Base32H-conformant encoders must emit for that value); all other characters (if present) are “aliases” (i.e. alternate forms of that digit that Base32H-conformant decoders must accept and correctly decode to that value).
For example, digits[27] returns ‘VvUu’, meaning that the “canonical” digit of value 27 is V, and that v, U, and u are all “aliases” of that canonical digit and decode to a value of 27.
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/base32h.rb', line 22 def digits ['0Oo', '1Ii', '2', '3', '4', '5Ss', '6', '7', '8', '9', 'Aa', 'Bb', 'Cc', 'Dd', 'Ee', 'Ff', 'Gg', 'Hh', 'Jj', 'Kk', 'Ll', 'Mm', 'Nn', 'Pp', 'Qq', 'Rr', 'Tt', 'VvUu', 'Ww', 'Xx', 'Yy', 'Zz'] end |
#encode(int) ⇒ Object
:category: Encoding Numeric
Encodes an integer to its Base32H representation.
72 73 74 75 76 77 78 79 80 81 |
# File 'lib/base32h.rb', line 72 def encode(int) rem = int.to_i.abs out = [] return '0' if rem == 0 while rem > 0 do out.unshift(encode_digit(rem % 32)) rem /= 32 end out.join '' end |
#encode_bin(bin) ⇒ Object
:category: Encoding Binary
Encodes a (binary) string to its Base32H representation.
87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/base32h.rb', line 87 def encode_bin(bin) data = bin.unpack('C*') extra = data.length % 5 data = ([0] * (5 - extra)) + data if extra > 0 out = [] data.each_slice(5) do |s| chunk = bytes_to_u40 s out.push encode(chunk).rjust(8, '0') end out.join '' end |
#encode_digit(d) ⇒ Object
:category: Encoding Digit
Encodes an integer between 0 and 31 (inclusive) to its Base32H representation.
62 63 64 65 66 |
# File 'lib/base32h.rb', line 62 def encode_digit(d) d = d.to_i return nil unless (0..31).include? d digits[d][0] end |