-- | Adapted from https://hackage.haskell.org/package/crockford module Base32 (decode) where import Data.Char as C (Char, toUpper) import Data.Text as T (Text, unpack) import Protolude ( Applicative (pure), Integral, Maybe (..), Traversable (mapM), ($), ) import Data.ULID.Digits (unDigits) {-| Decodes a Crockford-encoded `String` into an integer, if possible. Returns `Nothing` if the string is not a valid Crockford-encoded value. -} decode :: (Integral i) => Text -> Maybe i decode base32text = do numbers <- mapM decodeChar $ T.unpack base32text pure $ unDigits 32 numbers decodeChar :: (Integral i) => Char -> Maybe i decodeChar c = case C.toUpper c of '0' -> Just 0 'O' -> Just 0 '1' -> Just 1 'I' -> Just 1 'L' -> Just 1 '2' -> Just 2 '3' -> Just 3 '4' -> Just 4 '5' -> Just 5 '6' -> Just 6 '7' -> Just 7 '8' -> Just 8 '9' -> Just 9 'A' -> Just 10 'B' -> Just 11 'C' -> Just 12 'D' -> Just 13 'E' -> Just 14 'F' -> Just 15 'G' -> Just 16 'H' -> Just 17 'J' -> Just 18 'K' -> Just 19 'M' -> Just 20 'N' -> Just 21 'P' -> Just 22 'Q' -> Just 23 'R' -> Just 24 'S' -> Just 25 'T' -> Just 26 'V' -> Just 27 'W' -> Just 28 'X' -> Just 29 'Y' -> Just 30 'Z' -> Just 31 _ -> Nothing