on 52ddfee help sign in
streamly/core/src/Streamly/Data/Serialize.hs
94 lines 2.7 kB history raw
1-- |
2-- Module : Streamly.Data.Serialize
3-- Copyright : (c) 2023 Composewell Technologies
4-- License : BSD3-3-Clause
5-- Maintainer : streamly@composewell.com
6-- Portability : GHC
7--
8module Streamly.Data.Serialize
9 (
11 -- * Types
12 MutableByteArray
14 -- * Unbox
15 , Unbox(..)
16 , deriveUnbox
17 , deriveUnboxWith
19 -- * Serialize
20 , Size(..)
21 , Serialize(..)
22 , deriveSerialize
23 , deriveSerializeWith
25 -- * Encoding
26 , encode
27 , pinnedEncode
29 -- * Decoding
30 , decode
31 ) where
33#include "assert.hs"
35import Data.Int (Int64)
36import Data.Word (Word8)
37import Streamly.Internal.Data.Array.Type (Array(..))
38import Streamly.Internal.Data.Serialize (Serialize(..), Size(..))
39import Streamly.Internal.Data.Serialize.TH
40 ( deriveSerialize
41 , deriveSerializeWith
42 )
43import Streamly.Internal.Data.Unbox
44 ( MutableByteArray
45 , PinnedState(..)
46 , Unbox(..)
47 )
48import Streamly.Internal.Data.Unbox.TH (deriveUnbox, deriveUnboxWith)
49import Streamly.Internal.System.IO (unsafeInlineIO)
51import qualified Streamly.Internal.Data.Unbox as Unbox
52import qualified Streamly.Internal.Data.Array as Array
54--------------------------------------------------------------------------------
55-- Serialize
56--------------------------------------------------------------------------------
58{-# INLINE encodeAs #-}
59encodeAs :: forall a. Serialize a => PinnedState -> a -> Array Word8
60encodeAs ps a =
61 unsafeInlineIO $ do
62 let len =
63 case size :: Size a of
64 ConstSize sz -> sz
65 VarSize f -> f a
66 -- We encode the length of the encoding as a header hence the 8 extra
67 -- bytes to encode Int64
68 mbarr <- Unbox.newBytesAs ps (8 + len)
69 off1 <- serialize 0 mbarr (fromIntegral len :: Int64)
70 off2 <- serialize off1 mbarr a
71 assertM(off2 == len + off1)
72 pure $ Array mbarr 0 len
74{-# INLINE encode #-}
75encode :: Serialize a => a -> Array Word8
76encode = encodeAs Unpinned
78{-# INLINE pinnedEncode #-}
79pinnedEncode :: Serialize a => a -> Array Word8
80pinnedEncode = encodeAs Pinned
82--------------------------------------------------------------------------------
83-- Deserialize
84--------------------------------------------------------------------------------
86{-# INLINE decode #-}
87decode :: Serialize a => Array Word8 -> a
88decode arr@(Array {..}) = unsafeInlineIO $ do
89 let lenArr = Array.length arr
90 (off1, lenEncoding :: Int64) <- deserialize 0 arrContents
91 (off2, val) <- deserialize off1 arrContents
92 assertM(fromIntegral lenEncoding + off1 == off2)
93 assertM(lenArr == off2)
94 pure val