{-# LANGUAGE FlexibleContexts #-}

module Saturn.Unstable.Type.Number where

import qualified Data.Bits as Bits
import qualified Data.Coerce as Coerce
import qualified Data.Text.Lazy.Builder as Builder
import qualified Data.Text.Lazy.Builder.Int as Builder
import qualified Data.Word as Word
import qualified Saturn.Unstable.Extra.Ord as Ord
import qualified Text.Parsec as Parsec
import qualified Text.Read as Read

newtype Number
  = Number Word.Word8
  deriving (Number -> Number -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Number -> Number -> Bool
$c/= :: Number -> Number -> Bool
== :: Number -> Number -> Bool
$c== :: Number -> Number -> Bool
Eq, Int -> Number -> ShowS
[Number] -> ShowS
Number -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Number] -> ShowS
$cshowList :: [Number] -> ShowS
show :: Number -> String
$cshow :: Number -> String
showsPrec :: Int -> Number -> ShowS
$cshowsPrec :: Int -> Number -> ShowS
Show)

fromWord8 :: Word.Word8 -> Number
fromWord8 :: Word8 -> Number
fromWord8 = coerce :: forall a b. Coercible a b => a -> b
Coerce.coerce

toWord8 :: Number -> Word.Word8
toWord8 :: Number -> Word8
toWord8 = coerce :: forall a b. Coercible a b => a -> b
Coerce.coerce

parsec :: (Parsec.Stream s m Char) => Parsec.ParsecT s u m Number
parsec :: forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Number
parsec = do
  String
string <- forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
Parsec.many1 forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
Parsec.digit
  Integer
integer <- forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"invalidNumber") forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall a. Read a => String -> Maybe a
Read.readMaybe String
string
  forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"invalidNumber") (forall (f :: * -> *) a. Applicative f => a -> f a
pure forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Number
fromWord8) forall a b. (a -> b) -> a -> b
$
    forall a b.
(Integral a, Integral b, Bits a, Bits b) =>
a -> Maybe b
Bits.toIntegralSized (Integer
integer :: Integer)

toBuilder :: Number -> Builder.Builder
toBuilder :: Number -> Builder
toBuilder = forall a. Integral a => a -> Builder
Builder.decimal forall b c a. (b -> c) -> (a -> b) -> a -> c
. Number -> Word8
toWord8

isValid :: (Word.Word8, Word.Word8) -> Number -> Bool
isValid :: (Word8, Word8) -> Number -> Bool
isValid (Word8, Word8)
tuple = forall a. Ord a => (a, a) -> a -> Bool
Ord.within (Word8, Word8)
tuple forall b c a. (b -> c) -> (a -> b) -> a -> c
. Number -> Word8
toWord8