on master help sign in
Fix serialization derivation for unit constructor
commit12d85026291d9305f93f573d284d0d35abf40968 authorAdithya Kumar <adithya@composewell.com> dateSat 2 Dec 2023, 14:39 (3 years ago) parent6eee16a
3 files changed+18−3
core/src/Streamly/Internal/Data/Array.hs+10 core/src/Streamly/Internal/Data/Serialize/TH.hs+4−2 core/src/Streamly/Internal/Data/Unbox/TH.hs+4−1
core/src/Streamly/Internal/Data/Array.hs+10
@@ -564,6 +564,12 @@ encodeAs ps a =
564564 assertM(len == off)
565565 pure $ Array mbarr 0 off
566566
567+-- XXX The "Encoded Equivality" property is not (cannot be) true for Unbox.
568+
569+-- |
570+-- Properties:
571+-- 1. Identity: @deserialize . serialize == id@
572+-- 2. Encoded Equivality: @serialize a == serialize a@
567573{-# INLINE serialize #-}
568574serialize :: Serialize a => a -> Array Word8
569575serialize = encodeAs Unpinned
@@ -571,6 +577,10 @@ serialize = encodeAs Unpinned
571577-- | Serialize a Haskell type to a pinned byte array. The array is allocated
572578-- using pinned memory so that it can be used directly in OS APIs for writing
573579-- to file or sending over the network.
580+--
581+-- Properties:
582+-- 1. Identity: @deserialize . pinnedSerialize == id@
583+-- 2. Encoded Equivality: @pinnedSerialize a == serialize a@
574584{-# INLINE pinnedSerialize #-}
575585pinnedSerialize :: Serialize a => a -> Array Word8
576586pinnedSerialize = encodeAs Pinned
core/src/Streamly/Internal/Data/Serialize/TH.hs+4−2
@@ -217,6 +217,7 @@ mkDeserializeExpr True False headTy tyOfTy =
217217mkDeserializeExpr False False headTy tyOfTy =
218218 case tyOfTy of
219219 -- Unit constructor
220+ -- XXX Should we peek and check if the byte value is 0?
220221 UnitType cname ->
221222 [|pure ($(varE _initialOffset) + 1, $(conE cname))|]
222223 -- Product type
@@ -341,7 +342,8 @@ mkSerializeExpr True False tyOfTy =
341342mkSerializeExpr False False tyOfTy =
342343 case tyOfTy of
343344 -- Unit type
344− UnitType _ -> [|pure ($(varE _initialOffset) + 1)|]
345+ UnitType _ ->
346+ [|serializeAt $(varE _initialOffset) $(varE _arr) (0 :: Word8)|]
345347 -- Product type
346348 (TheType (SimpleDataCon cname fields)) ->
347349 letE
@@ -395,7 +397,7 @@ mkSerializeDec (SerializeConfig {..}) headTy cons = do
395397 'serializeAt
396398 [ Clause
397399 (if isUnitType cons && not cfgConstructorTagAsString
398− then [VarP _initialOffset, WildP, WildP]
400+ then [VarP _initialOffset, VarP _arr, WildP]
399401 else [VarP _initialOffset, VarP _arr, VarP _val])
400402 (NormalB pokeMethod)
401403 []
core/src/Streamly/Internal/Data/Unbox/TH.hs+4−1
@@ -241,6 +241,7 @@ mkSizeOfExpr headTy constructors =
241241mkPeekExprOne :: Int -> DataCon -> Q Exp
242242mkPeekExprOne tagSize (DataCon cname _ _ fields) =
243243 case fields of
244+ -- XXX Should we peek and check if the byte value is 0?
244245 [] -> [|pure $(conE cname)|]
245246 _ ->
246247 letE
@@ -336,7 +337,9 @@ mkPokeExpr headTy cons =
336337 [|error
337338 ("Attempting to poke type with no constructors (" ++
338339 $(lift (pprint headTy)) ++ ")")|]
339− [(DataCon _ _ _ [])] -> [|pure ()|]
340+ -- XXX We don't gaurentee encoded equivalilty for Unbox. Does it still
341+ -- make sense to encode a default value for unit constructor?
342+ [(DataCon _ _ _ [])] -> [|pure ()|] -- mkPokeExprTag ''Word8 0
340343 [(DataCon cname _ _ fields)] ->
341344 caseE
342345 (varE _val)