@@ -9,22 +9,29 @@
99module Streamly.Internal.Data.Serialize
1010 ( Size(..)
1111 , Serialize(..)
12+ , encode
13+ , pinnedEncode
14+ , decode
1215 ) where
1316
1417--------------------------------------------------------------------------------
1518-- Imports
1619--------------------------------------------------------------------------------
1720
21+#include "assert.hs"
22+
1823import Control.Monad (void)
1924import Data.List (foldl')
2025import Data.Proxy (Proxy (..))
21−import Streamly.Internal.Data.Unbox (MutableByteArray(..))
22−
26+import Streamly.Internal.Data.Unbox (MutableByteArray(..), PinnedState(..))
27+import Streamly.Internal.Data.Array.Type (Array(..))
28+import Streamly.Internal.System.IO (unsafeInlineIO)
2329import GHC.Int (Int16(..), Int32(..), Int64(..), Int8(..))
2430import GHC.Word (Word16(..), Word32(..), Word64(..), Word8(..))
2531import GHC.Stable (StablePtr(..))
2632
2733import qualified Streamly.Internal.Data.Unbox as Unbox
34+import qualified Streamly.Internal.Data.Array as Array
2835
2936import GHC.Exts
3037
@@ -167,3 +174,41 @@ instance forall a. Serialize a => Serialize [a] where
167174 o1 <- serialize o arr x
168175 pokeList o1 xs
169176 pokeList off1 val
177+
178+--------------------------------------------------------------------------------
179+-- High level functions
180+--------------------------------------------------------------------------------
181+
182+{-# INLINE encodeAs #-}
183+encodeAs :: forall a. Serialize a => PinnedState -> a -> Array Word8
184+encodeAs ps a =
185+ unsafeInlineIO $ do
186+ let len =
187+ case size :: Size a of
188+ ConstSize sz -> sz
189+ VarSize f -> f a
190+ -- We encode the length of the encoding as a header hence the 8 extra
191+ -- bytes to encode Int64
192+ mbarr <- Unbox.newBytesAs ps (8 + len)
193+ off1 <- serialize 0 mbarr (fromIntegral len :: Int64)
194+ off2 <- serialize off1 mbarr a
195+ assertM(off2 == len + off1)
196+ pure $ Array mbarr 0 len
197+
198+{-# INLINE encode #-}
199+encode :: Serialize a => a -> Array Word8
200+encode = encodeAs Unpinned
201+
202+{-# INLINE pinnedEncode #-}
203+pinnedEncode :: Serialize a => a -> Array Word8
204+pinnedEncode = encodeAs Pinned
205+
206+{-# INLINE decode #-}
207+decode :: Serialize a => Array Word8 -> a
208+decode arr@(Array {..}) = unsafeInlineIO $ do
209+ let lenArr = Array.length arr
210+ (off1, lenEncoding :: Int64) <- deserialize 0 arrContents
211+ (off2, val) <- deserialize off1 arrContents
212+ assertM(fromIntegral lenEncoding + off1 == off2)
213+ assertM(lenArr == off2)
214+ pure val