module Codec.Crockford (encode, decode, prop_crockfordRoundTrip) where
import Data.Char
import Data.Digits (digits, unDigits)
import Data.Maybe
import Test.QuickCheck
decode :: Integral i => String -> Maybe i
decode :: forall i. Integral i => String -> Maybe i
decode String
s = (Char -> Maybe i) -> String -> Maybe [i]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM Char -> Maybe i
forall i. Integral i => Char -> Maybe i
decodeChar String
s Maybe [i] -> ([i] -> Maybe i) -> Maybe i
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= i -> Maybe i
forall a. a -> Maybe a
forall (m :: * -> *) a. Monad m => a -> m a
return (i -> Maybe i) -> ([i] -> i) -> [i] -> Maybe i
forall b c a. (b -> c) -> (a -> b) -> a -> c
. i -> [i] -> i
forall n. Integral n => n -> [n] -> n
unDigits i
32
encode :: Integral i => i -> String
encode :: forall i. Integral i => i -> String
encode = Maybe String -> String
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe String -> String) -> (i -> Maybe String) -> i -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (i -> Maybe Char) -> [i] -> Maybe String
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM i -> Maybe Char
forall i. Integral i => i -> Maybe Char
encodeChar ([i] -> Maybe String) -> (i -> [i]) -> i -> Maybe String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. i -> i -> [i]
forall n. Integral n => n -> n -> [n]
digits i
32
decodeChar :: Integral i => Char -> Maybe i
decodeChar :: forall i. Integral i => Char -> Maybe i
decodeChar Char
c = case Char -> Char
toUpper Char
c of
Char
'0' -> i -> Maybe i
forall a. a -> Maybe a
Just i
0
Char
'O' -> i -> Maybe i
forall a. a -> Maybe a
Just i
0
Char
'1' -> i -> Maybe i
forall a. a -> Maybe a
Just i
1
Char
'I' -> i -> Maybe i
forall a. a -> Maybe a
Just i
1
Char
'L' -> i -> Maybe i
forall a. a -> Maybe a
Just i
1
Char
'2' -> i -> Maybe i
forall a. a -> Maybe a
Just i
2
Char
'3' -> i -> Maybe i
forall a. a -> Maybe a
Just i
3
Char
'4' -> i -> Maybe i
forall a. a -> Maybe a
Just i
4
Char
'5' -> i -> Maybe i
forall a. a -> Maybe a
Just i
5
Char
'6' -> i -> Maybe i
forall a. a -> Maybe a
Just i
6
Char
'7' -> i -> Maybe i
forall a. a -> Maybe a
Just i
7
Char
'8' -> i -> Maybe i
forall a. a -> Maybe a
Just i
8
Char
'9' -> i -> Maybe i
forall a. a -> Maybe a
Just i
9
Char
'A' -> i -> Maybe i
forall a. a -> Maybe a
Just i
10
Char
'B' -> i -> Maybe i
forall a. a -> Maybe a
Just i
11
Char
'C' -> i -> Maybe i
forall a. a -> Maybe a
Just i
12
Char
'D' -> i -> Maybe i
forall a. a -> Maybe a
Just i
13
Char
'E' -> i -> Maybe i
forall a. a -> Maybe a
Just i
14
Char
'F' -> i -> Maybe i
forall a. a -> Maybe a
Just i
15
Char
'G' -> i -> Maybe i
forall a. a -> Maybe a
Just i
16
Char
'H' -> i -> Maybe i
forall a. a -> Maybe a
Just i
17
Char
'J' -> i -> Maybe i
forall a. a -> Maybe a
Just i
18
Char
'K' -> i -> Maybe i
forall a. a -> Maybe a
Just i
19
Char
'M' -> i -> Maybe i
forall a. a -> Maybe a
Just i
20
Char
'N' -> i -> Maybe i
forall a. a -> Maybe a
Just i
21
Char
'P' -> i -> Maybe i
forall a. a -> Maybe a
Just i
22
Char
'Q' -> i -> Maybe i
forall a. a -> Maybe a
Just i
23
Char
'R' -> i -> Maybe i
forall a. a -> Maybe a
Just i
24
Char
'S' -> i -> Maybe i
forall a. a -> Maybe a
Just i
25
Char
'T' -> i -> Maybe i
forall a. a -> Maybe a
Just i
26
Char
'V' -> i -> Maybe i
forall a. a -> Maybe a
Just i
27
Char
'W' -> i -> Maybe i
forall a. a -> Maybe a
Just i
28
Char
'X' -> i -> Maybe i
forall a. a -> Maybe a
Just i
29
Char
'Y' -> i -> Maybe i
forall a. a -> Maybe a
Just i
30
Char
'Z' -> i -> Maybe i
forall a. a -> Maybe a
Just i
31
Char
_ -> Maybe i
forall a. Maybe a
Nothing
encodeChar :: Integral i => i -> Maybe Char
encodeChar :: forall i. Integral i => i -> Maybe Char
encodeChar i
i = case i
i of
i
0 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'0'
i
1 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'1'
i
2 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'2'
i
3 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'3'
i
4 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'4'
i
5 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'5'
i
6 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'6'
i
7 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'7'
i
8 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'8'
i
9 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'9'
i
10 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'A'
i
11 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'B'
i
12 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'C'
i
13 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'D'
i
14 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'E'
i
15 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'F'
i
16 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'G'
i
17 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'H'
i
18 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'J'
i
19 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'K'
i
20 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'M'
i
21 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'N'
i
22 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'P'
i
23 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'Q'
i
24 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'R'
i
25 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'S'
i
26 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'T'
i
27 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'V'
i
28 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'W'
i
29 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'X'
i
30 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'Y'
i
31 -> Char -> Maybe Char
forall a. a -> Maybe a
Just Char
'Z'
i
_ -> Maybe Char
forall a. Maybe a
Nothing
prop_crockfordRoundTrip
:: Integer
-> Property
prop_crockfordRoundTrip :: Integer -> Property
prop_crockfordRoundTrip Integer
i = Integer
i Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
0 Bool -> Bool -> Property
forall prop. Testable prop => Bool -> prop -> Property
==> Integer -> Maybe Integer
forall a. a -> Maybe a
Just Integer
i Maybe Integer -> Maybe Integer -> Bool
forall a. Eq a => a -> a -> Bool
== (String -> Maybe Integer
forall i. Integral i => String -> Maybe i
decode (String -> Maybe Integer)
-> (Integer -> String) -> Integer -> Maybe Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> String
forall i. Integral i => i -> String
encode) Integer
i