content: {-# LANGUAGE BangPatterns, CPP, MagicHash, UnboxedTuples, UnliftedFFITypes #-}
  {-# LANGUAGE ScopedTypeVariables #-}
  {-# LANGUAGE TypeFamilies #-}
  {-# LANGUAGE TypeApplications #-}
  {-# 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,
    shrinkMutableByteArray,
  
    -- * Element access
    readByteArray, writeByteArray, indexByteArray,
    -- * Char Element Access
    -- $charElementAccess
    readCharArray, writeCharArray, indexCharArray,
  
    -- * Constructing
    emptyByteArray,
    byteArrayFromList, byteArrayFromListN,
  
    -- * Folding
    foldrByteArray,
  
    -- * Comparing
    compareByteArrays,
  
    -- * Freezing and thawing
    freezeByteArray, thawByteArray, runByteArray,
    unsafeFreezeByteArray, unsafeThawByteArray,
  
    -- * Block operations
    copyByteArray, copyMutableByteArray,
    copyByteArrayToPtr, copyMutableByteArrayToPtr,
    copyByteArrayToAddr, copyMutableByteArrayToAddr,
    copyPtrToMutableByteArray,
    moveByteArray,
    setByteArray, fillByteArray,
    cloneByteArray, cloneMutableByteArray,
  
    -- * Information
    sizeofByteArray,
    sizeofMutableByteArray, getSizeofMutableByteArray, sameMutableByteArray,
  #if __GLASGOW_HASKELL__ >= 802
    isByteArrayPinned, isMutableByteArrayPinned,
  #endif
    byteArrayContents,
    withByteArrayContents,
    mutableByteArrayContents,
    withMutableByteArrayContents
  
  ) where
  
  import Control.Monad.Primitive
  import Control.Monad.ST
  import Data.Primitive.Types
  import Data.Proxy
  
  #if MIN_VERSION_base(4,10,0)
  import qualified GHC.ST as GHCST
  #endif
  
  import Foreign.C.Types
  import Data.Word ( Word8 )
  #if __GLASGOW_HASKELL__ >= 802
  import qualified GHC.Exts as Exts
  #endif
  import GHC.Exts hiding (setByteArray#)
  
  #if __GLASGOW_HASKELL__ < 804
  import System.IO.Unsafe (unsafeDupablePerformIO)
  #endif
  
  import Data.Array.Byte (ByteArray(..), MutableByteArray(..))
  
  import Data.Primitive.Internal.Operations (mutableByteArrayContentsShim)
  
  -- | Create a new mutable byte array of the specified size in bytes.
  -- The underlying memory is left uninitialized.
  --
  -- /Note:/ this function does not check if the input is non-negative.
  newByteArray :: PrimMonad m => Int -> m (MutableByteArray (PrimState m))
  {-# INLINE newByteArray #-}
  newByteArray (I# n#)
    = primitive (\s# -> case newByteArray# n# s# of
                          (# s'#, arr# #) -> (# s'#, MutableByteArray arr# #))
  
  -- | Create a /pinned/ byte array of the specified size in bytes. The garbage
  -- collector is guaranteed not to move it. The underlying memory is left uninitialized.
  --
  -- /Note:/ this function does not check if the input is non-negative.
  newPinnedByteArray :: PrimMonad m => Int -> m (MutableByteArray (PrimState m))
  {-# INLINE newPinnedByteArray #-}
  newPinnedByteArray (I# n#)
    = primitive (\s# -> case newPinnedByteArray# n# s# of
                          (# s'#, arr# #) -> (# s'#, MutableByteArray 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.
  -- The underlying memory is left uninitialized.
  --
  -- /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 (I# n#) (I# k#)
    = primitive (\s# -> case newAlignedPinnedByteArray# n# k# s# of
                          (# s'#, arr# #) -> (# s'#, MutableByteArray arr# #))
  
  -- | Yield a pointer to the array's data. This operation is only safe on
  -- /pinned/ byte arrays. Byte arrays allocated by 'newPinnedByteArray' and
  -- 'newAlignedPinnedByteArray' are guaranteed to be pinned. Byte arrays
  -- allocated by 'newByteArray' may or may not be pinned (use
  -- 'isByteArrayPinned' to figure out).
  --
  -- Prefer 'withByteArrayContents', which ensures that the array is not
  -- garbage collected while the pointer is being used.
  byteArrayContents :: ByteArray -> Ptr Word8
  {-# INLINE byteArrayContents #-}
  byteArrayContents (ByteArray arr#) = Ptr (byteArrayContents# arr#)
  
  -- | A composition of 'byteArrayContents' and 'keepAliveUnlifted'.
  -- The callback function must not return the pointer. The argument byte
  -- array must be /pinned/. See 'byteArrayContents' for an explanation
  -- of which byte arrays are pinned.
  --
  -- Note: This could be implemented with 'keepAlive' instead of
  -- 'keepAliveUnlifted', but 'keepAlive' here would cause GHC to materialize
  -- the wrapper data constructor on the heap.
  withByteArrayContents :: PrimBase m => ByteArray -> (Ptr Word8 -> m a) -> m a
  {-# INLINE withByteArrayContents #-}
  withByteArrayContents (ByteArray arr#) f =
    keepAliveUnlifted arr# (f (Ptr (byteArrayContents# arr#)))
  
  -- | Yield a pointer to the array's data. This operation is only safe on
  -- /pinned/ byte arrays. See 'byteArrayContents' for an explanation
  -- of which byte arrays are pinned.
  --
  -- Prefer 'withByteArrayContents', which ensures that the array is not
  -- garbage collected while the pointer is being used.
  mutableByteArrayContents :: MutableByteArray s -> Ptr Word8
  {-# INLINE mutableByteArrayContents #-}
  mutableByteArrayContents (MutableByteArray arr#) = Ptr (mutableByteArrayContentsShim arr#)
  
  -- | A composition of 'mutableByteArrayContents' and 'keepAliveUnlifted'.
  -- The callback function must not return the pointer. The argument byte
  -- array must be /pinned/. See 'byteArrayContents' for an explanation
  -- of which byte arrays are pinned.
  withMutableByteArrayContents :: PrimBase m => MutableByteArray (PrimState m) -> (Ptr Word8 -> m a) -> m a
  {-# INLINE withMutableByteArrayContents #-}
  withMutableByteArrayContents (MutableByteArray arr#) f =
    keepAliveUnlifted arr# (f (Ptr (mutableByteArrayContentsShim arr#)))
  
  -- | Check if the two arrays refer to the same memory block.
  sameMutableByteArray :: MutableByteArray s -> MutableByteArray s -> Bool
  {-# INLINE sameMutableByteArray #-}
  sameMutableByteArray (MutableByteArray arr#) (MutableByteArray brr#)
    = isTrue# (sameMutableByteArray# arr# 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 #-}
  resizeMutableByteArray (MutableByteArray arr#) (I# n#)
    = primitive (\s# -> case resizeMutableByteArray# arr# n# s# of
                          (# s'#, arr'# #) -> (# s'#, MutableByteArray arr'# #))
  
  -- | 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 arr#)
    = primitive (\s# -> case getSizeofMutableByteArray# arr# s# of
                          (# s'#, n# #) -> (# s'#, I# 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.
  --
  -- /Note:/ The provided array should contain the full subrange
  -- specified by the two Ints, but this is not checked.
  freezeByteArray
    :: PrimMonad m
    => MutableByteArray (PrimState m) -- ^ source
    -> Int                            -- ^ offset in bytes
    -> Int                            -- ^ length in bytes
    -> m ByteArray
  {-# INLINE freezeByteArray #-}
  freezeByteArray !src !off !len = do
    dst <- newByteArray len
    copyMutableByteArray dst 0 src off len
    unsafeFreezeByteArray 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.
  --
  -- /Note:/ The provided array should contain the full subrange
  -- specified by the two Ints, but this is not checked.
  --
  -- @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 !src !off !len = do
    dst <- newByteArray len
    copyByteArray dst 0 src off len
    return 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 arr#)
    = primitive (\s# -> case unsafeFreezeByteArray# arr# s# of
                          (# s'#, arr'# #) -> (# s'#, 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 arr#)
    = primitive (\s# -> (# s#, MutableByteArray (unsafeCoerce# arr#) #))
  
  -- | Size of the byte array in bytes.
  sizeofByteArray :: ByteArray -> Int
  {-# INLINE sizeofByteArray #-}
  sizeofByteArray (ByteArray arr#) = I# (sizeofByteArray# arr#)
  
  -- | Size of the mutable byte array in bytes.
  --
  -- This function is deprecated and will be removed. Its behavior
  -- is undefined if 'resizeMutableByteArray' is ever called on the mutable
  -- byte array given as the argument. Prefer 'getSizeofMutableByteArray',
  -- which ensures correct sequencing in the presence of resizing.
  sizeofMutableByteArray :: MutableByteArray s -> Int
  {-# INLINE sizeofMutableByteArray #-}
  {-# DEPRECATED sizeofMutableByteArray "use getSizeofMutableByteArray instead" #-}
  sizeofMutableByteArray (MutableByteArray arr#) = I# (sizeofMutableByteArray# arr#)
  
  -- | 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.
  --
  -- @since 0.7.1.0
  shrinkMutableByteArray :: PrimMonad m
    => MutableByteArray (PrimState m)
    -> Int -- ^ new size
    -> m ()
  {-# INLINE shrinkMutableByteArray #-}
  shrinkMutableByteArray (MutableByteArray arr#) (I# n#)
    = primitive_ (shrinkMutableByteArray# arr# n#)
  
  #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.
  --
  -- Caution: 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 arr#) = isTrue# (Exts.isByteArrayPinned# arr#)
  
  -- | Check whether or not the mutable byte array is pinned.
  --
  -- Caution: 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 marr#) = isTrue# (Exts.isMutableByteArrayPinned# 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 arr#) (I# i#) = indexByteArray# arr# 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 arr#) (I# i#)
    = primitive (readByteArray# arr# 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 arr#) (I# i#) x
    = primitive_ (writeByteArray# arr# i# x)
  
  -- | Right-fold over the elements of a 'ByteArray'.
  foldrByteArray :: forall a b. (Prim a) => (a -> b -> b) -> b -> ByteArray -> b
  {-# INLINE foldrByteArray #-}
  foldrByteArray f z arr = go 0
    where
      go i
        | i < maxI  = f (indexByteArray arr i) (go (i + 1))
        | otherwise = z
      maxI = sizeofByteArray arr `quot` sizeOfType @a
  
  -- | Create a 'ByteArray' from a list.
  --
  -- @byteArrayFromList xs = `byteArrayFromListN` (length xs) xs@
  byteArrayFromList :: Prim a => [a] -> ByteArray
  byteArrayFromList xs = byteArrayFromListN (length xs) 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 :: forall a. Prim a => Int -> [a] -> ByteArray
  byteArrayFromListN n ys = runST $ do
      marr <- newByteArray (n * sizeOfType @a)
      let go !ix [] = if ix == n
            then return ()
            else die "byteArrayFromListN" "list length less than specified size"
          go !ix (x : xs) = if ix < n
            then do
              writeByteArray marr ix x
              go (ix + 1) xs
            else die "byteArrayFromListN" "list length greater than specified size"
      go 0 ys
      unsafeFreezeByteArray marr
  
  unI# :: Int -> Int#
  unI# (I# n#) = 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 dst#) doff (ByteArray src#) soff sz
    = primitive_ (copyByteArray# src# (unI# soff) dst# (unI# doff) (unI# 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 dst#) doff
                       (MutableByteArray src#) soff sz
    = primitive_ (copyMutableByteArray# src# (unI# soff) dst# (unI# doff) (unI# sz))
  
  -- | Copy a slice of a byte array to an unmanaged pointer address. These must not
  -- overlap. The offset and length are given in elements, not in bytes.
  --
  -- /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 dst#) (ByteArray src#) soff sz
    = primitive_ (copyByteArrayToAddr# src# (unI# soff *# siz#) dst# (unI# sz *# siz#))
    where
    siz# = sizeOfType# (Proxy :: Proxy a)
  
  -- | Copy from an unmanaged pointer address to a byte array. These must not
  -- overlap. The offset and length are given in elements, not in bytes.
  --
  -- /Note:/ this function does not do bounds or overlap checking.
  copyPtrToMutableByteArray :: forall m a. (PrimMonad m, Prim a)
    => MutableByteArray (PrimState m) -- ^ destination array
    -> Int   -- ^ destination offset given in elements of type @a@
    -> Ptr a -- ^ source pointer
    -> Int   -- ^ number of elements
    -> m ()
  {-# INLINE copyPtrToMutableByteArray #-}
  copyPtrToMutableByteArray (MutableByteArray ba#) (I# doff#) (Ptr addr#) (I# n#) =
    primitive_ (copyAddrToByteArray# addr# ba# (doff# *# siz#) (n# *# siz#))
    where
    siz# = sizeOfType# (Proxy :: Proxy a)
  
  
  -- | Copy a slice of a mutable byte array to an unmanaged pointer address.
  -- These must not overlap. The offset and length are given in elements, not
  -- in bytes.
  --
  -- /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 dst#) (MutableByteArray src#) soff sz
    = primitive_ (copyMutableByteArrayToAddr# src# (unI# soff *# siz#) dst# (unI# sz *# siz#))
    where
    siz# = sizeOfType# (Proxy :: Proxy a)
  
  ------
  --- These latter two should be DEPRECATED
  -----
  
  -- | Copy a slice of a byte array to an unmanaged address. These must not
  -- overlap.
  --
  -- 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 dst#) (ByteArray src#) soff sz
    = primitive_ (copyByteArrayToAddr# src# (unI# soff) dst# (unI# sz))
  
  -- | Copy a slice of a mutable byte array to an unmanaged address. These must
  -- not overlap.
  --
  -- 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 dst#) (MutableByteArray src#) soff sz
    = primitive_ (copyMutableByteArrayToAddr# src# (unI# soff) dst# (unI# sz))
  
  -- | 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 dst#) doff
                (MutableByteArray src#) soff sz
    = unsafePrimToPrim
    $ memmove_mba dst# (fromIntegral doff) src# (fromIntegral soff)
                       (fromIntegral 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 dst#) (I# doff#) (I# sz#) x
    = primitive_ (setByteArray# dst# doff# sz# 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 = setByteArray
  
  foreign import ccall unsafe "primitive-memops.h hsprimitive_memmove"
    memmove_mba :: MutableByteArray# s -> CPtrdiff
                -> MutableByteArray# s -> CPtrdiff
                -> CSize -> IO ()
  
  -- | 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 the slice, given in bytes
    -> Ordering
  {-# INLINE compareByteArrays #-}
  #if __GLASGOW_HASKELL__ >= 804
  compareByteArrays (ByteArray ba1#) (I# off1#) (ByteArray ba2#) (I# off2#) (I# n#)
    = compare (I# (compareByteArrays# ba1# off1# ba2# off2# n#)) 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
  
  -- | The empty 'ByteArray'.
  emptyByteArray :: ByteArray
  {-# NOINLINE emptyByteArray #-}
  emptyByteArray = runST (newByteArray 0 >>= unsafeFreezeByteArray)
  
  die :: String -> String -> a
  die fun problem = error $ "Data.Primitive.ByteArray." ++ fun ++ ": " ++ 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 src off n = runByteArray $ do
    dst <- newByteArray n
    copyByteArray dst 0 src off n
    return 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 src off n = do
    dst <- newByteArray n
    copyMutableByteArray dst 0 src off n
    return dst
  
  -- | Execute the monadic action and freeze the resulting array.
  --
  -- > runByteArray m = runST $ m >>= unsafeFreezeByteArray
  runByteArray
    :: (forall s. ST s (MutableByteArray s))
    -> ByteArray
  #if MIN_VERSION_base(4,10,0) /* In new GHCs, runRW# is available. */
  runByteArray m = ByteArray (runByteArray# m)
  
  runByteArray#
    :: (forall s. ST s (MutableByteArray s))
    -> ByteArray#
  runByteArray# m = case runRW# $ \s ->
    case unST m s of { (# s', MutableByteArray mary# #) ->
    unsafeFreezeByteArray# mary# s'} of (# _, ary# #) -> ary#
  
  unST :: ST s a -> State# s -> (# State# s, a #)
  unST (GHCST.ST f) = f
  #else /* In older GHCs, runRW# is not available. */
  runByteArray m = runST $ m >>= unsafeFreezeByteArray
  #endif
  
  {- $charElementAccess
  GHC provides two sets of element accessors for 'Char'. One set faithfully
  represents 'Char' as 32-bit words using UTF-32. The other set represents
  'Char' as 8-bit words using Latin-1 (ISO-8859-1), and the write operation
  has undefined behavior for codepoints outside of the ASCII and Latin-1
  blocks. The 'Prim' instance for 'Char' uses the UTF-32 set of operators.
  -}
  
  -- | Read an 8-bit element from the byte array, interpreting it as a
  -- Latin-1-encoded character. The offset is given in bytes.
  --
  -- /Note:/ this function does not do bounds checking.
  readCharArray :: PrimMonad m => MutableByteArray (PrimState m) -> Int -> m Char
  {-# INLINE readCharArray #-}
  readCharArray (MutableByteArray arr#) (I# i#) = primitive
    (\s0 -> case readCharArray# arr# i# s0 of
      (# s1, c #) -> (# s1, C# c #)
    )
  
  -- | Write a character to the byte array, encoding it with Latin-1 as
  -- a single byte. Behavior is undefined for codepoints outside of the
  -- ASCII and Latin-1 blocks. The offset is given in bytes.
  --
  -- /Note:/ this function does not do bounds checking.
  writeCharArray
    :: PrimMonad m => MutableByteArray (PrimState m) -> Int -> Char -> m ()
  {-# INLINE writeCharArray #-}
  writeCharArray (MutableByteArray arr#) (I# i#) (C# c)
    = primitive_ (writeCharArray# arr# i# c)
  
  -- | Read an 8-bit element from the byte array, interpreting it as a
  -- Latin-1-encoded character. The offset is given in bytes.
  --
  -- /Note:/ this function does not do bounds checking.
  indexCharArray :: ByteArray -> Int -> Char
  {-# INLINE indexCharArray #-}
  indexCharArray (ByteArray arr#) (I# i#) = C# (indexCharArray# arr# i#)
  