module Binrep.Codec where
import Data.ByteString qualified as BS
import Data.ByteString.Lazy qualified as BL
import Data.ByteString.Builder qualified as B
import Data.Serialize
class BinaryCodec a where
toBin :: Putter a
fromBin :: Get a
binEncode :: BinaryCodec a => a -> BS.ByteString
binEncode :: forall a. BinaryCodec a => a -> ByteString
binEncode = Put -> ByteString
runPut (Put -> ByteString) -> (a -> Put) -> a -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Put
forall a. BinaryCodec a => Putter a
toBin
binDecode :: BinaryCodec a => BS.ByteString -> Either String a
binDecode :: forall a. BinaryCodec a => ByteString -> Either String a
binDecode = Get a -> ByteString -> Either String a
forall a. Get a -> ByteString -> Either String a
runGet Get a
forall a. BinaryCodec a => Get a
fromBin
instance BinaryCodec a => BinaryCodec [a] where
toBin :: Putter [a]
toBin [a]
as = (a -> Put) -> Putter [a]
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ a -> Put
forall a. BinaryCodec a => Putter a
toBin [a]
as
fromBin :: Get [a]
fromBin = [a] -> Get [a]
forall {a}. BinaryCodec a => [a] -> Get [a]
go []
where
go :: [a] -> Get [a]
go [a]
as = do
a
a <- Get a
forall a. BinaryCodec a => Get a
fromBin
Get Bool
isEmpty Get Bool -> (Bool -> Get [a]) -> Get [a]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Bool
True -> [a] -> Get [a]
forall (m :: * -> *) a. Monad m => a -> m a
return ([a] -> Get [a]) -> [a] -> Get [a]
forall a b. (a -> b) -> a -> b
$ [a] -> [a]
forall a. [a] -> [a]
reverse ([a] -> [a]) -> [a] -> [a]
forall a b. (a -> b) -> a -> b
$ a
a a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
as
Bool
False -> [a] -> Get [a]
go ([a] -> Get [a]) -> [a] -> Get [a]
forall a b. (a -> b) -> a -> b
$ a
a a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
as
class BinaryCodecWith r a where
toBinWith :: r -> a -> Either String B.Builder
default toBinWith :: BinaryCodec a => r -> a -> Either String B.Builder
toBinWith = (a -> Either String Builder) -> r -> a -> Either String Builder
forall a b. a -> b -> a
const ((a -> Either String Builder) -> r -> a -> Either String Builder)
-> (a -> Either String Builder) -> r -> a -> Either String Builder
forall a b. (a -> b) -> a -> b
$ Builder -> Either String Builder
forall a b. b -> Either a b
Right (Builder -> Either String Builder)
-> (a -> Builder) -> a -> Either String Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Put -> Builder
forall a. PutM a -> Builder
execPut (Put -> Builder) -> (a -> Put) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Put
forall a. BinaryCodec a => Putter a
toBin
fromBinWith :: r -> Get a
default fromBinWith :: BinaryCodec a => r -> Get a
fromBinWith = Get a -> r -> Get a
forall a b. a -> b -> a
const Get a
forall a. BinaryCodec a => Get a
fromBin
binEncodeWith :: BinaryCodecWith r a => r -> a -> Either String BS.ByteString
binEncodeWith :: forall r a.
BinaryCodecWith r a =>
r -> a -> Either String ByteString
binEncodeWith r
r a
a = ByteString -> ByteString
BL.toStrict (ByteString -> ByteString)
-> (Builder -> ByteString) -> Builder -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> ByteString
B.toLazyByteString (Builder -> ByteString)
-> Either String Builder -> Either String ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> r -> a -> Either String Builder
forall r a. BinaryCodecWith r a => r -> a -> Either String Builder
toBinWith r
r a
a
binDecodeWith :: BinaryCodecWith r a => r -> BS.ByteString -> Either String a
binDecodeWith :: forall r a.
BinaryCodecWith r a =>
r -> ByteString -> Either String a
binDecodeWith = Get a -> ByteString -> Either String a
forall a. Get a -> ByteString -> Either String a
runGet (Get a -> ByteString -> Either String a)
-> (r -> Get a) -> r -> ByteString -> Either String a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. r -> Get a
forall r a. BinaryCodecWith r a => r -> Get a
fromBinWith