{-# LANGUAGE DeriveDataTypeable #-}

module Burrito.Internal.Type.Digit
  ( Digit(..)
  , fromChar
  , fromWord8
  , toWord8
  ) where

import qualified Burrito.Internal.Type.Case as Case
import qualified Data.Bits as Bits
import qualified Data.Data as Data
import qualified Data.Word as Word

data Digit
  = Ox0
  | Ox1
  | Ox2
  | Ox3
  | Ox4
  | Ox5
  | Ox6
  | Ox7
  | Ox8
  | Ox9
  | OxA Case.Case
  | OxB Case.Case
  | OxC Case.Case
  | OxD Case.Case
  | OxE Case.Case
  | OxF Case.Case
  deriving (Typeable Digit
DataType
Constr
Typeable Digit
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> Digit -> c Digit)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c Digit)
-> (Digit -> Constr)
-> (Digit -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c Digit))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Digit))
-> ((forall b. Data b => b -> b) -> Digit -> Digit)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Digit -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Digit -> r)
-> (forall u. (forall d. Data d => d -> u) -> Digit -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> Digit -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> Digit -> m Digit)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Digit -> m Digit)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> Digit -> m Digit)
-> Data Digit
Digit -> DataType
Digit -> Constr
(forall b. Data b => b -> b) -> Digit -> Digit
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Digit -> c Digit
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Digit
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> Digit -> u
forall u. (forall d. Data d => d -> u) -> Digit -> [u]
forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Digit -> r
forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Digit -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Digit -> m Digit
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Digit -> m Digit
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Digit
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Digit -> c Digit
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Digit)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Digit)
$cOxF :: Constr
$cOxE :: Constr
$cOxD :: Constr
$cOxC :: Constr
$cOxB :: Constr
$cOxA :: Constr
$cOx9 :: Constr
$cOx8 :: Constr
$cOx7 :: Constr
$cOx6 :: Constr
$cOx5 :: Constr
$cOx4 :: Constr
$cOx3 :: Constr
$cOx2 :: Constr
$cOx1 :: Constr
$cOx0 :: Constr
$tDigit :: DataType
gmapMo :: (forall d. Data d => d -> m d) -> Digit -> m Digit
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Digit -> m Digit
gmapMp :: (forall d. Data d => d -> m d) -> Digit -> m Digit
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Digit -> m Digit
gmapM :: (forall d. Data d => d -> m d) -> Digit -> m Digit
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Digit -> m Digit
gmapQi :: Int -> (forall d. Data d => d -> u) -> Digit -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Digit -> u
gmapQ :: (forall d. Data d => d -> u) -> Digit -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Digit -> [u]
gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Digit -> r
$cgmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Digit -> r
gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Digit -> r
$cgmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Digit -> r
gmapT :: (forall b. Data b => b -> b) -> Digit -> Digit
$cgmapT :: (forall b. Data b => b -> b) -> Digit -> Digit
dataCast2 :: (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Digit)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Digit)
dataCast1 :: (forall d. Data d => c (t d)) -> Maybe (c Digit)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Digit)
dataTypeOf :: Digit -> DataType
$cdataTypeOf :: Digit -> DataType
toConstr :: Digit -> Constr
$ctoConstr :: Digit -> Constr
gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Digit
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Digit
gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Digit -> c Digit
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Digit -> c Digit
$cp1Data :: Typeable Digit
Data.Data, Digit -> Digit -> Bool
(Digit -> Digit -> Bool) -> (Digit -> Digit -> Bool) -> Eq Digit
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Digit -> Digit -> Bool
$c/= :: Digit -> Digit -> Bool
== :: Digit -> Digit -> Bool
$c== :: Digit -> Digit -> Bool
Eq, Eq Digit
Eq Digit
-> (Digit -> Digit -> Ordering)
-> (Digit -> Digit -> Bool)
-> (Digit -> Digit -> Bool)
-> (Digit -> Digit -> Bool)
-> (Digit -> Digit -> Bool)
-> (Digit -> Digit -> Digit)
-> (Digit -> Digit -> Digit)
-> Ord Digit
Digit -> Digit -> Bool
Digit -> Digit -> Ordering
Digit -> Digit -> Digit
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Digit -> Digit -> Digit
$cmin :: Digit -> Digit -> Digit
max :: Digit -> Digit -> Digit
$cmax :: Digit -> Digit -> Digit
>= :: Digit -> Digit -> Bool
$c>= :: Digit -> Digit -> Bool
> :: Digit -> Digit -> Bool
$c> :: Digit -> Digit -> Bool
<= :: Digit -> Digit -> Bool
$c<= :: Digit -> Digit -> Bool
< :: Digit -> Digit -> Bool
$c< :: Digit -> Digit -> Bool
compare :: Digit -> Digit -> Ordering
$ccompare :: Digit -> Digit -> Ordering
$cp1Ord :: Eq Digit
Ord, Int -> Digit -> ShowS
[Digit] -> ShowS
Digit -> String
(Int -> Digit -> ShowS)
-> (Digit -> String) -> ([Digit] -> ShowS) -> Show Digit
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Digit] -> ShowS
$cshowList :: [Digit] -> ShowS
show :: Digit -> String
$cshow :: Digit -> String
showsPrec :: Int -> Digit -> ShowS
$cshowsPrec :: Int -> Digit -> ShowS
Show)

fromChar :: Char -> Maybe Digit
fromChar :: Char -> Maybe Digit
fromChar Char
x = case Char
x of
  Char
'0' -> Digit -> Maybe Digit
forall a. a -> Maybe a
Just Digit
Ox0
  Char
'1' -> Digit -> Maybe Digit
forall a. a -> Maybe a
Just Digit
Ox1
  Char
'2' -> Digit -> Maybe Digit
forall a. a -> Maybe a
Just Digit
Ox2
  Char
'3' -> Digit -> Maybe Digit
forall a. a -> Maybe a
Just Digit
Ox3
  Char
'4' -> Digit -> Maybe Digit
forall a. a -> Maybe a
Just Digit
Ox4
  Char
'5' -> Digit -> Maybe Digit
forall a. a -> Maybe a
Just Digit
Ox5
  Char
'6' -> Digit -> Maybe Digit
forall a. a -> Maybe a
Just Digit
Ox6
  Char
'7' -> Digit -> Maybe Digit
forall a. a -> Maybe a
Just Digit
Ox7
  Char
'8' -> Digit -> Maybe Digit
forall a. a -> Maybe a
Just Digit
Ox8
  Char
'9' -> Digit -> Maybe Digit
forall a. a -> Maybe a
Just Digit
Ox9
  Char
'A' -> Digit -> Maybe Digit
forall a. a -> Maybe a
Just (Digit -> Maybe Digit) -> Digit -> Maybe Digit
forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxA Case
Case.Upper
  Char
'B' -> Digit -> Maybe Digit
forall a. a -> Maybe a
Just (Digit -> Maybe Digit) -> Digit -> Maybe Digit
forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxB Case
Case.Upper
  Char
'C' -> Digit -> Maybe Digit
forall a. a -> Maybe a
Just (Digit -> Maybe Digit) -> Digit -> Maybe Digit
forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxC Case
Case.Upper
  Char
'D' -> Digit -> Maybe Digit
forall a. a -> Maybe a
Just (Digit -> Maybe Digit) -> Digit -> Maybe Digit
forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxD Case
Case.Upper
  Char
'E' -> Digit -> Maybe Digit
forall a. a -> Maybe a
Just (Digit -> Maybe Digit) -> Digit -> Maybe Digit
forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxE Case
Case.Upper
  Char
'F' -> Digit -> Maybe Digit
forall a. a -> Maybe a
Just (Digit -> Maybe Digit) -> Digit -> Maybe Digit
forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxF Case
Case.Upper
  Char
'a' -> Digit -> Maybe Digit
forall a. a -> Maybe a
Just (Digit -> Maybe Digit) -> Digit -> Maybe Digit
forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxA Case
Case.Lower
  Char
'b' -> Digit -> Maybe Digit
forall a. a -> Maybe a
Just (Digit -> Maybe Digit) -> Digit -> Maybe Digit
forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxB Case
Case.Lower
  Char
'c' -> Digit -> Maybe Digit
forall a. a -> Maybe a
Just (Digit -> Maybe Digit) -> Digit -> Maybe Digit
forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxC Case
Case.Lower
  Char
'd' -> Digit -> Maybe Digit
forall a. a -> Maybe a
Just (Digit -> Maybe Digit) -> Digit -> Maybe Digit
forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxD Case
Case.Lower
  Char
'e' -> Digit -> Maybe Digit
forall a. a -> Maybe a
Just (Digit -> Maybe Digit) -> Digit -> Maybe Digit
forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxE Case
Case.Lower
  Char
'f' -> Digit -> Maybe Digit
forall a. a -> Maybe a
Just (Digit -> Maybe Digit) -> Digit -> Maybe Digit
forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxF Case
Case.Lower
  Char
_ -> Maybe Digit
forall a. Maybe a
Nothing

fromWord8 :: Word.Word8 -> (Digit, Digit)
fromWord8 :: Word8 -> (Digit, Digit)
fromWord8 Word8
x =
  let
    f :: Word.Word8 -> Digit
    f :: Word8 -> Digit
f Word8
y = case Word8
y of
      Word8
0x0 -> Digit
Ox0
      Word8
0x1 -> Digit
Ox1
      Word8
0x2 -> Digit
Ox2
      Word8
0x3 -> Digit
Ox3
      Word8
0x4 -> Digit
Ox4
      Word8
0x5 -> Digit
Ox5
      Word8
0x6 -> Digit
Ox6
      Word8
0x7 -> Digit
Ox7
      Word8
0x8 -> Digit
Ox8
      Word8
0x9 -> Digit
Ox9
      Word8
0xA -> Case -> Digit
OxA Case
Case.Upper
      Word8
0xB -> Case -> Digit
OxB Case
Case.Upper
      Word8
0xC -> Case -> Digit
OxC Case
Case.Upper
      Word8
0xD -> Case -> Digit
OxD Case
Case.Upper
      Word8
0xE -> Case -> Digit
OxE Case
Case.Upper
      Word8
0xF -> Case -> Digit
OxF Case
Case.Upper
      Word8
_ -> String -> Digit
forall a. HasCallStack => String -> a
error (String -> Digit) -> String -> Digit
forall a b. (a -> b) -> a -> b
$ String
"invalid nibble: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Word8 -> String
forall a. Show a => a -> String
show Word8
y
  in (Word8 -> Digit
f (Word8 -> Digit) -> Word8 -> Digit
forall a b. (a -> b) -> a -> b
$ Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
Bits.shiftR Word8
x Int
4, Word8 -> Digit
f (Word8 -> Digit) -> Word8 -> Digit
forall a b. (a -> b) -> a -> b
$ Word8
x Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
Bits..&. Word8
0x0F)

toWord8 :: Digit -> Digit -> Word.Word8
toWord8 :: Digit -> Digit -> Word8
toWord8 Digit
x Digit
y =
  let
    f :: Digit -> Word.Word8
    f :: Digit -> Word8
f Digit
z = case Digit
z of
      Digit
Ox0 -> Word8
0x0
      Digit
Ox1 -> Word8
0x1
      Digit
Ox2 -> Word8
0x2
      Digit
Ox3 -> Word8
0x3
      Digit
Ox4 -> Word8
0x4
      Digit
Ox5 -> Word8
0x5
      Digit
Ox6 -> Word8
0x6
      Digit
Ox7 -> Word8
0x7
      Digit
Ox8 -> Word8
0x8
      Digit
Ox9 -> Word8
0x9
      OxA Case
_ -> Word8
0xA
      OxB Case
_ -> Word8
0xB
      OxC Case
_ -> Word8
0xC
      OxD Case
_ -> Word8
0xD
      OxE Case
_ -> Word8
0xE
      OxF Case
_ -> Word8
0xF
  in Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
Bits.shiftL (Digit -> Word8
f Digit
x) Int
4 Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
Bits..|. Digit -> Word8
f Digit
y