@@ -84,6 +84,7 @@ import GHC.Ptr (Ptr(..))
8484import Streamly.Internal.Data.Array.Foreign.Mut.Type (Array, memcmp)
8585import Streamly.Internal.Data.Fold.Type (Fold(..), Step(..), lmap)
8686import Streamly.Internal.Data.Stream.Serial (SerialT(..))
87+import Streamly.Internal.Data.Stream.StreamD.Step (Step(..))
8788import Streamly.Internal.Data.Unfold.Type (Unfold(..))
8889import Streamly.Internal.System.IO (unsafeInlineIO)
8990
@@ -304,13 +305,31 @@ bytesFree = undefined
304305-- Unfolds
305306-------------------------------------------------------------------------------
306307
307−-- | Unfold a ring array into a stream.
308+-- XXX We can read the ring in a loop and use "take" to restrict the number of
309+-- elements to be taken.
308310--
309−-- /Unimplemented/
311+-- | Read n elements from the ring starting at the supplied ring head. If n is
312+-- more than the ring size it keeps reading the ring in a circular fashion.
313+--
314+-- If the ring is not full the user must ensure than n is less than or equal to
315+-- the number of valid elements in the ring.
316+--
317+-- /Internal/
310318{-# INLINE_NORMAL read #-}
311−read :: -- forall m a. (MonadIO m, Storable a) =>
312− Unfold m (Ring a) a
313−read = undefined
319+read :: forall m a. (MonadIO m, Storable a) => Unfold m (Ring a, Ptr a, Int) a
320+read = Unfold step return
321+
322+ where
323+
324+ step (rb, rh, n) = do
325+ if n <= 0
326+ then do
327+ liftIO $ touchForeignPtr (ringStart rb)
328+ return Stop
329+ else do
330+ x <- liftIO $ peek rh
331+ let rh1 = advance rb rh
332+ return $ Yield x (rb, rh1, n - 1)
314333
315334-- | Unfold a ring array into a stream in reverse order.
316335--