{-# LANGUAGE UnboxedTuples #-}

#include "inline.hs"

-- |
-- Module      : Streamly.Internal.Data.Array.Prim.Mut.Type
-- Copyright   : (c) 2020 Composewell Technologies
--
-- License     : BSD-3-Clause
-- Maintainer  : streamly@composewell.com
-- Stability   : experimental
-- Portability : GHC
--
module Streamly.Internal.Data.Array.Prim.Mut.Type
    (
      Array (..)

    -- * Construction
    , newArray
    , unsafeWriteIndex

    , spliceTwo
    , unsafeCopy

    , fromListM
    , fromListNM
    , fromStreamDN
    , fromStreamD

    -- * Streams of arrays
    , fromStreamDArraysOf

    , packArraysChunksOf
    , lpackArraysChunksOf

#if !defined(mingw32_HOST_OS)
--    , groupIOVecsOf
#endif

    -- * Elimination
    , unsafeReadIndex
    , length
    , byteLength

    , writeN
    , ArrayUnsafe(..)
    , writeNUnsafe
    , write

    -- * Utilities
    , resizeArray
    , shrinkArray
    )
where

#include "Streamly/Internal/Data/Array/Prim/MutTypesInclude.hs"

-------------------------------------------------------------------------------
-- Allocation (Unpinned)
-------------------------------------------------------------------------------

-- | Allocate an array that is unpinned and can hold 'count' items.  The memory
-- of the array is uninitialized.
--
-- Note that this is internal routine, the reference to this array cannot be
-- given out until the array has been written to and frozen.
{-# INLINE newArray #-}
newArray ::
       forall m a. (MonadIO m, Prim a)
    => Int
    -> m (Array a)
newArray :: forall (m :: * -> *) a. (MonadIO m, Prim a) => Int -> m (Array a)
newArray (I# Int#
n#) =
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ do
        let bytes :: Int#
bytes = Int#
n# Int# -> Int# -> Int#
*# forall a. Prim a => a -> Int#
sizeOf# (forall a. HasCallStack => a
undefined :: a)
        forall (m :: * -> *) a.
PrimMonad m =>
(State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
primitive forall a b. (a -> b) -> a -> b
$ \State# (PrimState IO)
s# ->
            case forall d. Int# -> State# d -> (# State# d, MutableByteArray# d #)
newByteArray# Int#
bytes State# (PrimState IO)
s# of
                (# State# RealWorld
s1#, MutableByteArray# RealWorld
arr# #) -> (# State# RealWorld
s1#, forall a. MutableByteArray# RealWorld -> Array a
Array MutableByteArray# RealWorld
arr# #)

-- | Resize (unpinned) mutable byte array to new specified size (in elem
-- count). The returned array is either the original array resized in-place or,
-- if not possible, a newly allocated (unpinned) array (with the original
-- content copied over).
{-# INLINE resizeArray #-}
resizeArray ::
       forall m a. (MonadIO m, Prim a)
    => Array a
    -> Int -- ^ new size in elem count
    -> m (Array a)
resizeArray :: forall (m :: * -> *) a.
(MonadIO m, Prim a) =>
Array a -> Int -> m (Array a)
resizeArray (Array MutableByteArray# RealWorld
arr#) (I# Int#
n#) =
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ do
        let bytes :: Int#
bytes = Int#
n# Int# -> Int# -> Int#
*# forall a. Prim a => a -> Int#
sizeOf# (forall a. HasCallStack => a
undefined :: a)
        forall (m :: * -> *) a.
PrimMonad m =>
(State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
primitive forall a b. (a -> b) -> a -> b
$ \State# (PrimState IO)
s# ->
            case forall d.
MutableByteArray# d
-> Int# -> State# d -> (# State# d, MutableByteArray# d #)
resizeMutableByteArray# MutableByteArray# RealWorld
arr# Int#
bytes State# (PrimState IO)
s# of
                (# State# RealWorld
s1#, MutableByteArray# RealWorld
arr1# #) -> (# State# RealWorld
s1#, forall a. MutableByteArray# RealWorld -> Array a
Array MutableByteArray# RealWorld
arr1# #)