{-# LANGUAGE ScopedTypeVariables #-}
module Cardano.Crypto.DirectSerialise
where
import Cardano.Crypto.Libsodium.Memory (copyMem)
import Control.Exception
import Control.Monad (when)
import Control.Monad.Class.MonadST (MonadST, stToIO)
import Control.Monad.Class.MonadThrow (MonadThrow)
import Data.STRef (newSTRef, readSTRef, writeSTRef)
import Foreign.C.Types
import Foreign.Ptr
data SizeCheckException
= SizeCheckException
{ SizeCheckException -> Int
expectedSize :: Int
, SizeCheckException -> Int
actualSize :: Int
}
deriving (Int -> SizeCheckException -> ShowS
[SizeCheckException] -> ShowS
SizeCheckException -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SizeCheckException] -> ShowS
$cshowList :: [SizeCheckException] -> ShowS
show :: SizeCheckException -> String
$cshow :: SizeCheckException -> String
showsPrec :: Int -> SizeCheckException -> ShowS
$cshowsPrec :: Int -> SizeCheckException -> ShowS
Show)
instance Exception SizeCheckException
sizeCheckFailed :: Int -> Int -> m ()
sizeCheckFailed :: forall (m :: * -> *). Int -> Int -> m ()
sizeCheckFailed Int
ex Int
ac =
forall a e. Exception e => e -> a
throw forall a b. (a -> b) -> a -> b
$ Int -> Int -> SizeCheckException
SizeCheckException Int
ex Int
ac
class DirectDeserialise a where
directDeserialise :: (MonadST m, MonadThrow m) => (Ptr CChar -> CSize -> m ()) -> m a
class DirectSerialise a where
directSerialise :: (MonadST m, MonadThrow m) => (Ptr CChar -> CSize -> m ()) -> a -> m ()
directSerialiseTo ::
forall m a.
DirectSerialise a =>
MonadST m =>
MonadThrow m =>
(Int -> Ptr CChar -> CSize -> m ()) ->
Int ->
a ->
m Int
directSerialiseTo :: forall (m :: * -> *) a.
(DirectSerialise a, MonadST m, MonadThrow m) =>
(Int -> Ptr CChar -> CSize -> m ()) -> Int -> a -> m Int
directSerialiseTo Int -> Ptr CChar -> CSize -> m ()
writeBytes Int
dstsize a
val = do
STRef (PrimState m) Int
posRef <- forall (m :: * -> *) a. MonadST m => ST (PrimState m) a -> m a
stToIO forall a b. (a -> b) -> a -> b
$ forall a s. a -> ST s (STRef s a)
newSTRef Int
0
let pusher :: Ptr CChar -> CSize -> m ()
pusher :: Ptr CChar -> CSize -> m ()
pusher Ptr CChar
src CSize
srcsize = do
Int
pos <- forall (m :: * -> *) a. MonadST m => ST (PrimState m) a -> m a
stToIO forall a b. (a -> b) -> a -> b
$ forall s a. STRef s a -> ST s a
readSTRef STRef (PrimState m) Int
posRef
let pos' :: Int
pos' = Int
pos forall a. Num a => a -> a -> a
+ forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
srcsize
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
pos' forall a. Ord a => a -> a -> Bool
> Int
dstsize) forall a b. (a -> b) -> a -> b
$
forall (m :: * -> *). Int -> Int -> m ()
sizeCheckFailed (Int
dstsize forall a. Num a => a -> a -> a
- Int
pos) (Int
pos' forall a. Num a => a -> a -> a
- Int
pos)
Int -> Ptr CChar -> CSize -> m ()
writeBytes Int
pos Ptr CChar
src (forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
srcsize)
forall (m :: * -> *) a. MonadST m => ST (PrimState m) a -> m a
stToIO forall a b. (a -> b) -> a -> b
$ forall s a. STRef s a -> a -> ST s ()
writeSTRef STRef (PrimState m) Int
posRef Int
pos'
forall a (m :: * -> *).
(DirectSerialise a, MonadST m, MonadThrow m) =>
(Ptr CChar -> CSize -> m ()) -> a -> m ()
directSerialise Ptr CChar -> CSize -> m ()
pusher a
val
forall (m :: * -> *) a. MonadST m => ST (PrimState m) a -> m a
stToIO forall a b. (a -> b) -> a -> b
$ forall s a. STRef s a -> ST s a
readSTRef STRef (PrimState m) Int
posRef
directSerialiseToChecked ::
forall m a.
DirectSerialise a =>
MonadST m =>
MonadThrow m =>
(Int -> Ptr CChar -> CSize -> m ()) ->
Int ->
a ->
m ()
directSerialiseToChecked :: forall (m :: * -> *) a.
(DirectSerialise a, MonadST m, MonadThrow m) =>
(Int -> Ptr CChar -> CSize -> m ()) -> Int -> a -> m ()
directSerialiseToChecked Int -> Ptr CChar -> CSize -> m ()
writeBytes Int
dstsize a
val = do
Int
bytesWritten <- forall (m :: * -> *) a.
(DirectSerialise a, MonadST m, MonadThrow m) =>
(Int -> Ptr CChar -> CSize -> m ()) -> Int -> a -> m Int
directSerialiseTo Int -> Ptr CChar -> CSize -> m ()
writeBytes Int
dstsize a
val
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
bytesWritten forall a. Eq a => a -> a -> Bool
/= Int
dstsize) forall a b. (a -> b) -> a -> b
$
forall (m :: * -> *). Int -> Int -> m ()
sizeCheckFailed Int
dstsize Int
bytesWritten
directSerialiseBuf ::
forall m a.
DirectSerialise a =>
MonadST m =>
MonadThrow m =>
Ptr CChar ->
Int ->
a ->
m Int
directSerialiseBuf :: forall (m :: * -> *) a.
(DirectSerialise a, MonadST m, MonadThrow m) =>
Ptr CChar -> Int -> a -> m Int
directSerialiseBuf Ptr CChar
dst =
forall (m :: * -> *) a.
(DirectSerialise a, MonadST m, MonadThrow m) =>
(Int -> Ptr CChar -> CSize -> m ()) -> Int -> a -> m Int
directSerialiseTo (forall (m :: * -> *) a.
MonadST m =>
Ptr a -> Ptr a -> CSize -> m ()
copyMem forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr CChar
dst)
directSerialiseBufChecked ::
forall m a.
DirectSerialise a =>
MonadST m =>
MonadThrow m =>
Ptr CChar ->
Int ->
a ->
m ()
directSerialiseBufChecked :: forall (m :: * -> *) a.
(DirectSerialise a, MonadST m, MonadThrow m) =>
Ptr CChar -> Int -> a -> m ()
directSerialiseBufChecked Ptr CChar
buf Int
dstsize a
val = do
Int
bytesWritten <- forall (m :: * -> *) a.
(DirectSerialise a, MonadST m, MonadThrow m) =>
Ptr CChar -> Int -> a -> m Int
directSerialiseBuf Ptr CChar
buf Int
dstsize a
val
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
bytesWritten forall a. Eq a => a -> a -> Bool
/= Int
dstsize) forall a b. (a -> b) -> a -> b
$
forall (m :: * -> *). Int -> Int -> m ()
sizeCheckFailed Int
dstsize Int
bytesWritten
directDeserialiseFrom ::
forall m a.
DirectDeserialise a =>
MonadST m =>
MonadThrow m =>
(Int -> Ptr CChar -> CSize -> m ()) ->
Int ->
m (a, Int)
directDeserialiseFrom :: forall (m :: * -> *) a.
(DirectDeserialise a, MonadST m, MonadThrow m) =>
(Int -> Ptr CChar -> CSize -> m ()) -> Int -> m (a, Int)
directDeserialiseFrom Int -> Ptr CChar -> CSize -> m ()
readBytes Int
srcsize = do
STRef (PrimState m) Int
posRef <- forall (m :: * -> *) a. MonadST m => ST (PrimState m) a -> m a
stToIO forall a b. (a -> b) -> a -> b
$ forall a s. a -> ST s (STRef s a)
newSTRef Int
0
let puller :: Ptr CChar -> CSize -> m ()
puller :: Ptr CChar -> CSize -> m ()
puller Ptr CChar
dst CSize
dstsize = do
Int
pos <- forall (m :: * -> *) a. MonadST m => ST (PrimState m) a -> m a
stToIO forall a b. (a -> b) -> a -> b
$ forall s a. STRef s a -> ST s a
readSTRef STRef (PrimState m) Int
posRef
let pos' :: Int
pos' = Int
pos forall a. Num a => a -> a -> a
+ forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
dstsize
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
pos' forall a. Ord a => a -> a -> Bool
> Int
srcsize) forall a b. (a -> b) -> a -> b
$
forall (m :: * -> *). Int -> Int -> m ()
sizeCheckFailed (Int
srcsize forall a. Num a => a -> a -> a
- Int
pos) (Int
pos' forall a. Num a => a -> a -> a
- Int
pos)
Int -> Ptr CChar -> CSize -> m ()
readBytes Int
pos Ptr CChar
dst (forall a b. (Integral a, Num b) => a -> b
fromIntegral CSize
dstsize)
forall (m :: * -> *) a. MonadST m => ST (PrimState m) a -> m a
stToIO forall a b. (a -> b) -> a -> b
$ forall s a. STRef s a -> a -> ST s ()
writeSTRef STRef (PrimState m) Int
posRef Int
pos'
(,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a (m :: * -> *).
(DirectDeserialise a, MonadST m, MonadThrow m) =>
(Ptr CChar -> CSize -> m ()) -> m a
directDeserialise Ptr CChar -> CSize -> m ()
puller forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (m :: * -> *) a. MonadST m => ST (PrimState m) a -> m a
stToIO (forall s a. STRef s a -> ST s a
readSTRef STRef (PrimState m) Int
posRef)
directDeserialiseFromChecked ::
forall m a.
DirectDeserialise a =>
MonadST m =>
MonadThrow m =>
(Int -> Ptr CChar -> CSize -> m ()) ->
Int ->
m a
directDeserialiseFromChecked :: forall (m :: * -> *) a.
(DirectDeserialise a, MonadST m, MonadThrow m) =>
(Int -> Ptr CChar -> CSize -> m ()) -> Int -> m a
directDeserialiseFromChecked Int -> Ptr CChar -> CSize -> m ()
readBytes Int
srcsize = do
(a
r, Int
bytesRead) <- forall (m :: * -> *) a.
(DirectDeserialise a, MonadST m, MonadThrow m) =>
(Int -> Ptr CChar -> CSize -> m ()) -> Int -> m (a, Int)
directDeserialiseFrom Int -> Ptr CChar -> CSize -> m ()
readBytes Int
srcsize
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
bytesRead forall a. Eq a => a -> a -> Bool
/= Int
srcsize) forall a b. (a -> b) -> a -> b
$
forall (m :: * -> *). Int -> Int -> m ()
sizeCheckFailed Int
srcsize Int
bytesRead
forall (m :: * -> *) a. Monad m => a -> m a
return a
r
directDeserialiseBuf ::
forall m a.
DirectDeserialise a =>
MonadST m =>
MonadThrow m =>
Ptr CChar ->
Int ->
m (a, Int)
directDeserialiseBuf :: forall (m :: * -> *) a.
(DirectDeserialise a, MonadST m, MonadThrow m) =>
Ptr CChar -> Int -> m (a, Int)
directDeserialiseBuf Ptr CChar
src =
forall (m :: * -> *) a.
(DirectDeserialise a, MonadST m, MonadThrow m) =>
(Int -> Ptr CChar -> CSize -> m ()) -> Int -> m (a, Int)
directDeserialiseFrom (\Int
pos Ptr CChar
dst -> forall (m :: * -> *) a.
MonadST m =>
Ptr a -> Ptr a -> CSize -> m ()
copyMem Ptr CChar
dst (forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr CChar
src Int
pos))
directDeserialiseBufChecked ::
forall m a.
DirectDeserialise a =>
MonadST m =>
MonadThrow m =>
Ptr CChar ->
Int ->
m a
directDeserialiseBufChecked :: forall (m :: * -> *) a.
(DirectDeserialise a, MonadST m, MonadThrow m) =>
Ptr CChar -> Int -> m a
directDeserialiseBufChecked Ptr CChar
buf Int
srcsize = do
(a
r, Int
bytesRead) <- forall (m :: * -> *) a.
(DirectDeserialise a, MonadST m, MonadThrow m) =>
Ptr CChar -> Int -> m (a, Int)
directDeserialiseBuf Ptr CChar
buf Int
srcsize
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
bytesRead forall a. Eq a => a -> a -> Bool
/= Int
srcsize) forall a b. (a -> b) -> a -> b
$
forall (m :: * -> *). Int -> Int -> m ()
sizeCheckFailed Int
srcsize Int
bytesRead
forall (m :: * -> *) a. Monad m => a -> m a
return a
r