1module Streamly.Internal.Data.Serialize
6--------------------------------------------------------------------------------
8--------------------------------------------------------------------------------
10import Control.Monad (void)
11import Data.List (foldl')
12import Data.Proxy (Proxy (..))
13import Streamly.Internal.Data.Unbox (MutableByteArray(..))
15import GHC.Int (Int16(..), Int32(..), Int64(..), Int8(..))
16import GHC.Word (Word16(..), Word32(..), Word64(..), Word8(..))
17import GHC.Stable (StablePtr(..))
19import qualified Streamly.Internal.Data.Unbox as Unbox
23--------------------------------------------------------------------------------
25--------------------------------------------------------------------------------
27-- | Info about the length of a serializable type. Length can depend on the
28-- value or can be independent.
33-- | A type implementing the 'Serialize' interface supplies operations for
34-- reading and writing the type from and to a mutable byte array (an unboxed
35-- representation of the type) in memory. The read operation 'deserialize'
36-- deserializes the boxed type from the mutable byte array. The write operation
37-- 'serialize' serializes the boxed type to the mutable byte array.
39-- IMPORTANT: The serialized data's byte ordering is not normalized, which means
40-- it remains the same as the machine's byte order where the function is
41-- executed. Consequently, it may not be compatible across machines with
42-- different byte ordering.
44-- 'Serialize' contains enough information to serialize and deserialize variable
47-- >>> import Streamly.Internal.Data.Serialize (Serialize(..), Size(..))
50-- data Object = Object
57-- instance Serialize Object where
59-- case (size :: Size [Int], size :: Size Int) of
60-- (VarSize f, ConstSize g) ->
63-- _ -> error "size is not defined properly"
64-- deserialize i arr = do
65-- (i1, x0) <- deserialize i arr
66-- (i2, x1) <- deserialize i1 arr
67-- pure (i2, Object x0 x1)
68-- serialize i arr (Object x0 x1) = do
69-- i1 <- serialize i arr x0
70-- i2 <- serialize i1 arr x1
74class Serialize a where
75 -- | Get the 'Size', in bytes, reqired to store the serialized
76 -- representation of the type. Size cannot be zero.
79 -- We can implement the following functions without returning the `Int`
80 -- offset but that may require traversing the Haskell structure again to get
81 -- the size. Therefore, this is a performance optimization.
83 -- | Deserialize a value from the given byte-index in the array. Returns a
84 -- tuple of the next byte-index and the deserialized value.
85 deserialize :: Int -> MutableByteArray -> IO (Int, a)
87 -- | Write the serialized representation of the value in the array at the
88 -- given byte-index. Returns the next byte-index.
89 serialize :: Int -> MutableByteArray -> a -> IO Int
91--------------------------------------------------------------------------------
93--------------------------------------------------------------------------------
95#define DERIVE_SERIALIZE_FROM_UNBOX(_type) \
96instance Serialize _type where \
97; size = ConstSize $ Unbox.sizeOf (Proxy :: Proxy _type) \
98; deserialize off arr = \
99 Unbox.peekByteIndex off arr >>= \
100 \val -> let sz = Unbox.sizeOf (Proxy :: Proxy _type) \
101 in pure (off + sz, val) \
102; serialize off arr val = \
103 Unbox.pokeByteIndex off arr val \
104 >> let sz = Unbox.sizeOf (Proxy :: Proxy _type) \
107DERIVE_SERIALIZE_FROM_UNBOX(Char)
108DERIVE_SERIALIZE_FROM_UNBOX(Int8)
109DERIVE_SERIALIZE_FROM_UNBOX(Int16)
110DERIVE_SERIALIZE_FROM_UNBOX(Int32)
111DERIVE_SERIALIZE_FROM_UNBOX(Int)
112DERIVE_SERIALIZE_FROM_UNBOX(Int64)
113DERIVE_SERIALIZE_FROM_UNBOX(Word)
114DERIVE_SERIALIZE_FROM_UNBOX(Word8)
115DERIVE_SERIALIZE_FROM_UNBOX(Word16)
116DERIVE_SERIALIZE_FROM_UNBOX(Word32)
117DERIVE_SERIALIZE_FROM_UNBOX(Word64)
118DERIVE_SERIALIZE_FROM_UNBOX(Double)
119DERIVE_SERIALIZE_FROM_UNBOX(Float)
120DERIVE_SERIALIZE_FROM_UNBOX((StablePtr a))
121DERIVE_SERIALIZE_FROM_UNBOX((Ptr a))
122DERIVE_SERIALIZE_FROM_UNBOX((FunPtr a))
124instance forall a. Serialize a => Serialize [a] where
127 size = VarSize $ \lst ->
128 case size :: Size a of
131 (\acc x -> acc + f x)
132 (Unbox.sizeOf (Proxy :: Proxy Int))
137 + Unbox.sizeOf (Proxy :: Proxy Int)
139 {-# INLINE deserialize #-}
140 deserialize off arr = do
141 len <- Unbox.peekByteIndex off arr :: IO Int
142 let off1 = off + Unbox.sizeOf (Proxy :: Proxy Int)
143 let peekList buf o 0 = pure (o, reverse buf)
144 peekList buf o i = do
145 (o1, x) <- deserialize o arr
146 peekList (x:buf) o1 (i - 1)
149 {-# INLINE serialize #-}
150 serialize off arr val = do
151 void $ serialize off arr (length val)
152 let off1 = off + Unbox.sizeOf (Proxy :: Proxy Int)
153 let pokeList o [] = pure o
154 pokeList o (x:xs) = do
155 o1 <- serialize o arr x
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list