@@ -39,9 +39,49 @@ import Streamly.Internal.Data.Serialize.TH.Common
40--------------------------------------------------------------------------------
40--------------------------------------------------------------------------------
42−-- Encoding the header length is required to check if we want to compare the
42+-- Compatibility Algorithm
43−-- header. We should not compare the headers if the lengths of the headers are
43+-- =======================
44−-- not equal as this might lead to a runtime error.
44+--
45+-- The algorithm is written without any low level implementation details. See
46+-- the code for any low level implementation details.
51+-- To serialize the data,
53+-- * Get the list of keys for the record as @keyList@.
54+-- * Serialize the @keyList@.
55+-- * Serialize the @fields@ one-by-one after serializing the @keyList@.
60+-- To deserialize the data to type @T@,
62+-- __Checking for type match__:
64+-- * Get the list of keys for type @T@ as @targetKeyList@.
65+-- * Get the list of keys encoded as @encodedKeyList@.
66+-- * If @targetKeyList == encodedKeyList@ see the __Type Match__ section else
67+-- see the __No Type Match__ section.
71+-- * Decode the fields one-by-one and construct the type @T@ in the end.
75+-- * Decode the list of keys encoded into @encodedKeyList@.
76+-- * Get the list of keys for type @T@ as @targetKeyList@.
77+-- * Loop through @encodedKeyList@ and start deserializing the encoded data.
78+-- * If the key is present in @encodedKeyList@ and not in @targetKeyList@
79+-- then skip parsing the corresponding value.
80+-- * If the key is present in @targetKeyList@ and not in @encodedKeyList@
81+-- then set the value for that key as @Nothing@.
82+-- * If the key is present in both @encodedKeyList@ and in @targetKeyList@
84+-- * Construct @T@ after parsing all the data.
46--------------------------------------------------------------------------------
86--------------------------------------------------------------------------------
47-- Compact lists
87-- Compact lists
@@ -170,8 +210,9 @@ headerValue (SimpleDataCon _ fields) =
171--------------------------------------------------------------------------------
211--------------------------------------------------------------------------------
173−-- Encoding the size is required if we want to skip the field.
213+-- Encoding the size is required if we want to skip the field without knowing
174−-- We encode the size as 'Word32' hence there is a 4 bytes increase in size.
214+-- its type. We encode the size as 'Word32' hence there is a 4 bytes increase
175{-# INLINE serializeWithSize #-}
216{-# INLINE serializeWithSize #-}
176serializeWithSize :: Serialize a => Int -> MutableByteArray -> a -> IO Int
217serializeWithSize :: Serialize a => Int -> MutableByteArray -> a -> IO Int
177serializeWithSize off arr val = do
218serializeWithSize off arr val = do
@@ -182,6 +223,9 @@ serializeWithSize off arr val = do
182mkSerializeExpr :: Name -> SimpleDataCon -> Q Exp
223mkSerializeExpr :: Name -> SimpleDataCon -> Q Exp
183mkSerializeExpr initialOffset (con@(SimpleDataCon cname fields)) = do
224mkSerializeExpr initialOffset (con@(SimpleDataCon cname fields)) = do
184 afterHLen <- newName "afterHLen"
225 afterHLen <- newName "afterHLen"
226+ -- Encoding the header length is required.
227+ -- We first compare the header length encoded and the current header
228+ -- length. Only if the header lengths match, we compare the headers.
185 [|do $(varP afterHLen) <-
229 [|do $(varP afterHLen) <-
186 serialize
230 serialize
187 ($(varE initialOffset) + 4)
231 ($(varE initialOffset) + 4)