@@ -200,6 +200,7 @@ module Streamly.Internal.Data.Array.Foreign.Mut.Type
200200 , memcpy
201201 , memcmp
202202 , c_memchr
203+ , sizeOfElem
203204 )
204205where
205206
@@ -275,6 +276,14 @@ import Prelude hiding
275276-- >>> import qualified Streamly.Internal.Data.Fold as Fold
276277-- >>> import qualified Streamly.Internal.Data.Fold.Type as Fold
277278
279+-------------------------------------------------------------------------------
280+-- Utilities
281+-------------------------------------------------------------------------------
282+
283+{-# INLINE sizeOfElem #-}
284+sizeOfElem :: forall a . (Storable a) => a -> Int
285+sizeOfElem _ = max 1 $ sizeOf (undefined :: a)
286+
278287-------------------------------------------------------------------------------
279288-- Foreign helpers
280289-------------------------------------------------------------------------------
@@ -294,7 +303,7 @@ foreign import ccall unsafe "string.h memcmp" c_memcmp
294303{-# INLINE bytesToElemCount #-}
295304bytesToElemCount :: Storable a => a -> Int -> Int
296305bytesToElemCount x n =
297− let elemSize = sizeOf x
306+ let elemSize = sizeOfElem x
298307 in n `div` elemSize
299308
300309-- XXX we are converting Int to CSize
@@ -447,7 +456,7 @@ fromForeignPtrUnsafe fp@(ForeignPtr start contents) end bound =
447456newArrayWith :: forall m a. (MonadIO m, Storable a)
448457 => (Int -> Int -> m (ArrayContents, Ptr a)) -> Int -> Int -> m (Array a)
449458newArrayWith alloc alignSize count = do
450− let size = max (count * sizeOf (undefined :: a)) 0
459+ let size = max (count * sizeOfElem (undefined :: a)) 0
451460 (contents, p) <- alloc size alignSize
452461 return $ Array
453462 { arrContents = contents
@@ -502,7 +511,7 @@ newArrayAlignedUnmanaged = do
502511 return (ArrayContents contents, Ptr addr)
503512#else
504513newArrayAlignedUnmanaged _align count = do
505− let size = max (count * sizeOf (undefined :: a)) 0
514+ let size = max (count * sizeOfElem (undefined :: a)) 0
506515 p <- liftIO $ mallocBytes size
507516 return $ Array
508517 { arrContents = nilArrayContents
@@ -556,7 +565,7 @@ putIndexUnsafe :: forall m a. (MonadIO m, Storable a)
556565 => Array a -> Int -> a -> m ()
557566putIndexUnsafe Array{..} i x =
558567 unsafeWithArrayContents arrContents arrStart $ \ptr -> do
559− let elemSize = sizeOf (undefined :: a)
568+ let elemSize = sizeOfElem (undefined :: a)
560569 elemPtr = ptr `plusPtr` (elemSize * i)
561570 assert (i >= 0 && elemPtr `plusPtr` elemSize <= aEnd) (return ())
562571 liftIO $ poke elemPtr x
@@ -569,7 +578,7 @@ invalidIndex label i =
569578putIndexPtr :: forall m a. (MonadIO m, Storable a) =>
570579 Ptr a -> Ptr a -> Int -> a -> m ()
571580putIndexPtr start end i x = do
572− let elemSize = sizeOf (undefined :: a)
581+ let elemSize = sizeOfElem (undefined :: a)
573582 elemPtr = start `plusPtr` (elemSize * i)
574583 if i >= 0 && elemPtr `plusPtr` elemSize <= end
575584 then liftIO $ poke elemPtr x
@@ -613,7 +622,7 @@ modifyIndexUnsafe :: forall m a b. (MonadIO m, Storable a) =>
613622 Array a -> Int -> (a -> (a, b)) -> m b
614623modifyIndexUnsafe Array{..} i f = do
615624 liftIO $ unsafeWithArrayContents arrContents arrStart $ \ptr -> do
616− let elemSize = sizeOf (undefined :: a)
625+ let elemSize = sizeOfElem (undefined :: a)
617626 elemPtr = ptr `plusPtr` (elemSize * i)
618627 assert (i >= 0 && elemPtr `plusPtr` elemSize <= aEnd) (return ())
619628 r <- peek elemPtr
@@ -769,7 +778,7 @@ roundUpToPower2 x =
769778{-# INLINE allocBytesToBytes #-}
770779allocBytesToBytes :: forall a. Storable a => a -> Int -> Int
771780allocBytesToBytes _ n =
772− max (arrayPayloadSize n) (sizeOf (undefined :: a))
781+ max (arrayPayloadSize n) (sizeOfElem (undefined :: a))
773782
774783-- | Given a 'Storable' type (unused first arg) and real allocation size
775784-- (including overhead), return how many elements of that type will completely
@@ -819,7 +828,7 @@ snocNewEnd newEnd arr@Array{..} x = liftIO $ do
819828snocUnsafe :: forall m a. (MonadIO m, Storable a) =>
820829 Array a -> a -> m (Array a)
821830snocUnsafe arr@Array{..} =
822− snocNewEnd (aEnd `plusPtr` sizeOf (undefined :: a)) arr
831+ snocNewEnd (aEnd `plusPtr` sizeOfElem (undefined :: a)) arr
823832
824833-- | Like 'snoc' but does not reallocate when pre-allocated array capacity
825834-- becomes full.
@@ -829,7 +838,7 @@ snocUnsafe arr@Array{..} =
829838snocMay :: forall m a. (MonadIO m, Storable a) =>
830839 Array a -> a -> m (Maybe (Array a))
831840snocMay arr@Array{..} x = liftIO $ do
832− let newEnd = aEnd `plusPtr` sizeOf (undefined :: a)
841+ let newEnd = aEnd `plusPtr` sizeOfElem (undefined :: a)
833842 if newEnd <= aBound
834843 then Just <$> snocNewEnd newEnd arr x
835844 else return Nothing
@@ -866,7 +875,7 @@ snocWithRealloc :: forall m a. (MonadIO m, Storable a) =>
866875 -> a
867876 -> m (Array a)
868877snocWithRealloc sizer arr x = do
869− let elemSize = sizeOf (undefined :: a)
878+ let elemSize = sizeOfElem (undefined :: a)
870879 arr1 <- liftIO $ reallocWith "snocWith" sizer elemSize arr
871880 snocUnsafe arr1 x
872881
@@ -890,7 +899,7 @@ snocWith :: forall m a. (MonadIO m, Storable a) =>
890899 -> a
891900 -> m (Array a)
892901snocWith allocSize arr x = liftIO $ do
893− let newEnd = aEnd arr `plusPtr` sizeOf (undefined :: a)
902+ let newEnd = aEnd arr `plusPtr` sizeOfElem (undefined :: a)
894903 if newEnd <= aBound arr
895904 then snocNewEnd newEnd arr x
896905 else snocWithRealloc allocSize arr x
@@ -963,7 +972,7 @@ realloc :: forall m a. (MonadIO m, Storable a) => Int -> Array a -> m (Array a)
963972realloc i arr =
964973 liftIO
965974 $ reallocAligned
966− (sizeOf (undefined :: a)) (alignment (undefined :: a)) i arr
975+ (sizeOfElem (undefined :: a)) (alignment (undefined :: a)) i arr
967976
968977-- | Change the reserved memory of the array so that it is enough to hold the
969978-- specified number of elements. Nothing is done if the specified capacity is
@@ -1005,7 +1014,7 @@ rightSize arr@Array{..} = do
10051014 target = roundUpLargeArray len
10061015 waste = aBound `minusPtr` aEnd
10071016 assert (target >= len) (return ())
1008− assert (len `mod` sizeOf (undefined :: a) == 0) (return ())
1017+ assert (len `mod` sizeOfElem (undefined :: a) == 0) (return ())
10091018 -- We trade off some wastage (25%) to avoid reallocations and copying.
10101019 if target < capacity && len < 3 * waste
10111020 then realloc target arr
@@ -1056,7 +1065,7 @@ truncateExp = undefined
10561065getIndexUnsafe :: forall m a. (MonadIO m, Storable a) => Array a -> Int -> m a
10571066getIndexUnsafe Array {..} i =
10581067 unsafeWithArrayContents arrContents arrStart $ \ptr -> do
1059− let elemSize = sizeOf (undefined :: a)
1068+ let elemSize = sizeOfElem (undefined :: a)
10601069 elemPtr = ptr `plusPtr` (elemSize * i)
10611070 assert (i >= 0 && elemPtr `plusPtr` elemSize <= aEnd) (return ())
10621071 liftIO $ peek elemPtr
@@ -1065,7 +1074,7 @@ getIndexUnsafe Array {..} i =
10651074getIndexPtr :: forall m a. (MonadIO m, Storable a) =>
10661075 Ptr a -> Ptr a -> Int -> m a
10671076getIndexPtr ptr end i = do
1068− let elemSize = sizeOf (undefined :: a)
1077+ let elemSize = sizeOfElem (undefined :: a)
10691078 elemPtr = ptr `plusPtr` (elemSize * i)
10701079 if i >= 0 && elemPtr `plusPtr` elemSize <= end
10711080 then liftIO $ peek elemPtr
@@ -1083,7 +1092,7 @@ getIndex arr i =
10831092getIndexPtrRev :: forall m a. (MonadIO m, Storable a) =>
10841093 Ptr a -> Ptr a -> Int -> m a
10851094getIndexPtrRev ptr end i = do
1086− let elemSize = sizeOf (undefined :: a)
1095+ let elemSize = sizeOfElem (undefined :: a)
10871096 elemPtr = end `plusPtr` negate (elemSize * (i + 1))
10881097 if i >= 0 && elemPtr >= ptr
10891098 then liftIO $ peek elemPtr
@@ -1151,7 +1160,7 @@ getSliceUnsafe :: forall a. Storable a
11511160 -> Array a
11521161 -> Array a
11531162getSliceUnsafe index len (Array contents start e _) =
1154− let size = sizeOf (undefined :: a)
1163+ let size = sizeOfElem (undefined :: a)
11551164 fp1 = start `plusPtr` (index * size)
11561165 end = fp1 `plusPtr` (len * size)
11571166 in assert
@@ -1169,7 +1178,7 @@ getSlice :: forall a. Storable a =>
11691178 -> Array a
11701179 -> Array a
11711180getSlice index len (Array contents start e _) =
1172− let size = sizeOf (undefined :: a)
1181+ let size = sizeOfElem (undefined :: a)
11731182 fp1 = start `plusPtr` (index * size)
11741183 end = fp1 `plusPtr` (len * size)
11751184 in if index >= 0 && len >= 0 && end <= e
@@ -1288,7 +1297,7 @@ byteLength Array{..} =
12881297{-# INLINE length #-}
12891298length :: forall a. Storable a => Array a -> Int
12901299length arr =
1291− let elemSize = sizeOf (undefined :: a)
1300+ let elemSize = sizeOfElem (undefined :: a)
12921301 blen = byteLength arr
12931302 in assert (blen `mod` elemSize == 0) (blen `div` elemSize)
12941303
@@ -1356,7 +1365,7 @@ arraysOf n (D.Stream step state) =
13561365 case r of
13571366 D.Yield x s -> do
13581367 liftIO $ poke end x >> touch contents
1359− let end' = end `plusPtr` sizeOf (undefined :: a)
1368+ let end' = end `plusPtr` sizeOfElem (undefined :: a)
13601369 return $
13611370 if end' >= bound
13621371 then D.Skip
@@ -1422,7 +1431,7 @@ flattenArrays (D.Stream step state) = D.Stream step' (OuterLoop state)
14221431 touch contents
14231432 return r
14241433 return $ D.Yield x (InnerLoop st contents
1425− (p `plusPtr` sizeOf (undefined :: a)) end)
1434+ (p `plusPtr` sizeOfElem (undefined :: a)) end)
14261435
14271436-- | Use the "readRev" unfold instead.
14281437--
@@ -1442,7 +1451,7 @@ flattenArraysRev (D.Stream step state) = D.Stream step' (OuterLoop state)
14421451 r <- step (adaptState gst) st
14431452 return $ case r of
14441453 D.Yield Array{..} s ->
1445− let p = aEnd `plusPtr` negate (sizeOf (undefined :: a))
1454+ let p = aEnd `plusPtr` negate (sizeOfElem (undefined :: a))
14461455 in D.Skip (InnerLoop s arrContents p arrStart)
14471456 D.Skip s -> D.Skip (OuterLoop s)
14481457 D.Stop -> D.Stop
@@ -1455,7 +1464,7 @@ flattenArraysRev (D.Stream step state) = D.Stream step' (OuterLoop state)
14551464 r <- peek p
14561465 touch contents
14571466 return r
1458− let cur = p `plusPtr` negate (sizeOf (undefined :: a))
1467+ let cur = p `plusPtr` negate (sizeOfElem (undefined :: a))
14591468 return $ D.Yield x (InnerLoop st contents cur start)
14601469
14611470-------------------------------------------------------------------------------
@@ -1484,7 +1493,7 @@ producer = Producer step (return . toReadUState) extract
14841493 return D.Stop
14851494 step (ReadUState contents end cur) = do
14861495 !x <- liftIO $ peek cur
1487− let cur1 = cur `plusPtr` sizeOf (undefined :: a)
1496+ let cur1 = cur `plusPtr` sizeOfElem (undefined :: a)
14881497 return $ D.Yield x (ReadUState contents end cur1)
14891498
14901499 extract (ReadUState contents end cur) = return $ Array contents cur end end
@@ -1505,7 +1514,7 @@ readRev = Unfold step inject
15051514 where
15061515
15071516 inject (Array contents start end _) =
1508− let p = end `plusPtr` negate (sizeOf (undefined :: a))
1517+ let p = end `plusPtr` negate (sizeOfElem (undefined :: a))
15091518 in return $ ReadUState contents start p
15101519
15111520 {-# INLINE_LATE step #-}
@@ -1514,7 +1523,7 @@ readRev = Unfold step inject
15141523 return D.Stop
15151524 step (ReadUState contents start p) = do
15161525 x <- liftIO $ peek p
1517− let cur = p `plusPtr` negate (sizeOf (undefined :: a))
1526+ let cur = p `plusPtr` negate (sizeOfElem (undefined :: a))
15181527 return $ D.Yield x (ReadUState contents start cur)
15191528
15201529-------------------------------------------------------------------------------
@@ -1542,7 +1551,7 @@ toListFB c n Array{..} = go arrStart
15421551 r <- peek p
15431552 touch arrContents
15441553 return r
1545− in c x (go (p `plusPtr` sizeOf (undefined :: a)))
1554+ in c x (go (p `plusPtr` sizeOfElem (undefined :: a)))
15461555-}
15471556
15481557-- XXX Monadic foldr/build fusion?
@@ -1559,7 +1568,7 @@ toList Array{..} = liftIO $ go arrStart
15591568 go p = do
15601569 x <- peek p
15611570 touch arrContents
1562− (:) x <$> go (p `plusPtr` sizeOf (undefined :: a))
1571+ (:) x <$> go (p `plusPtr` sizeOfElem (undefined :: a))
15631572
15641573-- | Use the 'read' unfold instead.
15651574--
@@ -1577,7 +1586,7 @@ toStreamD Array{..} = D.Stream step arrStart
15771586 step _ p = liftIO $ do
15781587 r <- peek p
15791588 touch arrContents
1580− return $ D.Yield r (p `plusPtr` sizeOf (undefined :: a))
1589+ return $ D.Yield r (p `plusPtr` sizeOfElem (undefined :: a))
15811590
15821591{-# INLINE toStreamK #-}
15831592toStreamK :: forall m a. (MonadIO m, Storable a) => Array a -> K.Stream m a
@@ -1591,7 +1600,7 @@ toStreamK Array{..} = go arrStart
15911600 r <- peek p
15921601 touch arrContents
15931602 return r
1594− in liftIO elemM `K.consM` go (p `plusPtr` sizeOf (undefined :: a))
1603+ in liftIO elemM `K.consM` go (p `plusPtr` sizeOfElem (undefined :: a))
15951604
15961605-- | Use the 'readRev' unfold instead.
15971606--
@@ -1601,7 +1610,7 @@ toStreamK Array{..} = go arrStart
16011610{-# INLINE_NORMAL toStreamDRev #-}
16021611toStreamDRev :: forall m a. (MonadIO m, Storable a) => Array a -> D.Stream m a
16031612toStreamDRev Array{..} =
1604− let p = aEnd `plusPtr` negate (sizeOf (undefined :: a))
1613+ let p = aEnd `plusPtr` negate (sizeOfElem (undefined :: a))
16051614 in D.Stream step p
16061615
16071616 where
@@ -1611,12 +1620,12 @@ toStreamDRev Array{..} =
16111620 step _ p = liftIO $ do
16121621 r <- peek p
16131622 touch arrContents
1614− return $ D.Yield r (p `plusPtr` negate (sizeOf (undefined :: a)))
1623+ return $ D.Yield r (p `plusPtr` negate (sizeOfElem (undefined :: a)))
16151624
16161625{-# INLINE toStreamKRev #-}
16171626toStreamKRev :: forall m a. (MonadIO m, Storable a) => Array a -> K.Stream m a
16181627toStreamKRev Array {..} =
1619− let p = aEnd `plusPtr` negate (sizeOf (undefined :: a))
1628+ let p = aEnd `plusPtr` negate (sizeOfElem (undefined :: a))
16201629 in go p
16211630
16221631 where
@@ -1627,7 +1636,7 @@ toStreamKRev Array {..} =
16271636 r <- peek p
16281637 touch arrContents
16291638 return r
1630− in liftIO elemM `K.consM` go (p `plusPtr` negate (sizeOf (undefined :: a)))
1639+ in liftIO elemM `K.consM` go (p `plusPtr` negate (sizeOfElem (undefined :: a)))
16311640
16321641-------------------------------------------------------------------------------
16331642-- Folding
@@ -1696,7 +1705,7 @@ appendNUnsafe action n =
16961705 assert (n >= 0) (return ())
16971706 arr@(Array _ _ end bound) <- action
16981707 let free = bound `minusPtr` end
1699− elemSize = sizeOf (undefined :: a)
1708+ elemSize = sizeOfElem (undefined :: a)
17001709 needed = n * elemSize
17011710 -- XXX We can also reallocate if the array has too much free space,
17021711 -- otherwise we lose that space.
@@ -1708,7 +1717,7 @@ appendNUnsafe action n =
17081717
17091718 step (ArrayUnsafe contents start end) x = do
17101719 liftIO $ poke end x >> touch contents
1711− let end1 = end `plusPtr` sizeOf (undefined :: a)
1720+ let end1 = end `plusPtr` sizeOfElem (undefined :: a)
17121721 return $ ArrayUnsafe contents start end1
17131722
17141723-- | Append @n@ elements to an existing array. Any free space left in the array
@@ -1826,7 +1835,7 @@ writeNWithUnsafe alloc n = Fold step initial (return . fromArrayUnsafe)
18261835 liftIO $ poke end x >> touch contents
18271836 return
18281837 $ FL.Partial
1829− $ ArrayUnsafe contents start (end `plusPtr` sizeOf (undefined :: a))
1838+ $ ArrayUnsafe contents start (end `plusPtr` sizeOfElem (undefined :: a))
18301839
18311840-- | Like 'writeN' but does not check the array bounds when writing. The fold
18321841-- driver must not call the step function more than 'n' times otherwise it will
@@ -1899,20 +1908,20 @@ writeWith elemCount =
18991908
19001909 insertElem (Array contents start end bound) x = do
19011910 liftIO $ poke end x
1902− let end1 = end `plusPtr` sizeOf (undefined :: a)
1911+ let end1 = end `plusPtr` sizeOfElem (undefined :: a)
19031912 return $ Array contents start end1 bound
19041913
19051914 initial = do
19061915 when (elemCount < 0) $ error "writeWith: elemCount is negative"
19071916 liftIO $ newArrayAligned (alignment (undefined :: a)) elemCount
19081917 step arr@(Array _ start end bound) x
1909− | end `plusPtr` sizeOf (undefined :: a) > bound = do
1918+ | end `plusPtr` sizeOfElem (undefined :: a) > bound = do
19101919 let oldSize = end `minusPtr` start
19111920 newSize = max (oldSize * 2) 1
19121921 arr1 <-
19131922 liftIO
19141923 $ reallocAligned
1915− (sizeOf (undefined :: a))
1924+ (sizeOfElem (undefined :: a))
19161925 (alignment (undefined :: a))
19171926 newSize
19181927 arr
@@ -1953,7 +1962,7 @@ fromStreamDN limit str = do
19531962
19541963 fwrite ptr x = do
19551964 liftIO $ poke ptr x
1956− return $ ptr `plusPtr` sizeOf (undefined :: a)
1965+ return $ ptr `plusPtr` sizeOfElem (undefined :: a)
19571966
19581967-- | Create an 'Array' from the first N elements of a list. The array is
19591968-- allocated to size N, if the list terminates before N elements then the
@@ -2147,7 +2156,7 @@ splitAt i arr@Array{..} =
21472156 else if i > maxIndex
21482157 then error $ "sliceAt: specified array index " ++ show i
21492158 ++ " is beyond the maximum index " ++ show maxIndex
2150− else let off = i * sizeOf (undefined :: a)
2159+ else let off = i * sizeOfElem (undefined :: a)
21512160 p = arrStart `plusPtr` off
21522161 in ( Array
21532162 { arrContents = arrContents
@@ -2198,7 +2207,7 @@ asBytes = castUnsafe
21982207cast :: forall a b. Storable b => Array a -> Maybe (Array b)
21992208cast arr =
22002209 let len = byteLength arr
2201− r = len `mod` sizeOf (undefined :: b)
2210+ r = len `mod` sizeOfElem (undefined :: b)
22022211 in if r /= 0
22032212 then Nothing
22042213 else Just $ castUnsafe arr