packages feed

packstream-bolt-0.1.0.0: src/Compat/Binary.hs

-- | Compat layer for serialization
--
-- Wraps @persist@ library
module Compat.Binary
    ( Persist(put, get)

    , runPut', runPut, runPutLazy, Put, PutM
    , runGet', runGet, Get

    , getWord64be, putWord64be
    , getWord32be, putWord32be
    , getWord16be, putWord16be
    , getWord8   , putWord8

    , getInt64be, putInt64be
    , getInt32be, putInt32be
    , getInt16be, putInt16be
    , getInt8   , putInt8

    , getFloat64be, putFloat64be

    , getByteString, putByteString
    ) where

import           Compat.Prelude

import qualified Data.ByteString      as BS
import qualified Data.ByteString.Lazy as BL
import           Data.Kind            (Type)
import qualified Data.Text            as T

import           Data.Persist         (Persist(put, get), Get)
import qualified Data.Persist         as P
import           GHC.Float            (castDoubleToWord64, castWord64ToDouble)

-- | The serialization monad (alias for @persist@'s 'P.Put' @()@).
type Put :: Type
type Put = P.Put ()

-- | The serialization monad parameterized by its result type.
type PutM :: Type -> Type
type PutM = P.Put

-- | Run a 'Put' action and return a strict 'BS.ByteString'.
runPut :: Put -> BS.ByteString
runPut = P.runPut

-- | Alias for 'runPut'.
runPut' :: Put -> BS.ByteString
runPut' = P.runPut

-- | Run a 'Put' action and return a lazy 'BL.ByteString'.
runPutLazy :: Put -> BL.ByteString
runPutLazy = P.runPutLazy

-- | Run a 'Get' parser on a strict 'BS.ByteString'.
runGet' :: BS.ByteString -> Get a -> Either T.Text a
runGet' bs g = case P.runGet g bs of
  Left e  -> Left (T.pack e)
  Right x -> Right x

-- | Run a 'Get' parser on a lazy 'BL.ByteString'.
runGet :: BL.ByteString -> Get a -> Either T.Text a
runGet bs g = runGet' (BL.toStrict bs) g

-- | Deserialize a single byte.
{-# INLINE getWord8 #-}
getWord8 :: Get Word8
getWord8 = P.get

-- | Serialize a single byte.
{-# INLINE putWord8 #-}
putWord8 :: Word8 -> Put
putWord8 = P.put

-- | Deserialize a big-endian 'Word16'.
{-# INLINE getWord16be #-}
getWord16be :: Get Word16
getWord16be = P.getBE

-- | Serialize a big-endian 'Word16'.
{-# INLINE putWord16be #-}
putWord16be :: Word16 -> Put
putWord16be = P.putBE

-- | Deserialize a big-endian 'Word32'.
{-# INLINE getWord32be #-}
getWord32be :: Get Word32
getWord32be = P.getBE

-- | Serialize a big-endian 'Word32'.
{-# INLINE putWord32be #-}
putWord32be :: Word32 -> Put
putWord32be = P.putBE

-- | Deserialize a big-endian 'Word64'.
{-# INLINE getWord64be #-}
getWord64be :: Get Word64
getWord64be = P.getBE

-- | Serialize a big-endian 'Word64'.
{-# INLINE putWord64be #-}
putWord64be :: Word64 -> Put
putWord64be = P.putBE

-- | Deserialize a signed 8-bit integer.
{-# INLINE getInt8 #-}
getInt8 :: Get Int8
getInt8 = intCastIso <$> P.get @Word8

-- | Deserialize a big-endian signed 16-bit integer.
{-# INLINE getInt16be #-}
getInt16be :: Get Int16
getInt16be = intCastIso <$> P.getBE @Word16

-- | Deserialize a big-endian signed 32-bit integer.
{-# INLINE getInt32be #-}
getInt32be :: Get Int32
getInt32be = intCastIso <$> P.getBE @Word32

-- | Deserialize a big-endian signed 64-bit integer.
{-# INLINE getInt64be #-}
getInt64be :: Get Int64
getInt64be = intCastIso <$> P.getBE @Word64

-- | Serialize a signed 8-bit integer.
{-# INLINE putInt8 #-}
putInt8 :: Int8 -> Put
putInt8 x = P.put (intCastIso x :: Word8)

-- | Serialize a big-endian signed 16-bit integer.
{-# INLINE putInt16be #-}
putInt16be :: Int16 -> Put
putInt16be x = P.putBE (intCastIso x :: Word16)

-- | Serialize a big-endian signed 32-bit integer.
{-# INLINE putInt32be #-}
putInt32be :: Int32 -> Put
putInt32be x = P.putBE (intCastIso x :: Word32)

-- | Serialize a big-endian signed 64-bit integer.
{-# INLINE putInt64be #-}
putInt64be :: Int64 -> Put
putInt64be x = P.putBE (intCastIso x :: Word64)

-- | Serialize a big-endian 64-bit IEEE 754 double.
{-# INLINE putFloat64be #-}
putFloat64be :: Double -> Put
putFloat64be x = P.putBE (castDoubleToWord64 x)

-- | Deserialize a big-endian 64-bit IEEE 754 double.
{-# INLINE getFloat64be #-}
getFloat64be :: Get Double
getFloat64be = castWord64ToDouble <$> P.getBE @Word64

-- | Deserialize exactly @n@ bytes into a strict 'BS.ByteString'.
{-# INLINE getByteString #-}
getByteString :: Int -> Get BS.ByteString
getByteString = P.getByteString

-- | Serialize a strict 'BS.ByteString' directly into the output.
{-# INLINE putByteString #-}
putByteString :: BS.ByteString -> Put
putByteString = P.putByteString