@@ -25,9 +25,61 @@
2525module Streamly.Internal.Data.Array.Foreign.Mut
2626 (
2727 module Streamly.Internal.Data.Array.Foreign.Mut.Type
28+ , splitOn
29+ , genSlicesFromLen
30+ , getSlicesFromLen
2831 )
2932where
3033
3134import Prelude hiding (foldr, length, read, splitAt)
3235
3336import Streamly.Internal.Data.Array.Foreign.Mut.Type
37+import qualified Streamly.Internal.Data.Stream.StreamD as D
38+import Foreign.Storable (Storable)
39+import Streamly.Internal.Data.Stream.IsStream.Type (SerialT)
40+import qualified Streamly.Internal.Data.Stream.IsStream.Type as IsStream
41+import qualified Streamly.Internal.Data.Unfold as Unfold
42+import Streamly.Internal.Data.Unfold.Type (Unfold(..))
43+
44+-- | Split the array into a stream of slices using a predicate. The element
45+-- matching the predicate is dropped.
46+--
47+-- /Pre-release/
48+{-# INLINE splitOn #-}
49+splitOn :: (Monad m, Storable a) =>
50+ (a -> Bool) -> Array a -> SerialT m (Array a)
51+splitOn predicate arr =
52+ IsStream.fromStreamD
53+ $ fmap (\(i, len) -> getSliceUnsafe i len arr)
54+ $ D.sliceOnSuffix predicate (toStreamD arr)
55+
56+-- | Generate a stream of array slice descriptors ((index, len)) of specified
57+-- length from an array, starting from the supplied array index. The last slice
58+-- may be shorter than the requested length depending on the array length.
59+--
60+-- /Pre-release/
61+{-# INLINE genSlicesFromLen #-}
62+genSlicesFromLen :: forall m a. (Monad m, Storable a)
63+ => Int -- ^ from index
64+ -> Int -- ^ length of the slice
65+ -> Unfold m (Array a) (Int, Int)
66+genSlicesFromLen from len =
67+ let fromThenTo n = (from, from + len, n - 1)
68+ mkSlice n i = return (i, min len (n - i))
69+ in Unfold.lmap length
70+ $ Unfold.mapMWithInput mkSlice
71+ $ Unfold.lmap fromThenTo Unfold.enumerateFromThenTo
72+
73+-- | Generate a stream of slices of specified length from an array, starting
74+-- from the supplied array index. The last slice may be shorter than the
75+-- requested length depending on the array length.
76+--
77+-- /Pre-release/
78+{-# INLINE getSlicesFromLen #-}
79+getSlicesFromLen :: forall m a. (Monad m, Storable a)
80+ => Int -- ^ from index
81+ -> Int -- ^ length of the slice
82+ -> Unfold m (Array a) (Array a)
83+getSlicesFromLen from len =
84+ let mkSlice arr (i, n) = return $ getSliceUnsafe i n arr
85+ in Unfold.mapMWithInput mkSlice (genSlicesFromLen from len)