{-# LANGUAGE DerivingStrategies #-}

{-# OPTIONS_GHC -Wno-orphans #-}

module ZkFold.Base.Data.ByteString
  ( Binary (..)
  , toByteString
  , fromByteString
  , putWord8
  , getWord8
  , skip
  , LittleEndian (..)
  , BigEndian (..)
  ) where

import           Control.Applicative    (many)
import qualified Data.Aeson             as Aeson
import           Data.Binary
import           Data.Binary.Get
import           Data.Binary.Put
import qualified Data.ByteString        as Strict
import qualified Data.ByteString.Base64 as Base64
import qualified Data.ByteString.Lazy   as Lazy
import           Data.Foldable          (foldl')
import qualified Data.Text.Encoding     as Text
import           Numeric.Natural        (Natural)
import           Prelude
import           Test.QuickCheck        (Arbitrary (..))

instance Aeson.FromJSON Strict.ByteString where
  parseJSON :: Value -> Parser ByteString
parseJSON Value
o =
    (String -> Parser ByteString)
-> (ByteString -> Parser ByteString)
-> Either String ByteString
-> Parser ByteString
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> Parser ByteString
forall a. String -> Parser a
forall (m :: Type -> Type) a. MonadFail m => String -> m a
fail ByteString -> Parser ByteString
forall a. a -> Parser a
forall (m :: Type -> Type) a. Monad m => a -> m a
return
    (Either String ByteString -> Parser ByteString)
-> (Text -> Either String ByteString) -> Text -> Parser ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either String ByteString
Base64.decode
    (ByteString -> Either String ByteString)
-> (Text -> ByteString) -> Text -> Either String ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
Text.encodeUtf8
    (Text -> Parser ByteString) -> Parser Text -> Parser ByteString
forall (m :: Type -> Type) a b. Monad m => (a -> m b) -> m a -> m b
=<< Value -> Parser Text
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON Value
o

instance Aeson.ToJSON Strict.ByteString where
  toJSON :: ByteString -> Value
toJSON = Text -> Value
forall a. ToJSON a => a -> Value
Aeson.toJSON (Text -> Value) -> (ByteString -> Text) -> ByteString -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Text
Text.decodeUtf8 (ByteString -> Text)
-> (ByteString -> ByteString) -> ByteString -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
Base64.encode

instance Aeson.FromJSONKey Strict.ByteString
instance Aeson.ToJSONKey Strict.ByteString

toByteString :: Binary a => a -> Strict.ByteString
toByteString :: forall a. Binary a => a -> ByteString
toByteString = ByteString -> ByteString
Lazy.toStrict (ByteString -> ByteString) -> (a -> ByteString) -> a -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Put -> ByteString
runPut (Put -> ByteString) -> (a -> Put) -> a -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Put
forall t. Binary t => t -> Put
put

fromByteString :: Binary a => Strict.ByteString -> Maybe a
fromByteString :: forall a. Binary a => ByteString -> Maybe a
fromByteString ByteString
x = case Get a
-> ByteString
-> Either
     (ByteString, ByteOffset, String) (ByteString, ByteOffset, a)
forall a.
Get a
-> ByteString
-> Either
     (ByteString, ByteOffset, String) (ByteString, ByteOffset, a)
runGetOrFail Get a
forall t. Binary t => Get t
get (ByteString -> ByteString
Lazy.fromStrict ByteString
x) of
  Left (ByteString, ByteOffset, String)
_ -> Maybe a
forall a. Maybe a
Nothing
  Right (ByteString
leftover, ByteOffset
_, a
a) ->
    if ByteString -> Bool
Lazy.null ByteString
leftover then a -> Maybe a
forall a. a -> Maybe a
Just a
a else Maybe a
forall a. Maybe a
Nothing

-- Little-endian encoding for unsigned & unsized integers
-- un little, deux little, trois little endians
newtype LittleEndian = LittleEndian {LittleEndian -> Natural
unLittleEndian :: Natural}
  deriving stock (ReadPrec [LittleEndian]
ReadPrec LittleEndian
Int -> ReadS LittleEndian
ReadS [LittleEndian]
(Int -> ReadS LittleEndian)
-> ReadS [LittleEndian]
-> ReadPrec LittleEndian
-> ReadPrec [LittleEndian]
-> Read LittleEndian
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS LittleEndian
readsPrec :: Int -> ReadS LittleEndian
$creadList :: ReadS [LittleEndian]
readList :: ReadS [LittleEndian]
$creadPrec :: ReadPrec LittleEndian
readPrec :: ReadPrec LittleEndian
$creadListPrec :: ReadPrec [LittleEndian]
readListPrec :: ReadPrec [LittleEndian]
Read, Int -> LittleEndian -> ShowS
[LittleEndian] -> ShowS
LittleEndian -> String
(Int -> LittleEndian -> ShowS)
-> (LittleEndian -> String)
-> ([LittleEndian] -> ShowS)
-> Show LittleEndian
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> LittleEndian -> ShowS
showsPrec :: Int -> LittleEndian -> ShowS
$cshow :: LittleEndian -> String
show :: LittleEndian -> String
$cshowList :: [LittleEndian] -> ShowS
showList :: [LittleEndian] -> ShowS
Show)
  deriving newtype (LittleEndian -> LittleEndian -> Bool
(LittleEndian -> LittleEndian -> Bool)
-> (LittleEndian -> LittleEndian -> Bool) -> Eq LittleEndian
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: LittleEndian -> LittleEndian -> Bool
== :: LittleEndian -> LittleEndian -> Bool
$c/= :: LittleEndian -> LittleEndian -> Bool
/= :: LittleEndian -> LittleEndian -> Bool
Eq, Eq LittleEndian
Eq LittleEndian =>
(LittleEndian -> LittleEndian -> Ordering)
-> (LittleEndian -> LittleEndian -> Bool)
-> (LittleEndian -> LittleEndian -> Bool)
-> (LittleEndian -> LittleEndian -> Bool)
-> (LittleEndian -> LittleEndian -> Bool)
-> (LittleEndian -> LittleEndian -> LittleEndian)
-> (LittleEndian -> LittleEndian -> LittleEndian)
-> Ord LittleEndian
LittleEndian -> LittleEndian -> Bool
LittleEndian -> LittleEndian -> Ordering
LittleEndian -> LittleEndian -> LittleEndian
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
$ccompare :: LittleEndian -> LittleEndian -> Ordering
compare :: LittleEndian -> LittleEndian -> Ordering
$c< :: LittleEndian -> LittleEndian -> Bool
< :: LittleEndian -> LittleEndian -> Bool
$c<= :: LittleEndian -> LittleEndian -> Bool
<= :: LittleEndian -> LittleEndian -> Bool
$c> :: LittleEndian -> LittleEndian -> Bool
> :: LittleEndian -> LittleEndian -> Bool
$c>= :: LittleEndian -> LittleEndian -> Bool
>= :: LittleEndian -> LittleEndian -> Bool
$cmax :: LittleEndian -> LittleEndian -> LittleEndian
max :: LittleEndian -> LittleEndian -> LittleEndian
$cmin :: LittleEndian -> LittleEndian -> LittleEndian
min :: LittleEndian -> LittleEndian -> LittleEndian
Ord, Integer -> LittleEndian
LittleEndian -> LittleEndian
LittleEndian -> LittleEndian -> LittleEndian
(LittleEndian -> LittleEndian -> LittleEndian)
-> (LittleEndian -> LittleEndian -> LittleEndian)
-> (LittleEndian -> LittleEndian -> LittleEndian)
-> (LittleEndian -> LittleEndian)
-> (LittleEndian -> LittleEndian)
-> (LittleEndian -> LittleEndian)
-> (Integer -> LittleEndian)
-> Num LittleEndian
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
$c+ :: LittleEndian -> LittleEndian -> LittleEndian
+ :: LittleEndian -> LittleEndian -> LittleEndian
$c- :: LittleEndian -> LittleEndian -> LittleEndian
- :: LittleEndian -> LittleEndian -> LittleEndian
$c* :: LittleEndian -> LittleEndian -> LittleEndian
* :: LittleEndian -> LittleEndian -> LittleEndian
$cnegate :: LittleEndian -> LittleEndian
negate :: LittleEndian -> LittleEndian
$cabs :: LittleEndian -> LittleEndian
abs :: LittleEndian -> LittleEndian
$csignum :: LittleEndian -> LittleEndian
signum :: LittleEndian -> LittleEndian
$cfromInteger :: Integer -> LittleEndian
fromInteger :: Integer -> LittleEndian
Num, Int -> LittleEndian
LittleEndian -> Int
LittleEndian -> [LittleEndian]
LittleEndian -> LittleEndian
LittleEndian -> LittleEndian -> [LittleEndian]
LittleEndian -> LittleEndian -> LittleEndian -> [LittleEndian]
(LittleEndian -> LittleEndian)
-> (LittleEndian -> LittleEndian)
-> (Int -> LittleEndian)
-> (LittleEndian -> Int)
-> (LittleEndian -> [LittleEndian])
-> (LittleEndian -> LittleEndian -> [LittleEndian])
-> (LittleEndian -> LittleEndian -> [LittleEndian])
-> (LittleEndian -> LittleEndian -> LittleEndian -> [LittleEndian])
-> Enum LittleEndian
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: LittleEndian -> LittleEndian
succ :: LittleEndian -> LittleEndian
$cpred :: LittleEndian -> LittleEndian
pred :: LittleEndian -> LittleEndian
$ctoEnum :: Int -> LittleEndian
toEnum :: Int -> LittleEndian
$cfromEnum :: LittleEndian -> Int
fromEnum :: LittleEndian -> Int
$cenumFrom :: LittleEndian -> [LittleEndian]
enumFrom :: LittleEndian -> [LittleEndian]
$cenumFromThen :: LittleEndian -> LittleEndian -> [LittleEndian]
enumFromThen :: LittleEndian -> LittleEndian -> [LittleEndian]
$cenumFromTo :: LittleEndian -> LittleEndian -> [LittleEndian]
enumFromTo :: LittleEndian -> LittleEndian -> [LittleEndian]
$cenumFromThenTo :: LittleEndian -> LittleEndian -> LittleEndian -> [LittleEndian]
enumFromThenTo :: LittleEndian -> LittleEndian -> LittleEndian -> [LittleEndian]
Enum, Num LittleEndian
Ord LittleEndian
(Num LittleEndian, Ord LittleEndian) =>
(LittleEndian -> Rational) -> Real LittleEndian
LittleEndian -> Rational
forall a. (Num a, Ord a) => (a -> Rational) -> Real a
$ctoRational :: LittleEndian -> Rational
toRational :: LittleEndian -> Rational
Real, Enum LittleEndian
Real LittleEndian
(Real LittleEndian, Enum LittleEndian) =>
(LittleEndian -> LittleEndian -> LittleEndian)
-> (LittleEndian -> LittleEndian -> LittleEndian)
-> (LittleEndian -> LittleEndian -> LittleEndian)
-> (LittleEndian -> LittleEndian -> LittleEndian)
-> (LittleEndian -> LittleEndian -> (LittleEndian, LittleEndian))
-> (LittleEndian -> LittleEndian -> (LittleEndian, LittleEndian))
-> (LittleEndian -> Integer)
-> Integral LittleEndian
LittleEndian -> Integer
LittleEndian -> LittleEndian -> (LittleEndian, LittleEndian)
LittleEndian -> LittleEndian -> LittleEndian
forall a.
(Real a, Enum a) =>
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> (a, a))
-> (a -> a -> (a, a))
-> (a -> Integer)
-> Integral a
$cquot :: LittleEndian -> LittleEndian -> LittleEndian
quot :: LittleEndian -> LittleEndian -> LittleEndian
$crem :: LittleEndian -> LittleEndian -> LittleEndian
rem :: LittleEndian -> LittleEndian -> LittleEndian
$cdiv :: LittleEndian -> LittleEndian -> LittleEndian
div :: LittleEndian -> LittleEndian -> LittleEndian
$cmod :: LittleEndian -> LittleEndian -> LittleEndian
mod :: LittleEndian -> LittleEndian -> LittleEndian
$cquotRem :: LittleEndian -> LittleEndian -> (LittleEndian, LittleEndian)
quotRem :: LittleEndian -> LittleEndian -> (LittleEndian, LittleEndian)
$cdivMod :: LittleEndian -> LittleEndian -> (LittleEndian, LittleEndian)
divMod :: LittleEndian -> LittleEndian -> (LittleEndian, LittleEndian)
$ctoInteger :: LittleEndian -> Integer
toInteger :: LittleEndian -> Integer
Integral)
instance Binary LittleEndian where
  get :: Get LittleEndian
get = do
    [Word8]
ns <- Get Word8 -> Get [Word8]
forall a. Get a -> Get [a]
forall (f :: Type -> Type) a. Alternative f => f a -> f [a]
many Get Word8
getWord8
    let accum :: (Natural, Natural) -> a -> (Natural, Natural)
accum (!Natural
pw :: Natural, !Natural
acc :: Natural) a
w8 = (Natural
pw Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
* Natural
256, Natural
pw Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
* a -> Natural
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
w8 Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
+ Natural
acc)
        littleEndian :: LittleEndian
littleEndian = Natural -> LittleEndian
LittleEndian ((Natural, Natural) -> Natural
forall a b. (a, b) -> b
snd ((Natural, Natural) -> Natural) -> (Natural, Natural) -> Natural
forall a b. (a -> b) -> a -> b
$ ((Natural, Natural) -> Word8 -> (Natural, Natural))
-> (Natural, Natural) -> [Word8] -> (Natural, Natural)
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: Type -> Type) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (Natural, Natural) -> Word8 -> (Natural, Natural)
forall {a}.
Integral a =>
(Natural, Natural) -> a -> (Natural, Natural)
accum (Natural
1, Natural
0) [Word8]
ns)
    LittleEndian -> Get LittleEndian
forall a. a -> Get a
forall (m :: Type -> Type) a. Monad m => a -> m a
return LittleEndian
littleEndian
  put :: LittleEndian -> Put
put (LittleEndian Natural
n)
    | Natural
n Natural -> Natural -> Bool
forall a. Eq a => a -> a -> Bool
== Natural
0 = Put
forall a. Monoid a => a
mempty
    | Bool
otherwise =
      let (Natural
n', Natural
r) = Natural
n Natural -> Natural -> (Natural, Natural)
forall a. Integral a => a -> a -> (a, a)
`divMod` Natural
256
      in Word8 -> Put
putWord8 (Natural -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Natural
r) Put -> Put -> Put
forall a. Semigroup a => a -> a -> a
<> LittleEndian -> Put
forall t. Binary t => t -> Put
put (Natural -> LittleEndian
LittleEndian Natural
n')
instance Arbitrary LittleEndian where
  arbitrary :: Gen LittleEndian
arbitrary = Integer -> LittleEndian
forall a. Num a => Integer -> a
fromInteger (Integer -> LittleEndian)
-> (Integer -> Integer) -> Integer -> LittleEndian
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Integer
forall a. Num a => a -> a
abs (Integer -> LittleEndian) -> Gen Integer -> Gen LittleEndian
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Integer
forall a. Arbitrary a => Gen a
arbitrary

-- Big-endian encoding for unsigned & unsized integers
newtype BigEndian = BigEndian {BigEndian -> Natural
unBigEndian :: Natural}
  deriving stock (ReadPrec [BigEndian]
ReadPrec BigEndian
Int -> ReadS BigEndian
ReadS [BigEndian]
(Int -> ReadS BigEndian)
-> ReadS [BigEndian]
-> ReadPrec BigEndian
-> ReadPrec [BigEndian]
-> Read BigEndian
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
$creadsPrec :: Int -> ReadS BigEndian
readsPrec :: Int -> ReadS BigEndian
$creadList :: ReadS [BigEndian]
readList :: ReadS [BigEndian]
$creadPrec :: ReadPrec BigEndian
readPrec :: ReadPrec BigEndian
$creadListPrec :: ReadPrec [BigEndian]
readListPrec :: ReadPrec [BigEndian]
Read, Int -> BigEndian -> ShowS
[BigEndian] -> ShowS
BigEndian -> String
(Int -> BigEndian -> ShowS)
-> (BigEndian -> String)
-> ([BigEndian] -> ShowS)
-> Show BigEndian
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BigEndian -> ShowS
showsPrec :: Int -> BigEndian -> ShowS
$cshow :: BigEndian -> String
show :: BigEndian -> String
$cshowList :: [BigEndian] -> ShowS
showList :: [BigEndian] -> ShowS
Show)
  deriving newtype (BigEndian -> BigEndian -> Bool
(BigEndian -> BigEndian -> Bool)
-> (BigEndian -> BigEndian -> Bool) -> Eq BigEndian
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: BigEndian -> BigEndian -> Bool
== :: BigEndian -> BigEndian -> Bool
$c/= :: BigEndian -> BigEndian -> Bool
/= :: BigEndian -> BigEndian -> Bool
Eq, Eq BigEndian
Eq BigEndian =>
(BigEndian -> BigEndian -> Ordering)
-> (BigEndian -> BigEndian -> Bool)
-> (BigEndian -> BigEndian -> Bool)
-> (BigEndian -> BigEndian -> Bool)
-> (BigEndian -> BigEndian -> Bool)
-> (BigEndian -> BigEndian -> BigEndian)
-> (BigEndian -> BigEndian -> BigEndian)
-> Ord BigEndian
BigEndian -> BigEndian -> Bool
BigEndian -> BigEndian -> Ordering
BigEndian -> BigEndian -> BigEndian
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
$ccompare :: BigEndian -> BigEndian -> Ordering
compare :: BigEndian -> BigEndian -> Ordering
$c< :: BigEndian -> BigEndian -> Bool
< :: BigEndian -> BigEndian -> Bool
$c<= :: BigEndian -> BigEndian -> Bool
<= :: BigEndian -> BigEndian -> Bool
$c> :: BigEndian -> BigEndian -> Bool
> :: BigEndian -> BigEndian -> Bool
$c>= :: BigEndian -> BigEndian -> Bool
>= :: BigEndian -> BigEndian -> Bool
$cmax :: BigEndian -> BigEndian -> BigEndian
max :: BigEndian -> BigEndian -> BigEndian
$cmin :: BigEndian -> BigEndian -> BigEndian
min :: BigEndian -> BigEndian -> BigEndian
Ord, Integer -> BigEndian
BigEndian -> BigEndian
BigEndian -> BigEndian -> BigEndian
(BigEndian -> BigEndian -> BigEndian)
-> (BigEndian -> BigEndian -> BigEndian)
-> (BigEndian -> BigEndian -> BigEndian)
-> (BigEndian -> BigEndian)
-> (BigEndian -> BigEndian)
-> (BigEndian -> BigEndian)
-> (Integer -> BigEndian)
-> Num BigEndian
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
$c+ :: BigEndian -> BigEndian -> BigEndian
+ :: BigEndian -> BigEndian -> BigEndian
$c- :: BigEndian -> BigEndian -> BigEndian
- :: BigEndian -> BigEndian -> BigEndian
$c* :: BigEndian -> BigEndian -> BigEndian
* :: BigEndian -> BigEndian -> BigEndian
$cnegate :: BigEndian -> BigEndian
negate :: BigEndian -> BigEndian
$cabs :: BigEndian -> BigEndian
abs :: BigEndian -> BigEndian
$csignum :: BigEndian -> BigEndian
signum :: BigEndian -> BigEndian
$cfromInteger :: Integer -> BigEndian
fromInteger :: Integer -> BigEndian
Num, Int -> BigEndian
BigEndian -> Int
BigEndian -> [BigEndian]
BigEndian -> BigEndian
BigEndian -> BigEndian -> [BigEndian]
BigEndian -> BigEndian -> BigEndian -> [BigEndian]
(BigEndian -> BigEndian)
-> (BigEndian -> BigEndian)
-> (Int -> BigEndian)
-> (BigEndian -> Int)
-> (BigEndian -> [BigEndian])
-> (BigEndian -> BigEndian -> [BigEndian])
-> (BigEndian -> BigEndian -> [BigEndian])
-> (BigEndian -> BigEndian -> BigEndian -> [BigEndian])
-> Enum BigEndian
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: BigEndian -> BigEndian
succ :: BigEndian -> BigEndian
$cpred :: BigEndian -> BigEndian
pred :: BigEndian -> BigEndian
$ctoEnum :: Int -> BigEndian
toEnum :: Int -> BigEndian
$cfromEnum :: BigEndian -> Int
fromEnum :: BigEndian -> Int
$cenumFrom :: BigEndian -> [BigEndian]
enumFrom :: BigEndian -> [BigEndian]
$cenumFromThen :: BigEndian -> BigEndian -> [BigEndian]
enumFromThen :: BigEndian -> BigEndian -> [BigEndian]
$cenumFromTo :: BigEndian -> BigEndian -> [BigEndian]
enumFromTo :: BigEndian -> BigEndian -> [BigEndian]
$cenumFromThenTo :: BigEndian -> BigEndian -> BigEndian -> [BigEndian]
enumFromThenTo :: BigEndian -> BigEndian -> BigEndian -> [BigEndian]
Enum, Num BigEndian
Ord BigEndian
(Num BigEndian, Ord BigEndian) =>
(BigEndian -> Rational) -> Real BigEndian
BigEndian -> Rational
forall a. (Num a, Ord a) => (a -> Rational) -> Real a
$ctoRational :: BigEndian -> Rational
toRational :: BigEndian -> Rational
Real, Enum BigEndian
Real BigEndian
(Real BigEndian, Enum BigEndian) =>
(BigEndian -> BigEndian -> BigEndian)
-> (BigEndian -> BigEndian -> BigEndian)
-> (BigEndian -> BigEndian -> BigEndian)
-> (BigEndian -> BigEndian -> BigEndian)
-> (BigEndian -> BigEndian -> (BigEndian, BigEndian))
-> (BigEndian -> BigEndian -> (BigEndian, BigEndian))
-> (BigEndian -> Integer)
-> Integral BigEndian
BigEndian -> Integer
BigEndian -> BigEndian -> (BigEndian, BigEndian)
BigEndian -> BigEndian -> BigEndian
forall a.
(Real a, Enum a) =>
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> (a, a))
-> (a -> a -> (a, a))
-> (a -> Integer)
-> Integral a
$cquot :: BigEndian -> BigEndian -> BigEndian
quot :: BigEndian -> BigEndian -> BigEndian
$crem :: BigEndian -> BigEndian -> BigEndian
rem :: BigEndian -> BigEndian -> BigEndian
$cdiv :: BigEndian -> BigEndian -> BigEndian
div :: BigEndian -> BigEndian -> BigEndian
$cmod :: BigEndian -> BigEndian -> BigEndian
mod :: BigEndian -> BigEndian -> BigEndian
$cquotRem :: BigEndian -> BigEndian -> (BigEndian, BigEndian)
quotRem :: BigEndian -> BigEndian -> (BigEndian, BigEndian)
$cdivMod :: BigEndian -> BigEndian -> (BigEndian, BigEndian)
divMod :: BigEndian -> BigEndian -> (BigEndian, BigEndian)
$ctoInteger :: BigEndian -> Integer
toInteger :: BigEndian -> Integer
Integral)
instance Binary BigEndian where
  get :: Get BigEndian
get = do
    [Word8]
ns <- Get Word8 -> Get [Word8]
forall a. Get a -> Get [a]
forall (f :: Type -> Type) a. Alternative f => f a -> f [a]
many Get Word8
getWord8
    let accum :: a -> a -> a
accum a
n a
w8 = a
n a -> a -> a
forall a. Num a => a -> a -> a
* a
256 a -> a -> a
forall a. Num a => a -> a -> a
+ a -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
w8
        bigEndian :: BigEndian
bigEndian = Natural -> BigEndian
BigEndian ((Natural -> Word8 -> Natural) -> Natural -> [Word8] -> Natural
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: Type -> Type) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Natural -> Word8 -> Natural
forall {a} {a}. (Integral a, Num a) => a -> a -> a
accum Natural
0 [Word8]
ns)
    BigEndian -> Get BigEndian
forall a. a -> Get a
forall (m :: Type -> Type) a. Monad m => a -> m a
return BigEndian
bigEndian
  put :: BigEndian -> Put
put (BigEndian Natural
n)
    | Natural
n Natural -> Natural -> Bool
forall a. Eq a => a -> a -> Bool
== Natural
0 = Put
forall a. Monoid a => a
mempty
    | Bool
otherwise =
      let (Natural
n', Natural
r) = Natural
n Natural -> Natural -> (Natural, Natural)
forall a. Integral a => a -> a -> (a, a)
`divMod` Natural
256
      in BigEndian -> Put
forall t. Binary t => t -> Put
put (Natural -> BigEndian
BigEndian Natural
n') Put -> Put -> Put
forall a. Semigroup a => a -> a -> a
<> Word8 -> Put
putWord8 (Natural -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Natural
r)
instance Arbitrary BigEndian where
  arbitrary :: Gen BigEndian
arbitrary = Integer -> BigEndian
forall a. Num a => Integer -> a
fromInteger (Integer -> BigEndian)
-> (Integer -> Integer) -> Integer -> BigEndian
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Integer
forall a. Num a => a -> a
abs (Integer -> BigEndian) -> Gen Integer -> Gen BigEndian
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Integer
forall a. Arbitrary a => Gen a
arbitrary