{-# 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
Digit -> DataType
Digit -> Constr
(forall b. Data b => b -> b) -> Digit -> 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)
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(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 (m :: * -> *).
MonadPlus m =>
(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 (m :: * -> *).
Monad m =>
(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 :: forall u. Int -> (forall d. Data d => d -> u) -> Digit -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Digit -> u
gmapQ :: forall u. (forall d. Data d => d -> u) -> Digit -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Digit -> [u]
gmapQr :: forall r r'.
(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 :: forall r r'.
(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 (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(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 (t :: * -> *) (c :: * -> *).
Typeable t =>
(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 (c :: * -> *).
(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 (c :: * -> *).
(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
Data.Data, Digit -> Digit -> Bool
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
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
Ord, Int -> Digit -> ShowS
[Digit] -> ShowS
Digit -> [Char]
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [Digit] -> ShowS
$cshowList :: [Digit] -> ShowS
show :: Digit -> [Char]
$cshow :: Digit -> [Char]
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' -> forall a. a -> Maybe a
Just Digit
Ox0
  Char
'1' -> forall a. a -> Maybe a
Just Digit
Ox1
  Char
'2' -> forall a. a -> Maybe a
Just Digit
Ox2
  Char
'3' -> forall a. a -> Maybe a
Just Digit
Ox3
  Char
'4' -> forall a. a -> Maybe a
Just Digit
Ox4
  Char
'5' -> forall a. a -> Maybe a
Just Digit
Ox5
  Char
'6' -> forall a. a -> Maybe a
Just Digit
Ox6
  Char
'7' -> forall a. a -> Maybe a
Just Digit
Ox7
  Char
'8' -> forall a. a -> Maybe a
Just Digit
Ox8
  Char
'9' -> forall a. a -> Maybe a
Just Digit
Ox9
  Char
'A' -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxA Case
Case.Upper
  Char
'B' -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxB Case
Case.Upper
  Char
'C' -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxC Case
Case.Upper
  Char
'D' -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxD Case
Case.Upper
  Char
'E' -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxE Case
Case.Upper
  Char
'F' -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxF Case
Case.Upper
  Char
'a' -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxA Case
Case.Lower
  Char
'b' -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxB Case
Case.Lower
  Char
'c' -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxC Case
Case.Lower
  Char
'd' -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxD Case
Case.Lower
  Char
'e' -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxE Case
Case.Lower
  Char
'f' -> forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ Case -> Digit
OxF Case
Case.Lower
  Char
_ -> 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
_ -> forall a. HasCallStack => [Char] -> a
error forall a b. (a -> b) -> a -> b
$ [Char]
"invalid nibble: " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> [Char]
show Word8
y
   in (Word8 -> Digit
f forall a b. (a -> b) -> a -> b
$ forall a. Bits a => a -> Int -> a
Bits.shiftR Word8
x Int
4, Word8 -> Digit
f forall a b. (a -> b) -> a -> b
$ Word8
x 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 forall a. Bits a => a -> Int -> a
Bits.shiftL (Digit -> Word8
f Digit
x) Int
4 forall a. Bits a => a -> a -> a
Bits..|. Digit -> Word8
f Digit
y