module Streamly.Internal.Data.Serialize.Type
(
Serialize(..)
) where
import Control.Monad (when)
import Data.List (foldl')
import Data.Proxy (Proxy (..))
import Streamly.Internal.Data.Unbox (Unbox)
import Streamly.Internal.Data.MutByteArray.Type (MutByteArray(..))
import Streamly.Internal.Data.Array.Type (Array(..))
import GHC.Int (Int16(..), Int32(..), Int64(..), Int8(..))
import GHC.Word (Word16(..), Word32(..), Word64(..), Word8(..))
import GHC.Stable (StablePtr(..))
import qualified Streamly.Internal.Data.MutByteArray.Type as MBA
import qualified Streamly.Internal.Data.Unbox as Unbox
import qualified Streamly.Internal.Data.Array.Type as Array
import qualified Streamly.Internal.Data.MutArray as MutArray
import GHC.Exts
class Serialize a where
addSizeTo :: Int -> a -> Int
deserializeAt :: Int -> MutByteArray -> Int -> IO (Int, a)
serializeAt :: Int -> MutByteArray -> a -> IO Int
#ifdef DEBUG
{-# INLINE checkBounds #-}
checkBounds :: String -> Int -> MutByteArray -> IO ()
checkBounds _label _size _arr = do
sz <- MBA.sizeOfMutableByteArray _arr
if (_size > sz)
then error
$ _label
++ ": accessing array at offset = "
++ show (_size - 1)
++ " max valid offset = " ++ show (sz - 1)
else return ()
#endif
{-# INLINE deserializeChecked #-}
deserializeChecked :: forall a. Unbox a => Int -> MutByteArray -> Int -> IO (Int, a)
deserializeChecked :: forall a. Unbox a => Int -> MutByteArray -> Int -> IO (Int, a)
deserializeChecked Int
off MutByteArray
arr Int
sz =
let next :: Int
next = Int
off forall a. Num a => a -> a -> a
+ forall a. Unbox a => Proxy a -> Int
Unbox.sizeOf (forall {k} (t :: k). Proxy t
Proxy :: Proxy a)
in do
if (Int
next forall a. Ord a => a -> a -> Bool
<= Int
sz)
then forall a. Unbox a => Int -> MutByteArray -> IO a
Unbox.peekAt Int
off MutByteArray
arr forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \a
val -> forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int
next, a
val)
else forall a. HasCallStack => [Char] -> a
error
forall a b. (a -> b) -> a -> b
$ [Char]
"deserializeAt: accessing array at offset = "
forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> [Char]
show (Int
next forall a. Num a => a -> a -> a
- Int
1)
forall a. [a] -> [a] -> [a]
++ [Char]
" max valid offset = " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> [Char]
show (Int
sz forall a. Num a => a -> a -> a
- Int
1)
{-# INLINE serializeUnsafe #-}
serializeUnsafe :: forall a. Unbox a => Int -> MutByteArray -> a -> IO Int
serializeUnsafe :: forall a. Unbox a => Int -> MutByteArray -> a -> IO Int
serializeUnsafe Int
off MutByteArray
arr a
val =
let next :: Int
next = Int
off forall a. Num a => a -> a -> a
+ forall a. Unbox a => Proxy a -> Int
Unbox.sizeOf (forall {k} (t :: k). Proxy t
Proxy :: Proxy a)
in do
#ifdef DEBUG
checkBounds "serializeAt" next arr
#endif
forall a. Unbox a => Int -> MutByteArray -> a -> IO ()
Unbox.pokeAt Int
off MutByteArray
arr a
val
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
next
#define DERIVE_SERIALIZE_FROM_UNBOX(_type) \
instance Serialize _type where \
; {-# INLINE addSizeTo #-} \
; addSizeTo acc _ = acc + Unbox.sizeOf (Proxy :: Proxy _type) \
; {-# INLINE deserializeAt #-} \
; deserializeAt off arr end = deserializeChecked off arr end :: IO (Int, _type) \
; {-# INLINE serializeAt #-} \
; serializeAt = \
serializeUnsafe :: Int -> MutByteArray -> _type -> IO Int
DERIVE_SERIALIZE_FROM_UNBOX(())
DERIVE_SERIALIZE_FROM_UNBOX(Bool)
DERIVE_SERIALIZE_FROM_UNBOX(Char)
DERIVE_SERIALIZE_FROM_UNBOX(Int8)
DERIVE_SERIALIZE_FROM_UNBOX(Int16)
DERIVE_SERIALIZE_FROM_UNBOX(Int32)
DERIVE_SERIALIZE_FROM_UNBOX(Int)
DERIVE_SERIALIZE_FROM_UNBOX(Int64)
DERIVE_SERIALIZE_FROM_UNBOX(Word)
DERIVE_SERIALIZE_FROM_UNBOX(Word8)
DERIVE_SERIALIZE_FROM_UNBOX(Word16)
DERIVE_SERIALIZE_FROM_UNBOX(Word32)
DERIVE_SERIALIZE_FROM_UNBOX(Word64)
DERIVE_SERIALIZE_FROM_UNBOX(Double)
DERIVE_SERIALIZE_FROM_UNBOX(Float)
DERIVE_SERIALIZE_FROM_UNBOX((StablePtr a))
DERIVE_SERIALIZE_FROM_UNBOX((Ptr a))
DERIVE_SERIALIZE_FROM_UNBOX((FunPtr a))
instance forall a. Serialize a => Serialize [a] where
addSizeTo :: Int -> [a] -> Int
addSizeTo Int
acc [a]
xs =
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' forall a. Serialize a => Int -> a -> Int
addSizeTo (Int
acc forall a. Num a => a -> a -> a
+ (forall a. Unbox a => Proxy a -> Int
Unbox.sizeOf (forall {k} (t :: k). Proxy t
Proxy :: Proxy Int))) [a]
xs
{-# INLINABLE deserializeAt #-}
deserializeAt :: Int -> MutByteArray -> Int -> IO (Int, [a])
deserializeAt Int
off MutByteArray
arr Int
sz = do
(Int
off1, Int64
len64) <- forall a. Serialize a => Int -> MutByteArray -> Int -> IO (Int, a)
deserializeAt Int
off MutByteArray
arr Int
sz :: IO (Int, Int64)
let len :: Int
len = (forall a b. (Integral a, Num b) => a -> b
fromIntegral :: Int64 -> Int) Int64
len64
peekList :: ([a] -> b) -> Int -> t -> IO (Int, b)
peekList [a] -> b
f Int
o t
i | t
i forall a. Ord a => a -> a -> Bool
>= t
3 = do
(Int
o1, a
x1) <- forall a. Serialize a => Int -> MutByteArray -> Int -> IO (Int, a)
deserializeAt Int
o MutByteArray
arr Int
sz
(Int
o2, a
x2) <- forall a. Serialize a => Int -> MutByteArray -> Int -> IO (Int, a)
deserializeAt Int
o1 MutByteArray
arr Int
sz
(Int
o3, a
x3) <- forall a. Serialize a => Int -> MutByteArray -> Int -> IO (Int, a)
deserializeAt Int
o2 MutByteArray
arr Int
sz
([a] -> b) -> Int -> t -> IO (Int, b)
peekList ([a] -> b
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. (\[a]
xs -> a
x1forall a. a -> [a] -> [a]
:a
x2forall a. a -> [a] -> [a]
:a
x3forall a. a -> [a] -> [a]
:[a]
xs)) Int
o3 (t
i forall a. Num a => a -> a -> a
- t
3)
peekList [a] -> b
f Int
o t
0 = forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int
o, [a] -> b
f [])
peekList [a] -> b
f Int
o t
i = do
(Int
o1, a
x) <- forall a. Serialize a => Int -> MutByteArray -> Int -> IO (Int, a)
deserializeAt Int
o MutByteArray
arr Int
sz
([a] -> b) -> Int -> t -> IO (Int, b)
peekList ([a] -> b
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a
xforall a. a -> [a] -> [a]
:)) Int
o1 (t
i forall a. Num a => a -> a -> a
- t
1)
forall {t} {a} {b}.
(Ord t, Num t, Serialize a) =>
([a] -> b) -> Int -> t -> IO (Int, b)
peekList forall a. a -> a
id Int
off1 Int
len
{-# INLINABLE serializeAt #-}
serializeAt :: Int -> MutByteArray -> [a] -> IO Int
serializeAt Int
off MutByteArray
arr [a]
val = do
let off1 :: Int
off1 = Int
off forall a. Num a => a -> a -> a
+ forall a. Unbox a => Proxy a -> Int
Unbox.sizeOf (forall {k} (t :: k). Proxy t
Proxy :: Proxy Int64)
let pokeList :: Int64 -> Int -> [a] -> IO Int
pokeList Int64
acc Int
o [] =
forall a. Unbox a => Int -> MutByteArray -> a -> IO ()
Unbox.pokeAt Int
off MutByteArray
arr (Int64
acc :: Int64) forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
o
pokeList Int64
acc Int
o (a
x:[a]
xs) = do
Int
o1 <- forall a. Serialize a => Int -> MutByteArray -> a -> IO Int
serializeAt Int
o MutByteArray
arr a
x
Int64 -> Int -> [a] -> IO Int
pokeList (Int64
acc forall a. Num a => a -> a -> a
+ Int64
1) Int
o1 [a]
xs
forall {a}. Serialize a => Int64 -> Int -> [a] -> IO Int
pokeList Int64
0 Int
off1 [a]
val
instance
#ifdef DEVBUILD
Unbox a =>
#endif
Serialize (Array a) where
{-# INLINE addSizeTo #-}
addSizeTo :: Int -> Array a -> Int
addSizeTo Int
i (Array {Int
MutByteArray
arrEnd :: forall a. Array a -> Int
arrStart :: forall a. Array a -> Int
arrContents :: forall a. Array a -> MutByteArray
arrEnd :: Int
arrStart :: Int
arrContents :: MutByteArray
..}) = Int
i forall a. Num a => a -> a -> a
+ (Int
arrEnd forall a. Num a => a -> a -> a
- Int
arrStart) forall a. Num a => a -> a -> a
+ Int
8
{-# INLINE deserializeAt #-}
deserializeAt :: Int -> MutByteArray -> Int -> IO (Int, Array a)
deserializeAt Int
off MutByteArray
arr Int
len = do
(Int
off1, Int
byteLen) <- forall a. Serialize a => Int -> MutByteArray -> Int -> IO (Int, a)
deserializeAt Int
off MutByteArray
arr Int
len :: IO (Int, Int)
let off2 :: Int
off2 = Int
off1 forall a. Num a => a -> a -> a
+ Int
byteLen
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
off2 forall a. Ord a => a -> a -> Bool
> Int
len) forall a b. (a -> b) -> a -> b
$
forall a. HasCallStack => [Char] -> a
error
forall a b. (a -> b) -> a -> b
$ [Char]
"deserializeAt: accessing array at offset = "
forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> [Char]
show (Int
off2 forall a. Num a => a -> a -> a
- Int
1)
forall a. [a] -> [a] -> [a]
++ [Char]
" max valid offset = " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> [Char]
show (Int
len forall a. Num a => a -> a -> a
- Int
1)
let slice :: MutArray a
slice = forall a. MutByteArray -> Int -> Int -> Int -> MutArray a
MutArray.MutArray MutByteArray
arr Int
off1 Int
off2 Int
off2
MutArray a
newArr <- forall (m :: * -> *) a. MonadIO m => MutArray a -> m (MutArray a)
MutArray.clone forall {a}. MutArray a
slice
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int
off2, forall a. MutArray a -> Array a
Array.unsafeFreeze MutArray a
newArr)
{-# INLINE serializeAt #-}
serializeAt :: Int -> MutByteArray -> Array a -> IO Int
serializeAt Int
off MutByteArray
arr (Array {Int
MutByteArray
arrEnd :: Int
arrStart :: Int
arrContents :: MutByteArray
arrEnd :: forall a. Array a -> Int
arrStart :: forall a. Array a -> Int
arrContents :: forall a. Array a -> MutByteArray
..}) = do
let arrLen :: Int
arrLen = Int
arrEnd forall a. Num a => a -> a -> a
- Int
arrStart
Int
off1 <- forall a. Serialize a => Int -> MutByteArray -> a -> IO Int
serializeAt Int
off MutByteArray
arr Int
arrLen
forall (m :: * -> *).
MonadIO m =>
MutByteArray -> Int -> MutByteArray -> Int -> Int -> m ()
MBA.putSliceUnsafe MutByteArray
arrContents Int
arrStart MutByteArray
arr Int
off1 Int
arrLen
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int
off1 forall a. Num a => a -> a -> a
+ Int
arrLen)
instance (Serialize a, Serialize b) => Serialize (a, b) where
{-# INLINE addSizeTo #-}
addSizeTo :: Int -> (a, b) -> Int
addSizeTo Int
acc (a
a, b
b) = forall a. Serialize a => Int -> a -> Int
addSizeTo (forall a. Serialize a => Int -> a -> Int
addSizeTo Int
acc a
a) b
b
{-# INLINE serializeAt #-}
serializeAt :: Int -> MutByteArray -> (a, b) -> IO Int
serializeAt Int
off MutByteArray
arr (a
a, b
b) = do
Int
off1 <- forall a. Serialize a => Int -> MutByteArray -> a -> IO Int
serializeAt Int
off MutByteArray
arr a
a
forall a. Serialize a => Int -> MutByteArray -> a -> IO Int
serializeAt Int
off1 MutByteArray
arr b
b
{-# INLINE deserializeAt #-}
deserializeAt :: Int -> MutByteArray -> Int -> IO (Int, (a, b))
deserializeAt Int
off MutByteArray
arr Int
end = do
(Int
off1, a
a) <- forall a. Serialize a => Int -> MutByteArray -> Int -> IO (Int, a)
deserializeAt Int
off MutByteArray
arr Int
end
(Int
off2, b
b) <- forall a. Serialize a => Int -> MutByteArray -> Int -> IO (Int, a)
deserializeAt Int
off1 MutByteArray
arr Int
end
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int
off2, (a
a, b
b))