{-# LANGUAGE UndecidableInstances #-} module Dahdit.BinaryRep ( BinaryRep (..) , ViaBoundedEnum (..) , ViaIntegral (..) , ViaBinaryRep (..) ) where import Dahdit.Binary (Binary (..)) import Dahdit.Sizes (StaticByteSized (..)) import Data.Proxy (Proxy (..)) class (Binary x) => BinaryRep x a | a -> x where fromBinaryRep :: x -> Either String a toBinaryRep :: a -> x newtype ViaBoundedEnum x a = ViaBoundedEnum {forall x a. ViaBoundedEnum x a -> a unViaBoundedEnum :: a} instance (Binary x, Integral x, Bounded a, Enum a) => BinaryRep x (ViaBoundedEnum x a) where fromBinaryRep :: x -> Either String (ViaBoundedEnum x a) fromBinaryRep x x = let i :: Int i = forall a b. (Integral a, Num b) => a -> b fromIntegral x x in if Int i forall a. Ord a => a -> a -> Bool < forall a. Enum a => a -> Int fromEnum (forall a. Bounded a => a minBound :: a) Bool -> Bool -> Bool || Int i forall a. Ord a => a -> a -> Bool > forall a. Enum a => a -> Int fromEnum (forall a. Bounded a => a maxBound :: a) then forall a b. a -> Either a b Left (String "Invalid enum value: " forall a. [a] -> [a] -> [a] ++ forall a. Show a => a -> String show Int i) else forall a b. b -> Either a b Right (forall x a. a -> ViaBoundedEnum x a ViaBoundedEnum (forall a. Enum a => Int -> a toEnum Int i)) toBinaryRep :: ViaBoundedEnum x a -> x toBinaryRep = forall a b. (Integral a, Num b) => a -> b fromIntegral forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a. Enum a => a -> Int fromEnum forall b c a. (b -> c) -> (a -> b) -> a -> c . forall x a. ViaBoundedEnum x a -> a unViaBoundedEnum newtype ViaIntegral x a = ViaIntegral {forall x a. ViaIntegral x a -> a unViaIntegral :: a} instance (Binary x, Integral x, Integral a) => BinaryRep x (ViaIntegral x a) where fromBinaryRep :: x -> Either String (ViaIntegral x a) fromBinaryRep = forall a b. b -> Either a b Right forall b c a. (b -> c) -> (a -> b) -> a -> c . forall x a. a -> ViaIntegral x a ViaIntegral forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a b. (Integral a, Num b) => a -> b fromIntegral toBinaryRep :: ViaIntegral x a -> x toBinaryRep = forall a b. (Integral a, Num b) => a -> b fromIntegral forall b c a. (b -> c) -> (a -> b) -> a -> c . forall x a. ViaIntegral x a -> a unViaIntegral newtype ViaBinaryRep x a = ViaBinaryRep {forall x a. ViaBinaryRep x a -> a unViaBinaryRep :: a} instance (StaticByteSized x, BinaryRep x a) => StaticByteSized (ViaBinaryRep x a) where type StaticSize (ViaBinaryRep x a) = StaticSize x staticByteSize :: Proxy (ViaBinaryRep x a) -> ByteCount staticByteSize Proxy (ViaBinaryRep x a) _ = forall a. StaticByteSized a => Proxy a -> ByteCount staticByteSize (forall {k} (t :: k). Proxy t Proxy :: Proxy x) instance (BinaryRep x a) => Binary (ViaBinaryRep x a) where byteSize :: ViaBinaryRep x a -> ByteCount byteSize = forall a. Binary a => a -> ByteCount byteSize forall b c a. (b -> c) -> (a -> b) -> a -> c . forall x a. BinaryRep x a => a -> x toBinaryRep forall b c a. (b -> c) -> (a -> b) -> a -> c . forall x a. ViaBinaryRep x a -> a unViaBinaryRep get :: Get (ViaBinaryRep x a) get = forall a. Binary a => Get a get forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>= forall a c b. (a -> c) -> (b -> c) -> Either a b -> c either forall (m :: * -> *) a. MonadFail m => String -> m a fail (forall (f :: * -> *) a. Applicative f => a -> f a pure forall b c a. (b -> c) -> (a -> b) -> a -> c . forall x a. a -> ViaBinaryRep x a ViaBinaryRep) forall b c a. (b -> c) -> (a -> b) -> a -> c . forall x a. BinaryRep x a => x -> Either String a fromBinaryRep put :: ViaBinaryRep x a -> Put put = forall a. Binary a => a -> Put put forall b c a. (b -> c) -> (a -> b) -> a -> c . forall x a. BinaryRep x a => a -> x toBinaryRep forall b c a. (b -> c) -> (a -> b) -> a -> c . forall x a. ViaBinaryRep x a -> a unViaBinaryRep