{-# LANGUAGE CPP #-}
{-# LANGUAGE TypeFamilies #-}
-- Must come after TypeFamilies, otherwise it is re-enabled.
-- MonoLocalBinds enabled by TypeFamilies causes perf regressions in general.
{-# LANGUAGE NoMonoLocalBinds #-}
{-# OPTIONS_GHC -Wno-deprecations #-}
-- |
-- Module      : Streamly.Internal.Data.Array.Type
-- Copyright   : (c) 2020 Composewell Technologies
-- License     : BSD3-3-Clause
-- Maintainer  : streamly@composewell.com
-- Stability   : experimental
-- Portability : GHC
--
-- See notes in "Streamly.Internal.Data.MutArray.Type"
--

module Streamly.Internal.Data.Array.Type
    (
    -- ** Type
    -- $arrayNotes
      Array (..)

    -- ** Conversion
    -- *** Mutable and Immutable
    , unsafeFreeze
    , unsafeFreezeWithShrink
    , unsafeThaw

    -- *** Pinned and Unpinned
    , pin
    , unpin
    , isPinned

    -- *** Casting
    , unsafePinnedAsPtr
    , unsafeAsForeignPtr

    -- * Subarrays
    , unsafeSliceOffLen

    -- ** Construction
    , empty

    -- * Random Access
    -- , (!!)
    , getIndex
    , getIndexRev
    , head
    , last
    , init
    , tail
    , uncons
    , unsnoc

    -- *** Slicing
    -- | Get a subarray without copying
    , unsafeBreakAt
    , breakAt
    , breakEndByWord8_
    , breakEndBy
    , breakEndBy_
    , revBreakEndBy
    , revBreakEndBy_
    -- drop
    -- dropRev/dropEnd
    , dropAround
    , dropWhile
    , revDropWhile

    -- *** Stream Folds
    , unsafeMakePure
    , createOf
    , createOf'
    , unsafeCreateOf
    , unsafeCreateOf'
    , create
    , create'
    , createWith

    -- *** From containers
    , fromListN
    , fromListN'
    , fromList
    , fromList'
    , fromListRevN
    , fromListRev
    , fromStreamN
    , fromStream
    , fromPureStreamN
    , fromPureStream
    , fromCString#
    , fromCString
    , fromW16CString#
    , fromW16CString
    , fromPtrN
    , fromChunks
    , fromChunksK
    , unsafeFromForeignPtr

    -- ** Reading

    -- *** Indexing
    , unsafeGetIndexIO
    , unsafeGetIndexRevIO
    , unsafeGetIndex
    , unsafeGetIndexRev

    -- *** To Streams
    , read
    , readRev
    , toStreamK
    , toStreamKRev

    -- *** To Containers
    , toList

    -- *** Unfolds
    , producer -- experimental
    , unsafeReader
    , reader
    , readerRev

    -- *** Size
    , null
    , length
    , byteLength

    -- ** Folding
    , foldl'
    , foldr
    , byteCmp
    , byteEq
    , listCmp
    , listEq

    -- ** Appending
    , splice -- XXX requires MonadIO
    -- appendString
    -- appendCString/CString#

    -- ** Streams of arrays
    -- *** Chunk
    -- | Group a stream into arrays.
    , chunksOf
    , chunksOf'
    , buildChunks
    , chunksEndBy
    , chunksEndBy'
    , chunksEndByLn
    , chunksEndByLn'

    -- *** Split
    -- | Split an array into slices.
    , splitEndBy
    , splitEndBy_

    -- *** Concat
    -- | Append the arrays in a stream to form a stream of elements.
    , concat
    , concatRev

    -- *** Compact
    -- | Append the arrays in a stream to form a stream of larger arrays.
    , createCompactMin
    , createCompactMin'
    , scanCompactMin
    , scanCompactMin'
    , compactMin

    -- ** Deprecated
    , unsafeGetSlice
    , strip
    , stripStart
    , stripEnd
    , breakOn
    , splitAt
    , unsafeSplitAt
    , asPtrUnsafe
    , unsafeIndex
    , bufferChunks
    , flattenArrays
    , flattenArraysRev
    , fromArrayStreamK
    , fromStreamDN
    , fromStreamD
    , toStreamD
    , toStreamDRev
    , toStream
    , toStreamRev
    , nil
    , writeWith
    , writeN
    , pinnedWriteN
    , writeNUnsafe
    , pinnedWriteNUnsafe
    , pinnedWriteNAligned
    , write
    , pinnedWrite
    , fromByteStr#
    , fromByteStr
    , fCompactGE
    , fPinnedCompactGE
    , lCompactGE
    , lPinnedCompactGE
    , compactGE
    , pinnedCreateOf
    , unsafePinnedCreateOf
    , pinnedCreate
    , pinnedFromListN
    , pinnedFromList
    , pinnedChunksOf
    , unsafeIndexIO
    , getIndexUnsafe
    , readerUnsafe
    )
where

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

import Control.Exception (assert)
import Control.Monad (replicateM, when)
import Control.Monad.IO.Class (MonadIO(..))
import Data.Char (ord)
import Data.Functor.Identity (Identity(..))
import Data.Int (Int8, Int16, Int32, Int64)
import Data.Proxy (Proxy(..))
import Data.Word (Word8, Word16, Word32, Word64)
import GHC.Base (build)
import GHC.Exts (IsList, IsString(..), Addr#, minusAddr#)
import GHC.Int (Int(..))
import GHC.ForeignPtr (ForeignPtr(..), ForeignPtrContents(..))

import GHC.IO (unsafePerformIO)
import GHC.Ptr (Ptr(..), nullPtr)
import Streamly.Internal.Data.Producer.Type (Producer(..))
import Streamly.Internal.Data.MutArray.Type (MutArray)
import Streamly.Internal.Data.MutByteArray.Type (MutByteArray)
import Streamly.Internal.Data.Fold.Type (Fold(..))
import Streamly.Internal.Data.Scanl.Type (Scanl (..))
import Streamly.Internal.Data.Stream.Type (Stream)
import Streamly.Internal.Data.StreamK.Type (StreamK)
import Streamly.Internal.Data.Unbox (Unbox(..))
import Streamly.Internal.Data.Unfold.Type (Unfold(..))
import Text.Read (readPrec)

import Prelude hiding
    ( Foldable(..), concat, head, init, last, read, tail, unlines, splitAt
    , dropWhile)

import qualified GHC.Exts as Exts
import qualified Streamly.Internal.Data.Fold.Type as Fold
import qualified Streamly.Internal.Data.MutArray.Type as MA
import qualified Streamly.Internal.Data.Stream.Type as D
import qualified Streamly.Internal.Data.StreamK.Type as K
import qualified Streamly.Internal.Data.MutByteArray.Type as Unboxed
import qualified Streamly.Internal.Data.Producer as Producer
import qualified Streamly.Internal.Data.Scanl.Type as Scanl
import qualified Streamly.Internal.Data.Unfold.Type as Unfold
import qualified Text.ParserCombinators.ReadPrec as ReadPrec

import Streamly.Internal.System.IO (unsafeInlineIO, defaultChunkSize)

#include "DocTestDataArray.hs"

-------------------------------------------------------------------------------
-- Notes
-------------------------------------------------------------------------------

-- IMPORTANT:

-- We need to be careful while using unsafePerformIO when array creation is
-- involved.
--
-- * We need to make sure the unsafe IO line does not float out of the binding.
-- * The order of the IO actions should be sane. For example, `touch` after `f`.
--
-- Assume the unsafe IO action floats up. If it makes sense given this
-- assumption, it's probably OK to use usafe IO.
--
-- A general approach should be never to use unsafe IO where Array creation is
-- involved or touch is involved.

-------------------------------------------------------------------------------
-- Array Data Type
-------------------------------------------------------------------------------

-- $arrayNotes
--
-- We can use an 'Unbox' constraint in the Array type and the constraint can
-- be automatically provided to a function that pattern matches on the Array
-- type. However, it has huge performance cost, so we do not use it.
-- Investigate a GHC improvement possiblity.
--
data Array a =
#ifdef DEVBUILD
    Unbox a =>
#endif
    -- All offsets are in terms of bytes from the start of arraycontents
    Array
    { forall a. Array a -> MutByteArray
arrContents :: {-# UNPACK #-} !MutByteArray
    , forall a. Array a -> Int
arrStart :: {-# UNPACK #-} !Int -- offset
    , forall a. Array a -> Int
arrEnd   :: {-# UNPACK #-} !Int   -- offset + len
    }

-------------------------------------------------------------------------------
-- Utility functions
-------------------------------------------------------------------------------

-- XXX Rename this to "unsafeAsPtr"?
-- | Use an @Array a@ as @Ptr a@.
--
-- See 'MA.unsafePinnedAsPtr' in the Mutable array module for more details.
--
-- /Unsafe/
--
-- 1. The accessor must not access the array beyond the specified length.
-- 2. The accessor must not mutate the array.
--
-- /Pre-release/
--
{-# INLINE unsafePinnedAsPtr #-}
unsafePinnedAsPtr :: MonadIO m => Array a -> (Ptr a -> Int -> IO b) -> m b
unsafePinnedAsPtr :: forall (m :: * -> *) a b.
MonadIO m =>
Array a -> (Ptr a -> Int -> IO b) -> m b
unsafePinnedAsPtr Array a
arr Ptr a -> Int -> IO b
f = do
    let marr :: MutArray a
marr = Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr
    MutArray a
pinned <- IO (MutArray a) -> m (MutArray a)
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (MutArray a) -> m (MutArray a))
-> IO (MutArray a) -> m (MutArray a)
forall a b. (a -> b) -> a -> b
$ MutArray a -> IO (MutArray a)
forall a. MutArray a -> IO (MutArray a)
MA.pin MutArray a
marr
    MutArray a -> (Ptr a -> Int -> IO b) -> m b
forall (m :: * -> *) a b.
MonadIO m =>
MutArray a -> (Ptr a -> Int -> IO b) -> m b
MA.unsafeAsPtr MutArray a
pinned Ptr a -> Int -> IO b
f

-- | Use an @Array a@ as @ForeignPtr a@.
--
-- /Unsafe/ because of direct pointer operations. The user must ensure that they
-- are writing within the legal bounds of the array.
--
-- /Pre-release/
--
{-# INLINE unsafeAsForeignPtr #-}
unsafeAsForeignPtr
    :: MonadIO m => Array a -> (ForeignPtr a -> Int -> IO b) -> m b
unsafeAsForeignPtr :: forall (m :: * -> *) a b.
MonadIO m =>
Array a -> (ForeignPtr a -> Int -> IO b) -> m b
unsafeAsForeignPtr Array a
arr0 ForeignPtr a -> Int -> IO b
f = do
    let marr :: MutArray a
marr = Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr0
    MutArray a
pinned <- IO (MutArray a) -> m (MutArray a)
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (MutArray a) -> m (MutArray a))
-> IO (MutArray a) -> m (MutArray a)
forall a b. (a -> b) -> a -> b
$ MutArray a -> IO (MutArray a)
forall a. MutArray a -> IO (MutArray a)
MA.pin MutArray a
marr
    MutArray a -> (Ptr a -> Int -> IO b) -> m b
forall (m :: * -> *) a b.
MonadIO m =>
MutArray a -> (Ptr a -> Int -> IO b) -> m b
MA.unsafeAsPtr MutArray a
pinned (MutByteArray -> Ptr a -> Int -> IO b
forall {a}. MutByteArray -> Ptr a -> Int -> IO b
finner (MutArray a -> MutByteArray
forall a. MutArray a -> MutByteArray
MA.arrContents MutArray a
pinned))
    where
    finner :: MutByteArray -> Ptr a -> Int -> IO b
finner MutByteArray
arrContents_ (Ptr Addr#
addr#) Int
i =
        let fptrContents :: ForeignPtrContents
fptrContents =
                MutableByteArray# RealWorld -> ForeignPtrContents
PlainPtr (MutByteArray -> MutableByteArray# RealWorld
Unboxed.getMutByteArray# MutByteArray
arrContents_)
            fptr :: ForeignPtr a
fptr = Addr# -> ForeignPtrContents -> ForeignPtr a
forall a. Addr# -> ForeignPtrContents -> ForeignPtr a
ForeignPtr Addr#
addr# ForeignPtrContents
fptrContents
         in ForeignPtr a -> Int -> IO b
f ForeignPtr a
forall {a}. ForeignPtr a
fptr Int
i

{-# INLINE mutableByteArrayContents# #-}
mutableByteArrayContents# :: Exts.MutableByteArray# s -> Addr#
#if __GLASGOW_HASKELL__ >= 902
mutableByteArrayContents# :: forall s. MutableByteArray# s -> Addr#
mutableByteArrayContents# = MutableByteArray# s -> Addr#
forall s. MutableByteArray# s -> Addr#
Exts.mutableByteArrayContents#
#else
mutableByteArrayContents# x = Exts.byteArrayContents# (Exts.unsafeCoerce# x)
#endif

-- | @unsafeFromForeignPtr fptr len@ converts the "ForeignPtr" to an "Array".
--
unsafeFromForeignPtr
    :: MonadIO m => ForeignPtr Word8 -> Int -> m (Array Word8)
unsafeFromForeignPtr :: forall (m :: * -> *).
MonadIO m =>
ForeignPtr Word8 -> Int -> m (Array Word8)
unsafeFromForeignPtr (ForeignPtr Addr#
addr# ForeignPtrContents
_) Int
i
    | Addr# -> Ptr Any
forall a. Addr# -> Ptr a
Ptr Addr#
addr# Ptr Any -> Ptr Any -> Bool
forall a. Eq a => a -> a -> Bool
== Ptr Any
forall a. Ptr a
nullPtr Bool -> Bool -> Bool
|| Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = Array Word8 -> m (Array Word8)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Array Word8
forall a. Array a
empty
unsafeFromForeignPtr (ForeignPtr Addr#
addr# (PlainPtr MutableByteArray# RealWorld
marr#)) Int
len =
    let off :: Int
off = Int# -> Int
I# (Addr#
addr# Addr# -> Addr# -> Int#
`minusAddr#` MutableByteArray# RealWorld -> Addr#
forall s. MutableByteArray# s -> Addr#
mutableByteArrayContents# MutableByteArray# RealWorld
marr#)
     in Array Word8 -> m (Array Word8)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (MutByteArray -> Int -> Int -> Array Word8
forall a. MutByteArray -> Int -> Int -> Array a
Array (MutableByteArray# RealWorld -> MutByteArray
Unboxed.MutByteArray MutableByteArray# RealWorld
marr#) Int
off (Int
off Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
len))
unsafeFromForeignPtr (ForeignPtr Addr#
addr# ForeignPtrContents
_) Int
len =
    Int -> Ptr Word8 -> m (Array Word8)
forall (m :: * -> *).
MonadIO m =>
Int -> Ptr Word8 -> m (Array Word8)
fromPtrN Int
len (Addr# -> Ptr Word8
forall a. Addr# -> Ptr a
Ptr Addr#
addr#)

{-# DEPRECATED asPtrUnsafe "Please use unsafePinnedAsPtr instead." #-}
{-# INLINE asPtrUnsafe #-}
asPtrUnsafe :: MonadIO m => Array a -> (Ptr a -> m b) -> m b
asPtrUnsafe :: forall (m :: * -> *) a b.
MonadIO m =>
Array a -> (Ptr a -> m b) -> m b
asPtrUnsafe Array a
arr Ptr a -> m b
f = MutArray a -> (Ptr a -> Int -> m b) -> m b
forall (m :: * -> *) a b.
MonadIO m =>
MutArray a -> (Ptr a -> Int -> m b) -> m b
MA.unsafePinnedAsPtr (Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr) (\Ptr a
p Int
_ -> Ptr a -> m b
f Ptr a
p)

-------------------------------------------------------------------------------
-- Freezing and Thawing
-------------------------------------------------------------------------------

-- XXX For debugging we can track slices/references through a weak IORef.  Then
-- trigger a GC after freeze/thaw and assert that there are no references
-- remaining.

-- | Makes an immutable array using the underlying memory of the mutable
-- array.
--
-- Please make sure that there are no other references to the mutable array
-- lying around, so that it is never used after freezing it using
-- /unsafeFreeze/.  If the underlying array is mutated, the immutable promise
-- is lost.
--
-- /Pre-release/
{-# INLINE unsafeFreeze #-}
unsafeFreeze :: MutArray a -> Array a
unsafeFreeze :: forall a. MutArray a -> Array a
unsafeFreeze (MA.MutArray MutByteArray
ac Int
as Int
ae Int
_) = MutByteArray -> Int -> Int -> Array a
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
ac Int
as Int
ae

-- | Similar to 'unsafeFreeze' but uses 'MA.rightSize' on the mutable array
-- first.
{-# INLINE unsafeFreezeWithShrink #-}
unsafeFreezeWithShrink :: Unbox a => MutArray a -> Array a
unsafeFreezeWithShrink :: forall a. Unbox a => MutArray a -> Array a
unsafeFreezeWithShrink MutArray a
arr = IO (Array a) -> Array a
forall a. IO a -> a
unsafePerformIO (IO (Array a) -> Array a) -> IO (Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ do
  MA.MutArray MutByteArray
ac Int
as Int
ae Int
_ <- MutArray a -> IO (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
MutArray a -> m (MutArray a)
MA.rightSize MutArray a
arr
  Array a -> IO (Array a)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Array a -> IO (Array a)) -> Array a -> IO (Array a)
forall a b. (a -> b) -> a -> b
$ MutByteArray -> Int -> Int -> Array a
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
ac Int
as Int
ae

-- | Makes a mutable array using the underlying memory of the immutable array.
--
-- Please make sure that there are no other references to the immutable array
-- lying around, so that it is never used after thawing it using /unsafeThaw/.
-- If the resulting array is mutated, any references to the older immutable
-- array are mutated as well.
--
-- /Pre-release/
{-# INLINE unsafeThaw #-}
unsafeThaw :: Array a -> MutArray a
unsafeThaw :: forall a. Array a -> MutArray a
unsafeThaw (Array MutByteArray
ac Int
as Int
ae) = MutByteArray -> Int -> Int -> Int -> MutArray a
forall a. MutByteArray -> Int -> Int -> Int -> MutArray a
MA.MutArray MutByteArray
ac Int
as Int
ae Int
ae

-------------------------------------------------------------------------------
-- Pinning & Unpinning
-------------------------------------------------------------------------------

-- | Return a copy of the 'Array' in pinned memory if unpinned, else return the
-- original array.
{-# INLINE pin #-}
pin :: Array a -> IO (Array a)
pin :: forall a. Array a -> IO (Array a)
pin = (MutArray a -> Array a) -> IO (MutArray a) -> IO (Array a)
forall a b. (a -> b) -> IO a -> IO 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 (IO (MutArray a) -> IO (Array a))
-> (Array a -> IO (MutArray a)) -> Array a -> IO (Array a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MutArray a -> IO (MutArray a)
forall a. MutArray a -> IO (MutArray a)
MA.pin (MutArray a -> IO (MutArray a))
-> (Array a -> MutArray a) -> Array a -> IO (MutArray a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw

-- | Return a copy of the 'Array' in unpinned memory if pinned, else return the
-- original array.
{-# INLINE unpin #-}
unpin :: Array a -> IO (Array a)
unpin :: forall a. Array a -> IO (Array a)
unpin = (MutArray a -> Array a) -> IO (MutArray a) -> IO (Array a)
forall a b. (a -> b) -> IO a -> IO 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 (IO (MutArray a) -> IO (Array a))
-> (Array a -> IO (MutArray a)) -> Array a -> IO (Array a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MutArray a -> IO (MutArray a)
forall a. MutArray a -> IO (MutArray a)
MA.unpin (MutArray a -> IO (MutArray a))
-> (Array a -> MutArray a) -> Array a -> IO (MutArray a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw

-- | Return 'True' if the array is allocated in pinned memory.
{-# INLINE isPinned #-}
isPinned :: Array a -> Bool
isPinned :: forall a. Array a -> Bool
isPinned = MutArray a -> Bool
forall a. MutArray a -> Bool
MA.isPinned (MutArray a -> Bool) -> (Array a -> MutArray a) -> Array a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw

-------------------------------------------------------------------------------
-- Construction
-------------------------------------------------------------------------------

-- | Copy two immutable arrays into a new array. If you want to splice more
-- than two arrays then this operation would be highly inefficient because it
-- would make a copy on every splice operation, instead use the
-- 'fromChunksK' operation to combine n immutable arrays.
{-# INLINE splice #-}
splice :: (MonadIO m
#ifdef DEVBUILD
    , Unbox a
#endif
    )
    => Array a -> Array a -> m (Array a)
splice :: forall (m :: * -> *) a.
MonadIO m =>
Array a -> Array a -> m (Array a)
splice Array a
arr1 Array a
arr2 =
    MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze (MutArray a -> Array a) -> m (MutArray a) -> m (Array a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> MutArray a -> MutArray a -> m (MutArray a)
forall (m :: * -> *) a.
MonadIO m =>
MutArray a -> MutArray a -> m (MutArray a)
MA.spliceCopy (Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr1) (Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr2)

-- | Create an 'Array' from the first N elements of a list. The array is
-- allocated to size N, if the list terminates before N elements then the
-- array may hold less than N elements.
--
{-# INLINABLE fromListN #-}
fromListN :: Unbox a => Int -> [a] -> Array a
fromListN :: forall a. Unbox a => Int -> [a] -> Array a
fromListN Int
n [a]
xs = IO (Array a) -> Array a
forall a. IO a -> a
unsafePerformIO (IO (Array a) -> Array a) -> IO (Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze (MutArray a -> Array a) -> IO (MutArray a) -> IO (Array a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> [a] -> IO (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> [a] -> m (MutArray a)
MA.fromListN Int
n [a]
xs

-- | Like 'fromListN' but creates a pinned array.
{-# INLINABLE fromListN' #-}
pinnedFromListN, fromListN' :: Unbox a => Int -> [a] -> Array a
fromListN' :: forall a. Unbox a => Int -> [a] -> Array a
fromListN' Int
n [a]
xs =
    IO (Array a) -> Array a
forall a. IO a -> a
unsafePerformIO (IO (Array a) -> Array a) -> IO (Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze (MutArray a -> Array a) -> IO (MutArray a) -> IO (Array a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> [a] -> IO (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> [a] -> m (MutArray a)
MA.fromListN' Int
n [a]
xs
RENAME_PRIME(pinnedFromListN,fromListN)

-- | Create an 'Array' from the first N elements of a list in reverse order.
-- The array is allocated to size N, if the list terminates before N elements
-- then the array may hold less than N elements.
--
-- /Pre-release/
{-# INLINABLE fromListRevN #-}
fromListRevN :: Unbox a => Int -> [a] -> Array a
fromListRevN :: forall a. Unbox a => Int -> [a] -> Array a
fromListRevN Int
n [a]
xs = IO (Array a) -> Array a
forall a. IO a -> a
unsafePerformIO (IO (Array a) -> Array a) -> IO (Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze (MutArray a -> Array a) -> IO (MutArray a) -> IO (Array a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> [a] -> IO (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> [a] -> m (MutArray a)
MA.fromListRevN Int
n [a]
xs

-- | Create an 'Array' from a list. The list must be of finite size.
--
{-# INLINE fromList #-}
fromList :: Unbox a => [a] -> Array a
fromList :: forall a. Unbox a => [a] -> Array a
fromList [a]
xs = IO (Array a) -> Array a
forall a. IO a -> a
unsafePerformIO (IO (Array a) -> Array a) -> IO (Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze (MutArray a -> Array a) -> IO (MutArray a) -> IO (Array a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [a] -> IO (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
[a] -> m (MutArray a)
MA.fromList [a]
xs

-- | Like 'fromList' but creates a pinned array.
{-# INLINE fromList' #-}
pinnedFromList, fromList' :: Unbox a => [a] -> Array a
fromList' :: forall a. Unbox a => [a] -> Array a
fromList' [a]
xs = IO (Array a) -> Array a
forall a. IO a -> a
unsafePerformIO (IO (Array a) -> Array a) -> IO (Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze (MutArray a -> Array a) -> IO (MutArray a) -> IO (Array a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [a] -> IO (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
[a] -> m (MutArray a)
MA.fromList' [a]
xs
RENAME_PRIME(pinnedFromList,fromList)

-- | Create an 'Array' from a list in reverse order. The list must be of finite
-- size.
--
-- /Pre-release/
{-# INLINABLE fromListRev #-}
fromListRev :: Unbox a => [a] -> Array a
fromListRev :: forall a. Unbox a => [a] -> Array a
fromListRev [a]
xs = IO (Array a) -> Array a
forall a. IO a -> a
unsafePerformIO (IO (Array a) -> Array a) -> IO (Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze (MutArray a -> Array a) -> IO (MutArray a) -> IO (Array a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [a] -> IO (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
[a] -> m (MutArray a)
MA.fromListRev [a]
xs

-- | Create an 'Array' from the first N elements of a stream. The array is
-- allocated to size N, if the stream terminates before N elements then the
-- array may hold less than N elements.
--
-- >>> fromStreamN n = Stream.fold (Array.createOf n)
--
-- /Pre-release/
{-# INLINE_NORMAL fromStreamN #-}
fromStreamN :: (MonadIO m, Unbox a) => Int -> Stream m a -> m (Array a)
fromStreamN :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Stream m a -> m (Array a)
fromStreamN Int
n Stream m a
m = do
    Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ [Char] -> m ()
forall a. HasCallStack => [Char] -> a
error [Char]
"writeN: negative write count specified"
    MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze (MutArray a -> Array a) -> m (MutArray a) -> m (Array a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Stream m a -> m (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Stream m a -> m (MutArray a)
MA.fromStreamN Int
n Stream m a
m
-- fromStreamN n = D.fold (writeN n)

{-# DEPRECATED fromStreamDN "Please use fromStreamN instead." #-}
fromStreamDN :: forall m a. (MonadIO m, Unbox a)
    => Int -> D.Stream m a -> m (Array a)
fromStreamDN :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Stream m a -> m (Array a)
fromStreamDN = Int -> Stream m a -> m (Array a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Stream m a -> m (Array a)
fromStreamN

-- | Create an 'Array' from a stream. This is useful when we want to create a
-- single array from a stream of unknown size. 'writeN' is at least twice
-- as efficient when the size is already known.
--
-- >>> fromStream = Stream.fold Array.create
--
-- Note that if the input stream is too large memory allocation for the array
-- may fail.  When the stream size is not known, `chunksOf` followed by
-- processing of indvidual arrays in the resulting stream should be preferred.
--
-- /Pre-release/
{-# INLINE_NORMAL fromStreamD #-}
fromStream :: (MonadIO m, Unbox a) => Stream m a -> m (Array a)
fromStream :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Stream m a -> m (Array a)
fromStream = Fold m a (Array a) -> Stream m a -> m (Array a)
forall (m :: * -> *) a b.
Monad m =>
Fold m a b -> Stream m a -> m b
D.fold Fold m a (Array a)
forall (m :: * -> *) a. (MonadIO m, Unbox a) => Fold m a (Array a)
write
-- fromStreamD str = unsafeFreeze <$> MA.fromStream str

{-# DEPRECATED fromStreamD "Please use fromStream instead." #-}
fromStreamD :: forall m a. (MonadIO m, Unbox a)
    => D.Stream m a -> m (Array a)
fromStreamD :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Stream m a -> m (Array a)
fromStreamD = Stream m a -> m (Array a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Stream m a -> m (Array a)
fromStream

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

-- | /O(1)/ Slice an array in constant time.
--
-- Caution: The bounds of the slice are not checked.
--
-- /Unsafe/
--
-- /Pre-release/
{-# INLINE unsafeSliceOffLen #-}
unsafeSliceOffLen, unsafeGetSlice ::
       forall a. Unbox a
    => Int -- ^ starting index
    -> Int -- ^ length of the slice
    -> Array a
    -> Array a
unsafeSliceOffLen :: forall a. Unbox a => Int -> Int -> Array a -> Array a
unsafeSliceOffLen 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)
RENAME(unsafeGetSlice,unsafeSliceOffLen)

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

-- |
--
-- >>> null arr = Array.byteLength arr == 0
--
-- Note that this may be faster than checking Array.length as length
-- calculation involves a division operation.
--
-- /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

-- 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

-- | 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

{-# INLINE head #-}
head :: Unbox a => Array a -> Maybe a
head :: forall a. Unbox a => Array a -> Maybe a
head = Int -> Array a -> Maybe a
forall a. Unbox a => Int -> Array a -> Maybe a
getIndex Int
0

{-# 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

{-# INLINE unsafeTail #-}
unsafeTail :: forall a. Unbox a => Array a -> Array a
unsafeTail :: forall a. Unbox a => Array a -> Array a
unsafeTail Array{Int
MutByteArray
arrContents :: forall a. Array a -> MutByteArray
arrStart :: forall a. Array a -> Int
arrEnd :: forall a. Array a -> Int
arrContents :: MutByteArray
arrStart :: Int
arrEnd :: Int
..} = MutByteArray -> Int -> Int -> Array a
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
arrContents (Int
arrStart Int -> Int -> Int
forall a. Num a => a -> a -> a
+ SIZE_OF(a)) arrEnd

{-# INLINE tail #-}
tail :: Unbox a => Array a -> Array a
tail :: forall a. Unbox a => Array a -> Array a
tail arr :: Array a
arr@Array{Int
MutByteArray
arrContents :: forall a. Array a -> MutByteArray
arrStart :: forall a. Array a -> Int
arrEnd :: forall a. Array a -> Int
arrContents :: MutByteArray
arrStart :: Int
arrEnd :: Int
..} =
    if Int
arrEnd Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
arrStart
    then Array a -> Array a
forall a. Unbox a => Array a -> Array a
unsafeTail Array a
arr
    else Array a
arr

{-# INLINE uncons #-}
uncons :: Unbox a => Array a -> Maybe (a, Array a)
uncons :: forall a. Unbox a => Array a -> Maybe (a, Array a)
uncons Array a
arr =
    if Array a -> Bool
forall a. Array a -> Bool
null Array a
arr
    then Maybe (a, Array a)
forall a. Maybe a
Nothing
    else (a, Array a) -> Maybe (a, Array a)
forall a. a -> Maybe a
Just (Int -> Array a -> a
forall a. Unbox a => Int -> Array a -> a
unsafeGetIndex Int
0 Array a
arr, Array a -> Array a
forall a. Unbox a => Array a -> Array a
unsafeTail Array a
arr)

{-# INLINE unsafeInit #-}
unsafeInit :: forall a. Unbox a => Array a -> Array a
unsafeInit :: forall a. Unbox a => Array a -> Array a
unsafeInit Array{Int
MutByteArray
arrContents :: forall a. Array a -> MutByteArray
arrStart :: forall a. Array a -> Int
arrEnd :: forall a. Array a -> Int
arrContents :: MutByteArray
arrStart :: Int
arrEnd :: Int
..} = MutByteArray -> Int -> Int -> Array a
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
arrContents Int
arrStart (Int
arrEnd Int -> Int -> Int
forall a. Num a => a -> a -> a
- SIZE_OF(a))

{-# INLINE init #-}
init :: Unbox a => Array a -> Array a
init :: forall a. Unbox a => Array a -> Array a
init arr :: Array a
arr@Array{Int
MutByteArray
arrContents :: forall a. Array a -> MutByteArray
arrStart :: forall a. Array a -> Int
arrEnd :: forall a. Array a -> Int
arrContents :: MutByteArray
arrStart :: Int
arrEnd :: Int
..} =
    if Int
arrEnd Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
arrStart
    then Array a -> Array a
forall a. Unbox a => Array a -> Array a
unsafeInit Array a
arr
    else Array a
arr

{-# INLINE unsnoc #-}
unsnoc :: Unbox a => Array a -> Maybe (Array a, a)
unsnoc :: forall a. Unbox a => Array a -> Maybe (Array a, a)
unsnoc Array a
arr =
    if Array a -> Bool
forall a. Array a -> Bool
null Array a
arr
    then Maybe (Array a, a)
forall a. Maybe a
Nothing
    else (Array a, a) -> Maybe (Array a, a)
forall a. a -> Maybe a
Just (Array a -> Array a
forall a. Unbox a => Array a -> Array a
unsafeTail Array a
arr, Int -> Array a -> a
forall a. Unbox a => Int -> Array a -> a
unsafeGetIndexRev Int
0 Array a
arr)

-------------------------------------------------------------------------------
-- Streams of arrays
-------------------------------------------------------------------------------

{-# INLINE buildChunks #-}
buildChunks :: (MonadIO m, Unbox a) =>
    D.Stream m a -> m (K.StreamK m (Array a))
buildChunks :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Stream m a -> m (StreamK m (Array a))
buildChunks Stream m a
m = (Array a -> StreamK m (Array a) -> StreamK m (Array a))
-> StreamK m (Array a)
-> Stream m (Array a)
-> m (StreamK m (Array a))
forall (m :: * -> *) a b.
Monad m =>
(a -> b -> b) -> b -> Stream m a -> m b
D.foldr Array a -> StreamK m (Array a) -> StreamK m (Array a)
forall a (m :: * -> *). a -> StreamK m a -> StreamK m a
K.cons StreamK m (Array a)
forall (m :: * -> *) a. StreamK m a
K.nil (Stream m (Array a) -> m (StreamK m (Array a)))
-> Stream m (Array a) -> m (StreamK m (Array a))
forall a b. (a -> b) -> a -> b
$ Int -> Stream m a -> Stream m (Array a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Stream m a -> Stream m (Array a)
chunksOf Int
defaultChunkSize Stream m a
m

{-# DEPRECATED bufferChunks "Please use buildChunks instead." #-}
bufferChunks :: (MonadIO m, Unbox a) =>
    D.Stream m a -> m (K.StreamK m (Array a))
bufferChunks :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Stream m a -> m (StreamK m (Array a))
bufferChunks = Stream m a -> m (StreamK m (Array a))
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Stream m a -> m (StreamK m (Array a))
buildChunks

-- | @chunksOf n stream@ groups the elements in the input stream into arrays of
-- @n@ elements each.
--
-- Same as the following but may be more efficient:
--
-- >>> chunksOf n = Stream.foldMany (Array.createOf n)
--
-- /Pre-release/
{-# INLINE_NORMAL chunksOf #-}
chunksOf :: forall m a. (MonadIO m, Unbox a)
    => Int -> D.Stream m a -> D.Stream m (Array a)
chunksOf :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Stream m a -> Stream m (Array a)
chunksOf Int
n Stream m a
str = (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 a -> Stream m (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Stream m a -> Stream m (MutArray a)
MA.chunksOf Int
n Stream m a
str

-- | Like 'chunksOf' but creates pinned arrays.
{-# INLINE_NORMAL chunksOf' #-}
pinnedChunksOf, chunksOf' :: forall m a. (MonadIO m, Unbox a)
    => Int -> D.Stream m a -> D.Stream m (Array a)
chunksOf' :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Stream m a -> Stream m (Array a)
chunksOf' Int
n Stream m a
str = (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 a -> Stream m (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Stream m a -> Stream m (MutArray a)
MA.chunksOf' Int
n Stream m a
str
RENAME_PRIME(pinnedChunksOf,chunksOf)

-- | Create arrays from the input stream using a predicate to find the end of
-- the chunk. When the predicate matches, the chunk ends, the matching element
-- is included in the chunk.
--
--  Definition:
--
-- >>> chunksEndBy p = Stream.foldMany (Fold.takeEndBy p Array.create)
--
{-# INLINE chunksEndBy #-}
chunksEndBy :: forall m a. (MonadIO m, Unbox a)
    => (a -> Bool) -> D.Stream m a -> D.Stream m (Array a)
chunksEndBy :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
(a -> Bool) -> Stream m a -> Stream m (Array a)
chunksEndBy a -> Bool
p = Fold m a (Array a) -> Stream m a -> Stream m (Array a)
forall (m :: * -> *) a b.
Monad m =>
Fold m a b -> Stream m a -> Stream m b
D.foldMany ((a -> Bool) -> Fold m a (Array a) -> Fold m a (Array a)
forall (m :: * -> *) a b.
Monad m =>
(a -> Bool) -> Fold m a b -> Fold m a b
Fold.takeEndBy a -> Bool
p Fold m a (Array a)
forall (m :: * -> *) a. (MonadIO m, Unbox a) => Fold m a (Array a)
create)

-- | Like 'chunksEndBy' but creates pinned arrays.
--
{-# INLINE chunksEndBy' #-}
chunksEndBy' :: forall m a. (MonadIO m, Unbox a)
    => (a -> Bool) -> D.Stream m a -> D.Stream m (Array a)
chunksEndBy' :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
(a -> Bool) -> Stream m a -> Stream m (Array a)
chunksEndBy' a -> Bool
p = Fold m a (Array a) -> Stream m a -> Stream m (Array a)
forall (m :: * -> *) a b.
Monad m =>
Fold m a b -> Stream m a -> Stream m b
D.foldMany ((a -> Bool) -> Fold m a (Array a) -> Fold m a (Array a)
forall (m :: * -> *) a b.
Monad m =>
(a -> Bool) -> Fold m a b -> Fold m a b
Fold.takeEndBy a -> Bool
p Fold m a (Array a)
forall (m :: * -> *) a. (MonadIO m, Unbox a) => Fold m a (Array a)
create')

-- | Create chunks using newline as the separator, including it.
{-# INLINE chunksEndByLn #-}
chunksEndByLn :: (MonadIO m)
    => D.Stream m Word8 -> D.Stream m (Array Word8)
chunksEndByLn :: forall (m :: * -> *).
MonadIO m =>
Stream m Word8 -> Stream m (Array Word8)
chunksEndByLn = (Word8 -> Bool) -> Stream m Word8 -> Stream m (Array Word8)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
(a -> Bool) -> Stream m a -> Stream m (Array a)
chunksEndBy (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Char -> Int
ord Char
'\n'))

-- | Like 'chunksEndByLn' but creates pinned arrays.
{-# INLINE chunksEndByLn' #-}
chunksEndByLn' :: (MonadIO m)
    => D.Stream m Word8 -> D.Stream m (Array Word8)
chunksEndByLn' :: forall (m :: * -> *).
MonadIO m =>
Stream m Word8 -> Stream m (Array Word8)
chunksEndByLn' = (Word8 -> Bool) -> Stream m Word8 -> Stream m (Array Word8)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
(a -> Bool) -> Stream m a -> Stream m (Array a)
chunksEndBy' (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Char -> Int
ord Char
'\n'))

-- XXX Remove MonadIO

{-# INLINE splitEndBy #-}
splitEndBy :: (MonadIO m, Unbox a) =>
    (a -> Bool) -> Array a -> Stream m (Array a)
splitEndBy :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
(a -> Bool) -> Array a -> Stream m (Array a)
splitEndBy a -> Bool
p Array a
arr = (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
$ (a -> Bool) -> MutArray a -> Stream m (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
(a -> Bool) -> MutArray a -> Stream m (MutArray a)
MA.splitEndBy a -> Bool
p (Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr)

-- | Split the array into a stream of slices using a predicate. The element
-- matching the predicate is dropped.
--
-- /Pre-release/
{-# INLINE splitEndBy_ #-}
splitEndBy_ :: (Monad m, Unbox a) =>
    (a -> Bool) -> Array a -> Stream m (Array a)
splitEndBy_ :: forall (m :: * -> *) a.
(Monad m, Unbox a) =>
(a -> Bool) -> Array a -> Stream m (Array a)
splitEndBy_ 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
unsafeSliceOffLen 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.indexEndBy_ a -> Bool
predicate (Array a -> Stream m a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
read Array a
arr)

-- | Convert a stream of arrays into a stream of their elements.
--
-- >>> concat = Stream.unfoldEach Array.reader
--
{-# INLINE_NORMAL concat #-}
concat :: (Monad m, Unbox a) => Stream m (Array a) -> Stream m a
concat :: forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Stream m (Array a) -> Stream m a
concat = (forall b. IO b -> m b) -> Stream m (MutArray a) -> Stream m a
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
(forall b. IO b -> m b) -> Stream m (MutArray a) -> Stream m a
MA.concatWith (b -> m b
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (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 (MutArray a) -> Stream m a)
-> (Stream m (Array a) -> Stream m (MutArray a))
-> Stream m (Array a)
-> Stream m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (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
-- concat = D.unfoldMany reader

{-# DEPRECATED flattenArrays "Please use \"unfoldMany reader\" instead." #-}
{-# INLINE flattenArrays #-}
flattenArrays :: forall m a. (MonadIO m, Unbox a)
    => D.Stream m (Array a) -> D.Stream m a
flattenArrays :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Stream m (Array a) -> Stream m a
flattenArrays = Stream m (Array a) -> Stream m a
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Stream m (Array a) -> Stream m a
concat

-- | Convert a stream of arrays into a stream of their elements reversing the
-- contents of each array before flattening.
--
-- >>> concatRev = Stream.unfoldEach Array.readerRev
--
{-# INLINE_NORMAL concatRev #-}
concatRev :: forall m a. (Monad m, Unbox a)
    => D.Stream m (Array a) -> D.Stream m a
-- XXX this requires MonadIO whereas the unfoldMany version does not
concatRev :: forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Stream m (Array a) -> Stream m a
concatRev = (forall b. IO b -> m b) -> Stream m (MutArray a) -> Stream m a
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
(forall b. IO b -> m b) -> Stream m (MutArray a) -> Stream m a
MA.concatRevWith (b -> m b
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (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 (MutArray a) -> Stream m a)
-> (Stream m (Array a) -> Stream m (MutArray a))
-> Stream m (Array a)
-> Stream m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (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
-- concatRev = D.unfoldMany readerRev

{-# DEPRECATED flattenArraysRev "Please use \"unfoldMany readerRev\" instead." #-}
{-# INLINE flattenArraysRev #-}
flattenArraysRev :: forall m a. (MonadIO m, Unbox a)
    => D.Stream m (Array a) -> D.Stream m a
flattenArraysRev :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Stream m (Array a) -> Stream m a
flattenArraysRev = Stream m (Array a) -> Stream m a
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Stream m (Array a) -> Stream m a
concatRev

-------------------------------------------------------------------------------
-- Compact
-------------------------------------------------------------------------------

-- XXX Note that this thaws immutable arrays for appending, that may be
-- problematic if multiple users do the same thing, however, thawed immutable
-- arrays would have no capacity to append, therefore, a copy will be forced
-- anyway.

-- | Fold @createCompactMin n@ coalesces adjacent arrays in the input
-- stream until the size becomes greater than or equal to n.
--
-- Generates unpinned arrays irrespective of the pinning status of input
-- arrays.
{-# INLINE_NORMAL createCompactMin #-}
createCompactMin, fCompactGE :: (MonadIO m, Unbox a) =>
    Int -> Fold m (Array a) (Array a)
createCompactMin :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m (Array a) (Array a)
createCompactMin Int
n =
    (MutArray a -> Array a)
-> Fold m (Array a) (MutArray a) -> Fold m (Array a) (Array a)
forall a b. (a -> b) -> Fold m (Array a) a -> Fold 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 (Fold m (Array a) (MutArray a) -> Fold m (Array a) (Array a))
-> Fold m (Array a) (MutArray a) -> Fold m (Array a) (Array a)
forall a b. (a -> b) -> a -> b
$ (Array a -> MutArray a)
-> Fold m (MutArray a) (MutArray a)
-> Fold m (Array a) (MutArray a)
forall a b (m :: * -> *) r. (a -> b) -> Fold m b r -> Fold m a r
Fold.lmap Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw (Fold m (MutArray a) (MutArray a) -> Fold m (Array a) (MutArray a))
-> Fold m (MutArray a) (MutArray a)
-> Fold m (Array a) (MutArray a)
forall a b. (a -> b) -> a -> b
$ Int -> Fold m (MutArray a) (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m (MutArray a) (MutArray a)
MA.createCompactMin Int
n

RENAME(fCompactGE,createCompactMin)

-- | Pinned version of 'createCompactMin'.
{-# INLINE_NORMAL createCompactMin' #-}
createCompactMin', fPinnedCompactGE :: (MonadIO m, Unbox a) =>
    Int -> Fold m (Array a) (Array a)
createCompactMin' :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m (Array a) (Array a)
createCompactMin' Int
n =
    (MutArray a -> Array a)
-> Fold m (Array a) (MutArray a) -> Fold m (Array a) (Array a)
forall a b. (a -> b) -> Fold m (Array a) a -> Fold 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 (Fold m (Array a) (MutArray a) -> Fold m (Array a) (Array a))
-> Fold m (Array a) (MutArray a) -> Fold m (Array a) (Array a)
forall a b. (a -> b) -> a -> b
$ (Array a -> MutArray a)
-> Fold m (MutArray a) (MutArray a)
-> Fold m (Array a) (MutArray a)
forall a b (m :: * -> *) r. (a -> b) -> Fold m b r -> Fold m a r
Fold.lmap Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw (Fold m (MutArray a) (MutArray a) -> Fold m (Array a) (MutArray a))
-> Fold m (MutArray a) (MutArray a)
-> Fold m (Array a) (MutArray a)
forall a b. (a -> b) -> a -> b
$ Int -> Fold m (MutArray a) (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m (MutArray a) (MutArray a)
MA.createCompactMin' Int
n

{-# DEPRECATED fPinnedCompactGE "Please use createCompactMin' instead." #-}
{-# INLINE fPinnedCompactGE #-}
fPinnedCompactGE :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m (Array a) (Array a)
fPinnedCompactGE = Int -> Fold m (Array a) (Array a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m (Array a) (Array a)
createCompactMin

-- | @compactBySize n stream@ coalesces adjacent arrays in the @stream@ until
-- the size becomes greater than or equal to @n@.
--
-- >>> compactBySize n = Stream.foldMany (Array.createCompactMin n)
--
-- Generates unpinned arrays irrespective of the pinning status of input
-- arrays.
{-# INLINE compactMin #-}
compactMin, compactGE ::
       (MonadIO m, Unbox a)
    => Int -> Stream m (Array a) -> Stream m (Array a)
compactMin :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Stream m (Array a) -> Stream m (Array a)
compactMin 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.compactMin 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

RENAME(compactGE,compactMin)

-- | Like 'compactBySizeGE' but for transforming folds instead of stream.
--
-- >>> lCompactBySizeGE n = Fold.many (Array.createCompactMin n)
--
-- Generates unpinned arrays irrespective of the pinning status of input
-- arrays.
{-# DEPRECATED lCompactGE "Please use scanCompactMin instead." #-}
{-# INLINE_NORMAL lCompactGE #-}
lCompactGE :: (MonadIO m, Unbox a)
    => Int -> Fold m (Array a) () -> Fold m (Array a) ()
lCompactGE :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m (Array a) () -> Fold m (Array a) ()
lCompactGE Int
n Fold m (Array a) ()
fld =
    (Array a -> MutArray a)
-> Fold m (MutArray a) () -> Fold m (Array a) ()
forall a b (m :: * -> *) r. (a -> b) -> Fold m b r -> Fold m a r
Fold.lmap Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw (Fold m (MutArray a) () -> Fold m (Array a) ())
-> Fold m (MutArray a) () -> Fold m (Array a) ()
forall a b. (a -> b) -> a -> b
$ Int -> Fold m (MutArray a) () -> Fold m (MutArray a) ()
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m (MutArray a) () -> Fold m (MutArray a) ()
MA.lCompactGE Int
n ((MutArray a -> Array a)
-> Fold m (Array a) () -> Fold m (MutArray a) ()
forall a b (m :: * -> *) r. (a -> b) -> Fold m b r -> Fold m a r
Fold.lmap MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze Fold m (Array a) ()
fld)

-- | Pinned version of 'lCompactGE'.
{-# DEPRECATED lPinnedCompactGE "Please use scanCompactMin' instead." #-}
{-# INLINE_NORMAL lPinnedCompactGE #-}
lPinnedCompactGE :: (MonadIO m, Unbox a)
    => Int -> Fold m (Array a) () -> Fold m (Array a) ()
lPinnedCompactGE :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m (Array a) () -> Fold m (Array a) ()
lPinnedCompactGE Int
n Fold m (Array a) ()
fld =
    (Array a -> MutArray a)
-> Fold m (MutArray a) () -> Fold m (Array a) ()
forall a b (m :: * -> *) r. (a -> b) -> Fold m b r -> Fold m a r
Fold.lmap Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw (Fold m (MutArray a) () -> Fold m (Array a) ())
-> Fold m (MutArray a) () -> Fold m (Array a) ()
forall a b. (a -> b) -> a -> b
$ Int -> Fold m (MutArray a) () -> Fold m (MutArray a) ()
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m (MutArray a) () -> Fold m (MutArray a) ()
MA.lPinnedCompactGE Int
n ((MutArray a -> Array a)
-> Fold m (Array a) () -> Fold m (MutArray a) ()
forall a b (m :: * -> *) r. (a -> b) -> Fold m b r -> Fold m a r
Fold.lmap MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze Fold m (Array a) ()
fld)

{-# INLINE scanCompactMin #-}
scanCompactMin :: forall m a. (MonadIO m, Unbox a)
    => Int -> Scanl m (Array a) (Maybe (Array a))
scanCompactMin :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Scanl m (Array a) (Maybe (Array a))
scanCompactMin Int
n =
    (Array a -> MutArray a)
-> Scanl m (MutArray a) (Maybe (Array a))
-> Scanl m (Array a) (Maybe (Array a))
forall a b (m :: * -> *) r. (a -> b) -> Scanl m b r -> Scanl m a r
Scanl.lmap Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw
        (Scanl m (MutArray a) (Maybe (Array a))
 -> Scanl m (Array a) (Maybe (Array a)))
-> Scanl m (MutArray a) (Maybe (Array a))
-> Scanl m (Array a) (Maybe (Array a))
forall a b. (a -> b) -> a -> b
$ (Maybe (MutArray a) -> Maybe (Array a))
-> Scanl m (MutArray a) (Maybe (MutArray a))
-> Scanl m (MutArray a) (Maybe (Array a))
forall a b.
(a -> b) -> Scanl m (MutArray a) a -> Scanl m (MutArray a) b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((MutArray a -> Array a) -> Maybe (MutArray a) -> Maybe (Array a)
forall a b. (a -> b) -> Maybe a -> Maybe 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)
        (Scanl m (MutArray a) (Maybe (MutArray a))
 -> Scanl m (MutArray a) (Maybe (Array a)))
-> Scanl m (MutArray a) (Maybe (MutArray a))
-> Scanl m (MutArray a) (Maybe (Array a))
forall a b. (a -> b) -> a -> b
$ Int -> Scanl m (MutArray a) (Maybe (MutArray a))
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Scanl m (MutArray a) (Maybe (MutArray a))
MA.scanCompactMin Int
n

{-# INLINE scanCompactMin' #-}
scanCompactMin' :: forall m a. (MonadIO m, Unbox a)
    => Int -> Scanl m (Array a) (Maybe (Array a))
scanCompactMin' :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Scanl m (Array a) (Maybe (Array a))
scanCompactMin' Int
n =
    (Array a -> MutArray a)
-> Scanl m (MutArray a) (Maybe (Array a))
-> Scanl m (Array a) (Maybe (Array a))
forall a b (m :: * -> *) r. (a -> b) -> Scanl m b r -> Scanl m a r
Scanl.lmap Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw
        (Scanl m (MutArray a) (Maybe (Array a))
 -> Scanl m (Array a) (Maybe (Array a)))
-> Scanl m (MutArray a) (Maybe (Array a))
-> Scanl m (Array a) (Maybe (Array a))
forall a b. (a -> b) -> a -> b
$ (Maybe (MutArray a) -> Maybe (Array a))
-> Scanl m (MutArray a) (Maybe (MutArray a))
-> Scanl m (MutArray a) (Maybe (Array a))
forall a b.
(a -> b) -> Scanl m (MutArray a) a -> Scanl m (MutArray a) b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((MutArray a -> Array a) -> Maybe (MutArray a) -> Maybe (Array a)
forall a b. (a -> b) -> Maybe a -> Maybe 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)
        (Scanl m (MutArray a) (Maybe (MutArray a))
 -> Scanl m (MutArray a) (Maybe (Array a)))
-> Scanl m (MutArray a) (Maybe (MutArray a))
-> Scanl m (MutArray a) (Maybe (Array a))
forall a b. (a -> b) -> a -> b
$ Int -> Scanl m (MutArray a) (Maybe (MutArray a))
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Scanl m (MutArray a) (Maybe (MutArray a))
MA.scanCompactMin' Int
n

-------------------------------------------------------------------------------
-- Splitting
-------------------------------------------------------------------------------

-- Drops the separator byte
{-# INLINE breakEndByWord8_ #-}
breakEndByWord8_, breakOn :: MonadIO m
    => Word8 -> Array Word8 -> m (Array Word8, Maybe (Array Word8))
breakEndByWord8_ :: forall (m :: * -> *).
MonadIO m =>
Word8 -> Array Word8 -> m (Array Word8, Maybe (Array Word8))
breakEndByWord8_ Word8
sep Array Word8
arr = do
  (MutArray Word8
a, Maybe (MutArray Word8)
b) <- Word8
-> MutArray Word8 -> m (MutArray Word8, Maybe (MutArray Word8))
forall (m :: * -> *).
MonadIO m =>
Word8
-> MutArray Word8 -> m (MutArray Word8, Maybe (MutArray Word8))
MA.breakOn Word8
sep (Array Word8 -> MutArray Word8
forall a. Array a -> MutArray a
unsafeThaw Array Word8
arr)
  (Array Word8, Maybe (Array Word8))
-> m (Array Word8, Maybe (Array Word8))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (MutArray Word8 -> Array Word8
forall a. MutArray a -> Array a
unsafeFreeze MutArray Word8
a, MutArray Word8 -> Array Word8
forall a. MutArray a -> Array a
unsafeFreeze (MutArray Word8 -> Array Word8)
-> Maybe (MutArray Word8) -> Maybe (Array Word8)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe (MutArray Word8)
b)
RENAME(breakOn,breakEndByWord8_)

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

-- | Return element at the specified index without checking the bounds.
--
-- Unsafe because it does not check the bounds of the array.
{-# INLINE_NORMAL unsafeGetIndexIO #-}
unsafeGetIndexIO, unsafeIndexIO :: forall a. Unbox a => Int -> Array a -> IO a
unsafeGetIndexIO :: forall a. Unbox a => Int -> Array a -> IO a
unsafeGetIndexIO Int
i Array a
arr = Int -> MutArray a -> IO a
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> MutArray a -> m a
MA.unsafeGetIndex Int
i (Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr)

-- | Return element at the specified index without checking the bounds.
{-# INLINE_NORMAL unsafeGetIndex #-}
unsafeGetIndex, getIndexUnsafe :: forall a. Unbox a => Int -> Array a -> a
unsafeGetIndex :: forall a. Unbox a => Int -> Array a -> a
unsafeGetIndex Int
i Array a
arr = let !r :: a
r = IO a -> a
forall a. IO a -> a
unsafeInlineIO (IO a -> a) -> IO a -> a
forall a b. (a -> b) -> a -> b
$ Int -> Array a -> IO a
forall a. Unbox a => Int -> Array a -> IO a
unsafeGetIndexIO Int
i Array a
arr in a
r

{-# DEPRECATED unsafeIndex "Please use 'unsafeGetIndex' instead" #-}
{-# INLINE_NORMAL unsafeIndex #-}
unsafeIndex :: forall a. Unbox a => Int -> Array a -> a
unsafeIndex :: forall a. Unbox a => Int -> Array a -> a
unsafeIndex = Int -> Array a -> a
forall a. Unbox a => Int -> Array a -> a
unsafeGetIndex

{-# INLINE_NORMAL unsafeGetIndexRevIO #-}
unsafeGetIndexRevIO :: forall a. Unbox a => Int -> Array a -> IO a
unsafeGetIndexRevIO :: forall a. Unbox a => Int -> Array a -> IO a
unsafeGetIndexRevIO Int
i Array a
arr = Int -> MutArray a -> IO a
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> MutArray a -> m a
MA.unsafeGetIndexRev Int
i (Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr)

{-# INLINE_NORMAL unsafeGetIndexRev #-}
unsafeGetIndexRev :: forall a. Unbox a => Int -> Array a -> a
unsafeGetIndexRev :: forall a. Unbox a => Int -> Array a -> a
unsafeGetIndexRev Int
i Array a
arr =
    let !r :: a
r = IO a -> a
forall a. IO a -> a
unsafeInlineIO (IO a -> a) -> IO a -> a
forall a b. (a -> b) -> a -> b
$ Int -> Array a -> IO a
forall a. Unbox a => Int -> Array a -> IO a
unsafeGetIndexRevIO Int
i Array a
arr in a
r

-- | /O(1)/ Get the byte length of the array.
--
{-# INLINE byteLength #-}
byteLength :: Array a -> Int
byteLength :: forall a. Array a -> Int
byteLength = MutArray a -> Int
forall a. MutArray a -> Int
MA.byteLength (MutArray a -> Int) -> (Array a -> MutArray a) -> Array a -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw

-- | /O(1)/ Get the length of the array i.e. the number of elements in the
-- array.
--
{-# INLINE length #-}
length :: Unbox a => Array a -> Int
length :: forall a. Unbox a => Array a -> Int
length Array a
arr = MutArray a -> Int
forall a. Unbox a => MutArray a -> Int
MA.length (Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr)

{-# INLINE_NORMAL producer #-}
producer :: forall m a. (Monad m, Unbox a) => Producer m (Array a) a
producer :: forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Producer m (Array a) a
producer =
    (Array a -> MutArray a)
-> (MutArray a -> Array a)
-> Producer m (MutArray a) a
-> Producer m (Array a) a
forall (m :: * -> *) a c b.
Functor m =>
(a -> c) -> (c -> a) -> Producer m c b -> Producer m a b
Producer.translate Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze
        (Producer m (MutArray a) a -> Producer m (Array a) a)
-> Producer m (MutArray a) a -> Producer m (Array a) a
forall a b. (a -> b) -> a -> b
$ (forall b. IO b -> m b) -> Producer m (MutArray a) a
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
(forall b. IO b -> m b) -> Producer m (MutArray a) a
MA.producerWith (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)

-- | Unfold an array into a stream.
--
{-# INLINE_NORMAL reader #-}
reader :: forall m a. (Monad m, Unbox a) => Unfold m (Array a) a
reader :: forall (m :: * -> *) a. (Monad m, Unbox a) => Unfold m (Array a) a
reader = Producer m (Array a) a -> Unfold m (Array a) a
forall (m :: * -> *) a b. Producer m a b -> Unfold m a b
Producer.simplify Producer m (Array a) a
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Producer m (Array a) a
producer

-- | Unfold an array into a stream, does not check the end of the array, the
-- user is responsible for terminating the stream within the array bounds. For
-- high performance application where the end condition can be determined by
-- a terminating fold.
--
-- Written in the hope that it may be faster than "read", however, in the case
-- for which this was written, "read" proves to be faster even though the core
-- generated with unsafeRead looks simpler.
--
-- /Pre-release/
--
{-# INLINE_NORMAL unsafeReader #-}
unsafeReader, readerUnsafe :: forall m a. (Monad m, Unbox a) => Unfold m (Array a) a
unsafeReader :: forall (m :: * -> *) a. (Monad m, Unbox a) => Unfold m (Array a) a
unsafeReader = (ArrayUnsafe Any -> m (Step (ArrayUnsafe Any) a))
-> (Array a -> m (ArrayUnsafe Any)) -> Unfold m (Array a) a
forall (m :: * -> *) a b s.
(s -> m (Step s b)) -> (a -> m s) -> Unfold m a b
Unfold ArrayUnsafe Any -> m (Step (ArrayUnsafe Any) a)
forall {m :: * -> *} {a} {a} {a}.
(Monad m, Unbox a) =>
ArrayUnsafe a -> m (Step (ArrayUnsafe a) a)
step Array a -> m (ArrayUnsafe Any)
forall {m :: * -> *} {a} {a}.
Monad m =>
Array a -> m (ArrayUnsafe a)
inject
    where

    inject :: Array a -> m (ArrayUnsafe a)
inject (Array MutByteArray
contents Int
start Int
end) =
        ArrayUnsafe a -> m (ArrayUnsafe a)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (MutByteArray -> Int -> Int -> ArrayUnsafe a
forall a. MutByteArray -> Int -> Int -> ArrayUnsafe a
MA.ArrayUnsafe MutByteArray
contents Int
end Int
start)

    {-# INLINE_LATE step #-}
    step :: ArrayUnsafe a -> m (Step (ArrayUnsafe a) a)
step (MA.ArrayUnsafe MutByteArray
contents Int
end Int
p) = do
            -- unsafeInlineIO allows us to run this in Identity monad for pure
            -- toList/foldr case which makes them much faster due to not
            -- accumulating the list and fusing better with the pure consumers.
            --
            -- This should be safe as the array contents are guaranteed to be
            -- evaluated/written to before we peek at them.
            let !x :: a
x = 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
            let !p1 :: Int
p1 = INDEX_NEXT(p,a)
            Step (ArrayUnsafe a) a -> m (Step (ArrayUnsafe a) a)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Step (ArrayUnsafe a) a -> m (Step (ArrayUnsafe a) a))
-> Step (ArrayUnsafe a) a -> m (Step (ArrayUnsafe a) a)
forall a b. (a -> b) -> a -> b
$ a -> ArrayUnsafe a -> Step (ArrayUnsafe a) a
forall s a. a -> s -> Step s a
D.Yield a
x (MutByteArray -> Int -> Int -> ArrayUnsafe a
forall a. MutByteArray -> Int -> Int -> ArrayUnsafe a
MA.ArrayUnsafe MutByteArray
contents Int
end Int
p1)

-- | Unfold an array into a stream in reverse order.
--
{-# INLINE_NORMAL readerRev #-}
readerRev :: forall m a. (Monad m, Unbox a) => Unfold m (Array a) a
readerRev :: forall (m :: * -> *) a. (Monad m, Unbox a) => Unfold m (Array a) a
readerRev = (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 -> Unfold m (Array a) a)
-> Unfold m (MutArray a) a -> Unfold m (Array a) a
forall a b. (a -> b) -> a -> b
$ (forall b. IO b -> m b) -> Unfold m (MutArray a) a
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
(forall b. IO b -> m b) -> Unfold m (MutArray a) a
MA.readerRevWith (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)

{-# DEPRECATED toStreamD "Please use 'read' instead." #-}
{-# INLINE_NORMAL toStreamD #-}
toStreamD :: forall m a. (Monad m, Unbox a) => Array a -> D.Stream m a
toStreamD :: forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
toStreamD = Array a -> Stream m a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
read

{-# INLINE toStreamK #-}
toStreamK :: forall m a. (Monad m, Unbox a) => Array a -> K.StreamK m a
toStreamK :: forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Array a -> StreamK m a
toStreamK Array a
arr = (forall b. IO b -> m b) -> MutArray a -> StreamK m a
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
(forall b. IO b -> m b) -> MutArray a -> StreamK m a
MA.toStreamKWith (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) (Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr)

{-# DEPRECATED toStreamDRev "Please use 'readRev' instead." #-}
{-# INLINE_NORMAL toStreamDRev #-}
toStreamDRev :: forall m a. (Monad m, Unbox a) => Array a -> D.Stream m a
toStreamDRev :: forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
toStreamDRev = Array a -> Stream m a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
readRev

{-# INLINE toStreamKRev #-}
toStreamKRev :: forall m a. (Monad m, Unbox a) => Array a -> K.StreamK m a
toStreamKRev :: forall (m :: * -> *) a.
(Monad m, Unbox a) =>
Array a -> StreamK m a
toStreamKRev Array a
arr =
    (forall b. IO b -> m b) -> MutArray a -> StreamK m a
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
(forall b. IO b -> m b) -> MutArray a -> StreamK m a
MA.toStreamKRevWith (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) (Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr)

-- | Convert an 'Array' into a stream.
--
-- /Pre-release/
{-# INLINE_EARLY read #-}
read :: (Monad m, Unbox a) => Array a -> Stream m a
read :: forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
read Array a
arr = (forall b. IO b -> m b) -> MutArray a -> Stream m a
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
(forall b. IO b -> m b) -> MutArray a -> Stream m a
MA.toStreamWith (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) (Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr)

-- | Same as 'read'
--
{-# DEPRECATED toStream "Please use 'read' instead." #-}
{-# INLINE_EARLY toStream #-}
toStream :: (Monad m, Unbox a) => Array a -> Stream m a
toStream :: forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
toStream = Array a -> Stream m a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
read
-- XXX add fallback to StreamK rule
-- {-# RULES "Streamly.Array.read fallback to StreamK" [1]
--     forall a. S.readK (read a) = K.fromArray a #-}

-- | Convert an 'Array' into a stream in reverse order.
--
-- /Pre-release/
{-# INLINE_EARLY readRev #-}
readRev :: (Monad m, Unbox a) => Array a -> Stream m a
readRev :: forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
readRev Array a
arr = (forall b. IO b -> m b) -> MutArray a -> Stream m a
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
(forall b. IO b -> m b) -> MutArray a -> Stream m a
MA.toStreamRevWith (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) (Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr)

-- | Same as 'readRev'
--
{-# DEPRECATED toStreamRev "Please use 'readRev' instead." #-}
{-# INLINE_EARLY toStreamRev #-}
toStreamRev :: (Monad m, Unbox a) => Array a -> Stream m a
toStreamRev :: forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
toStreamRev = Array a -> Stream m a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
readRev

-- XXX add fallback to StreamK rule
-- {-# RULES "Streamly.Array.readRev fallback to StreamK" [1]
--     forall a. S.toStreamK (readRev a) = K.revFromArray a #-}

{-# INLINE_NORMAL foldl' #-}
foldl' :: forall a b. Unbox a => (b -> a -> b) -> b -> Array a -> b
foldl' :: forall a b. Unbox a => (b -> a -> b) -> b -> Array a -> b
foldl' b -> a -> b
f b
z Array a
arr = Identity b -> b
forall a. Identity a -> a
runIdentity (Identity b -> b) -> Identity b -> b
forall a b. (a -> b) -> a -> b
$ (b -> a -> b) -> b -> Stream Identity a -> Identity b
forall (m :: * -> *) b a.
Monad m =>
(b -> a -> b) -> b -> Stream m a -> m b
D.foldl' b -> a -> b
f b
z (Stream Identity a -> Identity b)
-> Stream Identity a -> Identity b
forall a b. (a -> b) -> a -> b
$ Array a -> Stream Identity a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
toStreamD Array a
arr

{-# INLINE_NORMAL foldr #-}
foldr :: Unbox a => (a -> b -> b) -> b -> Array a -> b
foldr :: forall a b. Unbox a => (a -> b -> b) -> b -> Array a -> b
foldr a -> b -> b
f b
z Array a
arr = Identity b -> b
forall a. Identity a -> a
runIdentity (Identity b -> b) -> Identity b -> b
forall a b. (a -> b) -> a -> b
$ (a -> b -> b) -> b -> Stream Identity a -> Identity b
forall (m :: * -> *) a b.
Monad m =>
(a -> b -> b) -> b -> Stream m a -> m b
D.foldr a -> b -> b
f b
z (Stream Identity a -> Identity b)
-> Stream Identity a -> Identity b
forall a b. (a -> b) -> a -> b
$ Array a -> Stream Identity a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
toStreamD Array a
arr

-- | Like 'breakAt' but does not check whether the index is valid.
--
{-# INLINE unsafeBreakAt #-}
unsafeBreakAt, unsafeSplitAt :: Unbox a =>
    Int -> Array a -> (Array a, Array a)
unsafeBreakAt :: forall a. Unbox a => Int -> Array a -> (Array a, Array a)
unsafeBreakAt Int
i Array a
arr = (MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze MutArray a
a, MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze MutArray a
b)

    where

    (MutArray a
a, MutArray a
b) = Int -> MutArray a -> (MutArray a, MutArray a)
forall a. Unbox a => Int -> MutArray a -> (MutArray a, MutArray a)
MA.unsafeBreakAt Int
i (Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr)
RENAME(unsafeSplitAt,unsafeBreakAt)

-- | Create two slices of an array without copying the original array. The
-- specified index @i@ is the first index of the second slice.
--
{-# INLINE breakAt #-}
breakAt, splitAt :: Unbox a => Int -> Array a -> (Array a, Array a)
breakAt :: forall a. Unbox a => Int -> Array a -> (Array a, Array a)
breakAt Int
i Array a
arr = (MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze MutArray a
a, MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze MutArray a
b)

    where

    (MutArray a
a, MutArray a
b) = Int -> MutArray a -> (MutArray a, MutArray a)
forall a. Unbox a => Int -> MutArray a -> (MutArray a, MutArray a)
MA.breakAt Int
i (Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr)
RENAME(splitAt,breakAt)

{-# INLINE breakEndBy #-}
breakEndBy :: Unbox a => (a -> Bool) -> Array a -> (Array a, Array a)
breakEndBy :: forall a. Unbox a => (a -> Bool) -> Array a -> (Array a, Array a)
breakEndBy a -> Bool
p Array a
arr = (MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze MutArray a
a, MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze MutArray a
b)

    where

    (MutArray a
a, MutArray a
b) = IO (MutArray a, MutArray a) -> (MutArray a, MutArray a)
forall a. IO a -> a
unsafePerformIO (IO (MutArray a, MutArray a) -> (MutArray a, MutArray a))
-> IO (MutArray a, MutArray a) -> (MutArray a, MutArray a)
forall a b. (a -> b) -> a -> b
$ (a -> Bool) -> MutArray a -> IO (MutArray a, MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
(a -> Bool) -> MutArray a -> m (MutArray a, MutArray a)
MA.breakEndBy a -> Bool
p (Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr)

{-# INLINE breakEndBy_ #-}
breakEndBy_ :: Unbox a => (a -> Bool) -> Array a -> (Array a, Array a)
breakEndBy_ :: forall a. Unbox a => (a -> Bool) -> Array a -> (Array a, Array a)
breakEndBy_ a -> Bool
p Array a
arr = (MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze MutArray a
a, MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze MutArray a
b)

    where

    (MutArray a
a, MutArray a
b) = IO (MutArray a, MutArray a) -> (MutArray a, MutArray a)
forall a. IO a -> a
unsafePerformIO (IO (MutArray a, MutArray a) -> (MutArray a, MutArray a))
-> IO (MutArray a, MutArray a) -> (MutArray a, MutArray a)
forall a b. (a -> b) -> a -> b
$ (a -> Bool) -> MutArray a -> IO (MutArray a, MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
(a -> Bool) -> MutArray a -> m (MutArray a, MutArray a)
MA.breakEndBy_ a -> Bool
p (Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr)

{-# INLINE revBreakEndBy #-}
revBreakEndBy :: Unbox a => (a -> Bool) -> Array a -> (Array a, Array a)
revBreakEndBy :: forall a. Unbox a => (a -> Bool) -> Array a -> (Array a, Array a)
revBreakEndBy a -> Bool
p Array a
arr = (MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze MutArray a
a, MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze MutArray a
b)

    where

    (MutArray a
a, MutArray a
b) = IO (MutArray a, MutArray a) -> (MutArray a, MutArray a)
forall a. IO a -> a
unsafePerformIO (IO (MutArray a, MutArray a) -> (MutArray a, MutArray a))
-> IO (MutArray a, MutArray a) -> (MutArray a, MutArray a)
forall a b. (a -> b) -> a -> b
$ (a -> Bool) -> MutArray a -> IO (MutArray a, MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
(a -> Bool) -> MutArray a -> m (MutArray a, MutArray a)
MA.revBreakEndBy a -> Bool
p (Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr)

{-# INLINE revBreakEndBy_ #-}
revBreakEndBy_ :: Unbox a => (a -> Bool) -> Array a -> (Array a, Array a)
revBreakEndBy_ :: forall a. Unbox a => (a -> Bool) -> Array a -> (Array a, Array a)
revBreakEndBy_ a -> Bool
p Array a
arr = (MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze MutArray a
a, MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze MutArray a
b)

    where

    (MutArray a
a, MutArray a
b) = IO (MutArray a, MutArray a) -> (MutArray a, MutArray a)
forall a. IO a -> a
unsafePerformIO (IO (MutArray a, MutArray a) -> (MutArray a, MutArray a))
-> IO (MutArray a, MutArray a) -> (MutArray a, MutArray a)
forall a b. (a -> b) -> a -> b
$ (a -> Bool) -> MutArray a -> IO (MutArray a, MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
(a -> Bool) -> MutArray a -> m (MutArray a, MutArray a)
MA.revBreakEndBy_ a -> Bool
p (Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr)

-- XXX Remove unsafePerformIO

-- | Strip elements which match the predicate, from both ends.
--
-- /Pre-release/
{-# INLINE dropAround #-}
dropAround, strip :: Unbox a => (a -> Bool) -> Array a -> Array a
dropAround :: forall a. Unbox a => (a -> Bool) -> Array a -> Array a
dropAround a -> Bool
eq Array a
arr =
    MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze (MutArray a -> Array a) -> MutArray a -> Array a
forall a b. (a -> b) -> a -> b
$ IO (MutArray a) -> MutArray a
forall a. IO a -> a
unsafePerformIO (IO (MutArray a) -> MutArray a) -> IO (MutArray a) -> MutArray a
forall a b. (a -> b) -> a -> b
$ (a -> Bool) -> MutArray a -> IO (MutArray a)
forall a (m :: * -> *).
(Unbox a, MonadIO m) =>
(a -> Bool) -> MutArray a -> m (MutArray a)
MA.dropAround a -> Bool
eq (Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr)
RENAME(strip,dropAround)

-- | Strip elements which match the predicate, from the start of the array.
--
-- /Pre-release/
{-# INLINE dropWhile #-}
dropWhile, stripStart :: Unbox a => (a -> Bool) -> Array a -> Array a
dropWhile :: forall a. Unbox a => (a -> Bool) -> Array a -> Array a
dropWhile a -> Bool
eq Array a
arr =
    MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze (MutArray a -> Array a) -> MutArray a -> Array a
forall a b. (a -> b) -> a -> b
$ IO (MutArray a) -> MutArray a
forall a. IO a -> a
unsafePerformIO (IO (MutArray a) -> MutArray a) -> IO (MutArray a) -> MutArray a
forall a b. (a -> b) -> a -> b
$ (a -> Bool) -> MutArray a -> IO (MutArray a)
forall a (m :: * -> *).
(Unbox a, MonadIO m) =>
(a -> Bool) -> MutArray a -> m (MutArray a)
MA.dropWhile a -> Bool
eq (Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr)
RENAME(stripStart,dropWhile)

-- | Strip elements which match the predicate, from the end of the array.
--
-- /Pre-release/
{-# INLINE revDropWhile #-}
revDropWhile, stripEnd :: Unbox a => (a -> Bool) -> Array a -> Array a
revDropWhile :: forall a. Unbox a => (a -> Bool) -> Array a -> Array a
revDropWhile a -> Bool
eq Array a
arr =
    MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze (MutArray a -> Array a) -> MutArray a -> Array a
forall a b. (a -> b) -> a -> b
$ IO (MutArray a) -> MutArray a
forall a. IO a -> a
unsafePerformIO (IO (MutArray a) -> MutArray a) -> IO (MutArray a) -> MutArray a
forall a b. (a -> b) -> a -> b
$ (a -> Bool) -> MutArray a -> IO (MutArray a)
forall a (m :: * -> *).
(Unbox a, MonadIO m) =>
(a -> Bool) -> MutArray a -> m (MutArray a)
MA.revDropWhile a -> Bool
eq (Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr)
RENAME(stripEnd,revDropWhile)

-- Use foldr/build fusion to fuse with list consumers
-- This can be useful when using the IsList instance
{-# INLINE_LATE toListFB #-}
toListFB :: forall a b. Unbox a => (a -> b -> b) -> b -> Array a -> b
toListFB :: forall a b. Unbox a => (a -> b -> b) -> b -> Array a -> b
toListFB a -> b -> b
c b
n Array{Int
MutByteArray
arrContents :: forall a. Array a -> MutByteArray
arrStart :: forall a. Array a -> Int
arrEnd :: forall a. Array a -> Int
arrContents :: MutByteArray
arrStart :: Int
arrEnd :: Int
..} = Int -> b
go Int
arrStart
    where

    go :: Int -> b
go Int
p | Bool -> Bool -> Bool
forall a. HasCallStack => Bool -> a -> a
assert (Int
p Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
arrEnd) (Int
p Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
arrEnd) = b
n
    go Int
p =
        -- unsafeInlineIO allows us to run this in Identity monad for pure
        -- toList/foldr case which makes them much faster due to not
        -- accumulating the list and fusing better with the pure consumers.
        --
        -- This should be safe as the array contents are guaranteed to be
        -- evaluated/written to before we peekAt at them.
        let !x :: a
x = 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
arrContents
        in a -> b -> b
c a
x (Int -> b
go (INDEX_NEXT(p,a)))

-- | Convert an 'Array' into a list.
--
{-# INLINE toList #-}
toList :: Unbox a => Array a -> [a]
toList :: forall a. Unbox a => Array a -> [a]
toList Array a
s = (forall b. (a -> b -> b) -> b -> b) -> [a]
forall a. (forall b. (a -> b -> b) -> b -> b) -> [a]
build (\a -> b -> b
c b
n -> (a -> b -> b) -> b -> Array a -> b
forall a b. Unbox a => (a -> b -> b) -> b -> Array a -> b
toListFB a -> b -> b
c b
n Array a
s)

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

-- | @createOf n@ folds a maximum of @n@ elements from the input stream to an
-- 'Array'.
--
{-# INLINE_NORMAL createOf #-}
createOf :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
createOf :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m a (Array a)
createOf = (MutArray a -> Array a)
-> Fold m a (MutArray 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 MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze (Fold m a (MutArray a) -> Fold m a (Array a))
-> (Int -> Fold m a (MutArray a)) -> Int -> Fold m a (Array a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Fold m a (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m a (MutArray a)
MA.createOf

{-# DEPRECATED writeN  "Please use createOf instead." #-}
{-# INLINE writeN #-}
writeN :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
writeN :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m a (Array a)
writeN = Int -> Fold m a (Array a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m a (Array a)
createOf

-- | Like 'createOf' but creates a pinned array.
{-# INLINE_NORMAL createOf' #-}
pinnedCreateOf, createOf' :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
createOf' :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m a (Array a)
createOf' = (MutArray a -> Array a)
-> Fold m a (MutArray 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 MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze (Fold m a (MutArray a) -> Fold m a (Array a))
-> (Int -> Fold m a (MutArray a)) -> Int -> Fold m a (Array a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Fold m a (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m a (MutArray a)
MA.createOf'
RENAME_PRIME(pinnedCreateOf,createOf)

{-# DEPRECATED pinnedWriteN  "Please use createOf' instead." #-}
{-# INLINE pinnedWriteN #-}
pinnedWriteN :: forall m a. (MonadIO m, Unbox a) => Int -> Fold m a (Array a)
pinnedWriteN :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m a (Array a)
pinnedWriteN = Int -> Fold m a (Array a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m a (Array a)
createOf'

-- | @pinnedWriteNAligned alignment n@ folds a maximum of @n@ elements from the input
-- stream to an 'Array' aligned to the given size.
--
-- /Pre-release/
--
{-# INLINE_NORMAL pinnedWriteNAligned #-}
{-# DEPRECATED pinnedWriteNAligned  "To be removed." #-}
pinnedWriteNAligned :: forall m a. (MonadIO m, Unbox a)
    => Int -> Int -> Fold m a (Array a)
pinnedWriteNAligned :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Int -> Fold m a (Array a)
pinnedWriteNAligned Int
alignSize = (MutArray a -> Array a)
-> Fold m a (MutArray 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 MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze (Fold m a (MutArray a) -> Fold m a (Array a))
-> (Int -> Fold m a (MutArray a)) -> Int -> Fold m a (Array a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int -> Fold m a (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Int -> Fold m a (MutArray a)
MA.pinnedWriteNAligned Int
alignSize

-- | Like 'createOf' but does not check the array bounds when writing. The fold
-- driver must not call the step function more than 'n' times otherwise it will
-- corrupt the memory and crash. This function exists mainly because any
-- conditional in the step function blocks fusion causing 10x performance
-- slowdown.
--
{-# INLINE_NORMAL unsafeCreateOf #-}
unsafeCreateOf :: forall m a. (MonadIO m, Unbox a)
    => Int -> Fold m a (Array a)
unsafeCreateOf :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m a (Array a)
unsafeCreateOf Int
n = 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
<$> Int -> Fold m a (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m a (MutArray a)
MA.unsafeCreateOf Int
n

{-# DEPRECATED writeNUnsafe  "Please use unsafeCreateOf instead." #-}
{-# INLINE writeNUnsafe #-}
writeNUnsafe :: forall m a. (MonadIO m, Unbox a)
    => Int -> Fold m a (Array a)
writeNUnsafe :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m a (Array a)
writeNUnsafe = Int -> Fold m a (Array a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m a (Array a)
unsafeCreateOf

{-# INLINE_NORMAL unsafeCreateOf' #-}
unsafePinnedCreateOf, unsafeCreateOf' :: forall m a. (MonadIO m, Unbox a)
    => Int -> Fold m a (Array a)
unsafeCreateOf' :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m a (Array a)
unsafeCreateOf' Int
n = 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
<$> Int -> Fold m a (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m a (MutArray a)
MA.unsafeCreateOf' Int
n
RENAME_PRIME(unsafePinnedCreateOf,unsafeCreateOf)

{-# DEPRECATED pinnedWriteNUnsafe  "Please use unsafeCreateOf' instead." #-}
{-# INLINE pinnedWriteNUnsafe #-}
pinnedWriteNUnsafe :: forall m a. (MonadIO m, Unbox a)
    => Int -> Fold m a (Array a)
pinnedWriteNUnsafe :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m a (Array a)
pinnedWriteNUnsafe = Int -> Fold m a (Array a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m a (Array a)
unsafeCreateOf'

-- | A version of "create" that let's you pass in the initial capacity of the
-- array in terms of the number of elements.
--
-- Semantically @createWith 10@ and @createWith 100@ will behave in the same
-- way. @createWith 100@ will be more performant though.
--
-- > create = createWith elementCount
--
-- /Pre-release/
{-# INLINE_NORMAL createWith #-}
createWith :: forall m a. (MonadIO m, Unbox a)
    => Int -> Fold m a (Array a)
-- createWith n = FL.rmapM spliceArrays $ toArraysOf n
createWith :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m a (Array a)
createWith Int
elemCount = 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
<$> Int -> Fold m a (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m a (MutArray a)
MA.createWith Int
elemCount

{-# DEPRECATED writeWith "Please use createWith instead." #-}
{-# INLINE writeWith #-}
writeWith :: forall m a. (MonadIO m, Unbox a)
    => Int -> Fold m a (Array a)
writeWith :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m a (Array a)
writeWith = Int -> Fold m a (Array a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Fold m a (Array a)
createWith

-- | Fold the whole input to a single array.
--
-- /Caution! Do not use this on infinite streams./
--
{-# INLINE create #-}
create :: forall m a. (MonadIO m, Unbox a) => Fold m a (Array a)
create :: forall (m :: * -> *) a. (MonadIO m, Unbox a) => Fold m a (Array a)
create = (MutArray a -> Array a)
-> Fold m a (MutArray 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 MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze Fold m a (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Fold m a (MutArray a)
MA.create

{-# DEPRECATED write  "Please use create instead." #-}
{-# INLINE write #-}
write :: forall m a. (MonadIO m, Unbox a) => Fold m a (Array a)
write :: forall (m :: * -> *) a. (MonadIO m, Unbox a) => Fold m a (Array a)
write = Fold m a (Array a)
forall (m :: * -> *) a. (MonadIO m, Unbox a) => Fold m a (Array a)
create

-- | Like 'create' but creates a pinned array.
{-# INLINE create' #-}
pinnedCreate, create' :: forall m a. (MonadIO m, Unbox a) => Fold m a (Array a)
create' :: forall (m :: * -> *) a. (MonadIO m, Unbox a) => Fold m a (Array a)
create' = (MutArray a -> Array a)
-> Fold m a (MutArray 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 MutArray a -> Array a
forall a. MutArray a -> Array a
unsafeFreeze Fold m a (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Fold m a (MutArray a)
MA.create'
RENAME_PRIME(pinnedCreate,create)

{-# DEPRECATED pinnedWrite  "Please use create' instead." #-}
{-# INLINE pinnedWrite #-}
pinnedWrite :: forall m a. (MonadIO m, Unbox a) => Fold m a (Array a)
pinnedWrite :: forall (m :: * -> *) a. (MonadIO m, Unbox a) => Fold m a (Array a)
pinnedWrite = Fold m a (Array a)
forall (m :: * -> *) a. (MonadIO m, Unbox a) => Fold m a (Array a)
create'

-- | Fold "step" has a dependency on "initial", and each step is dependent on
-- the previous invocation of step due to state passing, finally extract
-- depends on the result of step, therefore, as long as the fold is driven in
-- the correct order the operations would be correctly ordered. We need to
-- ensure that we strictly evaluate the previous step completely before the
-- next step.
--
-- To not share the same array we need to make sure that the result of
-- "initial" is not shared. Existential type ensures that it does not get
-- shared across different folds. However, if we invoke "initial" multiple
-- times for the same fold, there is a possiblity of sharing the two because
-- the compiler would consider it as a pure value. One such example is the
-- chunksOf combinator, or using an array creation fold with foldMany
-- combinator. Is there a proper way in GHC to tell it to not share a pure
-- expression in a particular case?
--
-- For this reason array creation folds have a MonadIO constraint. Pure folds
-- could be unsafe and dangerous. This is dangerous especially when used with
-- foldMany like operations.
--
-- >>> unsafePureWrite = Array.unsafeMakePure Array.create
--
{-# INLINE unsafeMakePure #-}
unsafeMakePure :: Monad m => Fold IO a b -> Fold m a b
unsafeMakePure :: forall (m :: * -> *) a b. Monad m => Fold IO a b -> Fold m a b
unsafeMakePure (Fold s -> a -> IO (Step s b)
step IO (Step s b)
initial s -> IO b
extract s -> IO b
final) =
    (s -> a -> m (Step s b))
-> m (Step s b) -> (s -> m b) -> (s -> m b) -> Fold m a b
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 (\s
x a
a -> Step s b -> m (Step s b)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Step s b -> m (Step s b)) -> Step s b -> m (Step s b)
forall a b. (a -> b) -> a -> b
$! IO (Step s b) -> Step s b
forall a. IO a -> a
unsafeInlineIO (s -> a -> IO (Step s b)
step s
x a
a))
         (Step s b -> m (Step s b)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Step s b -> m (Step s b)) -> Step s b -> m (Step s b)
forall a b. (a -> b) -> a -> b
$! IO (Step s b) -> Step s b
forall a. IO a -> a
unsafePerformIO IO (Step s b)
initial)
         (\s
s -> b -> m b
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b -> m b) -> b -> m b
forall a b. (a -> b) -> a -> b
$! IO b -> b
forall a. IO a -> a
unsafeInlineIO (IO b -> b) -> IO b -> b
forall a b. (a -> b) -> a -> b
$ s -> IO b
extract s
s)
         (\s
s -> b -> m b
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (b -> m b) -> b -> m b
forall a b. (a -> b) -> a -> b
$! IO b -> b
forall a. IO a -> a
unsafeInlineIO (IO b -> b) -> IO b -> b
forall a b. (a -> b) -> a -> b
$ s -> IO b
final s
s)

{-# INLINE fromPureStreamN #-}
fromPureStreamN :: Unbox a => Int -> Stream Identity a -> Array a
fromPureStreamN :: forall a. Unbox a => Int -> Stream Identity a -> Array a
fromPureStreamN Int
n Stream Identity a
x =
    IO (Array a) -> Array a
forall a. IO a -> a
unsafePerformIO (IO (Array a) -> Array a) -> IO (Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ (MutArray a -> Array a) -> IO (MutArray a) -> IO (Array a)
forall a b. (a -> b) -> IO a -> IO 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 (Int -> Stream Identity a -> IO (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Int -> Stream Identity a -> m (MutArray a)
MA.fromPureStreamN Int
n Stream Identity a
x)

-- | Convert a pure stream in Identity monad to an immutable array.
--
-- Same as the following but with better performance:
--
-- >>> fromPureStream = Array.fromList . runIdentity . Stream.toList
--
fromPureStream :: Unbox a => Stream Identity a -> Array a
fromPureStream :: forall a. Unbox a => Stream Identity a -> Array a
fromPureStream Stream Identity a
x = IO (Array a) -> Array a
forall a. IO a -> a
unsafePerformIO (IO (Array a) -> Array a) -> IO (Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ (MutArray a -> Array a) -> IO (MutArray a) -> IO (Array a)
forall a b. (a -> b) -> IO a -> IO 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 (Stream Identity a -> IO (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Stream Identity a -> m (MutArray a)
MA.fromPureStream Stream Identity a
x)
-- fromPureStream = runIdentity . D.fold (unsafeMakePure write)
-- fromPureStream = fromList . runIdentity . D.toList

-- | @fromPtrN len addr@ copies @len@ bytes from @addr@ into an array. The
-- memory pointed by @addr@ must be pinned or static.
--
-- /Unsafe:/ The caller is responsible to ensure that the pointer passed is
-- valid up to the given length.
--
fromPtrN :: MonadIO m => Int -> Ptr Word8 -> m (Array Word8)
fromPtrN :: forall (m :: * -> *).
MonadIO m =>
Int -> Ptr Word8 -> m (Array Word8)
fromPtrN Int
n Ptr Word8
addr = (MutArray Word8 -> Array Word8)
-> m (MutArray Word8) -> m (Array Word8)
forall a b. (a -> b) -> m a -> 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 (Int -> Ptr Word8 -> m (MutArray Word8)
forall (m :: * -> *).
MonadIO m =>
Int -> Ptr Word8 -> m (MutArray Word8)
MA.fromPtrN Int
n Ptr Word8
addr)

-- | Copy a null terminated immutable 'Addr#' Word8 sequence into an array.
--
-- /Unsafe:/ The caller is responsible for safe addressing.
--
-- Note that this is completely safe when reading from Haskell string
-- literals because they are guaranteed to be NULL terminated:
--
-- Note, you can use lazy unsafePerformIO _only if_ the pointer is immutable.
--
-- >>> Array.toList $ unsafePerformIO $ Array.fromCString# "\1\2\3\0"#
-- [1,2,3]
--
fromCString# :: MonadIO m => Addr# -> m (Array Word8)
fromCString# :: forall (m :: * -> *). MonadIO m => Addr# -> m (Array Word8)
fromCString# Addr#
addr = (MutArray Word8 -> Array Word8)
-> m (MutArray Word8) -> m (Array Word8)
forall a b. (a -> b) -> m a -> 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 (Addr# -> m (MutArray Word8)
forall (m :: * -> *). MonadIO m => Addr# -> m (MutArray Word8)
MA.fromCString# Addr#
addr)

{-# DEPRECATED fromByteStr# "Please use fromCString# instead." #-}
fromByteStr# :: Addr# -> Array Word8
fromByteStr# :: Addr# -> Array Word8
fromByteStr# Addr#
addr = IO (Array Word8) -> Array Word8
forall a. IO a -> a
unsafePerformIO (IO (Array Word8) -> Array Word8)
-> IO (Array Word8) -> Array Word8
forall a b. (a -> b) -> a -> b
$ Addr# -> IO (Array Word8)
forall (m :: * -> *). MonadIO m => Addr# -> m (Array Word8)
fromCString# Addr#
addr

-- | Copy a C string consisting of 16-bit wide chars and terminated by a 16-bit
-- null char, into a Word16 array. The null character is not copied.
--
-- Useful for copying UTF16 strings on Windows.
--
fromW16CString# :: MonadIO m => Addr# -> m (Array Word16)
fromW16CString# :: forall (m :: * -> *). MonadIO m => Addr# -> m (Array Word16)
fromW16CString# Addr#
addr = (MutArray Word16 -> Array Word16)
-> m (MutArray Word16) -> m (Array Word16)
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap MutArray Word16 -> Array Word16
forall a. MutArray a -> Array a
unsafeFreeze (Addr# -> m (MutArray Word16)
forall (m :: * -> *). MonadIO m => Addr# -> m (MutArray Word16)
MA.fromW16CString# Addr#
addr)

fromCString :: MonadIO m => Ptr Word8 -> m (Array Word8)
fromCString :: forall (m :: * -> *). MonadIO m => Ptr Word8 -> m (Array Word8)
fromCString (Ptr Addr#
addr#) = Addr# -> m (Array Word8)
forall (m :: * -> *). MonadIO m => Addr# -> m (Array Word8)
fromCString# Addr#
addr#

{-# DEPRECATED fromByteStr "Please use fromCString instead." #-}
fromByteStr :: Ptr Word8 -> Array Word8
fromByteStr :: Ptr Word8 -> Array Word8
fromByteStr = IO (Array Word8) -> Array Word8
forall a. IO a -> a
unsafePerformIO (IO (Array Word8) -> Array Word8)
-> (Ptr Word8 -> IO (Array Word8)) -> Ptr Word8 -> Array Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr Word8 -> IO (Array Word8)
forall (m :: * -> *). MonadIO m => Ptr Word8 -> m (Array Word8)
fromCString

-- | Copy a C string consisting of 16-bit wide chars and terminated by a 16-bit
-- null char, into a Word16 array. The null character is not copied.
--
-- Useful for copying UTF16 strings on Windows.
--
fromW16CString :: MonadIO m => Ptr Word8 -> m (Array Word16)
fromW16CString :: forall (m :: * -> *). MonadIO m => Ptr Word8 -> m (Array Word16)
fromW16CString (Ptr Addr#
addr#) = Addr# -> m (Array Word16)
forall (m :: * -> *). MonadIO m => Addr# -> m (Array Word16)
fromW16CString# Addr#
addr#

-- XXX implement fromChunks/fromChunkList instead?

-- | Convert an array stream to an array. Note that this requires peak memory
-- that is double the size of the array stream.
--
{-# INLINE fromChunksK #-}
fromChunksK :: (MonadIO m, Unbox a) => StreamK m (Array a) -> m (Array a)
fromChunksK :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
StreamK m (Array a) -> m (Array a)
fromChunksK StreamK m (Array a)
stream =
    -- We buffer the entire stream and then allocate the target array of the
    -- same size, thus requiring double the memory.
    (MutArray a -> Array a) -> m (MutArray a) -> m (Array a)
forall a b. (a -> b) -> m a -> m 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 (m (MutArray a) -> m (Array a)) -> m (MutArray a) -> m (Array a)
forall a b. (a -> b) -> a -> b
$ StreamK m (MutArray a) -> m (MutArray a)
forall a (m :: * -> *).
(Unbox a, MonadIO m) =>
StreamK m (MutArray a) -> m (MutArray a)
MA.fromChunksK (StreamK m (MutArray a) -> m (MutArray a))
-> StreamK m (MutArray a) -> m (MutArray a)
forall a b. (a -> b) -> a -> b
$ (Array a -> MutArray a)
-> StreamK m (Array a) -> StreamK m (MutArray a)
forall a b. (a -> b) -> StreamK m a -> StreamK m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw StreamK m (Array a)
stream

{-# DEPRECATED fromArrayStreamK "Please use fromChunksK instead." #-}
fromArrayStreamK :: (Unbox a, MonadIO m) => StreamK m (Array a) -> m (Array a)
fromArrayStreamK :: forall a (m :: * -> *).
(Unbox a, MonadIO m) =>
StreamK m (Array a) -> m (Array a)
fromArrayStreamK = StreamK m (Array a) -> m (Array a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
StreamK m (Array a) -> m (Array a)
fromChunksK

-- | Given a stream of arrays, splice them all together to generate a single
-- array. The stream must be /finite/.
--
{-# INLINE fromChunks #-}
fromChunks :: (MonadIO m, Unbox a) => Stream m (Array a) -> m (Array a)
fromChunks :: forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Stream m (Array a) -> m (Array a)
fromChunks Stream m (Array a)
s =
    -- XXX Check which implementation is better
    -- This may also require double the memory as we double the space every
    -- time, when copying the last array we may have reallocated almost double
    -- the space required before we right size it.
    (MutArray a -> Array a) -> m (MutArray a) -> m (Array a)
forall a b. (a -> b) -> m a -> m 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 (m (MutArray a) -> m (Array a)) -> m (MutArray a) -> m (Array a)
forall a b. (a -> b) -> a -> b
$ Stream m (MutArray a) -> m (MutArray a)
forall (m :: * -> *) a.
(MonadIO m, Unbox a) =>
Stream m (MutArray a) -> m (MutArray a)
MA.fromChunksRealloced ((Array a -> MutArray a)
-> Stream m (Array a) -> Stream m (MutArray 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 Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Stream m (Array a)
s)
    -- fromChunkStreamK $ D.toStreamK s

-------------------------------------------------------------------------------
-- Instances
-------------------------------------------------------------------------------

instance (Show a, Unbox a) => Show (Array a) where
    {-# INLINE show #-}
    show :: Array a -> [Char]
show Array a
arr = [Char]
"fromList " [Char] -> ShowS
forall a. [a] -> [a] -> [a]
++ [a] -> [Char]
forall a. Show a => a -> [Char]
show (Array a -> [a]
forall a. Unbox a => Array a -> [a]
toList Array a
arr)

instance (Unbox a, Read a, Show a) => Read (Array a) where
    {-# INLINE readPrec #-}
    readPrec :: ReadPrec (Array a)
readPrec = do
        [Char]
fromListWord <- Int -> ReadPrec Char -> ReadPrec [Char]
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
9 ReadPrec Char
ReadPrec.get
        if [Char]
fromListWord [Char] -> [Char] -> Bool
forall a. Eq a => a -> a -> Bool
== [Char]
"fromList "
        then [a] -> Array a
forall a. Unbox a => [a] -> Array a
fromList ([a] -> Array a) -> ReadPrec [a] -> ReadPrec (Array a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadPrec [a]
forall a. Read a => ReadPrec a
readPrec
        else ReadPrec (Array a)
forall a. ReadPrec a
ReadPrec.pfail

instance (a ~ Char) => IsString (Array a) where
    {-# INLINE fromString #-}
    fromString :: [Char] -> Array a
fromString = [Char] -> Array a
[Char] -> Array Char
forall a. Unbox a => [a] -> Array a
fromList

-- GHC versions 8.0 and below cannot derive IsList
instance Unbox a => IsList (Array a) where
    type (Item (Array a)) = a
    {-# INLINE fromList #-}
    fromList :: [Item (Array a)] -> Array a
fromList = [a] -> Array a
[Item (Array a)] -> Array a
forall a. Unbox a => [a] -> Array a
fromList
    {-# INLINE fromListN #-}
    fromListN :: Int -> [Item (Array a)] -> Array a
fromListN = Int -> [a] -> Array a
Int -> [Item (Array a)] -> Array a
forall a. Unbox a => Int -> [a] -> Array a
fromListN
    {-# INLINE toList #-}
    toList :: Array a -> [Item (Array a)]
toList = Array a -> [a]
Array a -> [Item (Array a)]
forall a. Unbox a => Array a -> [a]
toList

-- | Compare an array with a list.
{-# INLINE listCmp #-}
listCmp :: (Unbox a, Ord a) => [a] -> Array a -> Ordering
listCmp :: forall a. (Unbox a, Ord a) => [a] -> Array a -> Ordering
listCmp [a]
xs Array a
arr = Identity Ordering -> Ordering
forall a. Identity a -> a
runIdentity (Identity Ordering -> Ordering) -> Identity Ordering -> Ordering
forall a b. (a -> b) -> a -> b
$ (a -> a -> Ordering)
-> Stream Identity a -> Stream Identity a -> Identity Ordering
forall (m :: * -> *) a b.
Monad m =>
(a -> b -> Ordering) -> Stream m a -> Stream m b -> m Ordering
D.cmpBy a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare ([a] -> Stream Identity a
forall (m :: * -> *) a. Applicative m => [a] -> Stream m a
D.fromList [a]
xs) (Array a -> Stream Identity a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
toStream Array a
arr)

-- | Check equality of an array with a list.
{-# INLINE listEq #-}
listEq :: (Unbox a, Ord a) => [a] -> Array a -> Bool
listEq :: forall a. (Unbox a, Ord a) => [a] -> Array a -> Bool
listEq [a]
xs Array a
arr = Identity Bool -> Bool
forall a. Identity a -> a
runIdentity (Identity Bool -> Bool) -> Identity Bool -> Bool
forall a b. (a -> b) -> a -> b
$ (a -> a -> Bool)
-> Stream Identity a -> Stream Identity a -> Identity Bool
forall (m :: * -> *) a b.
Monad m =>
(a -> b -> Bool) -> Stream m a -> Stream m b -> m Bool
D.eqBy a -> a -> Bool
forall a. Eq a => a -> a -> Bool
(==) ([a] -> Stream Identity a
forall (m :: * -> *) a. Applicative m => [a] -> Stream m a
D.fromList [a]
xs) (Array a -> Stream Identity a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
toStream Array a
arr)

-- | Byte compare two arrays. Compare the length of the arrays. If the length
-- is equal, compare the lexicographical ordering of two underlying byte arrays
-- otherwise return the result of length comparison.
--
-- /Unsafe/: Note that the 'Unbox' instance of sum types with constructors of
-- different sizes may leave some memory uninitialized which can make byte
-- comparison unreliable.
--
-- /Pre-release/
{-# INLINE byteCmp #-}
byteCmp :: Array a -> Array a -> Ordering
byteCmp :: forall a. Array a -> Array a -> Ordering
byteCmp Array a
arr1 Array a
arr2 =
    -- unsafePerformIO?
    IO Ordering -> Ordering
forall a. IO a -> a
unsafeInlineIO (IO Ordering -> Ordering) -> IO Ordering -> Ordering
forall a b. (a -> b) -> a -> b
$! Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr1 MutArray a -> MutArray a -> IO Ordering
forall (m :: * -> *) a.
MonadIO m =>
MutArray a -> MutArray a -> m Ordering
`MA.byteCmp` Array a -> MutArray a
forall a. Array a -> MutArray a
unsafeThaw Array a
arr2

-- | Byte equality of two arrays.
--
-- >>> byteEq arr1 arr2 = (==) EQ $ Array.byteCmp arr1 arr2
--
-- /Unsafe/: See 'byteCmp'.
{-# INLINE byteEq #-}
byteEq :: Array a -> Array a -> Bool
byteEq :: forall a. Array a -> Array a -> Bool
byteEq Array a
arr1 Array a
arr2 = Ordering -> Ordering -> Bool
forall a. Eq a => a -> a -> Bool
(==) Ordering
EQ (Ordering -> Bool) -> Ordering -> Bool
forall a b. (a -> b) -> a -> b
$ Array a -> Array a -> Ordering
forall a. Array a -> Array a -> Ordering
byteCmp Array a
arr1 Array a
arr2

#define MK_EQ_INSTANCE(typ)                              \
instance {-# OVERLAPPING #-} Eq (Array typ) where {      \
;    {-# INLINE (==) #-}                                 \
;    (==) = byteEq \
}

MK_EQ_INSTANCE(Char)
MK_EQ_INSTANCE(Word8)
MK_EQ_INSTANCE(Word16)
MK_EQ_INSTANCE(Word32)

-- XXX The Word64 default instance should be as fast because we are comparing
-- 64-bit at a time.
MK_EQ_INSTANCE(Word64)
MK_EQ_INSTANCE(Int)
MK_EQ_INSTANCE(Int8)
MK_EQ_INSTANCE(Int16)
MK_EQ_INSTANCE(Int32)

-- XXX The Int64 default instance should be as fast.
MK_EQ_INSTANCE(Int64)

-- | If the type allows a byte-by-byte comparison this instance can be
-- overlapped by a more specific instance that uses 'byteCmp'. Byte comparison
-- can be significantly faster.
--
instance {-# OVERLAPPABLE #-} (Unbox a, Eq a) => Eq (Array a) where
    {-# INLINE (==) #-}
    Array a
arr1 == :: Array a -> Array a -> Bool
== Array a
arr2 =
        -- Does unboxed byte equality mean element equality?
        -- XXX This is incorrect for sum types, as we may have some
        -- uninitialized memory in that case. If we always initialize the
        -- unused memory to zero we can use this.
        -- Byte comparison is 40% faster compared to stream equality.
        -- (==) EQ $ unsafeInlineIO $! unsafeThaw arr1 `MA.cmp` unsafeThaw arr2
           (Array a -> Stream Identity a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
toStreamD Array a
arr1 :: Stream Identity a) Stream Identity a -> Stream Identity a -> Bool
forall a. Eq a => a -> a -> Bool
== Array a -> Stream Identity a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
toStreamD Array a
arr2

instance (Unbox a, Ord a) => Ord (Array a) where
    {-# INLINE compare #-}
    compare :: Array a -> Array a -> Ordering
compare Array a
arr1 Array a
arr2 = Identity Ordering -> Ordering
forall a. Identity a -> a
runIdentity (Identity Ordering -> Ordering) -> Identity Ordering -> Ordering
forall a b. (a -> b) -> a -> b
$
        (a -> a -> Ordering)
-> Stream Identity a -> Stream Identity a -> Identity Ordering
forall (m :: * -> *) a b.
Monad m =>
(a -> b -> Ordering) -> Stream m a -> Stream m b -> m Ordering
D.cmpBy a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Array a -> Stream Identity a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
toStreamD Array a
arr1) (Array a -> Stream Identity a
forall (m :: * -> *) a. (Monad m, Unbox a) => Array a -> Stream m a
toStreamD Array a
arr2)

    -- Default definitions defined in base do not have an INLINE on them, so we
    -- replicate them here with an INLINE.
    {-# INLINE (<) #-}
    Array a
x < :: Array a -> Array a -> Bool
<  Array a
y = case Array a -> Array a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Array a
x Array a
y of { Ordering
LT -> Bool
True;  Ordering
_ -> Bool
False }

    {-# INLINE (<=) #-}
    Array a
x <= :: Array a -> Array a -> Bool
<= Array a
y = case Array a -> Array a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Array a
x Array a
y of { Ordering
GT -> Bool
False; Ordering
_ -> Bool
True }

    {-# INLINE (>) #-}
    Array a
x > :: Array a -> Array a -> Bool
>  Array a
y = case Array a -> Array a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Array a
x Array a
y of { Ordering
GT -> Bool
True;  Ordering
_ -> Bool
False }

    {-# INLINE (>=) #-}
    Array a
x >= :: Array a -> Array a -> Bool
>= Array a
y = case Array a -> Array a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Array a
x Array a
y of { Ordering
LT -> Bool
False; Ordering
_ -> Bool
True }

    -- These two default methods use '<=' rather than 'compare'
    -- because the latter is often more expensive
    {-# INLINE max #-}
    max :: Array a -> Array a -> Array a
max Array a
x Array a
y = if Array a
x Array a -> Array a -> Bool
forall a. Ord a => a -> a -> Bool
<= Array a
y then Array a
y else Array a
x

    {-# INLINE min #-}
    min :: Array a -> Array a -> Array a
min Array a
x Array a
y = if Array a
x Array a -> Array a -> Bool
forall a. Ord a => a -> a -> Bool
<= Array a
y then Array a
x else Array a
y

#ifdef DEVBUILD
-- Definitions using the Unboxed constraint from the Array type. These are to
-- make the Foldable instance possible though it is much slower (7x slower).
--
{-# INLINE_NORMAL _toStreamD_ #-}
_toStreamD_ :: forall m a. MonadIO m => Int -> Array a -> D.Stream m a
_toStreamD_ size Array{..} = D.Stream step arrStart

    where

    {-# INLINE_LATE step #-}
    step _ p | p == arrEnd = return D.Stop
    step _ p = liftIO $ do
        x <- peekAt p arrContents
        return $ D.Yield x (p + size)

{-
XXX Why isn't Unboxed implicit? This does not compile unless I use the Unboxed
contraint.
{-# INLINE_NORMAL _foldr #-}
_foldr :: forall a b. (a -> b -> b) -> b -> Array a -> b
_foldr f z arr =
    let !n = SIZE_OF(a)
    in unsafePerformIO $ D.foldr f z $ toStreamD_ n arr
-- | Note that the 'Foldable' instance is 7x slower than the direct
-- operations.
instance Foldable Array where
  foldr = _foldr
-}

#endif

-------------------------------------------------------------------------------
-- Semigroup and Monoid
-------------------------------------------------------------------------------

-- XXX Deprecate and remove the Semigroup and Monoid instances because of
-- potential misuse chances.

-- | This should not be used for combining many or N arrays as it would copy
-- the two arrays everytime to a new array. For coalescing multiple arrays use
-- 'fromChunksK' instead.
instance Unbox a => Semigroup (Array a) where
    Array a
arr1 <> :: Array a -> Array a -> Array a
<> Array a
arr2 = IO (Array a) -> Array a
forall a. IO a -> a
unsafePerformIO (IO (Array a) -> Array a) -> IO (Array a) -> Array a
forall a b. (a -> b) -> a -> b
$ Array a -> Array a -> IO (Array a)
forall (m :: * -> *) a.
MonadIO m =>
Array a -> Array a -> m (Array a)
splice Array a
arr1 Array a
arr2

empty ::
#ifdef DEVBUILD
    Unbox a =>
#endif
    Array a
empty :: forall a. Array a
empty = MutByteArray -> Int -> Int -> Array a
forall a. MutByteArray -> Int -> Int -> Array a
Array MutByteArray
Unboxed.empty Int
0 Int
0

{-# DEPRECATED nil "Please use empty instead." #-}
nil ::
#ifdef DEVBUILD
    Unbox a =>
#endif
    Array a
nil :: forall a. Array a
nil = Array a
forall a. Array a
empty

instance Unbox a => Monoid (Array a) where
    mempty :: Array a
mempty = Array a
forall a. Array a
nil
    mappend :: Array a -> Array a -> Array a
mappend = Array a -> Array a -> Array a
forall a. Semigroup a => a -> a -> a
(<>)

-------------------------------------------------------------------------------
-- Backward Compatibility
-------------------------------------------------------------------------------

RENAME(unsafeIndexIO,unsafeGetIndexIO)
RENAME(getIndexUnsafe,unsafeGetIndex)
RENAME(readerUnsafe,unsafeReader)