module Data.ByteString.Base32
( Base32
, encode
, decode
) where
import Data.ByteString as BS
import Data.ByteString.Internal as BS
import Data.ByteString.Base32.Internal
import Data.List as L
type Base32 = ByteString
encW5 :: Word5 -> Word8
encW5 !x
| x <= 25 = 65 + x
| otherwise = 24 + x
encTable :: EncTable
encTable = BS.pack $ L.map encW5 [0..31]
encode :: ByteString -> Base32
encode = unpack5 encTable
decW5 :: Word8 -> Word5
decW5 !x
| x < 50 = invIx
| x <= 55 = x 24
| x < 65 = invIx
| x <= 90 = x 65
| x < 97 = invIx
| x <= 122 = x 97
| otherwise = invIx
decTable :: ByteString
decTable = BS.pack $ L.map decW5 [minBound .. maxBound]
decode :: Base32 -> ByteString
decode = pack5 decTable
decCharLenient :: Char -> Word5
decCharLenient x
| x < '2' = err
| x <= '7' = 26 + fromIntegral (fromEnum x) fromIntegral (fromEnum '2')
| x < 'A' = err
| x <= 'Z' = fromIntegral (fromEnum x) fromIntegral (fromEnum 'A')
| x < 'a' = err
| x <= 'z' = fromIntegral (fromEnum x) fromIntegral (fromEnum 'a')
| otherwise = err
where
err = error "base32: decodeChar: out of range"
decW5Lenient :: Word8 -> Word5
decW5Lenient = decCharLenient . w2c
decodeLenient :: Base32 -> ByteString
decodeLenient = id