{-# LANGUAGE CPP #-}
-- |
-- Module      : Streamly.Internal.Data.Array
-- Copyright   : (c) 2019 Composewell Technologies
-- License     : BSD3
-- Maintainer  : streamly@composewell.com
-- Stability   : experimental
-- Portability : GHC
--
module Streamly.Internal.Data.Array
    (
    -- * Setup
    -- $setup

    -- * Design Notes
    -- $design

    -- * The Array Type
      module Streamly.Internal.Data.Array.Type

    -- * Construction
    -- Monadic Folds
    , writeLastN

    -- * Random Access
    -- , (!!)
    , getIndex
    , getIndexRev
    , last           -- XXX getLastIndex?
    -- , getIndicesFrom    -- read from a given position to the end of file
    -- , getIndicesUpto    -- read from beginning up to the given position
    -- , getIndicesFromTo
    -- , getIndicesFromRev  -- read from a given position to the beginning of file
    -- , getIndicesUptoRev  -- read from end to the given position in file
    , indexReader
    , indexReaderFromThenTo

    -- * Size
    , null

    -- * Search
    , binarySearch
    , findIndicesOf
    -- getIndicesOf
    , indexFinder -- see splitOn
    -- , findIndexOf
    -- , find

    -- * Casting
    , cast
    , asBytes
    , castUnsafe
    , asCStringUnsafe

    -- * Subarrays
    , getSliceUnsafe
    -- , getSlice
    , sliceIndexerFromLen
    , slicerFromLen
    , splitOn

    -- * Streaming Operations
    , streamTransform

    -- * Folding
    , streamFold
    , fold

    -- * Stream of Arrays

    -- XXX these are probably not very useful to have in this module as we can
    -- express these idiomatically using streams.
    , interpose
    , interposeSuffix
    , intercalateSuffix

    , compactLE
    , pinnedCompactLE
    , compactOnByte
    , compactOnByteSuffix

    , foldBreakChunks
    , foldChunks
    , foldBreakChunksK
    , parseBreakChunksK

    -- * Serialization
    , encodeAs
    , serialize
    , pinnedSerialize
    , deserialize

    -- * Deprecated
    , genSlicesFromLen
    , getSlicesFromLen
    , getIndices
    )
where

#include "assert.hs"
#include "inline.hs"
#include "ArrayMacros.h"

import Control.Monad.IO.Class (MonadIO(..))
-- import Data.Bifunctor (first)
-- import Data.Either (fromRight)
import Data.Functor.Identity (Identity)
import Data.Proxy (Proxy(..))
import Data.Word (Word8)
import Foreign.C.String (CString)
import Foreign.Ptr (castPtr)
import Foreign.Storable (Storable)
import GHC.Types (SPEC(..))
import Streamly.Internal.Data.Unbox (Unbox(..))
import Prelude hiding (length, null, last, map, (!!), read, concat)

import Streamly.Internal.Data.MutByteArray.Type (PinnedState(..), MutByteArray)
import Streamly.Internal.Data.Serialize.Type (Serialize)
import Streamly.Internal.Data.Fold.Type (Fold(..))
import Streamly.Internal.Data.Parser (Parser(..), Initial(..), ParseError(..))
import Streamly.Internal.Data.Stream (Stream(..))
import Streamly.Internal.Data.StreamK (StreamK)
import Streamly.Internal.Data.SVar.Type (adaptState, defState)
import Streamly.Internal.Data.Tuple.Strict (Tuple'(..), Tuple3Fused'(..))
import Streamly.Internal.Data.Unfold.Type (Unfold(..))
import Streamly.Internal.System.IO (unsafeInlineIO)

import qualified Streamly.Internal.Data.Fold.Type as Fold
import qualified Streamly.Internal.Data.Serialize.Type as Serialize
import qualified Streamly.Internal.Data.MutByteArray.Type as MBA
import qualified Streamly.Internal.Data.MutArray as MA
import qualified Streamly.Internal.Data.Fold as FL
import qualified Streamly.Internal.Data.Ring as RB
import qualified Streamly.Internal.Data.Parser as Parser
-- import qualified Streamly.Internal.Data.ParserK as ParserK
import qualified Streamly.Internal.Data.Stream as D
import qualified Streamly.Internal.Data.Stream as Stream
import qualified Streamly.Internal.Data.StreamK as StreamK
import qualified Streamly.Internal.Data.Unfold as Unfold
import qualified Prelude

import Streamly.Internal.Data.Array.Type

#include "DocTestDataArray.hs"

-- $design
--
-- To summarize:
--
--  * Arrays are finite and fixed in size
--  * provide /O(1)/ access to elements
--  * store only data and not functions
--  * provide efficient IO interfacing
--
-- 'Foldable' instance is not provided because the implementation would be much
-- less efficient compared to folding via streams.  'Semigroup' and 'Monoid'
-- instances should be used with care; concatenating arrays using binary
-- operations can be highly inefficient.  Instead, use
-- 'Streamly.Internal.Data.Stream.Chunked.toArray' to concatenate N
-- arrays at once.
--
-- Each array is one pointer visible to the GC.  Too many small arrays (e.g.
-- single byte) are only as good as holding those elements in a Haskell list.
-- However, small arrays can be compacted into large ones to reduce the
-- overhead. To hold 32GB memory in 32k sized buffers we need 1 million arrays
-- if we use one array for each chunk. This is still significant to add
-- pressure to GC.

-------------------------------------------------------------------------------
-- Elimination
-------------------------------------------------------------------------------

-- |
--
-- >>> null arr = Array.byteLength arr == 0
--
-- /Pre-release/
{-# INLINE null #-}
null :: Array a -> Bool
null :: forall a. Array a -> Bool
null Array a
arr = Array a -> Int
forall a. Array a -> Int
byteLength Array a
arr Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0

-- | Like 'getIndex' but indexes the array in reverse from the end.
--
-- /Pre-release/
{-# INLINE getIndexRev #-}
getIndexRev :: forall a. Unbox a => Int -> Array a -> Maybe a
getIndexRev :: forall a. Unbox a => Int -> Array a -> Maybe a
getIndexRev Int
i Array a
arr =
    IO (Maybe a) -> Maybe a
forall a. IO a -> a
unsafeInlineIO
        (IO (Maybe a) -> Maybe a) -> IO (Maybe a) -> Maybe a
forall a b. (a -> b) -> a -> b
$ do
                let elemPtr :: Int
elemPtr = RINDEX_OF(arrEnd arr, i, a)
                if Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
elemPtr Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Array a -> Int
forall a. Array a -> Int
arrStart Array a
arr
                then a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> IO a -> IO (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> MutByteArray -> IO a
forall a. Unbox a => Int -> MutByteArray -> IO a
peekAt Int
elemPtr (Array a -> MutByteArray
forall a. Array a -> MutByteArray
arrContents Array a
arr)
                else Maybe a -> IO (Maybe a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
forall a. Maybe a
Nothing

-- |
--
-- >>> last arr = Array.getIndexRev arr 0
--
-- /Pre-release/
{-# INLINE last #-}
last :: Unbox a => Array a -> Maybe a
last :: forall a. Unbox a => Array a -> Maybe a
last = Int -> Array a -> Maybe a
forall a. Unbox a => Int -> Array a -> Maybe a
getIndexRev Int
0

-------------------------------------------------------------------------------
-- Folds with Array as the container
-------------------------------------------------------------------------------

-- XXX We should generate this from Ring.

-- | @writeLastN n@ folds a maximum of @n@ elements from the end of the input
-- stream to an 'Array'.
--
{-# INLINE writeLastN #-}
writeLastN ::
       (Storable a, Unbox a, MonadIO m) => Int -> Fold m a (Array a)
writeLastN :: forall a (m :: * -> *).
(Storable a, Unbox a, MonadIO m) =>
Int -> Fold m a (Array a)
writeLastN Int
n
    | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 = (() -> Array a) -> Fold m a () -> Fold m a (Array a)
forall a b. (a -> b) -> Fold m a a -> Fold m a b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Array a -> () -> Array a
forall a b. a -> b -> a
const Array a
forall a. Monoid a => a
mempty) Fold m a ()
forall (m :: * -> *) a. Monad m => Fold m a ()
FL.drain
    | Bool
otherwise = MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze (MutArray a -> Array a)
-> Fold m a (MutArray a) -> Fold m a (Array a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Tuple3Fused' (Ring a) (Ptr a) Int
 -> a -> m (Step (Tuple3Fused' (Ring a) (Ptr a) Int) (MutArray a)))
-> m (Step (Tuple3Fused' (Ring a) (Ptr a) Int) (MutArray a))
-> (Tuple3Fused' (Ring a) (Ptr a) Int -> m (MutArray a))
-> (Tuple3Fused' (Ring a) (Ptr a) Int -> m (MutArray a))
-> Fold m a (MutArray a)
forall (m :: * -> *) a b s.
(s -> a -> m (Step s b))
-> m (Step s b) -> (s -> m b) -> (s -> m b) -> Fold m a b
Fold Tuple3Fused' (Ring a) (Ptr a) Int
-> a -> m (Step (Tuple3Fused' (Ring a) (Ptr a) Int) (MutArray a))
forall {m :: * -> *} {a} {c} {b}.
(MonadIO m, Storable a, Num c) =>
Tuple3Fused' (Ring a) (Ptr a) c
-> a -> m (Step (Tuple3Fused' (Ring a) (Ptr a) c) b)
step m (Step (Tuple3Fused' (Ring a) (Ptr a) Int) (MutArray a))
forall {b}. m (Step (Tuple3Fused' (Ring a) (Ptr a) Int) b)
initial Tuple3Fused' (Ring a) (Ptr a) Int -> m (MutArray a)
forall {m :: * -> *} {a}.
(MonadIO m, Unbox a, Storable a) =>
Tuple3Fused' (Ring a) (Ptr a) Int -> m (MutArray a)
done Tuple3Fused' (Ring a) (Ptr a) Int -> m (MutArray a)
forall {m :: * -> *} {a}.
(MonadIO m, Unbox a, Storable a) =>
Tuple3Fused' (Ring a) (Ptr a) Int -> m (MutArray a)
done

    where

    step :: Tuple3Fused' (Ring a) (Ptr a) c
-> a -> m (Step (Tuple3Fused' (Ring a) (Ptr a) c) b)
step (Tuple3Fused' Ring a
rb Ptr a
rh c
i) a
a = do
        Ptr a
rh1 <- IO (Ptr a) -> m (Ptr a)
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Ptr a) -> m (Ptr a)) -> IO (Ptr a) -> m (Ptr a)
forall a b. (a -> b) -> a -> b
$ Ring a -> Ptr a -> a -> IO (Ptr a)
forall a. Storable a => Ring a -> Ptr a -> a -> IO (Ptr a)
RB.unsafeInsert Ring a
rb Ptr a
rh a
a
        Step (Tuple3Fused' (Ring a) (Ptr a) c) b
-> m (Step (Tuple3Fused' (Ring a) (Ptr a) c) b)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Step (Tuple3Fused' (Ring a) (Ptr a) c) b
 -> m (Step (Tuple3Fused' (Ring a) (Ptr a) c) b))
-> Step (Tuple3Fused' (Ring a) (Ptr a) c) b
-> m (Step (Tuple3Fused' (Ring a) (Ptr a) c) b)
forall a b. (a -> b) -> a -> b
$ Tuple3Fused' (Ring a) (Ptr a) c
-> Step (Tuple3Fused' (Ring a) (Ptr a) c) b
forall s b. s -> Step s b
FL.Partial (Tuple3Fused' (Ring a) (Ptr a) c
 -> Step (Tuple3Fused' (Ring a) (Ptr a) c) b)
-> Tuple3Fused' (Ring a) (Ptr a) c
-> Step (Tuple3Fused' (Ring a) (Ptr a) c) b
forall a b. (a -> b) -> a -> b
$ Ring a -> Ptr a -> c -> Tuple3Fused' (Ring a) (Ptr a) c
forall a b c. a -> b -> c -> Tuple3Fused' a b c
Tuple3Fused' Ring a
rb Ptr a
rh1 (c
i c -> c -> c
forall a. Num a => a -> a -> a
+ c
1)

    initial :: m (Step (Tuple3Fused' (Ring a) (Ptr a) Int) b)
initial =
        let f :: (a, b) -> Step (Tuple3Fused' a b Int) b
f (a
a, b
b) = Tuple3Fused' a b Int -> Step (Tuple3Fused' a b Int) b
forall s b. s -> Step s b
FL.Partial (Tuple3Fused' a b Int -> Step (Tuple3Fused' a b Int) b)
-> Tuple3Fused' a b Int -> Step (Tuple3Fused' a b Int) b
forall a b. (a -> b) -> a -> b
$ a -> b -> Int -> Tuple3Fused' a b Int
forall a b c. a -> b -> c -> Tuple3Fused' a b c
Tuple3Fused' a
a b
b (Int
0 :: Int)
         in ((Ring a, Ptr a) -> Step (Tuple3Fused' (Ring a) (Ptr a) Int) b)
-> m (Ring a, Ptr a)
-> m (Step (Tuple3Fused' (Ring a) (Ptr a) Int) b)
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Ring a, Ptr a) -> Step (Tuple3Fused' (Ring a) (Ptr a) Int) b
forall {a} {b} {b}. (a, b) -> Step (Tuple3Fused' a b Int) b
f (m (Ring a, Ptr a)
 -> m (Step (Tuple3Fused' (Ring a) (Ptr a) Int) b))
-> m (Ring a, Ptr a)
-> m (Step (Tuple3Fused' (Ring a) (Ptr a) Int) b)
forall a b. (a -> b) -> a -> b
$ IO (Ring a, Ptr a) -> m (Ring a, Ptr a)
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Ring a, Ptr a) -> m (Ring a, Ptr a))
-> IO (Ring a, Ptr a) -> m (Ring a, Ptr a)
forall a b. (a -> b) -> a -> b
$ Int -> IO (Ring a, Ptr a)
forall a. Storable a => Int -> IO (Ring a, Ptr a)
RB.new Int
n

    done :: Tuple3Fused' (Ring a) (Ptr a) Int -> m (MutArray a)
done (Tuple3Fused' Ring a
rb Ptr a
rh Int
i) = do
        MutArray a
arr <- Int -> m (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> m (MutArray a)
MA.new Int
n
        -- XXX We should write a read unfold for ring.
        Int
-> Ptr a
-> (MutArray a -> a -> m (MutArray a))
-> MutArray a
-> Ring a
-> m (MutArray a)
forall {m :: * -> *} {a} {b}.
(MonadIO m, Storable a) =>
Int -> Ptr a -> (b -> a -> m b) -> b -> Ring a -> m b
foldFunc Int
i Ptr a
rh MutArray a -> a -> m (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
MutArray a -> a -> m (MutArray a)
MA.snocUnsafe MutArray a
arr Ring a
rb

    foldFunc :: Int -> Ptr a -> (b -> a -> m b) -> b -> Ring a -> m b
foldFunc Int
i
        | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
n = Ptr a -> (b -> a -> m b) -> b -> Ring a -> m b
forall (m :: * -> *) a b.
(MonadIO m, Storable a) =>
Ptr a -> (b -> a -> m b) -> b -> Ring a -> m b
RB.unsafeFoldRingM
        | Bool
otherwise = Ptr a -> (b -> a -> m b) -> b -> Ring a -> m b
forall (m :: * -> *) a b.
(MonadIO m, Storable a) =>
Ptr a -> (b -> a -> m b) -> b -> Ring a -> m b
RB.unsafeFoldRingFullM

-------------------------------------------------------------------------------
-- Random Access
-------------------------------------------------------------------------------

-------------------------------------------------------------------------------
-- Searching
-------------------------------------------------------------------------------

-- | Given a sorted array, perform a binary search to find the given element.
-- Returns the index of the element if found.
--
-- /Unimplemented/
{-# INLINE binarySearch #-}
binarySearch :: a -> Array a -> Maybe Int
binarySearch :: forall a. a -> Array a -> Maybe Int
binarySearch = a -> Array a -> Maybe Int
forall a. HasCallStack => a
undefined

-- find/findIndex etc can potentially be implemented more efficiently on arrays
-- compared to streams by using SIMD instructions.
-- We can also return a bit array instead.

-- Can use SIMD.

-- | Perform a linear search to find all the indices where a given element is
-- present in an array.
--
-- /Unimplemented/
indexFinder :: (a -> Bool) -> Unfold Identity (Array a) Int
indexFinder :: forall a. (a -> Bool) -> Unfold Identity (Array a) Int
indexFinder = (a -> Bool) -> Unfold Identity (Array a) Int
forall a. HasCallStack => a
undefined

-- |
-- /Unimplemented/
findIndicesOf :: (a -> Bool) -> Array a -> Stream Identity Int
findIndicesOf :: forall a. (a -> Bool) -> Array a -> Stream Identity Int
findIndicesOf a -> Bool
p = Unfold Identity (Array a) Int -> Array a -> Stream Identity Int
forall (m :: * -> *) a b.
Applicative m =>
Unfold m a b -> a -> Stream m b
Stream.unfold ((a -> Bool) -> Unfold Identity (Array a) Int
forall a. (a -> Bool) -> Unfold Identity (Array a) Int
indexFinder a -> Bool
p)

{-
findIndexOf :: (a -> Bool) -> Array a -> Maybe Int
findIndexOf p = Unfold.fold Fold.one . Stream.unfold (indexFinder p)

find :: (a -> Bool) -> Array a -> Bool
find = Unfold.fold Fold.null . Stream.unfold (indexFinder p)
-}

-------------------------------------------------------------------------------
-- Folds
-------------------------------------------------------------------------------

-- XXX We can potentially use SIMD instructions on arrays to fold faster.

-------------------------------------------------------------------------------
-- Slice
-------------------------------------------------------------------------------

-- | /O(1)/ Slice an array in constant time.
--
-- Caution: The bounds of the slice are not checked.
--
-- /Unsafe/
--
-- /Pre-release/
{-# INLINE getSliceUnsafe #-}
getSliceUnsafe ::
       forall a. Unbox a
    => Int -- ^ starting index
    -> Int -- ^ length of the slice
    -> Array a
    -> Array a
getSliceUnsafe :: forall a. Unbox a => Int -> Int -> Array a -> Array a
getSliceUnsafe Int
index Int
len (Array MutByteArray
contents Int
start Int
e) =
    let size :: Int
size = SIZE_OF(a)
        start1 :: Int
start1 = Int
start Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Int
index Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
size)
        end1 :: Int
end1 = Int
start1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Int
len Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
size)
     in Bool -> Array a -> Array a
forall a. HasCallStack => Bool -> a -> a
assert (Int
end1 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
e) (MutByteArray -> Int -> Int -> Array a
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
contents Int
start1 Int
end1)

-- | Split the array into a stream of slices using a predicate. The element
-- matching the predicate is dropped.
--
-- /Pre-release/
{-# INLINE splitOn #-}
splitOn :: (Monad m, Unbox a) =>
    (a -> Bool) -> Array a -> Stream m (Array a)
splitOn :: forall (m :: * -> *) a.
(Monad m, Unbox a) =>
(a -> Bool) -> Array a -> Stream m (Array a)
splitOn a -> Bool
predicate Array a
arr =
    ((Int, Int) -> Array a)
-> Stream m (Int, Int) -> Stream m (Array a)
forall a b. (a -> b) -> Stream m a -> Stream m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(Int
i, Int
len) -> Int -> Int -> Array a -> Array a
forall a. Unbox a => Int -> Int -> Array a -> Array a
getSliceUnsafe Int
i Int
len Array a
arr)
        (Stream m (Int, Int) -> Stream m (Array a))
-> Stream m (Int, Int) -> Stream m (Array a)
forall a b. (a -> b) -> a -> b
$ (a -> Bool) -> Stream m a -> Stream m (Int, Int)
forall (m :: * -> *) a.
Monad m =>
(a -> Bool) -> Stream m a -> Stream m (Int, Int)
D.indexOnSuffix a -> Bool
predicate (Array a -> Stream m a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
read Array a
arr)

{-# INLINE sliceIndexerFromLen #-}
sliceIndexerFromLen :: forall m a. (Monad m, Unbox a)
    => Int -- ^ from index
    -> Int -- ^ length of the slice
    -> Unfold m (Array a) (Int, Int)
sliceIndexerFromLen :: forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Int -> Int -> Unfold m (Array a) (Int, Int)
sliceIndexerFromLen Int
from Int
len =
    (Array a -> MutArray a)
-> Unfold m (MutArray a) (Int, Int)
-> Unfold m (Array a) (Int, Int)
forall a c (m :: * -> *) b.
(a -> c) -> Unfold m c b -> Unfold m a b
Unfold.lmap Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw (Int -> Int -> Unfold m (MutArray a) (Int, Int)
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Int -> Int -> Unfold m (MutArray a) (Int, Int)
MA.sliceIndexerFromLen Int
from Int
len)

{-# DEPRECATED genSlicesFromLen "Please use sliceIndexerFromLen instead." #-}
{-# INLINE genSlicesFromLen #-}
genSlicesFromLen :: forall m a. (Monad m, Unbox a)
    => Int -- ^ from index
    -> Int -- ^ length of the slice
    -> Unfold m (Array a) (Int, Int)
genSlicesFromLen :: forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Int -> Int -> Unfold m (Array a) (Int, Int)
genSlicesFromLen = Int -> Int -> Unfold m (Array a) (Int, Int)
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Int -> Int -> Unfold m (Array 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.
--
-- /Pre-release//
{-# INLINE slicerFromLen #-}
slicerFromLen :: forall m a. (Monad m, Unbox a)
    => Int -- ^ from index
    -> Int -- ^ length of the slice
    -> Unfold m (Array a) (Array a)
slicerFromLen :: forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Int -> Int -> Unfold m (Array a) (Array a)
slicerFromLen Int
from Int
len =
    (MutArray a -> Array a)
-> Unfold m (Array a) (MutArray a) -> Unfold m (Array a) (Array a)
forall a b.
(a -> b) -> Unfold m (Array a) a -> Unfold m (Array a) b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze
        (Unfold m (Array a) (MutArray a) -> Unfold m (Array a) (Array a))
-> Unfold m (Array a) (MutArray a) -> Unfold m (Array a) (Array a)
forall a b. (a -> b) -> a -> b
$ (Array a -> MutArray a)
-> Unfold m (MutArray a) (MutArray a)
-> Unfold m (Array a) (MutArray a)
forall a c (m :: * -> *) b.
(a -> c) -> Unfold m c b -> Unfold m a b
Unfold.lmap Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw (Int -> Int -> Unfold m (MutArray a) (MutArray a)
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Int -> Int -> Unfold m (MutArray a) (MutArray a)
MA.slicerFromLen Int
from Int
len)

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

-------------------------------------------------------------------------------
-- Random reads and writes
-------------------------------------------------------------------------------

-- XXX Change this to a partial function instead of a Maybe type? And use
-- MA.getIndex instead.
--
-- | /O(1)/ Lookup the element at the given index. Index starts from 0.
--
{-# INLINE getIndex #-}
getIndex :: forall a. Unbox a => Int -> Array a -> Maybe a
getIndex :: forall a. Unbox a => Int -> Array a -> Maybe a
getIndex Int
i Array a
arr =
    IO (Maybe a) -> Maybe a
forall a. IO a -> a
unsafeInlineIO
        (IO (Maybe a) -> Maybe a) -> IO (Maybe a) -> Maybe a
forall a b. (a -> b) -> a -> b
$ do
                let elemPtr :: Int
elemPtr = Array a -> Int
forall a. Array a -> Int
INDEX_OF(arrStart arr, i, a)
                if Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& INDEX_VALID(elemPtr, arrEnd arr, a)
                then a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> IO a -> IO (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> MutByteArray -> IO a
forall a. Unbox a => Int -> MutByteArray -> IO a
peekAt Int
elemPtr (Array a -> MutByteArray
forall a. Array a -> MutByteArray
arrContents Array a
arr)
                else Maybe a -> IO (Maybe a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
forall a. Maybe a
Nothing

-- | Given a stream of array indices, read the elements on those indices from
-- the supplied Array. An exception is thrown if an index is out of bounds.
--
-- This is the most general operation. We can implement other operations in
-- terms of this:
--
-- @
-- read =
--      let u = lmap (\arr -> (0, length arr - 1)) Unfold.enumerateFromTo
--       in Unfold.lmap f (indexReader arr)
--
-- readRev =
--      let i = length arr - 1
--       in Unfold.lmap f (indexReaderFromThenTo i (i - 1) 0)
-- @
--
-- /Pre-release/
{-# INLINE indexReader #-}
indexReader :: (Monad m, Unbox a) => Stream m Int -> Unfold m (Array a) a
indexReader :: forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Stream m Int -> Unfold m (Array a) a
indexReader Stream m Int
m =
    let unf :: Unfold m (MutArray a) a
unf = (forall b. IO b -> m b) -> Stream m Int -> Unfold m (MutArray a) a
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
(forall b. IO b -> m b) -> Stream m Int -> Unfold m (MutArray a) a
MA.indexReaderWith (b -> m b
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b -> m b) -> (IO b -> b) -> IO b -> m b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO b -> b
forall a. IO a -> a
unsafeInlineIO) Stream m Int
m
     in (Array a -> MutArray a)
-> Unfold m (MutArray a) a -> Unfold m (Array a) a
forall a c (m :: * -> *) b.
(a -> c) -> Unfold m c b -> Unfold m a b
Unfold.lmap Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Unfold m (MutArray a) a
unf

-- XXX DO NOT REMOVE, change the signature to use Stream instead of unfold
{-# DEPRECATED getIndices "Please use getIndices instead." #-}
{-# INLINE getIndices #-}
getIndices :: (Monad m, Unbox a) => Stream m Int -> Unfold m (Array a) a
getIndices :: forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Stream m Int -> Unfold m (Array a) a
getIndices = Stream m Int -> Unfold m (Array a) a
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Stream m Int -> Unfold m (Array a) a
indexReader

-- | Unfolds @(from, then, to, array)@ generating a finite stream whose first
-- element is the array value from the index @from@ and the successive elements
-- are from the indices in increments of @then@ up to @to@. Index enumeration
-- can occur downwards or upwards depending on whether @then@ comes before or
-- after @from@.
--
-- @
-- getIndicesFromThenTo =
--     let f (from, next, to, arr) =
--             (Stream.enumerateFromThenTo from next to, arr)
--      in Unfold.lmap f getIndices
-- @
--
-- /Unimplemented/
{-# INLINE indexReaderFromThenTo #-}
indexReaderFromThenTo :: Unfold m (Int, Int, Int, Array a) a
indexReaderFromThenTo :: forall (m :: * -> *) a. Unfold m (Int, Int, Int, Array a) a
indexReaderFromThenTo = Unfold m (Int, Int, Int, Array a) a
forall a. HasCallStack => a
undefined

-------------------------------------------------------------------------------
-- Transform via stream operations
-------------------------------------------------------------------------------

-- for non-length changing operations we can use the original length for
-- allocation. If we can predict the length then we can use the prediction for
-- new allocation. Otherwise we can use a hint and adjust dynamically.

{-
-- | Transform an array into another array using a pipe transformation
-- operation.
--
{-# INLINE runPipe #-}
runPipe :: (MonadIO m, Unbox a, Unbox b)
    => Pipe m a b -> Array a -> m (Array b)
runPipe f arr = P.runPipe (toArrayMinChunk (length arr)) $ f (read arr)
-}

-- XXX For transformations that cannot change the number of elements e.g. "map"
-- we can use a predetermined array length.
--
-- | Transform an array into another array using a stream transformation
-- operation.
--
-- /Pre-release/
{-# INLINE streamTransform #-}
streamTransform :: forall m a b. (MonadIO m, Unbox a, Unbox b)
    => (Stream m a -> Stream m b) -> Array a -> m (Array b)
streamTransform :: forall (m :: * -> *) a b.
(MonadIO m, Unbox a, Unbox b) =>
(Stream m a -> Stream m b) -> Array a -> m (Array b)
streamTransform Stream m a -> Stream m b
f Array a
arr =
    Fold m b (Array b) -> Stream m b -> m (Array b)
forall (m :: * -> *) a b.
Monad m =>
Fold m a b -> Stream m a -> m b
Stream.fold (Int -> Fold m b (Array b)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m a (Array a)
createWith (Array a -> Int
forall a. Unbox a => Array a -> Int
length Array a
arr)) (Stream m b -> m (Array b)) -> Stream m b -> m (Array b)
forall a b. (a -> b) -> a -> b
$ Stream m a -> Stream m b
f (Array a -> Stream m a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
read Array a
arr)

-------------------------------------------------------------------------------
-- Casts
-------------------------------------------------------------------------------

-- | Cast an array having elements of type @a@ into an array having elements of
-- type @b@. The array size must be a multiple of the size of type @b@
-- otherwise accessing the last element of the array may result into a crash or
-- a random value.
--
-- /Pre-release/
--
castUnsafe ::
#ifdef DEVBUILD
    Unbox b =>
#endif
    Array a -> Array b
castUnsafe :: forall a b. Array a -> Array b
castUnsafe (Array MutByteArray
contents Int
start Int
end) =
    MutByteArray -> Int -> Int -> Array b
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
contents Int
start Int
end

-- | Cast an @Array a@ into an @Array Word8@.
--
--
asBytes :: Array a -> Array Word8
asBytes :: forall a. Array a -> Array Word8
asBytes = Array a -> Array Word8
forall a b. Array a -> Array b
castUnsafe

-- | Cast an array having elements of type @a@ into an array having elements of
-- type @b@. The length of the array should be a multiple of the size of the
-- target element otherwise 'Nothing' is returned.
--
--
cast :: forall a b. (Unbox b) => Array a -> Maybe (Array b)
cast :: forall a b. Unbox b => Array a -> Maybe (Array b)
cast Array a
arr =
    let len :: Int
len = Array a -> Int
forall a. Array a -> Int
byteLength Array a
arr
        r :: Int
r = Int
len Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` SIZE_OF(b)
     in if Int
r Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0
        then Maybe (Array b)
forall a. Maybe a
Nothing
        else Array b -> Maybe (Array b)
forall a. a -> Maybe a
Just (Array b -> Maybe (Array b)) -> Array b -> Maybe (Array b)
forall a b. (a -> b) -> a -> b
$ Array a -> Array b
forall a b. Array a -> Array b
castUnsafe Array a
arr

-- | Convert an array of any type into a null terminated CString Ptr.  If the
-- array is unpinned it is first converted to a pinned array which requires a
-- copy.
--
-- /Unsafe/
--
-- /O(n) Time: (creates a copy of the array)/
--
-- /Pre-release/
--
asCStringUnsafe :: Array a -> (CString -> IO b) -> IO b
asCStringUnsafe :: forall a b. Array a -> (CString -> IO b) -> IO b
asCStringUnsafe Array a
arr CString -> IO b
act = do
    let arr1 :: Array Word8
arr1 = Array a -> Array Word8
forall a. Array a -> Array Word8
asBytes Array a
arr Array Word8 -> Array Word8 -> Array Word8
forall a. Semigroup a => a -> a -> a
<> [Word8] -> Array Word8
forall a. Unbox a => [a] -> Array a
fromList [Word8
0]
    -- unsafePinnedAsPtr makes sure the array is pinned
    Array Word8 -> (Ptr Word8 -> IO b) -> IO b
forall (m :: * -> *) a b.
MonadIO m =>
Array a -> (Ptr a -> m b) -> m b
unsafePinnedAsPtr Array Word8
arr1 ((Ptr Word8 -> IO b) -> IO b) -> (Ptr Word8 -> IO b) -> IO b
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
ptr -> CString -> IO b
act (Ptr Word8 -> CString
forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
ptr)

-------------------------------------------------------------------------------
-- Folds
-------------------------------------------------------------------------------

-- XXX We can directly use toStreamD and D.fold here.

-- | Fold an array using a 'Fold'.
--
-- /Pre-release/
{-# INLINE fold #-}
fold :: forall m a b. (Monad m, Unbox a) => Fold m a b -> Array a -> m b
fold :: forall (m :: * -> *) a b.
(Monad m, Unbox a) =>
Fold m a b -> Array a -> m b
fold Fold m a b
f Array a
arr = Fold m a b -> Stream m a -> m b
forall (m :: * -> *) a b.
Monad m =>
Fold m a b -> Stream m a -> m b
Stream.fold Fold m a b
f (Array a -> Stream m a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
read Array a
arr)

-- | Fold an array using a stream fold operation.
--
-- /Pre-release/
{-# INLINE streamFold #-}
streamFold :: (Monad m, Unbox a) => (Stream m a -> m b) -> Array a -> m b
streamFold :: forall (m :: * -> *) a b.
(Monad m, Unbox a) =>
(Stream m a -> m b) -> Array a -> m b
streamFold Stream m a -> m b
f Array a
arr = Stream m a -> m b
f (Array a -> Stream m a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
read Array a
arr)

--------------------------------------------------------------------------------
-- Serialization
--------------------------------------------------------------------------------

{-# INLINE encodeAs #-}
encodeAs :: forall a. Serialize a => PinnedState -> a -> Array Word8
encodeAs :: forall a. Serialize a => PinnedState -> a -> Array Word8
encodeAs PinnedState
ps a
a =
    IO (Array Word8) -> Array Word8
forall a. IO a -> a
unsafeInlineIO (IO (Array Word8) -> Array Word8)
-> IO (Array Word8) -> Array Word8
forall a b. (a -> b) -> a -> b
$ do
        let len :: Int
len = Int -> a -> Int
forall a. Serialize a => Int -> a -> Int
Serialize.addSizeTo Int
0 a
a
        MutByteArray
mbarr <- PinnedState -> Int -> IO MutByteArray
MBA.newBytesAs PinnedState
ps Int
len
        Int
off <- Int -> MutByteArray -> a -> IO Int
forall a. Serialize a => Int -> MutByteArray -> a -> IO Int
Serialize.serializeAt Int
0 MutByteArray
mbarr a
a
        assertM(Int
len Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
off)
        Array Word8 -> IO (Array Word8)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Array Word8 -> IO (Array Word8))
-> Array Word8 -> IO (Array Word8)
forall a b. (a -> b) -> a -> b
$ MutByteArray -> Int -> Int -> Array Word8
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
mbarr Int
0 Int
off

-- |
-- Properties:
-- 1. Identity: @deserialize . serialize == id@
-- 2. Encoded equivalence: @serialize a == serialize a@
{-# INLINE serialize #-}
serialize :: Serialize a => a -> Array Word8
serialize :: forall a. Serialize a => a -> Array Word8
serialize = PinnedState -> a -> Array Word8
forall a. Serialize a => PinnedState -> a -> Array Word8
encodeAs PinnedState
Unpinned

-- | Serialize a Haskell type to a pinned byte array. The array is allocated
-- using pinned memory so that it can be used directly in OS APIs for writing
-- to file or sending over the network.
--
-- Properties:
-- 1. Identity: @deserialize . pinnedSerialize == id@
-- 2. Encoded equivalence: @pinnedSerialize a == pinnedSerialize a@
{-# INLINE pinnedSerialize #-}
pinnedSerialize :: Serialize a => a -> Array Word8
pinnedSerialize :: forall a. Serialize a => a -> Array Word8
pinnedSerialize = PinnedState -> a -> Array Word8
forall a. Serialize a => PinnedState -> a -> Array Word8
encodeAs PinnedState
Pinned

-- | Decode a Haskell type from a byte array containing its serialized
-- representation.
{-# INLINE deserialize #-}
deserialize :: Serialize a => Array Word8 -> a
deserialize :: forall a. Serialize a => Array Word8 -> a
deserialize arr :: Array Word8
arr@(Array {Int
MutByteArray
arrEnd :: forall a. Array a -> Int
arrStart :: forall a. Array a -> Int
arrContents :: forall a. Array a -> MutByteArray
arrContents :: MutByteArray
arrStart :: Int
arrEnd :: Int
..}) = IO a -> a
forall a. IO a -> a
unsafeInlineIO (IO a -> a) -> IO a -> a
forall a b. (a -> b) -> a -> b
$ do
    let lenArr :: Int
lenArr = Array Word8 -> Int
forall a. Unbox a => Array a -> Int
length Array Word8
arr
    (Int
off, a
val) <-
        Int -> MutByteArray -> Int -> IO (Int, a)
forall a. Serialize a => Int -> MutByteArray -> Int -> IO (Int, a)
Serialize.deserializeAt Int
arrStart MutByteArray
arrContents (Int
arrStart Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
lenArr)
    assertM(Int
off Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
arrStart Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
lenArr)
    a -> IO a
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
val

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

-- TODO: efficiently compare two streams of arrays. Two streams can have chunks
-- of different sizes, we can handle that in the stream comparison abstraction.
-- This could be useful e.g. to fast compare whether two files differ.

-- | Insert the given element between arrays and flatten.
--
-- >>> interpose x = Stream.interpose x Array.reader
--
{-# INLINE interpose #-}
interpose :: (Monad m, Unbox a) => a -> Stream m (Array a) -> Stream m a
interpose :: forall (m :: * -> *) a.
(Monad m, Unbox a) =>
a -> Stream m (Array a) -> Stream m a
interpose a
x = a -> Unfold m (Array a) a -> Stream m (Array a) -> Stream m a
forall (m :: * -> *) c b.
Monad m =>
c -> Unfold m b c -> Stream m b -> Stream m c
D.interpose a
x Unfold m (Array a) a
forall (m :: * -> *) a. (Monad m, Unbox a) => Unfold m (Array a) a
reader

data FlattenState s =
      OuterLoop s
    | InnerLoop s !MutByteArray !Int !Int

-- | Insert the given element after each array and flatten. This is similar to
-- unlines.
--
-- >>> interposeSuffix x = Stream.interposeSuffix x Array.reader
--
{-# INLINE_NORMAL interposeSuffix #-}
interposeSuffix :: forall m a. (Monad m, Unbox a)
    => a -> Stream m (Array a) -> Stream m a
-- This does not require MonadIO constraint.
-- interposeSuffix x = D.interposeSuffix x reader
interposeSuffix :: forall (m :: * -> *) a.
(Monad m, Unbox a) =>
a -> Stream m (Array a) -> Stream m a
interposeSuffix a
sep (D.Stream State StreamK m (Array a) -> s -> m (Step s (Array a))
step s
state) = (State StreamK m a
 -> FlattenState s -> m (Step (FlattenState s) a))
-> FlattenState s -> Stream m a
forall (m :: * -> *) a s.
(State StreamK m a -> s -> m (Step s a)) -> s -> Stream m a
D.Stream State StreamK m a -> FlattenState s -> m (Step (FlattenState s) a)
forall {m :: * -> *} {a}.
State StreamK m a -> FlattenState s -> m (Step (FlattenState s) a)
step' (s -> FlattenState s
forall s. s -> FlattenState s
OuterLoop s
state)

    where

    {-# INLINE_LATE step' #-}
    step' :: State StreamK m a -> FlattenState s -> m (Step (FlattenState s) a)
step' State StreamK m a
gst (OuterLoop s
st) = do
        Step s (Array a)
r <- State StreamK m (Array a) -> s -> m (Step s (Array a))
step (State StreamK m a -> State StreamK m (Array a)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a (n :: * -> *) b.
State t m a -> State t n b
adaptState State StreamK m a
gst) s
st
        Step (FlattenState s) a -> m (Step (FlattenState s) a)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Step (FlattenState s) a -> m (Step (FlattenState s) a))
-> Step (FlattenState s) a -> m (Step (FlattenState s) a)
forall a b. (a -> b) -> a -> b
$ case Step s (Array a)
r of
            D.Yield Array{Int
MutByteArray
arrEnd :: forall a. Array a -> Int
arrStart :: forall a. Array a -> Int
arrContents :: forall a. Array a -> MutByteArray
arrContents :: MutByteArray
arrStart :: Int
arrEnd :: Int
..} s
s ->
                FlattenState s -> Step (FlattenState s) a
forall s a. s -> Step s a
D.Skip (s -> MutByteArray -> Int -> Int -> FlattenState s
forall s. s -> MutByteArray -> Int -> Int -> FlattenState s
InnerLoop s
s MutByteArray
arrContents Int
arrStart Int
arrEnd)
            D.Skip s
s -> FlattenState s -> Step (FlattenState s) a
forall s a. s -> Step s a
D.Skip (s -> FlattenState s
forall s. s -> FlattenState s
OuterLoop s
s)
            Step s (Array a)
D.Stop -> Step (FlattenState s) a
forall s a. Step s a
D.Stop

    step' State StreamK m a
_ (InnerLoop s
st MutByteArray
_ Int
p Int
end) | Int
p Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
end =
        Step (FlattenState s) a -> m (Step (FlattenState s) a)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Step (FlattenState s) a -> m (Step (FlattenState s) a))
-> Step (FlattenState s) a -> m (Step (FlattenState s) a)
forall a b. (a -> b) -> a -> b
$ a -> FlattenState s -> Step (FlattenState s) a
forall s a. a -> s -> Step s a
D.Yield a
sep (FlattenState s -> Step (FlattenState s) a)
-> FlattenState s -> Step (FlattenState s) a
forall a b. (a -> b) -> a -> b
$ s -> FlattenState s
forall s. s -> FlattenState s
OuterLoop s
st

    step' State StreamK m a
_ (InnerLoop s
st MutByteArray
contents Int
p Int
end) = do
        a
x <- a -> m a
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a -> m a) -> a -> m a
forall a b. (a -> b) -> a -> b
$ IO a -> a
forall a. IO a -> a
unsafeInlineIO (IO a -> a) -> IO a -> a
forall a b. (a -> b) -> a -> b
$ Int -> MutByteArray -> IO a
forall a. Unbox a => Int -> MutByteArray -> IO a
peekAt Int
p MutByteArray
contents
        Step (FlattenState s) a -> m (Step (FlattenState s) a)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Step (FlattenState s) a -> m (Step (FlattenState s) a))
-> Step (FlattenState s) a -> m (Step (FlattenState s) a)
forall a b. (a -> b) -> a -> b
$ a -> FlattenState s -> Step (FlattenState s) a
forall s a. a -> s -> Step s a
D.Yield a
x (s -> MutByteArray -> Int -> Int -> FlattenState s
forall s. s -> MutByteArray -> Int -> Int -> FlattenState s
InnerLoop s
st MutByteArray
contents (INDEX_NEXT(p,a)) end)

-- | Insert the given array after each array and flatten.
--
-- >>> intercalateSuffix = Stream.intercalateSuffix Array.reader
--
{-# INLINE intercalateSuffix #-}
intercalateSuffix :: (Monad m, Unbox a)
    => Array a -> Stream m (Array a) -> Stream m a
intercalateSuffix :: forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Array a -> Stream m (Array a) -> Stream m a
intercalateSuffix = Unfold m (Array a) a -> Array a -> Stream m (Array a) -> Stream m a
forall (m :: * -> *) b c.
Monad m =>
Unfold m b c -> b -> Stream m b -> Stream m c
D.intercalateSuffix Unfold m (Array a) a
forall (m :: * -> *) a. (Monad m, Unbox a) => Unfold m (Array a) a
reader

-- | @compactLE n@ coalesces adjacent arrays in the input stream
-- only if the combined size would be less than or equal to n.
--
-- Generates unpinned arrays irrespective of the pinning status of input
-- arrays.
{-# INLINE_NORMAL compactLE #-}
compactLE :: (MonadIO m, Unbox a)
    => Int -> Stream m (Array a) -> Stream m (Array a)
compactLE :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Stream m (Array a) -> Stream m (Array a)
compactLE Int
n Stream m (Array a)
stream =
    (MutArray a -> Array a)
-> Stream m (MutArray a) -> Stream m (Array a)
forall (m :: * -> *) a b.
Monad m =>
(a -> b) -> Stream m a -> Stream m b
D.map MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze (Stream m (MutArray a) -> Stream m (Array a))
-> Stream m (MutArray a) -> Stream m (Array a)
forall a b. (a -> b) -> a -> b
$ Int -> Stream m (MutArray a) -> Stream m (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Stream m (MutArray a) -> Stream m (MutArray a)
MA.compactLE Int
n (Stream m (MutArray a) -> Stream m (MutArray a))
-> Stream m (MutArray a) -> Stream m (MutArray a)
forall a b. (a -> b) -> a -> b
$ (Array a -> MutArray a)
-> Stream m (Array a) -> Stream m (MutArray a)
forall (m :: * -> *) a b.
Monad m =>
(a -> b) -> Stream m a -> Stream m b
D.map Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Stream m (Array a)
stream

-- | Pinned version of 'compactLE'.
{-# INLINE_NORMAL pinnedCompactLE #-}
pinnedCompactLE :: (MonadIO m, Unbox a)
    => Int -> Stream m (Array a) -> Stream m (Array a)
pinnedCompactLE :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Stream m (Array a) -> Stream m (Array a)
pinnedCompactLE Int
n Stream m (Array a)
stream =
    (MutArray a -> Array a)
-> Stream m (MutArray a) -> Stream m (Array a)
forall (m :: * -> *) a b.
Monad m =>
(a -> b) -> Stream m a -> Stream m b
D.map MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze (Stream m (MutArray a) -> Stream m (Array a))
-> Stream m (MutArray a) -> Stream m (Array a)
forall a b. (a -> b) -> a -> b
$ Int -> Stream m (MutArray a) -> Stream m (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Stream m (MutArray a) -> Stream m (MutArray a)
MA.pinnedCompactLE Int
n (Stream m (MutArray a) -> Stream m (MutArray a))
-> Stream m (MutArray a) -> Stream m (MutArray a)
forall a b. (a -> b) -> a -> b
$ (Array a -> MutArray a)
-> Stream m (Array a) -> Stream m (MutArray a)
forall (m :: * -> *) a b.
Monad m =>
(a -> b) -> Stream m a -> Stream m b
D.map Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Stream m (Array a)
stream

-- | 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 (Array Word8)
    -> Stream m (Array Word8)
compactOnByte :: forall (m :: * -> *).
MonadIO m =>
Word8 -> Stream m (Array Word8) -> Stream m (Array Word8)
compactOnByte Word8
byte =
    (MutArray Word8 -> Array Word8)
-> Stream m (MutArray Word8) -> Stream m (Array Word8)
forall a b. (a -> b) -> Stream m a -> Stream m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap MutArray Word8 -> Array Word8
forall a. MutArray a -> Array a
unsafeFreeze (Stream m (MutArray Word8) -> Stream m (Array Word8))
-> (Stream m (Array Word8) -> Stream m (MutArray Word8))
-> Stream m (Array Word8)
-> Stream m (Array Word8)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Stream m (MutArray Word8) -> Stream m (MutArray Word8)
forall (m :: * -> *).
MonadIO m =>
Word8 -> Stream m (MutArray Word8) -> Stream m (MutArray Word8)
MA.compactOnByte Word8
byte (Stream m (MutArray Word8) -> Stream m (MutArray Word8))
-> (Stream m (Array Word8) -> Stream m (MutArray Word8))
-> Stream m (Array Word8)
-> Stream m (MutArray Word8)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Array Word8 -> MutArray Word8)
-> Stream m (Array Word8) -> Stream m (MutArray Word8)
forall a b. (a -> b) -> Stream m a -> Stream m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Array Word8 -> MutArray Word8
forall a. Array a -> MutArray a
unsafeThaw

-- | Like 'compactOnByte' considers the separator in suffix position instead of
-- infix position.
{-# INLINE compactOnByteSuffix #-}
compactOnByteSuffix
    :: (MonadIO m)
    => Word8
    -> Stream m (Array Word8)
    -> Stream m (Array Word8)
compactOnByteSuffix :: forall (m :: * -> *).
MonadIO m =>
Word8 -> Stream m (Array Word8) -> Stream m (Array Word8)
compactOnByteSuffix Word8
byte =
    (MutArray Word8 -> Array Word8)
-> Stream m (MutArray Word8) -> Stream m (Array Word8)
forall a b. (a -> b) -> Stream m a -> Stream m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap MutArray Word8 -> Array Word8
forall a. MutArray a -> Array a
unsafeFreeze (Stream m (MutArray Word8) -> Stream m (Array Word8))
-> (Stream m (Array Word8) -> Stream m (MutArray Word8))
-> Stream m (Array Word8)
-> Stream m (Array Word8)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Stream m (MutArray Word8) -> Stream m (MutArray Word8)
forall (m :: * -> *).
MonadIO m =>
Word8 -> Stream m (MutArray Word8) -> Stream m (MutArray Word8)
MA.compactOnByteSuffix Word8
byte (Stream m (MutArray Word8) -> Stream m (MutArray Word8))
-> (Stream m (Array Word8) -> Stream m (MutArray Word8))
-> Stream m (Array Word8)
-> Stream m (MutArray Word8)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Array Word8 -> MutArray Word8)
-> Stream m (Array Word8) -> Stream m (MutArray Word8)
forall a b. (a -> b) -> Stream m a -> Stream m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Array Word8 -> MutArray Word8
forall a. Array a -> MutArray a
unsafeThaw

-------------------------------------------------------------------------------
-- Folding Streams of Arrays
-------------------------------------------------------------------------------

-- XXX This should not be used for breaking a stream as the D.cons used in
-- reconstructing the stream could be very bad for performance. This can only
-- be useful in folding without breaking.
{-# INLINE_NORMAL foldBreakChunks #-}
foldBreakChunks :: forall m a b. (MonadIO m, Unbox a) =>
    Fold m a b -> Stream m (Array a) -> m (b, Stream m (Array a))
foldBreakChunks :: forall (m :: * -> *) a b.
(MonadIO m, Unbox a) =>
Fold m a b -> Stream m (Array a) -> m (b, Stream m (Array a))
foldBreakChunks (Fold s -> a -> m (Step s b)
fstep m (Step s b)
initial s -> m b
_ s -> m b
final) stream :: Stream m (Array a)
stream@(Stream State StreamK m (Array a) -> s -> m (Step s (Array a))
step s
state) = do
    Step s b
res <- m (Step s b)
initial
    case Step s b
res of
        Fold.Partial s
fs -> SPEC -> s -> s -> m (b, Stream m (Array a))
go SPEC
SPEC s
state s
fs
        Fold.Done b
fb -> (b, Stream m (Array a)) -> m (b, Stream m (Array a))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ((b, Stream m (Array a)) -> m (b, Stream m (Array a)))
-> (b, Stream m (Array a)) -> m (b, Stream m (Array a))
forall a b. (a -> b) -> a -> b
$! (b
fb, Stream m (Array a)
stream)

    where

    {-# INLINE go #-}
    go :: SPEC -> s -> s -> m (b, Stream m (Array a))
go !SPEC
_ s
st !s
fs = do
        Step s (Array a)
r <- State StreamK m (Array a) -> s -> m (Step s (Array a))
step State StreamK m (Array a)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a. State t m a
defState s
st
        case Step s (Array a)
r of
            Stream.Yield (Array MutByteArray
contents Int
start Int
end) s
s ->
                let fp :: Tuple' Int MutByteArray
fp = Int -> MutByteArray -> Tuple' Int MutByteArray
forall a b. a -> b -> Tuple' a b
Tuple' Int
end MutByteArray
contents
                 in SPEC
-> s
-> Tuple' Int MutByteArray
-> Int
-> s
-> m (b, Stream m (Array a))
goArray SPEC
SPEC s
s Tuple' Int MutByteArray
fp Int
start s
fs
            Stream.Skip s
s -> SPEC -> s -> s -> m (b, Stream m (Array a))
go SPEC
SPEC s
s s
fs
            Step s (Array a)
Stream.Stop -> do
                b
b <- s -> m b
final s
fs
                (b, Stream m (Array a)) -> m (b, Stream m (Array a))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b
b, Stream m (Array a)
forall (m :: * -> *) a. Applicative m => Stream m a
D.nil)

    goArray :: SPEC
-> s
-> Tuple' Int MutByteArray
-> Int
-> s
-> m (b, Stream m (Array a))
goArray !SPEC
_ s
s (Tuple' Int
end MutByteArray
_) !Int
cur !s
fs
        | Int
cur Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
end = do
            SPEC -> s -> s -> m (b, Stream m (Array a))
go SPEC
SPEC s
s s
fs
    goArray !SPEC
_ s
st fp :: Tuple' Int MutByteArray
fp@(Tuple' Int
end MutByteArray
contents) !Int
cur !s
fs = do
        a
x <- IO a -> m a
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> m a) -> IO a -> m a
forall a b. (a -> b) -> a -> b
$ Int -> MutByteArray -> IO a
forall a. Unbox a => Int -> MutByteArray -> IO a
peekAt Int
cur MutByteArray
contents
        Step s b
res <- s -> a -> m (Step s b)
fstep s
fs a
x
        let next :: Int
next = INDEX_NEXT(cur,a)
        case Step s b
res of
            Fold.Done b
b -> do
                let arr :: Array a
arr = MutByteArray -> Int -> Int -> Array a
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
contents Int
next Int
end
                (b, Stream m (Array a)) -> m (b, Stream m (Array a))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ((b, Stream m (Array a)) -> m (b, Stream m (Array a)))
-> (b, Stream m (Array a)) -> m (b, Stream m (Array a))
forall a b. (a -> b) -> a -> b
$! (b
b, Array a -> Stream m (Array a) -> Stream m (Array a)
forall (m :: * -> *) a.
Applicative m =>
a -> Stream m a -> Stream m a
D.cons Array a
forall {a}. Array a
arr ((State StreamK m (Array a) -> s -> m (Step s (Array a)))
-> s -> Stream m (Array a)
forall (m :: * -> *) a s.
(State StreamK m a -> s -> m (Step s a)) -> s -> Stream m a
D.Stream State StreamK m (Array a) -> s -> m (Step s (Array a))
step s
st))
            Fold.Partial s
fs1 -> SPEC
-> s
-> Tuple' Int MutByteArray
-> Int
-> s
-> m (b, Stream m (Array a))
goArray SPEC
SPEC s
st Tuple' Int MutByteArray
fp Int
next s
fs1

-- This may be more robust wrt fusion compared to unfoldMany?

-- | Fold a stream of arrays using a 'Fold'. This is equivalent to the
-- following:
--
-- >>> foldChunks f = Stream.fold f . Stream.unfoldMany Array.reader
--
foldChunks :: (MonadIO m, Unbox a) => Fold m a b -> Stream m (Array a) -> m b
foldChunks :: forall (m :: * -> *) a b.
(MonadIO m, Unbox a) =>
Fold m a b -> Stream m (Array a) -> m b
foldChunks Fold m a b
f Stream m (Array a)
s = ((b, Stream m (Array a)) -> b) -> m (b, Stream m (Array a)) -> m b
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (b, Stream m (Array a)) -> b
forall a b. (a, b) -> a
fst (Fold m a b -> Stream m (Array a) -> m (b, Stream m (Array a))
forall (m :: * -> *) a b.
(MonadIO m, Unbox a) =>
Fold m a b -> Stream m (Array a) -> m (b, Stream m (Array a))
foldBreakChunks Fold m a b
f Stream m (Array a)
s)
-- foldStream f = Stream.fold f . Stream.unfoldMany reader

-- | Fold a stream of arrays using a 'Fold' and return the remaining stream.
--
-- The following alternative to this function allows composing the fold using
-- the parser Monad:
--
-- @
-- foldBreakStreamK f s =
--       fmap (first (fromRight undefined))
--     $ StreamK.parseBreakChunks (ParserK.adaptC (Parser.fromFold f)) s
-- @
--
-- We can compare perf and remove this one or define it in terms of that.
--
foldBreakChunksK :: forall m a b. (MonadIO m, Unbox a) =>
    Fold m a b -> StreamK m (Array a) -> m (b, StreamK m (Array a))
{-
foldBreakChunksK f s =
      fmap (first (fromRight undefined))
    $ StreamK.parseBreakChunks (ParserK.adaptC (Parser.fromFold f)) s
-}
foldBreakChunksK :: forall (m :: * -> *) a b.
(MonadIO m, Unbox a) =>
Fold m a b -> StreamK m (Array a) -> m (b, StreamK m (Array a))
foldBreakChunksK (Fold s -> a -> m (Step s b)
fstep m (Step s b)
initial s -> m b
_ s -> m b
final) StreamK m (Array a)
stream = do
    Step s b
res <- m (Step s b)
initial
    case Step s b
res of
        Fold.Partial s
fs -> s -> StreamK m (Array a) -> m (b, StreamK m (Array a))
forall {a}. s -> StreamK m (Array a) -> m (b, StreamK m (Array a))
go s
fs StreamK m (Array a)
stream
        Fold.Done b
fb -> (b, StreamK m (Array a)) -> m (b, StreamK m (Array a))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b
fb, StreamK m (Array a)
stream)

    where

    {-# INLINE go #-}
    go :: s -> StreamK m (Array a) -> m (b, StreamK m (Array a))
go !s
fs StreamK m (Array a)
st = do
        let stop :: m (b, StreamK m a)
stop = (, StreamK m a
forall (m :: * -> *) a. StreamK m a
StreamK.nil) (b -> (b, StreamK m a)) -> m b -> m (b, StreamK m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> s -> m b
final s
fs
            single :: Array a -> m (b, StreamK m (Array a))
single Array a
a = Array a -> StreamK m (Array a) -> m (b, StreamK m (Array a))
forall {a}.
Array a -> StreamK m (Array a) -> m (b, StreamK m (Array a))
yieldk Array a
a StreamK m (Array a)
forall (m :: * -> *) a. StreamK m a
StreamK.nil
            yieldk :: Array a -> StreamK m (Array a) -> m (b, StreamK m (Array a))
yieldk (Array MutByteArray
contents Int
start Int
end) StreamK m (Array a)
r =
                let fp :: Tuple' Int MutByteArray
fp = Int -> MutByteArray -> Tuple' Int MutByteArray
forall a b. a -> b -> Tuple' a b
Tuple' Int
end MutByteArray
contents
                 in s
-> StreamK m (Array a)
-> Tuple' Int MutByteArray
-> Int
-> m (b, StreamK m (Array a))
goArray s
fs StreamK m (Array a)
r Tuple' Int MutByteArray
fp Int
start
         in State StreamK m (Array a)
-> (Array a -> StreamK m (Array a) -> m (b, StreamK m (Array a)))
-> (Array a -> m (b, StreamK m (Array a)))
-> m (b, StreamK m (Array a))
-> StreamK m (Array a)
-> m (b, StreamK m (Array a))
forall (m :: * -> *) a r.
State StreamK m a
-> (a -> StreamK m a -> m r)
-> (a -> m r)
-> m r
-> StreamK m a
-> m r
StreamK.foldStream State StreamK m (Array a)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a. State t m a
defState Array a -> StreamK m (Array a) -> m (b, StreamK m (Array a))
forall {a}.
Array a -> StreamK m (Array a) -> m (b, StreamK m (Array a))
yieldk Array a -> m (b, StreamK m (Array a))
forall {a}. Array a -> m (b, StreamK m (Array a))
single m (b, StreamK m (Array a))
forall {m :: * -> *} {a}. m (b, StreamK m a)
stop StreamK m (Array a)
st

    goArray :: s
-> StreamK m (Array a)
-> Tuple' Int MutByteArray
-> Int
-> m (b, StreamK m (Array a))
goArray !s
fs StreamK m (Array a)
st (Tuple' Int
end MutByteArray
_) !Int
cur
        | Int
cur Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
end = do
            s -> StreamK m (Array a) -> m (b, StreamK m (Array a))
go s
fs StreamK m (Array a)
st
    goArray !s
fs StreamK m (Array a)
st fp :: Tuple' Int MutByteArray
fp@(Tuple' Int
end MutByteArray
contents) !Int
cur = do
        a
x <- IO a -> m a
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> m a) -> IO a -> m a
forall a b. (a -> b) -> a -> b
$ Int -> MutByteArray -> IO a
forall a. Unbox a => Int -> MutByteArray -> IO a
peekAt Int
cur MutByteArray
contents
        Step s b
res <- s -> a -> m (Step s b)
fstep s
fs a
x
        let next :: Int
next = INDEX_NEXT(cur,a)
        case Step s b
res of
            Fold.Done b
b -> do
                let arr :: Array a
arr = MutByteArray -> Int -> Int -> Array a
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
contents Int
next Int
end
                (b, StreamK m (Array a)) -> m (b, StreamK m (Array a))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ((b, StreamK m (Array a)) -> m (b, StreamK m (Array a)))
-> (b, StreamK m (Array a)) -> m (b, StreamK m (Array a))
forall a b. (a -> b) -> a -> b
$! (b
b, Array a -> StreamK m (Array a) -> StreamK m (Array a)
forall a (m :: * -> *). a -> StreamK m a -> StreamK m a
StreamK.cons Array a
forall {a}. Array a
arr StreamK m (Array a)
st)
            Fold.Partial s
fs1 -> s
-> StreamK m (Array a)
-> Tuple' Int MutByteArray
-> Int
-> m (b, StreamK m (Array a))
goArray s
fs1 StreamK m (Array a)
st Tuple' Int MutByteArray
fp Int
next

{-
-- This can be generalized to any type provided it can be unfolded to a stream
-- and it can be combined using a semigroup operation.
--
{-# INLINE_NORMAL parseBreakD #-}
parseBreakD ::
       forall m a b. (MonadIO m, MonadThrow m, Unbox a)
    => PRD.Parser a m b
    -> D.Stream m (Array.Array a)
    -> m (b, D.Stream m (Array.Array a))
parseBreakD
    (PRD.Parser pstep initial extract) stream@(D.Stream step state) = do

    res <- initial
    case res of
        PRD.IPartial s -> go SPEC state (List []) s
        PRD.IDone b -> return (b, stream)
        PRD.IError err -> throwM $ ParseError err

    where

    -- "backBuf" contains last few items in the stream that we may have to
    -- backtrack to.
    --
    -- XXX currently we are using a dumb list based approach for backtracking
    -- buffer. This can be replaced by a sliding/ring buffer using Data.Array.
    -- That will allow us more efficient random back and forth movement.
    go !_ st backBuf !pst = do
        r <- step defState st
        case r of
            D.Yield (Array contents start end) s ->
                gobuf SPEC s backBuf
                    (Tuple' end contents) start pst
            D.Skip s -> go SPEC s backBuf pst
            D.Stop -> do
                b <- extract pst
                return (b, D.nil)

    -- Use strictness on "cur" to keep it unboxed
    gobuf !_ s backBuf (Tuple' end _) !cur !pst
        | cur == end = do
            go SPEC s backBuf pst
    gobuf !_ s backBuf fp@(Tuple' end contents) !cur !pst = do
        x <- liftIO $ peekByteIndex contents cur
        pRes <- pstep pst x
        let next = INDEX_NEXT(cur,a)
        case pRes of
            PR.Partial 0 pst1 ->
                 gobuf SPEC s (List []) fp next pst1
            PR.Partial n pst1 -> do
                assert (n <= Prelude.length (x:getList backBuf)) (return ())
                let src0 = Prelude.take n (x:getList backBuf)
                    arr0 = A.fromListN n (Prelude.reverse src0)
                    arr1 = Array contents next end
                    src = arr0 <> arr1
                let !(Array cont1 start end1) = src
                    fp1 = Tuple' end1 cont1
                gobuf SPEC s (List []) fp1 start pst1
            PR.Continue 0 pst1 ->
                gobuf SPEC s (List (x:getList backBuf)) fp next pst1
            PR.Continue n pst1 -> do
                assert (n <= Prelude.length (x:getList backBuf)) (return ())
                let (src0, buf1) = splitAt n (x:getList backBuf)
                    arr0 = A.fromListN n (Prelude.reverse src0)
                    arr1 = Array contents next end
                    src = arr0 <> arr1
                let !(Array cont1 start end1) = src
                    fp1 = Tuple' end1 cont1
                gobuf SPEC s (List buf1) fp1 start pst1
            PR.Done 0 b -> do
                let arr = Array contents next end
                return (b, D.cons arr (D.Stream step s))
            PR.Done n b -> do
                assert (n <= Prelude.length (x:getList backBuf)) (return ())
                let src0 = Prelude.take n (x:getList backBuf)
                    -- XXX create the array in reverse instead
                    arr0 = A.fromListN n (Prelude.reverse src0)
                    arr1 = Array contents next end
                    -- XXX Use StreamK to avoid adding arbitrary layers of
                    -- constructors every time.
                    str = D.cons arr0 (D.cons arr1 (D.Stream step s))
                return (b, str)
            PR.Error err -> throwM $ ParseError err
-}

-- | Parse an array stream using the supplied 'Parser'.  Returns the parse
-- result and the unconsumed stream. Throws 'ParseError' if the parse fails.
--
-- The following alternative to this function allows composing the parser using
-- the parser Monad:
--
-- >>> parseBreakStreamK p = StreamK.parseBreakChunks (ParserK.adaptC p)
--
-- We can compare perf and remove this one or define it in terms of that.
--
-- /Internal/
--
{-# INLINE_NORMAL parseBreakChunksK #-}
parseBreakChunksK ::
       forall m a b. (MonadIO m, Unbox a)
    => Parser a m b
    -> StreamK m (Array a)
    -> m (Either ParseError b, StreamK m (Array a))
-- parseBreakStreamK p = StreamK.parseBreakChunks (ParserK.adaptC p)
parseBreakChunksK :: forall (m :: * -> *) a b.
(MonadIO m, Unbox a) =>
Parser a m b
-> StreamK m (Array a)
-> m (Either ParseError b, StreamK m (Array a))
parseBreakChunksK (Parser s -> a -> m (Step s b)
pstep m (Initial s b)
initial s -> m (Step s b)
extract) StreamK m (Array a)
stream = do
    Initial s b
res <- m (Initial s b)
initial
    case Initial s b
res of
        IPartial s
s -> s
-> StreamK m (Array a)
-> [a]
-> m (Either ParseError b, StreamK m (Array a))
go s
s StreamK m (Array a)
stream []
        IDone b
b -> (Either ParseError b, StreamK m (Array a))
-> m (Either ParseError b, StreamK m (Array a))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b -> Either ParseError b
forall a b. b -> Either a b
Right b
b, StreamK m (Array a)
stream)
        IError String
err -> (Either ParseError b, StreamK m (Array a))
-> m (Either ParseError b, StreamK m (Array a))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (ParseError -> Either ParseError b
forall a b. a -> Either a b
Left (String -> ParseError
ParseError String
err), StreamK m (Array a)
stream)

    where

    -- "backBuf" contains last few items in the stream that we may have to
    -- backtrack to.
    --
    -- XXX currently we are using a dumb list based approach for backtracking
    -- buffer. This can be replaced by a sliding/ring buffer using Data.Array.
    -- That will allow us more efficient random back and forth movement.
    go :: s
-> StreamK m (Array a)
-> [a]
-> m (Either ParseError b, StreamK m (Array a))
go !s
pst StreamK m (Array a)
st [a]
backBuf = do
        let stop :: m (Either ParseError b, StreamK m (Array a))
stop = s -> [a] -> m (Either ParseError b, StreamK m (Array a))
goStop s
pst [a]
backBuf -- (, K.nil) <$> extract pst
            single :: Array a -> m (Either ParseError b, StreamK m (Array a))
single Array a
a = Array a
-> StreamK m (Array a)
-> m (Either ParseError b, StreamK m (Array a))
yieldk Array a
a StreamK m (Array a)
forall (m :: * -> *) a. StreamK m a
StreamK.nil
            yieldk :: Array a
-> StreamK m (Array a)
-> m (Either ParseError b, StreamK m (Array a))
yieldk Array a
arr StreamK m (Array a)
r = s
-> [a]
-> StreamK m (Array a)
-> Array a
-> m (Either ParseError b, StreamK m (Array a))
goArray s
pst [a]
backBuf StreamK m (Array a)
r Array a
arr
         in State StreamK m (Array a)
-> (Array a
    -> StreamK m (Array a)
    -> m (Either ParseError b, StreamK m (Array a)))
-> (Array a -> m (Either ParseError b, StreamK m (Array a)))
-> m (Either ParseError b, StreamK m (Array a))
-> StreamK m (Array a)
-> m (Either ParseError b, StreamK m (Array a))
forall (m :: * -> *) a r.
State StreamK m a
-> (a -> StreamK m a -> m r)
-> (a -> m r)
-> m r
-> StreamK m a
-> m r
StreamK.foldStream State StreamK m (Array a)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a. State t m a
defState Array a
-> StreamK m (Array a)
-> m (Either ParseError b, StreamK m (Array a))
yieldk Array a -> m (Either ParseError b, StreamK m (Array a))
single m (Either ParseError b, StreamK m (Array a))
stop StreamK m (Array a)
st

    -- Use strictness on "cur" to keep it unboxed
    goArray :: s
-> [a]
-> StreamK m (Array a)
-> Array a
-> m (Either ParseError b, StreamK m (Array a))
goArray !s
pst [a]
backBuf StreamK m (Array a)
st (Array MutByteArray
_ Int
cur Int
end) | Int
cur Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
end = s
-> StreamK m (Array a)
-> [a]
-> m (Either ParseError b, StreamK m (Array a))
go s
pst StreamK m (Array a)
st [a]
backBuf
    goArray !s
pst [a]
backBuf StreamK m (Array a)
st (Array MutByteArray
contents Int
cur Int
end) = do
        a
x <- IO a -> m a
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> m a) -> IO a -> m a
forall a b. (a -> b) -> a -> b
$ Int -> MutByteArray -> IO a
forall a. Unbox a => Int -> MutByteArray -> IO a
peekAt Int
cur MutByteArray
contents
        Step s b
pRes <- s -> a -> m (Step s b)
pstep s
pst a
x
        let next :: Int
next = INDEX_NEXT(cur,a)
        case Step s b
pRes of
            Parser.Partial Int
0 s
s ->
                 s
-> [a]
-> StreamK m (Array a)
-> Array a
-> m (Either ParseError b, StreamK m (Array a))
goArray s
s [] StreamK m (Array a)
st (MutByteArray -> Int -> Int -> Array a
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
contents Int
next Int
end)
            Parser.Partial Int
n s
s -> do
                Bool -> m () -> m ()
forall a. HasCallStack => Bool -> a -> a
assert (Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
Prelude.length (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
backBuf)) (() -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ())
                let src0 :: [a]
src0 = Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
Prelude.take Int
n (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
backBuf)
                    arr0 :: Array a
arr0 = Int -> [a] -> Array a
forall a. Unbox a => Int -> [a] -> Array a
fromListN Int
n ([a] -> [a]
forall a. [a] -> [a]
Prelude.reverse [a]
src0)
                    arr1 :: Array a
arr1 = MutByteArray -> Int -> Int -> Array a
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
contents Int
next Int
end
                    src :: Array a
src = Array a
arr0 Array a -> Array a -> Array a
forall a. Semigroup a => a -> a -> a
<> Array a
forall {a}. Array a
arr1
                s
-> [a]
-> StreamK m (Array a)
-> Array a
-> m (Either ParseError b, StreamK m (Array a))
goArray s
s [] StreamK m (Array a)
st Array a
src
            Parser.Continue Int
0 s
s ->
                s
-> [a]
-> StreamK m (Array a)
-> Array a
-> m (Either ParseError b, StreamK m (Array a))
goArray s
s (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
backBuf) StreamK m (Array a)
st (MutByteArray -> Int -> Int -> Array a
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
contents Int
next Int
end)
            Parser.Continue Int
n s
s -> do
                Bool -> m () -> m ()
forall a. HasCallStack => Bool -> a -> a
assert (Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
Prelude.length (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
backBuf)) (() -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ())
                let ([a]
src0, [a]
buf1) = Int -> [a] -> ([a], [a])
forall a. Int -> [a] -> ([a], [a])
Prelude.splitAt Int
n (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
backBuf)
                    arr0 :: Array a
arr0 = Int -> [a] -> Array a
forall a. Unbox a => Int -> [a] -> Array a
fromListN Int
n ([a] -> [a]
forall a. [a] -> [a]
Prelude.reverse [a]
src0)
                    arr1 :: Array a
arr1 = MutByteArray -> Int -> Int -> Array a
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
contents Int
next Int
end
                    src :: Array a
src = Array a
arr0 Array a -> Array a -> Array a
forall a. Semigroup a => a -> a -> a
<> Array a
forall {a}. Array a
arr1
                s
-> [a]
-> StreamK m (Array a)
-> Array a
-> m (Either ParseError b, StreamK m (Array a))
goArray s
s [a]
buf1 StreamK m (Array a)
st Array a
src
            Parser.Done Int
0 b
b -> do
                let arr :: Array a
arr = MutByteArray -> Int -> Int -> Array a
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
contents Int
next Int
end
                (Either ParseError b, StreamK m (Array a))
-> m (Either ParseError b, StreamK m (Array a))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b -> Either ParseError b
forall a b. b -> Either a b
Right b
b, Array a -> StreamK m (Array a) -> StreamK m (Array a)
forall a (m :: * -> *). a -> StreamK m a -> StreamK m a
StreamK.cons Array a
forall {a}. Array a
arr StreamK m (Array a)
st)
            Parser.Done Int
n b
b -> do
                Bool -> m () -> m ()
forall a. HasCallStack => Bool -> a -> a
assert (Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
Prelude.length (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
backBuf)) (() -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ())
                let src0 :: [a]
src0 = Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
Prelude.take Int
n (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
backBuf)
                    -- XXX Use fromListRevN once implemented
                    -- arr0 = A.fromListRevN n src0
                    arr0 :: Array a
arr0 = Int -> [a] -> Array a
forall a. Unbox a => Int -> [a] -> Array a
fromListN Int
n ([a] -> [a]
forall a. [a] -> [a]
Prelude.reverse [a]
src0)
                    arr1 :: Array a
arr1 = MutByteArray -> Int -> Int -> Array a
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
contents Int
next Int
end
                    str :: StreamK m (Array a)
str = Array a -> StreamK m (Array a) -> StreamK m (Array a)
forall a (m :: * -> *). a -> StreamK m a -> StreamK m a
StreamK.cons Array a
arr0 (Array a -> StreamK m (Array a) -> StreamK m (Array a)
forall a (m :: * -> *). a -> StreamK m a -> StreamK m a
StreamK.cons Array a
forall {a}. Array a
arr1 StreamK m (Array a)
st)
                (Either ParseError b, StreamK m (Array a))
-> m (Either ParseError b, StreamK m (Array a))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b -> Either ParseError b
forall a b. b -> Either a b
Right b
b, StreamK m (Array a)
str)
            Parser.Error String
err -> do
                let n :: Int
n = [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
Prelude.length [a]
backBuf
                    arr0 :: Array a
arr0 = Int -> [a] -> Array a
forall a. Unbox a => Int -> [a] -> Array a
fromListN Int
n ([a] -> [a]
forall a. [a] -> [a]
Prelude.reverse [a]
backBuf)
                    arr1 :: Array a
arr1 = MutByteArray -> Int -> Int -> Array a
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
contents Int
cur Int
end
                    str :: StreamK m (Array a)
str = Array a -> StreamK m (Array a) -> StreamK m (Array a)
forall a (m :: * -> *). a -> StreamK m a -> StreamK m a
StreamK.cons Array a
arr0 (Array a -> StreamK m (Array a) -> StreamK m (Array a)
forall a (m :: * -> *). a -> StreamK m a -> StreamK m a
StreamK.cons Array a
forall {a}. Array a
arr1 StreamK m (Array a)
stream)
                (Either ParseError b, StreamK m (Array a))
-> m (Either ParseError b, StreamK m (Array a))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (ParseError -> Either ParseError b
forall a b. a -> Either a b
Left (String -> ParseError
ParseError String
err), StreamK m (Array a)
str)

    -- This is a simplified goArray
    goExtract :: s -> [a] -> Array a -> m (Either ParseError b, StreamK m (Array a))
goExtract !s
pst [a]
backBuf (Array MutByteArray
_ Int
cur Int
end)
        | Int
cur Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
end = s -> [a] -> m (Either ParseError b, StreamK m (Array a))
goStop s
pst [a]
backBuf
    goExtract !s
pst [a]
backBuf (Array MutByteArray
contents Int
cur Int
end) = do
        a
x <- IO a -> m a
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> m a) -> IO a -> m a
forall a b. (a -> b) -> a -> b
$ Int -> MutByteArray -> IO a
forall a. Unbox a => Int -> MutByteArray -> IO a
peekAt Int
cur MutByteArray
contents
        Step s b
pRes <- s -> a -> m (Step s b)
pstep s
pst a
x
        let next :: Int
next = INDEX_NEXT(cur,a)
        case Step s b
pRes of
            Parser.Partial Int
0 s
s ->
                 s -> [a] -> Array a -> m (Either ParseError b, StreamK m (Array a))
goExtract s
s [] (MutByteArray -> Int -> Int -> Array a
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
contents Int
next Int
end)
            Parser.Partial Int
n s
s -> do
                Bool -> m () -> m ()
forall a. HasCallStack => Bool -> a -> a
assert (Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
Prelude.length (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
backBuf)) (() -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ())
                let src0 :: [a]
src0 = Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
Prelude.take Int
n (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
backBuf)
                    arr0 :: Array a
arr0 = Int -> [a] -> Array a
forall a. Unbox a => Int -> [a] -> Array a
fromListN Int
n ([a] -> [a]
forall a. [a] -> [a]
Prelude.reverse [a]
src0)
                    arr1 :: Array a
arr1 = MutByteArray -> Int -> Int -> Array a
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
contents Int
next Int
end
                    src :: Array a
src = Array a
arr0 Array a -> Array a -> Array a
forall a. Semigroup a => a -> a -> a
<> Array a
forall {a}. Array a
arr1
                s -> [a] -> Array a -> m (Either ParseError b, StreamK m (Array a))
goExtract s
s [] Array a
src
            Parser.Continue Int
0 s
s ->
                s -> [a] -> Array a -> m (Either ParseError b, StreamK m (Array a))
goExtract s
s [a]
backBuf (MutByteArray -> Int -> Int -> Array a
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
contents Int
next Int
end)
            Parser.Continue Int
n s
s -> do
                Bool -> m () -> m ()
forall a. HasCallStack => Bool -> a -> a
assert (Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
Prelude.length (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
backBuf)) (() -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ())
                let ([a]
src0, [a]
buf1) = Int -> [a] -> ([a], [a])
forall a. Int -> [a] -> ([a], [a])
Prelude.splitAt Int
n (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
backBuf)
                    arr0 :: Array a
arr0 = Int -> [a] -> Array a
forall a. Unbox a => Int -> [a] -> Array a
fromListN Int
n ([a] -> [a]
forall a. [a] -> [a]
Prelude.reverse [a]
src0)
                    arr1 :: Array a
arr1 = MutByteArray -> Int -> Int -> Array a
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
contents Int
next Int
end
                    src :: Array a
src = Array a
arr0 Array a -> Array a -> Array a
forall a. Semigroup a => a -> a -> a
<> Array a
forall {a}. Array a
arr1
                s -> [a] -> Array a -> m (Either ParseError b, StreamK m (Array a))
goExtract s
s [a]
buf1 Array a
src
            Parser.Done Int
0 b
b -> do
                let arr :: Array a
arr = MutByteArray -> Int -> Int -> Array a
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
contents Int
next Int
end
                (Either ParseError b, StreamK m (Array a))
-> m (Either ParseError b, StreamK m (Array a))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b -> Either ParseError b
forall a b. b -> Either a b
Right b
b, Array a -> StreamK m (Array a)
forall a (m :: * -> *). a -> StreamK m a
StreamK.fromPure Array a
forall {a}. Array a
arr)
            Parser.Done Int
n b
b -> do
                Bool -> m () -> m ()
forall a. HasCallStack => Bool -> a -> a
assert (Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
Prelude.length [a]
backBuf) (() -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ())
                let src0 :: [a]
src0 = Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
Prelude.take Int
n [a]
backBuf
                    -- XXX Use fromListRevN once implemented
                    -- arr0 = A.fromListRevN n src0
                    arr0 :: Array a
arr0 = Int -> [a] -> Array a
forall a. Unbox a => Int -> [a] -> Array a
fromListN Int
n ([a] -> [a]
forall a. [a] -> [a]
Prelude.reverse [a]
src0)
                    arr1 :: Array a
arr1 = MutByteArray -> Int -> Int -> Array a
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
contents Int
next Int
end
                    str :: StreamK m (Array a)
str = Array a -> StreamK m (Array a) -> StreamK m (Array a)
forall a (m :: * -> *). a -> StreamK m a -> StreamK m a
StreamK.cons Array a
arr0 (Array a -> StreamK m (Array a)
forall a (m :: * -> *). a -> StreamK m a
StreamK.fromPure Array a
forall {a}. Array a
arr1)
                (Either ParseError b, StreamK m (Array a))
-> m (Either ParseError b, StreamK m (Array a))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b -> Either ParseError b
forall a b. b -> Either a b
Right b
b, StreamK m (Array a)
forall {m :: * -> *}. StreamK m (Array a)
str)
            Parser.Error String
err -> do
                let n :: Int
n = [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
Prelude.length [a]
backBuf
                    arr0 :: Array a
arr0 = Int -> [a] -> Array a
forall a. Unbox a => Int -> [a] -> Array a
fromListN Int
n ([a] -> [a]
forall a. [a] -> [a]
Prelude.reverse [a]
backBuf)
                    arr1 :: Array a
arr1 = MutByteArray -> Int -> Int -> Array a
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
contents Int
cur Int
end
                    str :: StreamK m (Array a)
str = Array a -> StreamK m (Array a) -> StreamK m (Array a)
forall a (m :: * -> *). a -> StreamK m a -> StreamK m a
StreamK.cons Array a
arr0 (Array a -> StreamK m (Array a) -> StreamK m (Array a)
forall a (m :: * -> *). a -> StreamK m a -> StreamK m a
StreamK.cons Array a
forall {a}. Array a
arr1 StreamK m (Array a)
stream)
                (Either ParseError b, StreamK m (Array a))
-> m (Either ParseError b, StreamK m (Array a))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (ParseError -> Either ParseError b
forall a b. a -> Either a b
Left (String -> ParseError
ParseError String
err), StreamK m (Array a)
str)

    -- This is a simplified goExtract
    {-# INLINE goStop #-}
    goStop :: s -> [a] -> m (Either ParseError b, StreamK m (Array a))
goStop !s
pst [a]
backBuf = do
        Step s b
pRes <- s -> m (Step s b)
extract s
pst
        case Step s b
pRes of
            Parser.Partial Int
_ s
_ -> String -> m (Either ParseError b, StreamK m (Array a))
forall a. HasCallStack => String -> a
error String
"Bug: parseBreak: Partial in extract"
            Parser.Continue Int
0 s
s ->
                s -> [a] -> m (Either ParseError b, StreamK m (Array a))
goStop s
s [a]
backBuf
            Parser.Continue Int
n s
s -> do
                Bool -> m () -> m ()
forall a. HasCallStack => Bool -> a -> a
assert (Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
Prelude.length [a]
backBuf) (() -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ())
                let ([a]
src0, [a]
buf1) = Int -> [a] -> ([a], [a])
forall a. Int -> [a] -> ([a], [a])
Prelude.splitAt Int
n [a]
backBuf
                    arr :: Array a
arr = Int -> [a] -> Array a
forall a. Unbox a => Int -> [a] -> Array a
fromListN Int
n ([a] -> [a]
forall a. [a] -> [a]
Prelude.reverse [a]
src0)
                s -> [a] -> Array a -> m (Either ParseError b, StreamK m (Array a))
goExtract s
s [a]
buf1 Array a
arr
            Parser.Done Int
0 b
b ->
                (Either ParseError b, StreamK m (Array a))
-> m (Either ParseError b, StreamK m (Array a))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b -> Either ParseError b
forall a b. b -> Either a b
Right b
b, StreamK m (Array a)
forall (m :: * -> *) a. StreamK m a
StreamK.nil)
            Parser.Done Int
n b
b -> do
                Bool -> m () -> m ()
forall a. HasCallStack => Bool -> a -> a
assert (Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
Prelude.length [a]
backBuf) (() -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ())
                let src0 :: [a]
src0 = Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
Prelude.take Int
n [a]
backBuf
                    -- XXX Use fromListRevN once implemented
                    -- arr0 = A.fromListRevN n src0
                    arr0 :: Array a
arr0 = Int -> [a] -> Array a
forall a. Unbox a => Int -> [a] -> Array a
fromListN Int
n ([a] -> [a]
forall a. [a] -> [a]
Prelude.reverse [a]
src0)
                (Either ParseError b, StreamK m (Array a))
-> m (Either ParseError b, StreamK m (Array a))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b -> Either ParseError b
forall a b. b -> Either a b
Right b
b, Array a -> StreamK m (Array a)
forall a (m :: * -> *). a -> StreamK m a
StreamK.fromPure Array a
arr0)
            Parser.Error String
err -> do
                let n :: Int
n = [a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
Prelude.length [a]
backBuf
                    arr0 :: Array a
arr0 = Int -> [a] -> Array a
forall a. Unbox a => Int -> [a] -> Array a
fromListN Int
n ([a] -> [a]
forall a. [a] -> [a]
Prelude.reverse [a]
backBuf)
                (Either ParseError b, StreamK m (Array a))
-> m (Either ParseError b, StreamK m (Array a))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (ParseError -> Either ParseError b
forall a b. a -> Either a b
Left (String -> ParseError
ParseError String
err), Array a -> StreamK m (Array a)
forall a (m :: * -> *). a -> StreamK m a
StreamK.fromPure Array a
arr0)