{-# LANGUAGE BangPatterns, CPP, MagicHash, UnboxedTuples, UnliftedFFITypes, DeriveDataTypeable #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE RankNTypes #-}

-- |
-- Module      : Data.Primitive.ByteArray
-- Copyright   : (c) Roman Leshchinskiy 2009-2012
-- License     : BSD-style
--
-- Maintainer  : Roman Leshchinskiy <rl@cse.unsw.edu.au>
-- Portability : non-portable
--
-- Primitive operations on byte arrays. Most functions in this module include
-- an element type in their type signature and interpret the unit for offsets
-- and lengths as that element. A few functions (e.g. 'copyByteArray',
-- 'freezeByteArray') do not include an element type. Such functions
-- interpret offsets and lengths as units of 8-bit words.

module Data.Primitive.ByteArray (
  -- * Types
  ByteArray(..), MutableByteArray(..), ByteArray#, MutableByteArray#,

  -- * Allocation
  newByteArray, newPinnedByteArray, newAlignedPinnedByteArray,
  resizeMutableByteArray,
#if __GLASGOW_HASKELL__ >= 710
  shrinkMutableByteArray,
#endif

  -- * Element access
  readByteArray, writeByteArray, indexByteArray,

  -- * Constructing
  byteArrayFromList, byteArrayFromListN,

  -- * Folding
  foldrByteArray,

  -- * Comparing
  compareByteArrays,

  -- * Freezing and thawing
  freezeByteArray, thawByteArray,
  unsafeFreezeByteArray, unsafeThawByteArray,

  -- * Block operations
  copyByteArray, copyMutableByteArray,
#if __GLASGOW_HASKELL__ >= 708
  copyByteArrayToPtr, copyMutableByteArrayToPtr,
  copyByteArrayToAddr, copyMutableByteArrayToAddr,
#endif
  moveByteArray,
  setByteArray, fillByteArray,
  cloneByteArray, cloneMutableByteArray,

  -- * Information
  sizeofByteArray,
  sizeofMutableByteArray, getSizeofMutableByteArray, sameMutableByteArray,
#if __GLASGOW_HASKELL__ >= 802
  isByteArrayPinned, isMutableByteArrayPinned,
#endif
  byteArrayContents, mutableByteArrayContents

) where

import Control.Monad.Primitive
import Control.Monad.ST
import Control.DeepSeq
import Data.Data (mkNoRepType)
import Data.Primitive.Types

import qualified GHC.ST as GHCST

import Foreign.C.Types
import Data.Word ( Word8 )
import Data.Bits ( (.&.), unsafeShiftR )
import GHC.Show ( intToDigit )
import GHC.Base ( Int(..) )
#if __GLASGOW_HASKELL__ >= 708
import qualified GHC.Exts as Exts ( IsList(..) )
#endif
import GHC.Exts
#if __GLASGOW_HASKELL__ >= 706
    hiding (setByteArray#)
#endif

import Data.Typeable ( Typeable )
import Data.Data ( Data(..) )
import Data.Primitive.Internal.Compat ( isTrue# )
import Numeric

#if MIN_VERSION_base(4,9,0)
import qualified Data.Semigroup as SG
import qualified Data.Foldable as F
#endif

#if !(MIN_VERSION_base(4,8,0))
import Data.Monoid (Monoid(..))
#endif

#if __GLASGOW_HASKELL__ >= 802
import GHC.Exts as Exts (isByteArrayPinned#,isMutableByteArrayPinned#)
#endif

#if __GLASGOW_HASKELL__ >= 804
import GHC.Exts (compareByteArrays#)
#else
import System.IO.Unsafe (unsafeDupablePerformIO)
#endif

-- | Byte arrays
data ByteArray = ByteArray ByteArray# deriving ( Typeable )

-- | Mutable byte arrays associated with a primitive state token
data MutableByteArray s = MutableByteArray (MutableByteArray# s)
                                        deriving( Typeable )

instance NFData ByteArray where
  rnf :: ByteArray -> ()
rnf (ByteArray ByteArray#
_) = ()

instance NFData (MutableByteArray s) where
  rnf :: MutableByteArray s -> ()
rnf (MutableByteArray MutableByteArray# s
_) = ()

-- | Create a new mutable byte array of the specified size in bytes.
--
-- /Note:/ this function does not check if the input is non-negative.
newByteArray :: PrimMonad m => Int -> m (MutableByteArray (PrimState m))
{-# INLINE newByteArray #-}
newByteArray :: Int -> m (MutableByteArray (PrimState m))
newByteArray (I# Int#
n#)
  = (State# (PrimState m)
 -> (# State# (PrimState m), MutableByteArray (PrimState m) #))
-> m (MutableByteArray (PrimState m))
forall (m :: * -> *) a.
PrimMonad m =>
(State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
primitive (\State# (PrimState m)
s# -> case Int#
-> State# (PrimState m)
-> (# State# (PrimState m), MutableByteArray# (PrimState m) #)
forall d. Int# -> State# d -> (# State# d, MutableByteArray# d #)
newByteArray# Int#
n# State# (PrimState m)
s# of
                        (# State# (PrimState m)
s'#, MutableByteArray# (PrimState m)
arr# #) -> (# State# (PrimState m)
s'#, MutableByteArray# (PrimState m) -> MutableByteArray (PrimState m)
forall s. MutableByteArray# s -> MutableByteArray s
MutableByteArray MutableByteArray# (PrimState m)
arr# #))

-- | Create a /pinned/ byte array of the specified size in bytes. The garbage
-- collector is guaranteed not to move it.
--
-- /Note:/ this function does not check if the input is non-negative.
newPinnedByteArray :: PrimMonad m => Int -> m (MutableByteArray (PrimState m))
{-# INLINE newPinnedByteArray #-}
newPinnedByteArray :: Int -> m (MutableByteArray (PrimState m))
newPinnedByteArray (I# Int#
n#)
  = (State# (PrimState m)
 -> (# State# (PrimState m), MutableByteArray (PrimState m) #))
-> m (MutableByteArray (PrimState m))
forall (m :: * -> *) a.
PrimMonad m =>
(State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
primitive (\State# (PrimState m)
s# -> case Int#
-> State# (PrimState m)
-> (# State# (PrimState m), MutableByteArray# (PrimState m) #)
forall d. Int# -> State# d -> (# State# d, MutableByteArray# d #)
newPinnedByteArray# Int#
n# State# (PrimState m)
s# of
                        (# State# (PrimState m)
s'#, MutableByteArray# (PrimState m)
arr# #) -> (# State# (PrimState m)
s'#, MutableByteArray# (PrimState m) -> MutableByteArray (PrimState m)
forall s. MutableByteArray# s -> MutableByteArray s
MutableByteArray MutableByteArray# (PrimState m)
arr# #))

-- | Create a /pinned/ byte array of the specified size in bytes and with the
-- given alignment. The garbage collector is guaranteed not to move it.
--
-- /Note:/ this function does not check if the input is non-negative.
newAlignedPinnedByteArray
  :: PrimMonad m
  => Int  -- ^ size
  -> Int  -- ^ alignment
  -> m (MutableByteArray (PrimState m))
{-# INLINE newAlignedPinnedByteArray #-}
newAlignedPinnedByteArray :: Int -> Int -> m (MutableByteArray (PrimState m))
newAlignedPinnedByteArray (I# Int#
n#) (I# Int#
k#)
  = (State# (PrimState m)
 -> (# State# (PrimState m), MutableByteArray (PrimState m) #))
-> m (MutableByteArray (PrimState m))
forall (m :: * -> *) a.
PrimMonad m =>
(State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
primitive (\State# (PrimState m)
s# -> case Int#
-> Int#
-> State# (PrimState m)
-> (# State# (PrimState m), MutableByteArray# (PrimState m) #)
forall d.
Int# -> Int# -> State# d -> (# State# d, MutableByteArray# d #)
newAlignedPinnedByteArray# Int#
n# Int#
k# State# (PrimState m)
s# of
                        (# State# (PrimState m)
s'#, MutableByteArray# (PrimState m)
arr# #) -> (# State# (PrimState m)
s'#, MutableByteArray# (PrimState m) -> MutableByteArray (PrimState m)
forall s. MutableByteArray# s -> MutableByteArray s
MutableByteArray MutableByteArray# (PrimState m)
arr# #))

-- | Yield a pointer to the array's data. This operation is only safe on
-- /pinned/ byte arrays allocated by 'newPinnedByteArray' or
-- 'newAlignedPinnedByteArray'.
byteArrayContents :: ByteArray -> Ptr Word8
{-# INLINE byteArrayContents #-}
byteArrayContents :: ByteArray -> Ptr Word8
byteArrayContents (ByteArray ByteArray#
arr#) = Addr# -> Ptr Word8
forall a. Addr# -> Ptr a
Ptr (ByteArray# -> Addr#
byteArrayContents# ByteArray#
arr#)

-- | Yield a pointer to the array's data. This operation is only safe on
-- /pinned/ byte arrays allocated by 'newPinnedByteArray' or
-- 'newAlignedPinnedByteArray'.
mutableByteArrayContents :: MutableByteArray s -> Ptr Word8
{-# INLINE mutableByteArrayContents #-}
mutableByteArrayContents :: MutableByteArray s -> Ptr Word8
mutableByteArrayContents (MutableByteArray MutableByteArray# s
arr#)
  = Addr# -> Ptr Word8
forall a. Addr# -> Ptr a
Ptr (ByteArray# -> Addr#
byteArrayContents# (MutableByteArray# s -> ByteArray#
unsafeCoerce# MutableByteArray# s
arr#))

-- | Check if the two arrays refer to the same memory block.
sameMutableByteArray :: MutableByteArray s -> MutableByteArray s -> Bool
{-# INLINE sameMutableByteArray #-}
sameMutableByteArray :: MutableByteArray s -> MutableByteArray s -> Bool
sameMutableByteArray (MutableByteArray MutableByteArray# s
arr#) (MutableByteArray MutableByteArray# s
brr#)
  = Int# -> Bool
isTrue# (MutableByteArray# s -> MutableByteArray# s -> Int#
forall d. MutableByteArray# d -> MutableByteArray# d -> Int#
sameMutableByteArray# MutableByteArray# s
arr# MutableByteArray# s
brr#)

-- | Resize a mutable byte array. The new size is given in bytes.
--
-- This will either resize the array in-place or, if not possible, allocate the
-- contents into a new, unpinned array and copy the original array's contents.
--
-- To avoid undefined behaviour, the original 'MutableByteArray' shall not be
-- accessed anymore after a 'resizeMutableByteArray' has been performed.
-- Moreover, no reference to the old one should be kept in order to allow
-- garbage collection of the original 'MutableByteArray' in case a new
-- 'MutableByteArray' had to be allocated.
--
-- @since 0.6.4.0
resizeMutableByteArray
  :: PrimMonad m => MutableByteArray (PrimState m) -> Int
                 -> m (MutableByteArray (PrimState m))
{-# INLINE resizeMutableByteArray #-}
#if __GLASGOW_HASKELL__ >= 710
resizeMutableByteArray :: MutableByteArray (PrimState m)
-> Int -> m (MutableByteArray (PrimState m))
resizeMutableByteArray (MutableByteArray MutableByteArray# (PrimState m)
arr#) (I# Int#
n#)
  = (State# (PrimState m)
 -> (# State# (PrimState m), MutableByteArray (PrimState m) #))
-> m (MutableByteArray (PrimState m))
forall (m :: * -> *) a.
PrimMonad m =>
(State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
primitive (\State# (PrimState m)
s# -> case MutableByteArray# (PrimState m)
-> Int#
-> State# (PrimState m)
-> (# State# (PrimState m), MutableByteArray# (PrimState m) #)
forall d.
MutableByteArray# d
-> Int# -> State# d -> (# State# d, MutableByteArray# d #)
resizeMutableByteArray# MutableByteArray# (PrimState m)
arr# Int#
n# State# (PrimState m)
s# of
                        (# State# (PrimState m)
s'#, MutableByteArray# (PrimState m)
arr'# #) -> (# State# (PrimState m)
s'#, MutableByteArray# (PrimState m) -> MutableByteArray (PrimState m)
forall s. MutableByteArray# s -> MutableByteArray s
MutableByteArray MutableByteArray# (PrimState m)
arr'# #))
#else
resizeMutableByteArray arr n
  = do arr' <- newByteArray n
       copyMutableByteArray arr' 0 arr 0 (min (sizeofMutableByteArray arr) n)
       return arr'
#endif

-- | Get the size of a byte array in bytes. Unlike 'sizeofMutableByteArray',
-- this function ensures sequencing in the presence of resizing.
getSizeofMutableByteArray
  :: PrimMonad m => MutableByteArray (PrimState m) -> m Int
{-# INLINE getSizeofMutableByteArray #-}
#if __GLASGOW_HASKELL__ >= 801
getSizeofMutableByteArray :: MutableByteArray (PrimState m) -> m Int
getSizeofMutableByteArray (MutableByteArray MutableByteArray# (PrimState m)
arr#)
  = (State# (PrimState m) -> (# State# (PrimState m), Int #)) -> m Int
forall (m :: * -> *) a.
PrimMonad m =>
(State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
primitive (\State# (PrimState m)
s# -> case MutableByteArray# (PrimState m)
-> State# (PrimState m) -> (# State# (PrimState m), Int# #)
forall d. MutableByteArray# d -> State# d -> (# State# d, Int# #)
getSizeofMutableByteArray# MutableByteArray# (PrimState m)
arr# State# (PrimState m)
s# of
                        (# State# (PrimState m)
s'#, Int#
n# #) -> (# State# (PrimState m)
s'#, Int# -> Int
I# Int#
n# #))
#else
getSizeofMutableByteArray arr
  = return (sizeofMutableByteArray arr)
#endif

-- | Create an immutable copy of a slice of a byte array. The offset and
-- length are given in bytes.
--
-- This operation makes a copy of the specified section, so it is safe to
-- continue using the mutable array afterward.
freezeByteArray
  :: PrimMonad m
  => MutableByteArray (PrimState m) -- ^ source
  -> Int                            -- ^ offset in bytes
  -> Int                            -- ^ length in bytes
  -> m ByteArray
{-# INLINE freezeByteArray #-}
freezeByteArray :: MutableByteArray (PrimState m) -> Int -> Int -> m ByteArray
freezeByteArray !MutableByteArray (PrimState m)
src !Int
off !Int
len = do
  MutableByteArray (PrimState m)
dst <- Int -> m (MutableByteArray (PrimState m))
forall (m :: * -> *).
PrimMonad m =>
Int -> m (MutableByteArray (PrimState m))
newByteArray Int
len
  MutableByteArray (PrimState m)
-> Int -> MutableByteArray (PrimState m) -> Int -> Int -> m ()
forall (m :: * -> *).
PrimMonad m =>
MutableByteArray (PrimState m)
-> Int -> MutableByteArray (PrimState m) -> Int -> Int -> m ()
copyMutableByteArray MutableByteArray (PrimState m)
dst Int
0 MutableByteArray (PrimState m)
src Int
off Int
len
  MutableByteArray (PrimState m) -> m ByteArray
forall (m :: * -> *).
PrimMonad m =>
MutableByteArray (PrimState m) -> m ByteArray
unsafeFreezeByteArray MutableByteArray (PrimState m)
dst

-- | Create a mutable byte array from a slice of an immutable byte array.
-- The offset and length are given in bytes.
--
-- This operation makes a copy of the specified slice, so it is safe to
-- use the immutable array afterward.
--
-- @since 0.7.2.0
thawByteArray
  :: PrimMonad m
  => ByteArray -- ^ source
  -> Int       -- ^ offset in bytes
  -> Int       -- ^ length in bytes
  -> m (MutableByteArray (PrimState m))
{-# INLINE thawByteArray #-}
thawByteArray :: ByteArray -> Int -> Int -> m (MutableByteArray (PrimState m))
thawByteArray !ByteArray
src !Int
off !Int
len = do
  MutableByteArray (PrimState m)
dst <- Int -> m (MutableByteArray (PrimState m))
forall (m :: * -> *).
PrimMonad m =>
Int -> m (MutableByteArray (PrimState m))
newByteArray Int
len
  MutableByteArray (PrimState m)
-> Int -> ByteArray -> Int -> Int -> m ()
forall (m :: * -> *).
PrimMonad m =>
MutableByteArray (PrimState m)
-> Int -> ByteArray -> Int -> Int -> m ()
copyByteArray MutableByteArray (PrimState m)
dst Int
0 ByteArray
src Int
off Int
len
  MutableByteArray (PrimState m)
-> m (MutableByteArray (PrimState m))
forall (m :: * -> *) a. Monad m => a -> m a
return MutableByteArray (PrimState m)
dst

-- | Convert a mutable byte array to an immutable one without copying. The
-- array should not be modified after the conversion.
unsafeFreezeByteArray
  :: PrimMonad m => MutableByteArray (PrimState m) -> m ByteArray
{-# INLINE unsafeFreezeByteArray #-}
unsafeFreezeByteArray :: MutableByteArray (PrimState m) -> m ByteArray
unsafeFreezeByteArray (MutableByteArray MutableByteArray# (PrimState m)
arr#)
  = (State# (PrimState m) -> (# State# (PrimState m), ByteArray #))
-> m ByteArray
forall (m :: * -> *) a.
PrimMonad m =>
(State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
primitive (\State# (PrimState m)
s# -> case MutableByteArray# (PrimState m)
-> State# (PrimState m) -> (# State# (PrimState m), ByteArray# #)
forall d.
MutableByteArray# d -> State# d -> (# State# d, ByteArray# #)
unsafeFreezeByteArray# MutableByteArray# (PrimState m)
arr# State# (PrimState m)
s# of
                        (# State# (PrimState m)
s'#, ByteArray#
arr'# #) -> (# State# (PrimState m)
s'#, ByteArray# -> ByteArray
ByteArray ByteArray#
arr'# #))

-- | Convert an immutable byte array to a mutable one without copying. The
-- original array should not be used after the conversion.
unsafeThawByteArray
  :: PrimMonad m => ByteArray -> m (MutableByteArray (PrimState m))
{-# INLINE unsafeThawByteArray #-}
unsafeThawByteArray :: ByteArray -> m (MutableByteArray (PrimState m))
unsafeThawByteArray (ByteArray ByteArray#
arr#)
  = (State# (PrimState m)
 -> (# State# (PrimState m), MutableByteArray (PrimState m) #))
-> m (MutableByteArray (PrimState m))
forall (m :: * -> *) a.
PrimMonad m =>
(State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
primitive (\State# (PrimState m)
s# -> (# State# (PrimState m)
s#, MutableByteArray# (PrimState m) -> MutableByteArray (PrimState m)
forall s. MutableByteArray# s -> MutableByteArray s
MutableByteArray (ByteArray# -> MutableByteArray# (PrimState m)
unsafeCoerce# ByteArray#
arr#) #))

-- | Size of the byte array in bytes.
sizeofByteArray :: ByteArray -> Int
{-# INLINE sizeofByteArray #-}
sizeofByteArray :: ByteArray -> Int
sizeofByteArray (ByteArray ByteArray#
arr#) = Int# -> Int
I# (ByteArray# -> Int#
sizeofByteArray# ByteArray#
arr#)

-- | Size of the mutable byte array in bytes. This function\'s behavior
-- is undefined if 'resizeMutableByteArray' is ever called on the mutable
-- byte array given as the argument. Consequently, use of this function
-- is discouraged. Prefer 'getSizeofMutableByteArray', which ensures correct
-- sequencing in the presence of resizing.
sizeofMutableByteArray :: MutableByteArray s -> Int
{-# INLINE sizeofMutableByteArray #-}
sizeofMutableByteArray :: MutableByteArray s -> Int
sizeofMutableByteArray (MutableByteArray MutableByteArray# s
arr#) = Int# -> Int
I# (MutableByteArray# s -> Int#
forall d. MutableByteArray# d -> Int#
sizeofMutableByteArray# MutableByteArray# s
arr#)

-- Although it is possible to shim resizeMutableByteArray for old GHCs, this
-- is not the case with shrinkMutableByteArray.
#if __GLASGOW_HASKELL__ >= 710
-- | Shrink a mutable byte array. The new size is given in bytes.
-- It must be smaller than the old size. The array will be resized in place.
-- This function is only available when compiling with GHC 7.10 or newer.
--
-- @since 0.7.1.0
shrinkMutableByteArray :: PrimMonad m
  => MutableByteArray (PrimState m)
  -> Int -- ^ new size
  -> m ()
{-# INLINE shrinkMutableByteArray #-}
shrinkMutableByteArray :: MutableByteArray (PrimState m) -> Int -> m ()
shrinkMutableByteArray (MutableByteArray MutableByteArray# (PrimState m)
arr#) (I# Int#
n#)
  = (State# (PrimState m) -> State# (PrimState m)) -> m ()
forall (m :: * -> *).
PrimMonad m =>
(State# (PrimState m) -> State# (PrimState m)) -> m ()
primitive_ (MutableByteArray# (PrimState m)
-> Int# -> State# (PrimState m) -> State# (PrimState m)
forall d. MutableByteArray# d -> Int# -> State# d -> State# d
shrinkMutableByteArray# MutableByteArray# (PrimState m)
arr# Int#
n#)
#endif

#if __GLASGOW_HASKELL__ >= 802
-- | Check whether or not the byte array is pinned. Pinned byte arrays cannot
--   be moved by the garbage collector. It is safe to use 'byteArrayContents'
--   on such byte arrays. This function is only available when compiling with
--   GHC 8.2 or newer.
--
--   @since 0.6.4.0
isByteArrayPinned :: ByteArray -> Bool
{-# INLINE isByteArrayPinned #-}
isByteArrayPinned :: ByteArray -> Bool
isByteArrayPinned (ByteArray ByteArray#
arr#) = Int# -> Bool
isTrue# (ByteArray# -> Int#
Exts.isByteArrayPinned# ByteArray#
arr#)

-- | Check whether or not the mutable byte array is pinned. This function is
--   only available when compiling with GHC 8.2 or newer.
--
--   @since 0.6.4.0
isMutableByteArrayPinned :: MutableByteArray s -> Bool
{-# INLINE isMutableByteArrayPinned #-}
isMutableByteArrayPinned :: MutableByteArray s -> Bool
isMutableByteArrayPinned (MutableByteArray MutableByteArray# s
marr#) = Int# -> Bool
isTrue# (MutableByteArray# s -> Int#
forall d. MutableByteArray# d -> Int#
Exts.isMutableByteArrayPinned# MutableByteArray# s
marr#)
#endif

-- | Read a primitive value from the byte array. The offset is given in
-- elements of type @a@ rather than in bytes.
--
-- /Note:/ this function does not do bounds checking.
indexByteArray :: Prim a => ByteArray -> Int -> a
{-# INLINE indexByteArray #-}
indexByteArray :: ByteArray -> Int -> a
indexByteArray (ByteArray ByteArray#
arr#) (I# Int#
i#) = ByteArray# -> Int# -> a
forall a. Prim a => ByteArray# -> Int# -> a
indexByteArray# ByteArray#
arr# Int#
i#

-- | Read a primitive value from the byte array. The offset is given in
-- elements of type @a@ rather than in bytes.
--
-- /Note:/ this function does not do bounds checking.
readByteArray
  :: (Prim a, PrimMonad m) => MutableByteArray (PrimState m) -> Int -> m a
{-# INLINE readByteArray #-}
readByteArray :: MutableByteArray (PrimState m) -> Int -> m a
readByteArray (MutableByteArray MutableByteArray# (PrimState m)
arr#) (I# Int#
i#)
  = (State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
forall (m :: * -> *) a.
PrimMonad m =>
(State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
primitive (MutableByteArray# (PrimState m)
-> Int# -> State# (PrimState m) -> (# State# (PrimState m), a #)
forall a s.
Prim a =>
MutableByteArray# s -> Int# -> State# s -> (# State# s, a #)
readByteArray# MutableByteArray# (PrimState m)
arr# Int#
i#)

-- | Write a primitive value to the byte array. The offset is given in
-- elements of type @a@ rather than in bytes.
--
-- /Note:/ this function does not do bounds checking.
writeByteArray
  :: (Prim a, PrimMonad m) => MutableByteArray (PrimState m) -> Int -> a -> m ()
{-# INLINE writeByteArray #-}
writeByteArray :: MutableByteArray (PrimState m) -> Int -> a -> m ()
writeByteArray (MutableByteArray MutableByteArray# (PrimState m)
arr#) (I# Int#
i#) a
x
  = (State# (PrimState m) -> State# (PrimState m)) -> m ()
forall (m :: * -> *).
PrimMonad m =>
(State# (PrimState m) -> State# (PrimState m)) -> m ()
primitive_ (MutableByteArray# (PrimState m)
-> Int# -> a -> State# (PrimState m) -> State# (PrimState m)
forall a s.
Prim a =>
MutableByteArray# s -> Int# -> a -> State# s -> State# s
writeByteArray# MutableByteArray# (PrimState m)
arr# Int#
i# a
x)

-- | Right-fold over the elements of a 'ByteArray'.
foldrByteArray :: forall a b. (Prim a) => (a -> b -> b) -> b -> ByteArray -> b
{-# INLINE foldrByteArray #-}
foldrByteArray :: (a -> b -> b) -> b -> ByteArray -> b
foldrByteArray a -> b -> b
f b
z ByteArray
arr = Int -> b
go Int
0
  where
    go :: Int -> b
go Int
i
      | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
maxI  = a -> b -> b
f (ByteArray -> Int -> a
forall a. Prim a => ByteArray -> Int -> a
indexByteArray ByteArray
arr Int
i) (Int -> b
go (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1))
      | Bool
otherwise = b
z
    maxI :: Int
maxI = ByteArray -> Int
sizeofByteArray ByteArray
arr Int -> Int -> Int
forall a. Integral a => a -> a -> a
`quot` a -> Int
forall a. Prim a => a -> Int
sizeOf (a
forall a. HasCallStack => a
undefined :: a)

-- | Create a 'ByteArray' from a list.
--
-- @byteArrayFromList xs = `byteArrayFromListN` (length xs) xs@
byteArrayFromList :: Prim a => [a] -> ByteArray
byteArrayFromList :: [a] -> ByteArray
byteArrayFromList [a]
xs = Int -> [a] -> ByteArray
forall a. Prim a => Int -> [a] -> ByteArray
byteArrayFromListN ([a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xs) [a]
xs

-- | Create a 'ByteArray' from a list of a known length. If the length
--   of the list does not match the given length, this throws an exception.
byteArrayFromListN :: Prim a => Int -> [a] -> ByteArray
byteArrayFromListN :: Int -> [a] -> ByteArray
byteArrayFromListN Int
n [a]
ys = (forall s. ST s ByteArray) -> ByteArray
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s ByteArray) -> ByteArray)
-> (forall s. ST s ByteArray) -> ByteArray
forall a b. (a -> b) -> a -> b
$ do
    MutableByteArray s
marr <- Int -> ST s (MutableByteArray (PrimState (ST s)))
forall (m :: * -> *).
PrimMonad m =>
Int -> m (MutableByteArray (PrimState m))
newByteArray (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
* a -> Int
forall a. Prim a => a -> Int
sizeOf ([a] -> a
forall a. [a] -> a
head [a]
ys))
    let go :: Int -> [a] -> ST s ()
go !Int
ix [] = if Int
ix Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
n
          then () -> ST s ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
          else String -> String -> ST s ()
forall a. String -> String -> a
die String
"byteArrayFromListN" String
"list length less than specified size"
        go !Int
ix (a
x : [a]
xs) = if Int
ix Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
n
          then do
            MutableByteArray (PrimState (ST s)) -> Int -> a -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> a -> m ()
writeByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
marr Int
ix a
x
            Int -> [a] -> ST s ()
go (Int
ix Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) [a]
xs
          else String -> String -> ST s ()
forall a. String -> String -> a
die String
"byteArrayFromListN" String
"list length greater than specified size"
    Int -> [a] -> ST s ()
go Int
0 [a]
ys
    MutableByteArray (PrimState (ST s)) -> ST s ByteArray
forall (m :: * -> *).
PrimMonad m =>
MutableByteArray (PrimState m) -> m ByteArray
unsafeFreezeByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
marr

unI# :: Int -> Int#
unI# :: Int -> Int#
unI# (I# Int#
n#) = Int#
n#

-- | Copy a slice of an immutable byte array to a mutable byte array.
--
-- /Note:/ this function does not do bounds or overlap checking.
copyByteArray
  :: PrimMonad m => MutableByteArray (PrimState m)
                                        -- ^ destination array
                 -> Int                 -- ^ offset into destination array
                 -> ByteArray           -- ^ source array
                 -> Int                 -- ^ offset into source array
                 -> Int                 -- ^ number of bytes to copy
                 -> m ()
{-# INLINE copyByteArray #-}
copyByteArray :: MutableByteArray (PrimState m)
-> Int -> ByteArray -> Int -> Int -> m ()
copyByteArray (MutableByteArray MutableByteArray# (PrimState m)
dst#) Int
doff (ByteArray ByteArray#
src#) Int
soff Int
sz
  = (State# (PrimState m) -> State# (PrimState m)) -> m ()
forall (m :: * -> *).
PrimMonad m =>
(State# (PrimState m) -> State# (PrimState m)) -> m ()
primitive_ (ByteArray#
-> Int#
-> MutableByteArray# (PrimState m)
-> Int#
-> Int#
-> State# (PrimState m)
-> State# (PrimState m)
forall d.
ByteArray#
-> Int#
-> MutableByteArray# d
-> Int#
-> Int#
-> State# d
-> State# d
copyByteArray# ByteArray#
src# (Int -> Int#
unI# Int
soff) MutableByteArray# (PrimState m)
dst# (Int -> Int#
unI# Int
doff) (Int -> Int#
unI# Int
sz))

-- | Copy a slice of a mutable byte array into another array. The two slices
-- may not overlap.
--
-- /Note:/ this function does not do bounds or overlap checking.
copyMutableByteArray
  :: PrimMonad m => MutableByteArray (PrimState m)
                                        -- ^ destination array
                 -> Int                 -- ^ offset into destination array
                 -> MutableByteArray (PrimState m)
                                        -- ^ source array
                 -> Int                 -- ^ offset into source array
                 -> Int                 -- ^ number of bytes to copy
                 -> m ()
{-# INLINE copyMutableByteArray #-}
copyMutableByteArray :: MutableByteArray (PrimState m)
-> Int -> MutableByteArray (PrimState m) -> Int -> Int -> m ()
copyMutableByteArray (MutableByteArray MutableByteArray# (PrimState m)
dst#) Int
doff
                     (MutableByteArray MutableByteArray# (PrimState m)
src#) Int
soff Int
sz
  = (State# (PrimState m) -> State# (PrimState m)) -> m ()
forall (m :: * -> *).
PrimMonad m =>
(State# (PrimState m) -> State# (PrimState m)) -> m ()
primitive_ (MutableByteArray# (PrimState m)
-> Int#
-> MutableByteArray# (PrimState m)
-> Int#
-> Int#
-> State# (PrimState m)
-> State# (PrimState m)
forall d.
MutableByteArray# d
-> Int#
-> MutableByteArray# d
-> Int#
-> Int#
-> State# d
-> State# d
copyMutableByteArray# MutableByteArray# (PrimState m)
src# (Int -> Int#
unI# Int
soff) MutableByteArray# (PrimState m)
dst# (Int -> Int#
unI# Int
doff) (Int -> Int#
unI# Int
sz))

#if __GLASGOW_HASKELL__ >= 708
-- | Copy a slice of a byte array to an unmanaged Pointer Address. These must not
--   overlap. The offset and length given in elements, not in bytes. This function
--   is only available when compiling with GHC 7.8 or newer.
--
--   /Note:/ this function does not do bounds or overlap checking.
--
--   @since 0.7.1.0
copyByteArrayToPtr
  :: forall m a. (PrimMonad m, Prim a)
  => Ptr a -- ^ destination
  -> ByteArray -- ^ source array
  -> Int -- ^ offset into source array, interpreted as elements of type @a@
  -> Int -- ^ number of elements to copy
  -> m ()
{-# INLINE copyByteArrayToPtr #-}
copyByteArrayToPtr :: Ptr a -> ByteArray -> Int -> Int -> m ()
copyByteArrayToPtr (Ptr Addr#
dst#) (ByteArray ByteArray#
src#) Int
soff Int
sz
  = (State# (PrimState m) -> State# (PrimState m)) -> m ()
forall (m :: * -> *).
PrimMonad m =>
(State# (PrimState m) -> State# (PrimState m)) -> m ()
primitive_ (ByteArray#
-> Int#
-> Addr#
-> Int#
-> State# (PrimState m)
-> State# (PrimState m)
forall d.
ByteArray# -> Int# -> Addr# -> Int# -> State# d -> State# d
copyByteArrayToAddr# ByteArray#
src# (Int -> Int#
unI# Int
soff Int# -> Int# -> Int#
*# Int#
siz# ) Addr#
dst# (Int -> Int#
unI# Int
sz))
  where
  siz# :: Int#
siz# = a -> Int#
forall a. Prim a => a -> Int#
sizeOf# (a
forall a. HasCallStack => a
undefined :: a)

-- | Copy a slice of a mutable byte array to an unmanaged Pointer address.
--   These must not overlap. The offset and length given in elements, not
--   in bytes. This function is only available when compiling with GHC 7.8
--   or newer.
--
--   /Note:/ this function does not do bounds or overlap checking.
--
--   @since 0.7.1.0
copyMutableByteArrayToPtr
  :: forall m a. (PrimMonad m, Prim a)
  => Ptr a -- ^ destination
  -> MutableByteArray (PrimState m) -- ^ source array
  -> Int -- ^ offset into source array, interpreted as elements of type @a@
  -> Int -- ^ number of elements to copy
  -> m ()
{-# INLINE copyMutableByteArrayToPtr #-}
copyMutableByteArrayToPtr :: Ptr a -> MutableByteArray (PrimState m) -> Int -> Int -> m ()
copyMutableByteArrayToPtr (Ptr Addr#
dst#) (MutableByteArray MutableByteArray# (PrimState m)
src#) Int
soff Int
sz
  = (State# (PrimState m) -> State# (PrimState m)) -> m ()
forall (m :: * -> *).
PrimMonad m =>
(State# (PrimState m) -> State# (PrimState m)) -> m ()
primitive_ (MutableByteArray# (PrimState m)
-> Int#
-> Addr#
-> Int#
-> State# (PrimState m)
-> State# (PrimState m)
forall d.
MutableByteArray# d
-> Int# -> Addr# -> Int# -> State# d -> State# d
copyMutableByteArrayToAddr# MutableByteArray# (PrimState m)
src# (Int -> Int#
unI# Int
soff Int# -> Int# -> Int#
*# Int#
siz# ) Addr#
dst# (Int -> Int#
unI# Int
sz))
  where
  siz# :: Int#
siz# = a -> Int#
forall a. Prim a => a -> Int#
sizeOf# (a
forall a. HasCallStack => a
undefined :: a)

------
--- These latter two should be DEPRECATED
-----

-- | Copy a slice of a byte array to an unmanaged address. These must not
--   overlap. This function is only available when compiling with GHC 7.8
--   or newer.
--
--   Note: This function is just 'copyByteArrayToPtr' where @a@ is 'Word8'.
--
--   @since 0.6.4.0
copyByteArrayToAddr
  :: PrimMonad m
  => Ptr Word8 -- ^ destination
  -> ByteArray -- ^ source array
  -> Int -- ^ offset into source array
  -> Int -- ^ number of bytes to copy
  -> m ()
{-# INLINE copyByteArrayToAddr #-}
copyByteArrayToAddr :: Ptr Word8 -> ByteArray -> Int -> Int -> m ()
copyByteArrayToAddr (Ptr Addr#
dst#) (ByteArray ByteArray#
src#) Int
soff Int
sz
  = (State# (PrimState m) -> State# (PrimState m)) -> m ()
forall (m :: * -> *).
PrimMonad m =>
(State# (PrimState m) -> State# (PrimState m)) -> m ()
primitive_ (ByteArray#
-> Int#
-> Addr#
-> Int#
-> State# (PrimState m)
-> State# (PrimState m)
forall d.
ByteArray# -> Int# -> Addr# -> Int# -> State# d -> State# d
copyByteArrayToAddr# ByteArray#
src# (Int -> Int#
unI# Int
soff) Addr#
dst# (Int -> Int#
unI# Int
sz))

-- | Copy a slice of a mutable byte array to an unmanaged address. These must
--   not overlap. This function is only available when compiling with GHC 7.8
--   or newer.
--
--   Note: This function is just 'copyMutableByteArrayToPtr' where @a@ is 'Word8'.
--
--   @since 0.6.4.0
copyMutableByteArrayToAddr
  :: PrimMonad m
  => Ptr Word8 -- ^ destination
  -> MutableByteArray (PrimState m) -- ^ source array
  -> Int -- ^ offset into source array
  -> Int -- ^ number of bytes to copy
  -> m ()
{-# INLINE copyMutableByteArrayToAddr #-}
copyMutableByteArrayToAddr :: Ptr Word8 -> MutableByteArray (PrimState m) -> Int -> Int -> m ()
copyMutableByteArrayToAddr (Ptr Addr#
dst#) (MutableByteArray MutableByteArray# (PrimState m)
src#) Int
soff Int
sz
  = (State# (PrimState m) -> State# (PrimState m)) -> m ()
forall (m :: * -> *).
PrimMonad m =>
(State# (PrimState m) -> State# (PrimState m)) -> m ()
primitive_ (MutableByteArray# (PrimState m)
-> Int#
-> Addr#
-> Int#
-> State# (PrimState m)
-> State# (PrimState m)
forall d.
MutableByteArray# d
-> Int# -> Addr# -> Int# -> State# d -> State# d
copyMutableByteArrayToAddr# MutableByteArray# (PrimState m)
src# (Int -> Int#
unI# Int
soff) Addr#
dst# (Int -> Int#
unI# Int
sz))
#endif

-- | Copy a slice of a mutable byte array into another, potentially
-- overlapping array.
moveByteArray
  :: PrimMonad m => MutableByteArray (PrimState m)
                                        -- ^ destination array
                 -> Int                 -- ^ offset into destination array
                 -> MutableByteArray (PrimState m)
                                        -- ^ source array
                 -> Int                 -- ^ offset into source array
                 -> Int                 -- ^ number of bytes to copy
                 -> m ()
{-# INLINE moveByteArray #-}
moveByteArray :: MutableByteArray (PrimState m)
-> Int -> MutableByteArray (PrimState m) -> Int -> Int -> m ()
moveByteArray (MutableByteArray MutableByteArray# (PrimState m)
dst#) Int
doff
              (MutableByteArray MutableByteArray# (PrimState m)
src#) Int
soff Int
sz
  = IO () -> m ()
forall (m1 :: * -> *) (m2 :: * -> *) a.
(PrimBase m1, PrimMonad m2) =>
m1 a -> m2 a
unsafePrimToPrim
  (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ MutableByteArray# (PrimState m)
-> CPtrdiff
-> MutableByteArray# (PrimState m)
-> CPtrdiff
-> CSize
-> IO ()
forall s.
MutableByteArray# s
-> CPtrdiff -> MutableByteArray# s -> CPtrdiff -> CSize -> IO ()
memmove_mba MutableByteArray# (PrimState m)
dst# (Int -> CPtrdiff
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
doff) MutableByteArray# (PrimState m)
src# (Int -> CPtrdiff
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
soff)
                     (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
sz)

-- | Fill a slice of a mutable byte array with a value. The offset and length
-- are given in elements of type @a@ rather than in bytes.
--
-- /Note:/ this function does not do bounds checking.
setByteArray
  :: (Prim a, PrimMonad m) => MutableByteArray (PrimState m) -- ^ array to fill
                           -> Int                 -- ^ offset into array
                           -> Int                 -- ^ number of values to fill
                           -> a                   -- ^ value to fill with
                           -> m ()
{-# INLINE setByteArray #-}
setByteArray :: MutableByteArray (PrimState m) -> Int -> Int -> a -> m ()
setByteArray (MutableByteArray MutableByteArray# (PrimState m)
dst#) (I# Int#
doff#) (I# Int#
sz#) a
x
  = (State# (PrimState m) -> State# (PrimState m)) -> m ()
forall (m :: * -> *).
PrimMonad m =>
(State# (PrimState m) -> State# (PrimState m)) -> m ()
primitive_ (MutableByteArray# (PrimState m)
-> Int#
-> Int#
-> a
-> State# (PrimState m)
-> State# (PrimState m)
forall a s.
Prim a =>
MutableByteArray# s -> Int# -> Int# -> a -> State# s -> State# s
setByteArray# MutableByteArray# (PrimState m)
dst# Int#
doff# Int#
sz# a
x)

-- | Fill a slice of a mutable byte array with a byte.
--
-- /Note:/ this function does not do bounds checking.
fillByteArray
  :: PrimMonad m => MutableByteArray (PrimState m)
                                        -- ^ array to fill
                 -> Int                 -- ^ offset into array
                 -> Int                 -- ^ number of bytes to fill
                 -> Word8               -- ^ byte to fill with
                 -> m ()
{-# INLINE fillByteArray #-}
fillByteArray :: MutableByteArray (PrimState m) -> Int -> Int -> Word8 -> m ()
fillByteArray = MutableByteArray (PrimState m) -> Int -> Int -> Word8 -> m ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutableByteArray (PrimState m) -> Int -> Int -> a -> m ()
setByteArray

foreign import ccall unsafe "primitive-memops.h hsprimitive_memmove"
  memmove_mba :: MutableByteArray# s -> CPtrdiff
              -> MutableByteArray# s -> CPtrdiff
              -> CSize -> IO ()

instance Eq (MutableByteArray s) where
  == :: MutableByteArray s -> MutableByteArray s -> Bool
(==) = MutableByteArray s -> MutableByteArray s -> Bool
forall s. MutableByteArray s -> MutableByteArray s -> Bool
sameMutableByteArray

instance Data ByteArray where
  toConstr :: ByteArray -> Constr
toConstr ByteArray
_ = String -> Constr
forall a. HasCallStack => String -> a
error String
"toConstr"
  gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ByteArray
gunfold forall b r. Data b => c (b -> r) -> c r
_ forall r. r -> c r
_ = String -> Constr -> c ByteArray
forall a. HasCallStack => String -> a
error String
"gunfold"
  dataTypeOf :: ByteArray -> DataType
dataTypeOf ByteArray
_ = String -> DataType
mkNoRepType String
"Data.Primitive.ByteArray.ByteArray"

instance Typeable s => Data (MutableByteArray s) where
  toConstr :: MutableByteArray s -> Constr
toConstr MutableByteArray s
_ = String -> Constr
forall a. HasCallStack => String -> a
error String
"toConstr"
  gunfold :: (forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (MutableByteArray s)
gunfold forall b r. Data b => c (b -> r) -> c r
_ forall r. r -> c r
_ = String -> Constr -> c (MutableByteArray s)
forall a. HasCallStack => String -> a
error String
"gunfold"
  dataTypeOf :: MutableByteArray s -> DataType
dataTypeOf MutableByteArray s
_ = String -> DataType
mkNoRepType String
"Data.Primitive.ByteArray.MutableByteArray"

-- | @since 0.6.3.0
--
-- Behavior changed in 0.7.2.0. Before 0.7.2.0, this instance rendered
-- 8-bit words less than 16 as a single hexadecimal digit (e.g. 13 was @0xD@).
-- Starting with 0.7.2.0, all 8-bit words are represented as two digits
-- (e.g. 13 is @0x0D@).
instance Show ByteArray where
  showsPrec :: Int -> ByteArray -> ShowS
showsPrec Int
_ ByteArray
ba =
      String -> ShowS
showString String
"[" ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ShowS
go Int
0
    where
      showW8 :: Word8 -> String -> String
      showW8 :: Word8 -> ShowS
showW8 !Word8
w String
s =
          Char
'0'
        Char -> ShowS
forall k1. k1 -> [k1] -> [k1]
: Char
'x'
        Char -> ShowS
forall k1. k1 -> [k1] -> [k1]
: Int -> Char
intToDigit (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8 -> Int -> Word8
forall a. Bits a => a -> Int -> a
unsafeShiftR Word8
w Int
4))
        Char -> ShowS
forall k1. k1 -> [k1] -> [k1]
: Int -> Char
intToDigit (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word8
w Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0x0F))
        Char -> ShowS
forall k1. k1 -> [k1] -> [k1]
: String
s
      go :: Int -> ShowS
go Int
i
        | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< ByteArray -> Int
sizeofByteArray ByteArray
ba = ShowS
comma ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> ShowS
showW8 (ByteArray -> Int -> Word8
forall a. Prim a => ByteArray -> Int -> a
indexByteArray ByteArray
ba Int
i :: Word8) ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ShowS
go (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)
        | Bool
otherwise              = Char -> ShowS
showChar Char
']'
        where
          comma :: ShowS
comma | Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0    = ShowS
forall a. a -> a
id
                | Bool
otherwise = String -> ShowS
showString String
", "


-- Only used internally
compareByteArraysFromBeginning :: ByteArray -> ByteArray -> Int -> Ordering
{-# INLINE compareByteArraysFromBeginning #-}
#if __GLASGOW_HASKELL__ >= 804
compareByteArraysFromBeginning :: ByteArray -> ByteArray -> Int -> Ordering
compareByteArraysFromBeginning (ByteArray ByteArray#
ba1#) (ByteArray ByteArray#
ba2#) (I# Int#
n#)
  = Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Int# -> Int
I# (ByteArray# -> Int# -> ByteArray# -> Int# -> Int# -> Int#
compareByteArrays# ByteArray#
ba1# Int#
0# ByteArray#
ba2# Int#
0# Int#
n#)) Int
0
#else
-- Emulate GHC 8.4's 'GHC.Prim.compareByteArrays#'
compareByteArraysFromBeginning (ByteArray ba1#) (ByteArray ba2#) (I# n#)
  = compare (fromCInt (unsafeDupablePerformIO (memcmp_ba ba1# ba2# n))) 0
  where
    n = fromIntegral (I# n#) :: CSize
    fromCInt = fromIntegral :: CInt -> Int

foreign import ccall unsafe "primitive-memops.h hsprimitive_memcmp"
  memcmp_ba :: ByteArray# -> ByteArray# -> CSize -> IO CInt
#endif

-- | Lexicographic comparison of equal-length slices into two byte arrays.
-- This wraps the @compareByteArrays#@ primop, which wraps @memcmp@.
compareByteArrays ::
     ByteArray -- ^ Array A
  -> Int -- ^ Offset A, given in bytes
  -> ByteArray -- ^ Array B
  -> Int -- ^ Offset B, given in bytes
  -> Int -- ^ Length of slice, given in bytes
  -> Ordering
{-# INLINE compareByteArrays #-}
#if __GLASGOW_HASKELL__ >= 804
compareByteArrays :: ByteArray -> Int -> ByteArray -> Int -> Int -> Ordering
compareByteArrays (ByteArray ByteArray#
ba1#) (I# Int#
off1#) (ByteArray ByteArray#
ba2#) (I# Int#
off2#) (I# Int#
n#)
  = Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Int# -> Int
I# (ByteArray# -> Int# -> ByteArray# -> Int# -> Int# -> Int#
compareByteArrays# ByteArray#
ba1# Int#
off1# ByteArray#
ba2# Int#
off2# Int#
n#)) Int
0
#else
-- Emulate GHC 8.4's 'GHC.Prim.compareByteArrays#'
compareByteArrays (ByteArray ba1#) (I# off1#) (ByteArray ba2#) (I# off2#) (I# n#)
  = compare (fromCInt (unsafeDupablePerformIO (memcmp_ba_offs ba1# off1# ba2# off2# n))) 0
  where
    n = fromIntegral (I# n#) :: CSize
    fromCInt = fromIntegral :: CInt -> Int

foreign import ccall unsafe "primitive-memops.h hsprimitive_memcmp_offset"
  memcmp_ba_offs :: ByteArray# -> Int# -> ByteArray# -> Int# -> CSize -> IO CInt
#endif


sameByteArray :: ByteArray# -> ByteArray# -> Bool
sameByteArray :: ByteArray# -> ByteArray# -> Bool
sameByteArray ByteArray#
ba1 ByteArray#
ba2 =
    case () -> () -> Int#
forall k1. k1 -> k1 -> Int#
reallyUnsafePtrEquality# (ByteArray# -> ()
unsafeCoerce# ByteArray#
ba1 :: ()) (ByteArray# -> ()
unsafeCoerce# ByteArray#
ba2 :: ()) of
#if __GLASGOW_HASKELL__ >= 708
      Int#
r -> Int# -> Bool
isTrue# Int#
r
#else
      1# -> True
      0# -> False
#endif

-- | @since 0.6.3.0
instance Eq ByteArray where
  ba1 :: ByteArray
ba1@(ByteArray ByteArray#
ba1#) == :: ByteArray -> ByteArray -> Bool
== ba2 :: ByteArray
ba2@(ByteArray ByteArray#
ba2#)
    | ByteArray# -> ByteArray# -> Bool
sameByteArray ByteArray#
ba1# ByteArray#
ba2# = Bool
True
    | Int
n1 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
n2 = Bool
False
    | Bool
otherwise = ByteArray -> ByteArray -> Int -> Ordering
compareByteArraysFromBeginning ByteArray
ba1 ByteArray
ba2 Int
n1 Ordering -> Ordering -> Bool
forall a. Eq a => a -> a -> Bool
== Ordering
EQ
    where
      n1 :: Int
n1 = ByteArray -> Int
sizeofByteArray ByteArray
ba1
      n2 :: Int
n2 = ByteArray -> Int
sizeofByteArray ByteArray
ba2

-- | Non-lexicographic ordering. This compares the lengths of
-- the byte arrays first and uses a lexicographic ordering if
-- the lengths are equal. Subject to change between major versions.
--
-- @since 0.6.3.0
instance Ord ByteArray where
  ba1 :: ByteArray
ba1@(ByteArray ByteArray#
ba1#) compare :: ByteArray -> ByteArray -> Ordering
`compare` ba2 :: ByteArray
ba2@(ByteArray ByteArray#
ba2#)
    | ByteArray# -> ByteArray# -> Bool
sameByteArray ByteArray#
ba1# ByteArray#
ba2# = Ordering
EQ
    | Int
n1 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
n2 = Int
n1 Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare` Int
n2
    | Bool
otherwise = ByteArray -> ByteArray -> Int -> Ordering
compareByteArraysFromBeginning ByteArray
ba1 ByteArray
ba2 Int
n1
    where
      n1 :: Int
n1 = ByteArray -> Int
sizeofByteArray ByteArray
ba1
      n2 :: Int
n2 = ByteArray -> Int
sizeofByteArray ByteArray
ba2
-- Note: On GHC 8.4, the primop compareByteArrays# performs a check for pointer
-- equality as a shortcut, so the check here is actually redundant. However, it
-- is included here because it is likely better to check for pointer equality
-- before checking for length equality. Getting the length requires deferencing
-- the pointers, which could cause accesses to memory that is not in the cache.
-- By contrast, a pointer equality check is always extremely cheap.

appendByteArray :: ByteArray -> ByteArray -> ByteArray
appendByteArray :: ByteArray -> ByteArray -> ByteArray
appendByteArray ByteArray
a ByteArray
b = (forall s. ST s ByteArray) -> ByteArray
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s ByteArray) -> ByteArray)
-> (forall s. ST s ByteArray) -> ByteArray
forall a b. (a -> b) -> a -> b
$ do
  MutableByteArray s
marr <- Int -> ST s (MutableByteArray (PrimState (ST s)))
forall (m :: * -> *).
PrimMonad m =>
Int -> m (MutableByteArray (PrimState m))
newByteArray (ByteArray -> Int
sizeofByteArray ByteArray
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ByteArray -> Int
sizeofByteArray ByteArray
b)
  MutableByteArray (PrimState (ST s))
-> Int -> ByteArray -> Int -> Int -> ST s ()
forall (m :: * -> *).
PrimMonad m =>
MutableByteArray (PrimState m)
-> Int -> ByteArray -> Int -> Int -> m ()
copyByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
marr Int
0 ByteArray
a Int
0 (ByteArray -> Int
sizeofByteArray ByteArray
a)
  MutableByteArray (PrimState (ST s))
-> Int -> ByteArray -> Int -> Int -> ST s ()
forall (m :: * -> *).
PrimMonad m =>
MutableByteArray (PrimState m)
-> Int -> ByteArray -> Int -> Int -> m ()
copyByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
marr (ByteArray -> Int
sizeofByteArray ByteArray
a) ByteArray
b Int
0 (ByteArray -> Int
sizeofByteArray ByteArray
b)
  MutableByteArray (PrimState (ST s)) -> ST s ByteArray
forall (m :: * -> *).
PrimMonad m =>
MutableByteArray (PrimState m) -> m ByteArray
unsafeFreezeByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
marr

concatByteArray :: [ByteArray] -> ByteArray
concatByteArray :: [ByteArray] -> ByteArray
concatByteArray [ByteArray]
arrs = (forall s. ST s ByteArray) -> ByteArray
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s ByteArray) -> ByteArray)
-> (forall s. ST s ByteArray) -> ByteArray
forall a b. (a -> b) -> a -> b
$ do
  let len :: Int
len = [ByteArray] -> Int -> Int
calcLength [ByteArray]
arrs Int
0
  MutableByteArray s
marr <- Int -> ST s (MutableByteArray (PrimState (ST s)))
forall (m :: * -> *).
PrimMonad m =>
Int -> m (MutableByteArray (PrimState m))
newByteArray Int
len
  MutableByteArray s -> Int -> [ByteArray] -> ST s ()
forall s. MutableByteArray s -> Int -> [ByteArray] -> ST s ()
pasteByteArrays MutableByteArray s
marr Int
0 [ByteArray]
arrs
  MutableByteArray (PrimState (ST s)) -> ST s ByteArray
forall (m :: * -> *).
PrimMonad m =>
MutableByteArray (PrimState m) -> m ByteArray
unsafeFreezeByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
marr

pasteByteArrays :: MutableByteArray s -> Int -> [ByteArray] -> ST s ()
pasteByteArrays :: MutableByteArray s -> Int -> [ByteArray] -> ST s ()
pasteByteArrays !MutableByteArray s
_ !Int
_ [] = () -> ST s ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
pasteByteArrays !MutableByteArray s
marr !Int
ix (ByteArray
x : [ByteArray]
xs) = do
  MutableByteArray (PrimState (ST s))
-> Int -> ByteArray -> Int -> Int -> ST s ()
forall (m :: * -> *).
PrimMonad m =>
MutableByteArray (PrimState m)
-> Int -> ByteArray -> Int -> Int -> m ()
copyByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
marr Int
ix ByteArray
x Int
0 (ByteArray -> Int
sizeofByteArray ByteArray
x)
  MutableByteArray s -> Int -> [ByteArray] -> ST s ()
forall s. MutableByteArray s -> Int -> [ByteArray] -> ST s ()
pasteByteArrays MutableByteArray s
marr (Int
ix Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ByteArray -> Int
sizeofByteArray ByteArray
x) [ByteArray]
xs

calcLength :: [ByteArray] -> Int -> Int
calcLength :: [ByteArray] -> Int -> Int
calcLength [] !Int
n = Int
n
calcLength (ByteArray
x : [ByteArray]
xs) !Int
n = [ByteArray] -> Int -> Int
calcLength [ByteArray]
xs (ByteArray -> Int
sizeofByteArray ByteArray
x Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
n)

emptyByteArray :: ByteArray
emptyByteArray :: ByteArray
emptyByteArray = (forall s. ST s ByteArray) -> ByteArray
forall a. (forall s. ST s a) -> a
runST (Int -> ST s (MutableByteArray (PrimState (ST s)))
forall (m :: * -> *).
PrimMonad m =>
Int -> m (MutableByteArray (PrimState m))
newByteArray Int
0 ST s (MutableByteArray s)
-> (MutableByteArray s -> ST s ByteArray) -> ST s ByteArray
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= MutableByteArray s -> ST s ByteArray
forall (m :: * -> *).
PrimMonad m =>
MutableByteArray (PrimState m) -> m ByteArray
unsafeFreezeByteArray)

replicateByteArray :: Int -> ByteArray -> ByteArray
replicateByteArray :: Int -> ByteArray -> ByteArray
replicateByteArray Int
n ByteArray
arr = (forall s. ST s ByteArray) -> ByteArray
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s ByteArray) -> ByteArray)
-> (forall s. ST s ByteArray) -> ByteArray
forall a b. (a -> b) -> a -> b
$ do
  MutableByteArray s
marr <- Int -> ST s (MutableByteArray (PrimState (ST s)))
forall (m :: * -> *).
PrimMonad m =>
Int -> m (MutableByteArray (PrimState m))
newByteArray (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
* ByteArray -> Int
sizeofByteArray ByteArray
arr)
  let go :: Int -> ST s ()
go Int
i = if Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
n
        then do
          MutableByteArray (PrimState (ST s))
-> Int -> ByteArray -> Int -> Int -> ST s ()
forall (m :: * -> *).
PrimMonad m =>
MutableByteArray (PrimState m)
-> Int -> ByteArray -> Int -> Int -> m ()
copyByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
marr (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
* ByteArray -> Int
sizeofByteArray ByteArray
arr) ByteArray
arr Int
0 (ByteArray -> Int
sizeofByteArray ByteArray
arr)
          Int -> ST s ()
go (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)
        else () -> ST s ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
  Int -> ST s ()
go Int
0
  MutableByteArray (PrimState (ST s)) -> ST s ByteArray
forall (m :: * -> *).
PrimMonad m =>
MutableByteArray (PrimState m) -> m ByteArray
unsafeFreezeByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
marr

#if MIN_VERSION_base(4,9,0)
instance SG.Semigroup ByteArray where
  <> :: ByteArray -> ByteArray -> ByteArray
(<>) = ByteArray -> ByteArray -> ByteArray
appendByteArray
  sconcat :: NonEmpty ByteArray -> ByteArray
sconcat = [ByteArray] -> ByteArray
forall a. Monoid a => [a] -> a
mconcat ([ByteArray] -> ByteArray)
-> (NonEmpty ByteArray -> [ByteArray])
-> NonEmpty ByteArray
-> ByteArray
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty ByteArray -> [ByteArray]
forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList
  stimes :: b -> ByteArray -> ByteArray
stimes b
i ByteArray
arr
    | Integer
itgr Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
1 = ByteArray
emptyByteArray
    | Integer
itgr Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= (Int -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
forall a. Bounded a => a
maxBound :: Int)) = Int -> ByteArray -> ByteArray
replicateByteArray (Integer -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
itgr) ByteArray
arr
    | Bool
otherwise = String -> ByteArray
forall a. HasCallStack => String -> a
error String
"Data.Primitive.ByteArray#stimes: cannot allocate the requested amount of memory"
    where itgr :: Integer
itgr = b -> Integer
forall a. Integral a => a -> Integer
toInteger b
i :: Integer
#endif

instance Monoid ByteArray where
  mempty :: ByteArray
mempty = ByteArray
emptyByteArray
#if !(MIN_VERSION_base(4,11,0))
  mappend = appendByteArray
#endif
  mconcat :: [ByteArray] -> ByteArray
mconcat = [ByteArray] -> ByteArray
concatByteArray

#if __GLASGOW_HASKELL__ >= 708
-- | @since 0.6.3.0
instance Exts.IsList ByteArray where
  type Item ByteArray = Word8

  toList :: ByteArray -> [Item ByteArray]
toList = (Word8 -> [Word8] -> [Word8]) -> [Word8] -> ByteArray -> [Word8]
forall a b. Prim a => (a -> b -> b) -> b -> ByteArray -> b
foldrByteArray (:) []
  fromList :: [Item ByteArray] -> ByteArray
fromList [Item ByteArray]
xs = Int -> [Word8] -> ByteArray
forall a. Prim a => Int -> [a] -> ByteArray
byteArrayFromListN ([Word8] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Word8]
[Item ByteArray]
xs) [Word8]
[Item ByteArray]
xs
  fromListN :: Int -> [Item ByteArray] -> ByteArray
fromListN = Int -> [Item ByteArray] -> ByteArray
forall a. Prim a => Int -> [a] -> ByteArray
byteArrayFromListN
#endif

die :: String -> String -> a
die :: String -> String -> a
die String
fun String
problem = String -> a
forall a. HasCallStack => String -> a
error (String -> a) -> String -> a
forall a b. (a -> b) -> a -> b
$ String
"Data.Primitive.ByteArray." String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
fun String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
": " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
problem

-- | Return a newly allocated array with the specified subrange of the
-- provided array. The provided array should contain the full subrange
-- specified by the two Ints, but this is not checked.
cloneByteArray ::
     ByteArray -- ^ source array
  -> Int       -- ^ offset into destination array
  -> Int       -- ^ number of bytes to copy
  -> ByteArray
{-# INLINE cloneByteArray #-}
cloneByteArray :: ByteArray -> Int -> Int -> ByteArray
cloneByteArray ByteArray
src Int
off Int
n = (forall s. ST s (MutableByteArray s)) -> ByteArray
runByteArray ((forall s. ST s (MutableByteArray s)) -> ByteArray)
-> (forall s. ST s (MutableByteArray s)) -> ByteArray
forall a b. (a -> b) -> a -> b
$ do
  MutableByteArray s
dst <- Int -> ST s (MutableByteArray (PrimState (ST s)))
forall (m :: * -> *).
PrimMonad m =>
Int -> m (MutableByteArray (PrimState m))
newByteArray Int
n
  MutableByteArray (PrimState (ST s))
-> Int -> ByteArray -> Int -> Int -> ST s ()
forall (m :: * -> *).
PrimMonad m =>
MutableByteArray (PrimState m)
-> Int -> ByteArray -> Int -> Int -> m ()
copyByteArray MutableByteArray s
MutableByteArray (PrimState (ST s))
dst Int
0 ByteArray
src Int
off Int
n
  MutableByteArray s -> ST s (MutableByteArray s)
forall (m :: * -> *) a. Monad m => a -> m a
return MutableByteArray s
dst

-- | Return a newly allocated mutable array with the specified subrange of
-- the provided mutable array. The provided mutable array should contain the
-- full subrange specified by the two Ints, but this is not checked.
cloneMutableByteArray :: PrimMonad m
  => MutableByteArray (PrimState m) -- ^ source array
  -> Int -- ^ offset into destination array
  -> Int -- ^ number of bytes to copy
  -> m (MutableByteArray (PrimState m))
{-# INLINE cloneMutableByteArray #-}
cloneMutableByteArray :: MutableByteArray (PrimState m)
-> Int -> Int -> m (MutableByteArray (PrimState m))
cloneMutableByteArray MutableByteArray (PrimState m)
src Int
off Int
n = do
  MutableByteArray (PrimState m)
dst <- Int -> m (MutableByteArray (PrimState m))
forall (m :: * -> *).
PrimMonad m =>
Int -> m (MutableByteArray (PrimState m))
newByteArray Int
n
  MutableByteArray (PrimState m)
-> Int -> MutableByteArray (PrimState m) -> Int -> Int -> m ()
forall (m :: * -> *).
PrimMonad m =>
MutableByteArray (PrimState m)
-> Int -> MutableByteArray (PrimState m) -> Int -> Int -> m ()
copyMutableByteArray MutableByteArray (PrimState m)
dst Int
0 MutableByteArray (PrimState m)
src Int
off Int
n
  MutableByteArray (PrimState m)
-> m (MutableByteArray (PrimState m))
forall (m :: * -> *) a. Monad m => a -> m a
return MutableByteArray (PrimState m)
dst

#if MIN_VERSION_base(4,10,0) /* In new GHCs, runRW# is available. */
runByteArray
  :: (forall s. ST s (MutableByteArray s))
  -> ByteArray
runByteArray :: (forall s. ST s (MutableByteArray s)) -> ByteArray
runByteArray forall s. ST s (MutableByteArray s)
m = ByteArray# -> ByteArray
ByteArray ((forall s. ST s (MutableByteArray s)) -> ByteArray#
runByteArray# forall s. ST s (MutableByteArray s)
m)

runByteArray#
  :: (forall s. ST s (MutableByteArray s))
  -> ByteArray#
runByteArray# :: (forall s. ST s (MutableByteArray s)) -> ByteArray#
runByteArray# forall s. ST s (MutableByteArray s)
m = case (State# RealWorld -> (# State# RealWorld, ByteArray# #))
-> (# State# RealWorld, ByteArray# #)
forall o. (State# RealWorld -> o) -> o
runRW# ((State# RealWorld -> (# State# RealWorld, ByteArray# #))
 -> (# State# RealWorld, ByteArray# #))
-> (State# RealWorld -> (# State# RealWorld, ByteArray# #))
-> (# State# RealWorld, ByteArray# #)
forall a b. (a -> b) -> a -> b
$ \State# RealWorld
s ->
  case ST RealWorld (MutableByteArray RealWorld)
-> State# RealWorld
-> (# State# RealWorld, MutableByteArray RealWorld #)
forall s a. ST s a -> State# s -> (# State# s, a #)
unST ST RealWorld (MutableByteArray RealWorld)
forall s. ST s (MutableByteArray s)
m State# RealWorld
s of { (# State# RealWorld
s', MutableByteArray MutableByteArray# RealWorld
mary# #) ->
  MutableByteArray# RealWorld
-> State# RealWorld -> (# State# RealWorld, ByteArray# #)
forall d.
MutableByteArray# d -> State# d -> (# State# d, ByteArray# #)
unsafeFreezeByteArray# MutableByteArray# RealWorld
mary# State# RealWorld
s'} of (# State# RealWorld
_, ByteArray#
ary# #) -> ByteArray#
ary#

unST :: ST s a -> State# s -> (# State# s, a #)
unST :: ST s a -> State# s -> (# State# s, a #)
unST (GHCST.ST State# s -> (# State# s, a #)
f) = State# s -> (# State# s, a #)
f
#else /* In older GHCs, runRW# is not available. */
runByteArray
  :: (forall s. ST s (MutableByteArray s))
  -> ByteArray
runByteArray m = runST $ m >>= unsafeFreezeByteArray
#endif