@@ -19,13 +19,13 @@ module Streamly.Internal.Data.Array.Stream
19 , Array.bufferChunks
19 , Array.bufferChunks
21 -- * Flattening to elements
21 -- * Flattening to elements
22− , concat
22+ , Array.concat
23 , Array.flattenArrays
23 , Array.flattenArrays
24− , concatRev
24+ , Array.concatRev
25 , Array.flattenArraysRev
25 , Array.flattenArraysRev
26− , interpose
26+ , Array.interpose
27− , interposeSuffix
27+ , Array.interposeSuffix
28− , intercalateSuffix
28+ , Array.intercalateSuffix
31 -- * Elimination
31 -- * Elimination
@@ -90,7 +90,6 @@ import Prelude hiding (null, last, (!!), read, concat, unlines)
91import Streamly.Data.Fold (Fold)
91import Streamly.Data.Fold (Fold)
92import Streamly.Internal.Data.Array.Type (Array(..))
92import Streamly.Internal.Data.Array.Type (Array(..))
93−import Streamly.Internal.Data.MutByteArray.Type (MutByteArray)
94import Streamly.Internal.Data.Fold.Chunked (ChunkFold(..))
93import Streamly.Internal.Data.Fold.Chunked (ChunkFold(..))
95import Streamly.Internal.Data.Parser (ParseError(..))
94import Streamly.Internal.Data.Parser (ParseError(..))
96import Streamly.Internal.Data.Stream (Stream)
95import Streamly.Internal.Data.Stream (Stream)
@@ -98,11 +97,8 @@ import Streamly.Internal.Data.StreamK (StreamK, fromStream, toStream)
98import Streamly.Internal.Data.SVar.Type (adaptState, defState)
97import Streamly.Internal.Data.SVar.Type (adaptState, defState)
99import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
98import Streamly.Internal.Data.Tuple.Strict (Tuple'(..))
101−import qualified Streamly.Data.Fold as FL
102import qualified Streamly.Internal.Data.Array as A
100import qualified Streamly.Internal.Data.Array as A
103import qualified Streamly.Internal.Data.Array as Array
101import qualified Streamly.Internal.Data.Array as Array
104−import qualified Streamly.Internal.Data.MutArray.Type as MA
105−import qualified Streamly.Internal.Data.MutArray.Stream as AS
106import qualified Streamly.Internal.Data.Fold.Type as FL (Fold(..), Step(..))
102import qualified Streamly.Internal.Data.Fold.Type as FL (Fold(..), Step(..))
107import qualified Streamly.Internal.Data.Parser as PR
103import qualified Streamly.Internal.Data.Parser as PR
108import qualified Streamly.Internal.Data.Parser as PRD
104import qualified Streamly.Internal.Data.Parser as PRD
@@ -114,110 +110,19 @@ import qualified Streamly.Internal.Data.StreamK as K
114-- XXX Since these are immutable arrays MonadIO constraint can be removed from
110-- XXX Since these are immutable arrays MonadIO constraint can be removed from
115-- most places.
111-- most places.
117−-------------------------------------------------------------------------------
119−-------------------------------------------------------------------------------
121−-- XXX efficiently compare two streams of arrays. Two streams can have chunks
122−-- of different sizes, we can handle that in the stream comparison abstraction.
123−-- This could be useful e.g. to fast compare whether two files differ.
125−-- | Convert a stream of arrays into a stream of their elements.
127−-- Same as the following:
129−-- > concat = Stream.unfoldMany Array.read
132−{-# INLINE concat #-}
133−concat :: (Monad m, Unbox a) => Stream m (Array a) -> Stream m a
134−-- concat m = fromStreamD $ A.flattenArrays (toStreamD m)
135−-- concat m = fromStreamD $ D.concatMap A.toStreamD (toStreamD m)
136−concat = D.unfoldMany A.reader
138−-- | Convert a stream of arrays into a stream of their elements reversing the
139−-- contents of each array before flattening.
141−-- > concatRev = Stream.unfoldMany Array.readerRev
144−{-# INLINE concatRev #-}
145−concatRev :: (Monad m, Unbox a) => Stream m (Array a) -> Stream m a
146−-- concatRev m = fromStreamD $ A.flattenArraysRev (toStreamD m)
147−concatRev = D.unfoldMany A.readerRev
149-------------------------------------------------------------------------------
113-------------------------------------------------------------------------------
150-- Intersperse and append
114-- Intersperse and append
151-------------------------------------------------------------------------------
115-------------------------------------------------------------------------------
153−-- | Flatten a stream of arrays after inserting the given element between
157−{-# INLINE interpose #-}
158−interpose :: (Monad m, Unbox a) => a -> Stream m (Array a) -> Stream m a
159−interpose x = D.interpose x A.reader
161−{-# INLINE intercalateSuffix #-}
162−intercalateSuffix :: (Monad m, Unbox a)
163− => Array a -> Stream m (Array a) -> Stream m a
164−intercalateSuffix = D.intercalateSuffix A.reader
166−-- | Flatten a stream of arrays appending the given element after each
170−{-# INLINE interposeSuffix #-}
171−interposeSuffix :: (Monad m, Unbox a)
172− => a -> Stream m (Array a) -> Stream m a
173−-- interposeSuffix x = fromStreamD . A.unlines x . toStreamD
174−interposeSuffix x = D.interposeSuffix x A.reader
176−data FlattenState s =
178− | InnerLoop s !MutByteArray !Int !Int
180−-- XXX This is a special case of interposeSuffix, can be removed.
181−-- XXX Remove monadIO constraint
182{-# INLINE_NORMAL unlines #-}
117{-# INLINE_NORMAL unlines #-}
183unlines :: forall m a. (MonadIO m, Unbox a)
118unlines :: forall m a. (MonadIO m, Unbox a)
184 => a -> D.Stream m (Array a) -> D.Stream m a
119 => a -> D.Stream m (Array a) -> D.Stream m a
185−unlines sep (D.Stream step state) = D.Stream step' (OuterLoop state)
120+unlines = Array.interposeSuffix
187− {-# INLINE_LATE step' #-}
188− step' gst (OuterLoop st) = do
189− r <- step (adaptState gst) st
191− D.Yield Array{..} s ->
192− D.Skip (InnerLoop s arrContents arrStart arrEnd)
193− D.Skip s -> D.Skip (OuterLoop s)
196− step' _ (InnerLoop st _ p end) | p == end =
197− return $ D.Yield sep $ OuterLoop st
199− step' _ (InnerLoop st contents p end) = do
200− x <- liftIO $ peekByteIndex p contents
201− return $ D.Yield x (InnerLoop st contents (INDEX_NEXT(p,a)) end)
203-------------------------------------------------------------------------------
122-------------------------------------------------------------------------------
204-- Compact
123-- Compact
205-------------------------------------------------------------------------------
124-------------------------------------------------------------------------------
207−-- XXX These would not be needed once we implement compactLEFold, see
208−-- module Streamly.Internal.Data.Stream.MutChunked
210−-- XXX Note that this thaws immutable arrays for appending, that may be
211−-- problematic if multiple users do the same thing, however, immutable arrays
212−-- would usually have no capacity to append, therefore, a copy will be forced
213−-- anyway. Confirm this. We can forcefully trim the array capacity before thaw
215−{-# INLINE_NORMAL packArraysChunksOf #-}
216−packArraysChunksOf :: (MonadIO m, Unbox a)
217− => Int -> D.Stream m (Array a) -> D.Stream m (Array a)
218−packArraysChunksOf n str =
219− D.map A.unsafeFreeze $ AS.packArraysChunksOf n $ D.map A.unsafeThaw str
221-- XXX instead of writing two different versions of this operation, we should
126-- XXX instead of writing two different versions of this operation, we should
222-- write it as a pipe.
127-- write it as a pipe.
@@ -225,8 +130,7 @@ packArraysChunksOf n str =
225{-# INLINE_NORMAL lpackArraysChunksOf #-}
130{-# INLINE_NORMAL lpackArraysChunksOf #-}
226lpackArraysChunksOf :: (MonadIO m, Unbox a)
131lpackArraysChunksOf :: (MonadIO m, Unbox a)
227 => Int -> Fold m (Array a) () -> Fold m (Array a) ()
132 => Int -> Fold m (Array a) () -> Fold m (Array a) ()
228−lpackArraysChunksOf n fld =
133+lpackArraysChunksOf = Array.lCompactGE
229− FL.lmap A.unsafeThaw $ AS.lpackArraysChunksOf n (FL.lmap A.unsafeFreeze fld)
231-- | Coalesce adjacent arrays in incoming stream to form bigger arrays of a
135-- | Coalesce adjacent arrays in incoming stream to form bigger arrays of a
232-- maximum specified size in bytes.
136-- maximum specified size in bytes.
@@ -235,7 +139,7 @@ lpackArraysChunksOf n fld =
235{-# INLINE compact #-}
139{-# INLINE compact #-}
236compact :: (MonadIO m, Unbox a)
140compact :: (MonadIO m, Unbox a)
237 => Int -> Stream m (Array a) -> Stream m (Array a)
141 => Int -> Stream m (Array a) -> Stream m (Array a)
238−compact = packArraysChunksOf
142+compact = Array.compactLE
240-- | Given a stream of arrays, splice them all together to generate a single
144-- | Given a stream of arrays, splice them all together to generate a single
241-- array. The stream must be /finite/.
145-- array. The stream must be /finite/.
@@ -243,71 +147,12 @@ compact = packArraysChunksOf
243-- @since 0.7.0
147-- @since 0.7.0
244{-# INLINE toArray #-}
148{-# INLINE toArray #-}
245toArray :: (MonadIO m, Unbox a) => Stream m (Array a) -> m (Array a)
149toArray :: (MonadIO m, Unbox a) => Stream m (Array a) -> m (Array a)
246−toArray s =
150+toArray = Array.fromChunks
247− fmap A.unsafeFreeze $ MA.fromChunksRealloced (fmap A.unsafeThaw s)
249-------------------------------------------------------------------------------
152-------------------------------------------------------------------------------
251-------------------------------------------------------------------------------
154-------------------------------------------------------------------------------
253−data SplitState s arr
257− | Yielding arr (SplitState s arr)
260−-- | Split a stream of arrays on a given separator byte, dropping the separator
261−-- and coalescing all the arrays between two separators into a single array.
264−{-# INLINE_NORMAL _splitOn #-}
268− -> D.Stream m (Array Word8)
269− -> D.Stream m (Array Word8)
270−_splitOn byte (D.Stream step state) = D.Stream step' (Initial state)
274− {-# INLINE_LATE step' #-}
275− step' gst (Initial st) = do
279− (arr1, marr2) <- A.breakOn byte arr
280− return $ case marr2 of
281− Nothing -> D.Skip (Buffering s arr1)
282− Just arr2 -> D.Skip (Yielding arr1 (Splitting s arr2))
283− D.Skip s -> return $ D.Skip (Initial s)
284− D.Stop -> return D.Stop
286− step' gst (Buffering st buf) = do
290− (arr1, marr2) <- A.breakOn byte arr
291− -- XXX Should use MutArray.splice
292− buf' <- A.splice buf arr1
293− return $ case marr2 of
294− Nothing -> D.Skip (Buffering s buf')
295− Just x -> D.Skip (Yielding buf' (Splitting s x))
296− D.Skip s -> return $ D.Skip (Buffering s buf)
298− if A.byteLength buf == 0
300− else D.Skip (Yielding buf Finishing)
302− step' _ (Splitting st buf) = do
303− (arr1, marr2) <- A.breakOn byte buf
304− return $ case marr2 of
305− Nothing -> D.Skip $ Buffering st arr1
306− Just arr2 -> D.Skip $ Yielding arr1 (Splitting st arr2)
308− step' _ (Yielding arr next) = return $ D.Yield arr next
309− step' _ Finishing = return D.Stop
311-- XXX Remove MonadIO constraint.
156-- XXX Remove MonadIO constraint.
312-- | Split a stream of arrays on a given separator byte, dropping the separator
157-- | Split a stream of arrays on a given separator byte, dropping the separator
313-- and coalescing all the arrays between two separators into a single array.
158-- and coalescing all the arrays between two separators into a single array.
@@ -319,11 +164,7 @@ splitOn
320 -> Stream m (Array Word8)
165 -> Stream m (Array Word8)
321 -> Stream m (Array Word8)
166 -> Stream m (Array Word8)
322−splitOn byte =
167+splitOn = Array.compactOnByte
324− -- XXX use spliceExp and rightSize?
325− . D.splitInnerBy (MA.breakOn byte) MA.splice
328{-# INLINE splitOnSuffix #-}
169{-# INLINE splitOnSuffix #-}
329splitOnSuffix
170splitOnSuffix
@@ -331,13 +172,7 @@ splitOnSuffix
332 -> Stream m (Array Word8)
173 -> Stream m (Array Word8)
333 -> Stream m (Array Word8)
174 -> Stream m (Array Word8)
334−-- splitOn byte s = fromStreamD $ A.splitOn byte $ toStreamD s
335−splitOnSuffix byte =
175+splitOnSuffix = Array.compactOnByteSuffix
337− -- XXX use spliceExp and rightSize?
338− . D.splitInnerBySuffix
339− (\arr -> MA.byteLength arr == 0) (MA.breakOn byte) MA.splice
342-------------------------------------------------------------------------------
177-------------------------------------------------------------------------------
343-- Elimination - Running folds
178-- Elimination - Running folds