@@ -62,6 +62,7 @@ module Streamly.Memory.Array.Types
66 -- * Utilities
67 -- * Utilities
67 , defaultChunkSize
68 , defaultChunkSize
@@ -100,6 +101,7 @@ import GHC.IO (IO(IO), unsafePerformIO)
100import GHC.Ptr (Ptr(..))
101import GHC.Ptr (Ptr(..))
102import Streamly.Fold.Types (Fold(..))
103import Streamly.Fold.Types (Fold(..))
104+import Streamly.Unfold.Types (Unfold(..))
103import Streamly.Strict (Tuple'(..))
105import Streamly.Strict (Tuple'(..))
104import Streamly.SVar (adaptState)
106import Streamly.SVar (adaptState)
@@ -388,6 +390,31 @@ byteCapacity Array{..} =
388 len = aBound `minusPtr` p
390 len = aBound `minusPtr` p
389 in assert (len >= 0) len
391 in assert (len >= 0) len
393+{-# INLINE_NORMAL readU #-}
394+readU :: forall m a. (Monad m, Storable a) => Unfold m (Array a) a
395+readU = Unfold step inject
398+ -- Note we have repurposed the Array type here
400+ return $ Array aStart (unsafeForeignPtrToPtr aStart) aEnd
402+ {-# INLINE_LATE step #-}
403+ step (Array _ p end) | p == end = return D.Stop
404+ step (Array start p end) = do
405+ -- unsafeInlineIO allows us to run this in Identity monad for pure
406+ -- toList/foldr case which makes them much faster due to not
407+ -- accumulating the list and fusing better with the pure consumers.
409+ -- This should be safe as the array contents are guaranteed to be
410+ -- evaluated/written to before we peek at them.
411+ let !x = unsafeInlineIO $ do
413+ touchForeignPtr start
416+ (Array start (p `plusPtr` (sizeOf (undefined :: a))) end)
391{-# INLINE_NORMAL toStreamD #-}
418{-# INLINE_NORMAL toStreamD #-}
392toStreamD :: forall m a. (Monad m, Storable a) => Array a -> D.Stream m a
419toStreamD :: forall m a. (Monad m, Storable a) => Array a -> D.Stream m a
393toStreamD Array{..} =
420toStreamD Array{..} =