-- |
-- Module      : Streamly.Internal.Data.MutArray
-- Copyright   : (c) 2020 Composewell Technologies
-- License     : BSD-3-Clause
-- Maintainer  : streamly@composewell.com
-- Stability   : experimental
-- Portability : GHC
--
module Streamly.Internal.Data.MutArray
    (
    -- * MutArray.Type module
      module Streamly.Internal.Data.MutArray.Type
    -- * MutArray module
    , sliceIndexerFromLen
    , slicerFromLen
    , compactLE
    , pinnedCompactLE
    , compactOnByte
    , compactOnByteSuffix
    -- * Unboxed IORef
    , module Streamly.Internal.Data.IORef.Unboxed

    -- * Deprecated
    , genSlicesFromLen
    , getSlicesFromLen
    )
where

#include "inline.hs"

import Control.Monad.IO.Class (MonadIO(..))
import Data.Word (Word8)
import Streamly.Internal.Data.MutByteArray.Type (PinnedState(..))
import Streamly.Internal.Data.Stream.Type (Stream)
import Streamly.Internal.Data.Unbox (Unbox)
import Streamly.Internal.Data.Unfold.Type (Unfold(..))

import qualified Streamly.Internal.Data.Stream.Type as Stream
import qualified Streamly.Internal.Data.Stream.Nesting as Stream
-- import qualified Streamly.Internal.Data.Stream.Transform as Stream
import qualified Streamly.Internal.Data.Unfold as Unfold

import Prelude hiding (foldr, length, read, splitAt)
import Streamly.Internal.Data.MutArray.Type
import Streamly.Internal.Data.IORef.Unboxed

-- | Generate a stream of array slice descriptors ((index, len)) of specified
-- length from an array, starting from the supplied array index. The last slice
-- may be shorter than the requested length depending on the array length.
--
-- /Pre-release/
{-# INLINE sliceIndexerFromLen #-}
sliceIndexerFromLen :: forall m a. (Monad m, Unbox a)
    => Int -- ^ from index
    -> Int -- ^ length of the slice
    -> Unfold m (MutArray a) (Int, Int)
sliceIndexerFromLen :: forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Int -> Int -> Unfold m (MutArray a) (Int, Int)
sliceIndexerFromLen Int
from Int
len =
    let fromThenTo :: c -> (Int, Int, c)
fromThenTo c
n = (Int
from, Int
from Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
len, c
n c -> c -> c
forall a. Num a => a -> a -> a
- c
1)
        mkSlice :: Int -> Int -> m (Int, Int)
mkSlice Int
n Int
i = (Int, Int) -> m (Int, Int)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int
i, Int -> Int -> Int
forall a. Ord a => a -> a -> a
min Int
len (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
i))
     in (MutArray a -> Int)
-> Unfold m Int (Int, Int) -> Unfold m (MutArray a) (Int, Int)
forall a c (m :: * -> *) b.
(a -> c) -> Unfold m c b -> Unfold m a b
Unfold.lmap MutArray a -> Int
forall a. Unbox a => MutArray a -> Int
length
        (Unfold m Int (Int, Int) -> Unfold m (MutArray a) (Int, Int))
-> Unfold m Int (Int, Int) -> Unfold m (MutArray a) (Int, Int)
forall a b. (a -> b) -> a -> b
$ (Int -> Int -> m (Int, Int))
-> Unfold m Int Int -> Unfold m Int (Int, Int)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> Unfold m a b -> Unfold m a c
Unfold.mapM2 Int -> Int -> m (Int, Int)
forall {m :: * -> *}. Monad m => Int -> Int -> m (Int, Int)
mkSlice
        (Unfold m Int Int -> Unfold m Int (Int, Int))
-> Unfold m Int Int -> Unfold m Int (Int, Int)
forall a b. (a -> b) -> a -> b
$ (Int -> (Int, Int, Int))
-> Unfold m (Int, Int, Int) Int -> Unfold m Int Int
forall a c (m :: * -> *) b.
(a -> c) -> Unfold m c b -> Unfold m a b
Unfold.lmap Int -> (Int, Int, Int)
forall {c}. Num c => c -> (Int, Int, c)
fromThenTo Unfold m (Int, Int, Int) Int
forall a (m :: * -> *).
(Enumerable a, Monad m) =>
Unfold m (a, a, a) a
forall (m :: * -> *). Monad m => Unfold m (Int, Int, Int) Int
Unfold.enumerateFromThenTo

{-# DEPRECATED genSlicesFromLen "Please use sliceIndexerFromLen instead." #-}
genSlicesFromLen :: forall m a. (Monad m, Unbox a)
    => Int -- ^ from index
    -> Int -- ^ length of the slice
    -> Unfold m (MutArray a) (Int, Int)
genSlicesFromLen :: forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Int -> Int -> Unfold m (MutArray a) (Int, Int)
genSlicesFromLen = Int -> Int -> Unfold m (MutArray a) (Int, Int)
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Int -> Int -> Unfold m (MutArray a) (Int, Int)
sliceIndexerFromLen

-- | Generate a stream of slices of specified length from an array, starting
-- from the supplied array index. The last slice may be shorter than the
-- requested length depending on the array length.
--
-- /Pre-release/
{-# INLINE slicerFromLen #-}
slicerFromLen :: forall m a. (Monad m, Unbox a)
    => Int -- ^ from index
    -> Int -- ^ length of the slice
    -> Unfold m (MutArray a) (MutArray a)
slicerFromLen :: forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Int -> Int -> Unfold m (MutArray a) (MutArray a)
slicerFromLen Int
from Int
len =
    let mkSlice :: MutArray a -> (Int, Int) -> m (MutArray a)
mkSlice MutArray a
arr (Int
i, Int
n) = MutArray a -> m (MutArray a)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (MutArray a -> m (MutArray a)) -> MutArray a -> m (MutArray a)
forall a b. (a -> b) -> a -> b
$ Int -> Int -> MutArray a -> MutArray a
forall a. Unbox a => Int -> Int -> MutArray a -> MutArray a
getSliceUnsafe Int
i Int
n MutArray a
arr
     in (MutArray a -> (Int, Int) -> m (MutArray a))
-> Unfold m (MutArray a) (Int, Int)
-> Unfold m (MutArray a) (MutArray a)
forall (m :: * -> *) a b c.
Monad m =>
(a -> b -> m c) -> Unfold m a b -> Unfold m a c
Unfold.mapM2 MutArray a -> (Int, Int) -> m (MutArray a)
forall {m :: * -> *} {a}.
(Monad m, Unbox a) =>
MutArray a -> (Int, Int) -> m (MutArray a)
mkSlice (Int -> Int -> Unfold m (MutArray a) (Int, Int)
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Int -> Int -> Unfold m (MutArray a) (Int, Int)
sliceIndexerFromLen Int
from Int
len)

{-# DEPRECATED getSlicesFromLen "Please use slicerFromLen instead." #-}
getSlicesFromLen :: forall m a. (Monad m, Unbox a)
    => Int -- ^ from index
    -> Int -- ^ length of the slice
    -> Unfold m (MutArray a) (MutArray a)
getSlicesFromLen :: forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Int -> Int -> Unfold m (MutArray a) (MutArray a)
getSlicesFromLen = Int -> Int -> Unfold m (MutArray a) (MutArray a)
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Int -> Int -> Unfold m (MutArray a) (MutArray a)
slicerFromLen

-------------------------------------------------------------------------------
-- Compacting Streams of Arrays
-------------------------------------------------------------------------------

-- | @compactLE maxElems@ coalesces adjacent arrays in the input stream
-- only if the combined size would be less than or equal to @maxElems@
-- elements. Note that it won't split an array if the original array is already
-- larger than maxElems.
--
-- @maxElems@ must be greater than 0.
--
-- Generates unpinned arrays irrespective of the pinning status of input
-- arrays.
{-# INLINE compactLE #-}
compactLE :: (MonadIO m, Unbox a) =>
    Int -> Stream m (MutArray a) -> Stream m (MutArray a)
-- XXX compactLE can be moved to MutArray/Type if we are not using the parser
-- to implement it.
compactLE :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Stream m (MutArray a) -> Stream m (MutArray a)
compactLE = PinnedState
-> Int -> Stream m (MutArray a) -> Stream m (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
PinnedState
-> Int -> Stream m (MutArray a) -> Stream m (MutArray a)
compactLeAs PinnedState
Unpinned
-- The parser version turns out to be a little bit slower.
-- compactLE n = Stream.catRights . Stream.parseManyD (pCompactLE n)

-- | Pinned version of 'compactLE'.
{-# INLINE pinnedCompactLE #-}
pinnedCompactLE :: forall m a. (MonadIO m, Unbox a)
    => Int -> Stream m (MutArray a) -> Stream m (MutArray a)
pinnedCompactLE :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Stream m (MutArray a) -> Stream m (MutArray a)
pinnedCompactLE = PinnedState
-> Int -> Stream m (MutArray a) -> Stream m (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
PinnedState
-> Int -> Stream m (MutArray a) -> Stream m (MutArray a)
compactLeAs PinnedState
Pinned
-- pinnedCompactLE n = Stream.catRights . Stream.parseManyD (pPinnedCompactLE n)

data SplitState s arr
    = Initial s
    | Buffering s arr
    | Splitting s arr
    | Yielding arr (SplitState s arr)
    | Finishing

-- | Split a stream of arrays on a given separator byte, dropping the separator
-- and coalescing all the arrays between two separators into a single array.
--
{-# INLINE_NORMAL _compactOnByteCustom #-}
_compactOnByteCustom
    :: MonadIO m
    => Word8
    -> Stream m (MutArray Word8)
    -> Stream m (MutArray Word8)
_compactOnByteCustom :: forall (m :: * -> *).
MonadIO m =>
Word8 -> Stream m (MutArray Word8) -> Stream m (MutArray Word8)
_compactOnByteCustom Word8
byte (Stream.Stream State StreamK m (MutArray Word8)
-> s -> m (Step s (MutArray Word8))
step s
state) =
    (State StreamK m (MutArray Word8)
 -> SplitState s (MutArray Word8)
 -> m (Step (SplitState s (MutArray Word8)) (MutArray Word8)))
-> SplitState s (MutArray Word8) -> Stream m (MutArray Word8)
forall (m :: * -> *) a s.
(State StreamK m a -> s -> m (Step s a)) -> s -> Stream m a
Stream.Stream State StreamK m (MutArray Word8)
-> SplitState s (MutArray Word8)
-> m (Step (SplitState s (MutArray Word8)) (MutArray Word8))
step' (s -> SplitState s (MutArray Word8)
forall s arr. s -> SplitState s arr
Initial s
state)

    where

    {-# INLINE_LATE step' #-}
    step' :: State StreamK m (MutArray Word8)
-> SplitState s (MutArray Word8)
-> m (Step (SplitState s (MutArray Word8)) (MutArray Word8))
step' State StreamK m (MutArray Word8)
gst (Initial s
st) = do
        Step s (MutArray Word8)
r <- State StreamK m (MutArray Word8)
-> s -> m (Step s (MutArray Word8))
step State StreamK m (MutArray Word8)
gst s
st
        case Step s (MutArray Word8)
r of
            Stream.Yield MutArray Word8
arr s
s -> do
                (MutArray Word8
arr1, Maybe (MutArray Word8)
marr2) <- Word8
-> MutArray Word8 -> m (MutArray Word8, Maybe (MutArray Word8))
forall (m :: * -> *).
MonadIO m =>
Word8
-> MutArray Word8 -> m (MutArray Word8, Maybe (MutArray Word8))
breakOn Word8
byte MutArray Word8
arr
                Step (SplitState s (MutArray Word8)) (MutArray Word8)
-> m (Step (SplitState s (MutArray Word8)) (MutArray Word8))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Step (SplitState s (MutArray Word8)) (MutArray Word8)
 -> m (Step (SplitState s (MutArray Word8)) (MutArray Word8)))
-> Step (SplitState s (MutArray Word8)) (MutArray Word8)
-> m (Step (SplitState s (MutArray Word8)) (MutArray Word8))
forall a b. (a -> b) -> a -> b
$ case Maybe (MutArray Word8)
marr2 of
                    Maybe (MutArray Word8)
Nothing   -> SplitState s (MutArray Word8)
-> Step (SplitState s (MutArray Word8)) (MutArray Word8)
forall s a. s -> Step s a
Stream.Skip (s -> MutArray Word8 -> SplitState s (MutArray Word8)
forall s arr. s -> arr -> SplitState s arr
Buffering s
s MutArray Word8
arr1)
                    Just MutArray Word8
arr2 -> SplitState s (MutArray Word8)
-> Step (SplitState s (MutArray Word8)) (MutArray Word8)
forall s a. s -> Step s a
Stream.Skip (MutArray Word8
-> SplitState s (MutArray Word8) -> SplitState s (MutArray Word8)
forall s arr. arr -> SplitState s arr -> SplitState s arr
Yielding MutArray Word8
arr1 (s -> MutArray Word8 -> SplitState s (MutArray Word8)
forall s arr. s -> arr -> SplitState s arr
Splitting s
s MutArray Word8
arr2))
            Stream.Skip s
s -> Step (SplitState s (MutArray Word8)) (MutArray Word8)
-> m (Step (SplitState s (MutArray Word8)) (MutArray Word8))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Step (SplitState s (MutArray Word8)) (MutArray Word8)
 -> m (Step (SplitState s (MutArray Word8)) (MutArray Word8)))
-> Step (SplitState s (MutArray Word8)) (MutArray Word8)
-> m (Step (SplitState s (MutArray Word8)) (MutArray Word8))
forall a b. (a -> b) -> a -> b
$ SplitState s (MutArray Word8)
-> Step (SplitState s (MutArray Word8)) (MutArray Word8)
forall s a. s -> Step s a
Stream.Skip (s -> SplitState s (MutArray Word8)
forall s arr. s -> SplitState s arr
Initial s
s)
            Step s (MutArray Word8)
Stream.Stop -> Step (SplitState s (MutArray Word8)) (MutArray Word8)
-> m (Step (SplitState s (MutArray Word8)) (MutArray Word8))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Step (SplitState s (MutArray Word8)) (MutArray Word8)
forall s a. Step s a
Stream.Stop

    step' State StreamK m (MutArray Word8)
gst (Buffering s
st MutArray Word8
buf) = do
        Step s (MutArray Word8)
r <- State StreamK m (MutArray Word8)
-> s -> m (Step s (MutArray Word8))
step State StreamK m (MutArray Word8)
gst s
st
        case Step s (MutArray Word8)
r of
            Stream.Yield MutArray Word8
arr s
s -> do
                (MutArray Word8
arr1, Maybe (MutArray Word8)
marr2) <- Word8
-> MutArray Word8 -> m (MutArray Word8, Maybe (MutArray Word8))
forall (m :: * -> *).
MonadIO m =>
Word8
-> MutArray Word8 -> m (MutArray Word8, Maybe (MutArray Word8))
breakOn Word8
byte MutArray Word8
arr
                -- XXX Use spliceExp instead and then rightSize?
                MutArray Word8
buf1 <- MutArray Word8 -> MutArray Word8 -> m (MutArray Word8)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
MutArray a -> MutArray a -> m (MutArray a)
splice MutArray Word8
buf MutArray Word8
arr1
                Step (SplitState s (MutArray Word8)) (MutArray Word8)
-> m (Step (SplitState s (MutArray Word8)) (MutArray Word8))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Step (SplitState s (MutArray Word8)) (MutArray Word8)
 -> m (Step (SplitState s (MutArray Word8)) (MutArray Word8)))
-> Step (SplitState s (MutArray Word8)) (MutArray Word8)
-> m (Step (SplitState s (MutArray Word8)) (MutArray Word8))
forall a b. (a -> b) -> a -> b
$ case Maybe (MutArray Word8)
marr2 of
                    Maybe (MutArray Word8)
Nothing -> SplitState s (MutArray Word8)
-> Step (SplitState s (MutArray Word8)) (MutArray Word8)
forall s a. s -> Step s a
Stream.Skip (s -> MutArray Word8 -> SplitState s (MutArray Word8)
forall s arr. s -> arr -> SplitState s arr
Buffering s
s MutArray Word8
buf1)
                    Just MutArray Word8
x -> SplitState s (MutArray Word8)
-> Step (SplitState s (MutArray Word8)) (MutArray Word8)
forall s a. s -> Step s a
Stream.Skip (MutArray Word8
-> SplitState s (MutArray Word8) -> SplitState s (MutArray Word8)
forall s arr. arr -> SplitState s arr -> SplitState s arr
Yielding MutArray Word8
buf1 (s -> MutArray Word8 -> SplitState s (MutArray Word8)
forall s arr. s -> arr -> SplitState s arr
Splitting s
s MutArray Word8
x))
            Stream.Skip s
s -> Step (SplitState s (MutArray Word8)) (MutArray Word8)
-> m (Step (SplitState s (MutArray Word8)) (MutArray Word8))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Step (SplitState s (MutArray Word8)) (MutArray Word8)
 -> m (Step (SplitState s (MutArray Word8)) (MutArray Word8)))
-> Step (SplitState s (MutArray Word8)) (MutArray Word8)
-> m (Step (SplitState s (MutArray Word8)) (MutArray Word8))
forall a b. (a -> b) -> a -> b
$ SplitState s (MutArray Word8)
-> Step (SplitState s (MutArray Word8)) (MutArray Word8)
forall s a. s -> Step s a
Stream.Skip (s -> MutArray Word8 -> SplitState s (MutArray Word8)
forall s arr. s -> arr -> SplitState s arr
Buffering s
s MutArray Word8
buf)
            Step s (MutArray Word8)
Stream.Stop -> Step (SplitState s (MutArray Word8)) (MutArray Word8)
-> m (Step (SplitState s (MutArray Word8)) (MutArray Word8))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Step (SplitState s (MutArray Word8)) (MutArray Word8)
 -> m (Step (SplitState s (MutArray Word8)) (MutArray Word8)))
-> Step (SplitState s (MutArray Word8)) (MutArray Word8)
-> m (Step (SplitState s (MutArray Word8)) (MutArray Word8))
forall a b. (a -> b) -> a -> b
$
                if MutArray Word8 -> Int
forall a. MutArray a -> Int
byteLength MutArray Word8
buf Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0
                then Step (SplitState s (MutArray Word8)) (MutArray Word8)
forall s a. Step s a
Stream.Stop
                else SplitState s (MutArray Word8)
-> Step (SplitState s (MutArray Word8)) (MutArray Word8)
forall s a. s -> Step s a
Stream.Skip (MutArray Word8
-> SplitState s (MutArray Word8) -> SplitState s (MutArray Word8)
forall s arr. arr -> SplitState s arr -> SplitState s arr
Yielding MutArray Word8
buf SplitState s (MutArray Word8)
forall s arr. SplitState s arr
Finishing)

    step' State StreamK m (MutArray Word8)
_ (Splitting s
st MutArray Word8
buf) = do
        (MutArray Word8
arr1, Maybe (MutArray Word8)
marr2) <- Word8
-> MutArray Word8 -> m (MutArray Word8, Maybe (MutArray Word8))
forall (m :: * -> *).
MonadIO m =>
Word8
-> MutArray Word8 -> m (MutArray Word8, Maybe (MutArray Word8))
breakOn Word8
byte MutArray Word8
buf
        Step (SplitState s (MutArray Word8)) (MutArray Word8)
-> m (Step (SplitState s (MutArray Word8)) (MutArray Word8))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Step (SplitState s (MutArray Word8)) (MutArray Word8)
 -> m (Step (SplitState s (MutArray Word8)) (MutArray Word8)))
-> Step (SplitState s (MutArray Word8)) (MutArray Word8)
-> m (Step (SplitState s (MutArray Word8)) (MutArray Word8))
forall a b. (a -> b) -> a -> b
$ case Maybe (MutArray Word8)
marr2 of
                Maybe (MutArray Word8)
Nothing -> SplitState s (MutArray Word8)
-> Step (SplitState s (MutArray Word8)) (MutArray Word8)
forall s a. s -> Step s a
Stream.Skip (SplitState s (MutArray Word8)
 -> Step (SplitState s (MutArray Word8)) (MutArray Word8))
-> SplitState s (MutArray Word8)
-> Step (SplitState s (MutArray Word8)) (MutArray Word8)
forall a b. (a -> b) -> a -> b
$ s -> MutArray Word8 -> SplitState s (MutArray Word8)
forall s arr. s -> arr -> SplitState s arr
Buffering s
st MutArray Word8
arr1
                Just MutArray Word8
arr2 -> SplitState s (MutArray Word8)
-> Step (SplitState s (MutArray Word8)) (MutArray Word8)
forall s a. s -> Step s a
Stream.Skip (SplitState s (MutArray Word8)
 -> Step (SplitState s (MutArray Word8)) (MutArray Word8))
-> SplitState s (MutArray Word8)
-> Step (SplitState s (MutArray Word8)) (MutArray Word8)
forall a b. (a -> b) -> a -> b
$ MutArray Word8
-> SplitState s (MutArray Word8) -> SplitState s (MutArray Word8)
forall s arr. arr -> SplitState s arr -> SplitState s arr
Yielding MutArray Word8
arr1 (s -> MutArray Word8 -> SplitState s (MutArray Word8)
forall s arr. s -> arr -> SplitState s arr
Splitting s
st MutArray Word8
arr2)

    step' State StreamK m (MutArray Word8)
_ (Yielding MutArray Word8
arr SplitState s (MutArray Word8)
next) = Step (SplitState s (MutArray Word8)) (MutArray Word8)
-> m (Step (SplitState s (MutArray Word8)) (MutArray Word8))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Step (SplitState s (MutArray Word8)) (MutArray Word8)
 -> m (Step (SplitState s (MutArray Word8)) (MutArray Word8)))
-> Step (SplitState s (MutArray Word8)) (MutArray Word8)
-> m (Step (SplitState s (MutArray Word8)) (MutArray Word8))
forall a b. (a -> b) -> a -> b
$ MutArray Word8
-> SplitState s (MutArray Word8)
-> Step (SplitState s (MutArray Word8)) (MutArray Word8)
forall s a. a -> s -> Step s a
Stream.Yield MutArray Word8
arr SplitState s (MutArray Word8)
next
    step' State StreamK m (MutArray Word8)
_ SplitState s (MutArray Word8)
Finishing = Step (SplitState s (MutArray Word8)) (MutArray Word8)
-> m (Step (SplitState s (MutArray Word8)) (MutArray Word8))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Step (SplitState s (MutArray Word8)) (MutArray Word8)
forall s a. Step s a
Stream.Stop

-- XXX implement predicate based version of this
-- XXX Naming of predicate based vs custom version

-- | Split a stream of arrays on a given separator byte, dropping the separator
-- and coalescing all the arrays between two separators into a single array.
--
{-# INLINE compactOnByte #-}
compactOnByte
    :: (MonadIO m)
    => Word8
    -> Stream m (MutArray Word8)
    -> Stream m (MutArray Word8)
-- XXX compare perf of custom vs idiomatic version
-- compactOnByte = _compactOnByteCustom
-- XXX use spliceExp and rightSize?
compactOnByte :: forall (m :: * -> *).
MonadIO m =>
Word8 -> Stream m (MutArray Word8) -> Stream m (MutArray Word8)
compactOnByte Word8
byte = (MutArray Word8 -> m (MutArray Word8, Maybe (MutArray Word8)))
-> (MutArray Word8 -> MutArray Word8 -> m (MutArray Word8))
-> Stream m (MutArray Word8)
-> Stream m (MutArray Word8)
forall (m :: * -> *) (f :: * -> *) a.
Monad m =>
(f a -> m (f a, Maybe (f a)))
-> (f a -> f a -> m (f a)) -> Stream m (f a) -> Stream m (f a)
Stream.splitInnerBy (Word8
-> MutArray Word8 -> m (MutArray Word8, Maybe (MutArray Word8))
forall (m :: * -> *).
MonadIO m =>
Word8
-> MutArray Word8 -> m (MutArray Word8, Maybe (MutArray Word8))
breakOn Word8
byte) MutArray Word8 -> MutArray Word8 -> m (MutArray Word8)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
MutArray a -> MutArray a -> m (MutArray a)
splice

-- | Like 'compactOnByte' considers the separator in suffix position instead of
-- infix position.
{-# INLINE compactOnByteSuffix #-}
compactOnByteSuffix
    :: (MonadIO m)
    => Word8
    -> Stream m (MutArray Word8)
    -> Stream m (MutArray Word8)
compactOnByteSuffix :: forall (m :: * -> *).
MonadIO m =>
Word8 -> Stream m (MutArray Word8) -> Stream m (MutArray Word8)
compactOnByteSuffix Word8
byte =
        -- XXX use spliceExp and rightSize?
        (MutArray Word8 -> Bool)
-> (MutArray Word8 -> m (MutArray Word8, Maybe (MutArray Word8)))
-> (MutArray Word8 -> MutArray Word8 -> m (MutArray Word8))
-> Stream m (MutArray Word8)
-> Stream m (MutArray Word8)
forall (m :: * -> *) (f :: * -> *) a.
Monad m =>
(f a -> Bool)
-> (f a -> m (f a, Maybe (f a)))
-> (f a -> f a -> m (f a))
-> Stream m (f a)
-> Stream m (f a)
Stream.splitInnerBySuffix
            (\MutArray Word8
arr -> MutArray Word8 -> Int
forall a. MutArray a -> Int
byteLength MutArray Word8
arr Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0) (Word8
-> MutArray Word8 -> m (MutArray Word8, Maybe (MutArray Word8))
forall (m :: * -> *).
MonadIO m =>
Word8
-> MutArray Word8 -> m (MutArray Word8, Maybe (MutArray Word8))
breakOn Word8
byte) MutArray Word8 -> MutArray Word8 -> m (MutArray Word8)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
MutArray a -> MutArray a -> m (MutArray a)
splice