lib/otp/base32.rb in otp-0.0.10 vs lib/otp/base32.rb in otp-0.0.11
- old
+ new
@@ -8,71 +8,52 @@
DECODE_MAP = {
"A"=>0, "B"=>1, "C"=>2, "D"=>3, "E"=>4, "F"=>5, "G"=>6, "H"=>7,
"I"=>8, "J"=>9, "K"=>10, "L"=>11, "M"=>12, "N"=>13, "O"=>14, "P"=>15,
"Q"=>16, "R"=>17, "S"=>18, "T"=>19, "U"=>20, "V"=>21, "W"=>22, "X"=>23,
"Y"=>24, "Z"=>25, "2"=>26, "3"=>27, "4"=>28, "5"=>29, "6"=>30, "7"=>31,
- "="=>-1,
+ "0"=>14, "1"=>11, "8"=>1, # mistyped chars
+ " "=>-2, "-"=>-2, "\n"=>-2, "\r"=>-2, "\t"=>-2, # separators
+ "="=>-1, # padding
}
- DECODE_LENGTH = {
- 1 => 1, # 5 bits -> 1 byte (irregular)
- 2 => 1, # 10 bits -> 1 byte
- 3 => 2, # 15 bits -> 2 bytes (irregular)
- 4 => 2, # 20 bits -> 2 bytes
- 5 => 3, # 25 bits -> 3 bytes
- 6 => 4, # 30 bits -> 4 bytes (irregular)
- 7 => 4, # 35 bits -> 4 bytes
- 8 => 5, # 40 bits -> 5 bytes
- }
-
module_function
- def encode(bytes, padding: true)
+ def encode(bytes)
return nil unless bytes
- pad = padding ? "=" : ""
- ret = ""
bytes = bytes.dup.force_encoding("binary")
- off = 0
- while off < bytes.length
- n = 0
- bits = bytes[off, 5]
- off += 5
- l = (bits.length * 8.0 / 5.0).ceil
- bits << "\0" while bits.length < 5
- bits.each_byte{|b| n = (n << 8) | b }
- (1..8).each do |i|
- ret << ((i > l) ? pad : ENCODE_CHARS[(n >> (8-i)*5) & 0x1f])
+ ret = ""
+ offset = buffer = buffered = 0
+ while offset < bytes.length
+ buffer = ((buffer << 8) | bytes[offset].ord)
+ buffered += 8
+ offset += 1
+ while buffered >= 5
+ ret << ENCODE_CHARS[buffer >> (buffered - 5)]
+ buffered -= 5
+ buffer &= (0xff >> (8 - buffered))
end
end
+ if buffered > 0
+ ret << ENCODE_CHARS[buffer << (5 - buffered)]
+ end
return ret
end
def decode(chars)
return nil unless chars
- ret = ""
+ ret = "".force_encoding("binary")
chars = chars.upcase
- ret.force_encoding("binary")
- off = 0
- while off < chars.length
- n = l = 0
- bits = chars[off, 8]
- off += 8
- bits << "=" while bits.length < 8
- bits.each_char.with_index do |c, i|
- d = DECODE_MAP[c]
- if d.nil?
- raise ArgumentError, "invalid char: #{c}"
- elsif d < 0
- n <<= 5 * (8-i)
- off = chars.length
- break
- else
- n <<= 5
- n |= d
- l = DECODE_LENGTH[i+1]
- end
- end
- ret << (1..l).map{|i| (n >> 40 - i * 8) & 0xff }.pack("c*")
+ buffer = buffered = 0
+ chars.each_char do |c|
+ d = DECODE_MAP[c]
+ raise ArgumentError, "invalid char: #{c}" if d.nil?
+ next if d == -2
+ break if d == -1
+ buffer = (buffer << 5) | d
+ buffered += 5
+ next if buffered < 8
+ ret << ((buffer >> (buffered - 8)) & 0xff)
+ buffered -= 8
end
return ret
end
end
end