Module: Philiprehberger::BaseConvert::Base32

Defined in:
lib/philiprehberger/base_convert/base32.rb

Overview

Crockford Base32 encoding and decoding

Alphabet: 0123456789ABCDEFGHJKMNPQRSTVWXYZ Case-insensitive decoding, excludes I, L, O, U

Constant Summary collapse

ALPHABET =
'0123456789ABCDEFGHJKMNPQRSTVWXYZ'
DECODE_MAP =
ALPHABET.each_char.with_index.each_with_object({}) do |(char, idx), map|
  map[char] = idx
  map[char.downcase] = idx
end.merge(
  'I' => 1, 'i' => 1,
  'L' => 1, 'l' => 1,
  'O' => 0, 'o' => 0
).freeze

Class Method Summary collapse

Class Method Details

.decode(string) ⇒ String

Decode a Crockford Base32 string

Parameters:

  • string (String)

    the Base32-encoded string

Returns:

  • (String)

    the decoded string

Raises:

  • (Error)

    if the string contains invalid characters



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/philiprehberger/base_convert/base32.rb', line 52

def self.decode(string)
  return '' if string.empty?

  string = string.delete('-')

  buffer = 0
  bits_left = 0
  result = []

  string.each_char do |char|
    value = DECODE_MAP[char]
    raise Error, "invalid Base32 character: #{char}" if value.nil?

    buffer = (buffer << 5) | value
    bits_left += 5

    if bits_left >= 8
      bits_left -= 8
      result << ((buffer >> bits_left) & 0xFF)
    end
  end

  result.pack('C*')
end

.encode(string) ⇒ String

Encode a string to Crockford Base32

Parameters:

  • string (String)

    the input string

Returns:

  • (String)

    the Base32-encoded string



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/philiprehberger/base_convert/base32.rb', line 24

def self.encode(string)
  return '' if string.empty?

  bytes = string.bytes
  result = []
  buffer = 0
  bits_left = 0

  bytes.each do |byte|
    buffer = (buffer << 8) | byte
    bits_left += 8

    while bits_left >= 5
      bits_left -= 5
      result << ALPHABET[(buffer >> bits_left) & 0x1F]
    end
  end

  result << ALPHABET[(buffer << (5 - bits_left)) & 0x1F] if bits_left.positive?

  result.join
end