quicp2p/base32.nim

84 lines
1.7 KiB
Nim

#
# Nim's Unofficial Library
# (c) Copyright 2015 Huy Doan
#
# See the file "LICENSE", included in this
# distribution, for details about the copyright.
#
## This module implements a base32 encoder and decoder.
const
VERSION* = "0.1.2"
base32Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567="
proc encode*(s: openArray[char]; pad=true): string =
var i, j, idx, digit: int = 0
var current, next: int
var len = (s.len * 8 / 5).int
if len mod 8 != 0:
len += 8 - (len mod 8)
result = newString(len)
while i < s.len:
current = s[i].ord
if idx > 3:
if i + 1 < s.len:
next = s[i+1].ord
else:
next = 0
digit = current and (0xFF shr idx)
idx = (idx + 5) mod 8
digit = digit shl idx
digit = digit or (next shr (8 - idx))
i += 1
else:
digit = (current shr (8 - (idx + 5))) and 0x1F
idx = (idx + 5) mod 8
if idx == 0:
i += 1
result[j] = base32Chars[digit]
j += 1
if pad:
for i in j..<len:
result[i] = base32Chars[32]
else:
result.setLen j
proc decode*(s: openArray[char]): string =
var ch, idx, bits, buf: int = 0
let len = (s.len * 5 / 8).int
result = newString(len)
for i in 0..s.len-1:
ch = s[i].ord
case ch
of 0x41..0x5A, 0x61..0x7A:
ch = (ch and 0x1F) - 1
of 0x32..0x37:
ch -= 0x32 - 26
of 0x3D:
continue
else:
raise newException(ValueError, "Non-base32 digit found: " & $ch)
buf = buf shl 5
buf = buf xor ch
bits += 5
if bits >= 8:
bits -= 8
result[idx] = char(buf shr bits and 0xFF)
idx += 1
if idx < len:
setLen(result, idx)