    -- |
    -- Module      : Data.Array.Byte
    -- Copyright   : (c) Roman Leshchinskiy 2009-2012
    -- License     : BSD-style
    --
    -- Maintainer  : libraries@haskell.org
    -- Portability : non-portable
    --
    -- Derived from @primitive@ package.

    {-# LANGUAGE BangPatterns #-}
    {-# LANGUAGE MagicHash #-}
    {-# LANGUAGE TypeFamilies #-}
    {-# LANGUAGE Trustworthy #-}
    {-# LANGUAGE UnboxedTuples #-}

    module Data.Array.Byte (
      ByteArray(..),
      MutableByteArray(..),
    ) where

    import Data.Bits ((.&.), unsafeShiftR)
    import Data.Data (mkNoRepType, Data(..), Typeable)
    import qualified Data.Foldable as F
    import Data.Semigroup
    import GHC.Show (intToDigit)
    import GHC.Exts
    import GHC.ST (ST(..), runST)
    import GHC.Word (Word8(..))

    -- | Boxed wrapper for 'ByteArray#'.
    --
    -- Since 'ByteArray#' is an unlifted type and not a member of kind 'Data.Kind.Type',
    -- things like @[ByteArray#]@ or @IO ByteArray#@ are ill-typed. To work around this
    -- inconvenience this module provides a standard boxed wrapper, inhabiting 'Data.Kind.Type'.
    -- Clients are expected to use 'ByteArray' in higher-level APIs,
    -- but wrap and unwrap 'ByteArray' internally as they please
    -- and use functions from "GHC.Exts".
    --
    -- @since 4.17.0.0
    data ByteArray = ByteArray ByteArray#

    -- | Boxed wrapper for 'MutableByteArray#'.
    --
    -- Since 'MutableByteArray#' is an unlifted type and not a member of kind 'Data.Kind.Type',
    -- things like @[MutableByteArray#]@ or @IO MutableByteArray#@ are ill-typed. To work around this
    -- inconvenience this module provides a standard boxed wrapper, inhabiting 'Data.Kind.Type'.
    -- Clients are expected to use 'MutableByteArray' in higher-level APIs,
    -- but wrap and unwrap 'MutableByteArray' internally as they please
    -- and use functions from "GHC.Exts".
    --
    -- @since 4.17.0.0
    data MutableByteArray s = 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 :: Int -> ST s (MutableByteArray s)
    {-# INLINE newByteArray #-}
    newByteArray :: forall s. Int -> ST s (MutableByteArray s)
    newByteArray (I# Int#
    n#) =
      STRep s (MutableByteArray s) -> ST s (MutableByteArray s)
    forall s a. STRep s a -> ST s a
    ST (\State# s
    s# -> case Int# -> State# s -> (# State# s, MutableByteArray# s #)
    forall d. Int# -> State# d -> (# State# d, MutableByteArray# d #)
    newByteArray# Int#
    n# State# s
    s# of
        (# State# s
    s'#, MutableByteArray# s
    arr# #) -> (# State# s
    s'#, MutableByteArray# s -> MutableByteArray s
    forall s. MutableByteArray# s -> MutableByteArray s
    MutableByteArray MutableByteArray# s
    arr# #))

    -- | Convert a mutable byte array to an immutable one without copying. The
    -- array should not be modified after the conversion.
    unsafeFreezeByteArray :: MutableByteArray s -> ST s ByteArray
    {-# INLINE unsafeFreezeByteArray #-}
    unsafeFreezeByteArray :: forall s. MutableByteArray s -> ST s ByteArray
    unsafeFreezeByteArray (MutableByteArray MutableByteArray# s
    arr#) =
      STRep s ByteArray -> ST s ByteArray
    forall s a. STRep s a -> ST s a
    ST (\State# s
    s# -> case MutableByteArray# s -> State# s -> (# State# s, ByteArray# #)
    forall d.
    MutableByteArray# d -> State# d -> (# State# d, ByteArray# #)
    unsafeFreezeByteArray# MutableByteArray# s
    arr# State# s
    s# of
        (# State# s
    s'#, ByteArray#
    arr'# #) -> (# State# s
    s'#, ByteArray# -> ByteArray
    ByteArray 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#)

    -- | Read byte at specific index.
    indexByteArray :: ByteArray -> Int -> Word8
    {-# INLINE indexByteArray #-}
    indexByteArray :: ByteArray -> Int -> Word8
    indexByteArray (ByteArray ByteArray#
    arr#) (I# Int#
    i#) = Word8# -> Word8
    W8# (ByteArray# -> Int# -> Word8#
    indexWord8Array# ByteArray#
    arr# Int#
    i#)

    -- | Write byte at specific index.
    writeByteArray :: MutableByteArray s -> Int -> Word8 -> ST s ()
    {-# INLINE writeByteArray #-}
    writeByteArray :: forall s. MutableByteArray s -> Int -> Word8 -> ST s ()
    writeByteArray (MutableByteArray MutableByteArray# s
    arr#) (I# Int#
    i#) (W8# Word8#
    x#) =
      STRep s () -> ST s ()
    forall s a. STRep s a -> ST s a
    ST (\State# s
    s# -> case MutableByteArray# s -> Int# -> Word8# -> State# s -> State# s
    forall d.
    MutableByteArray# d -> Int# -> Word8# -> State# d -> State# d
    writeWord8Array# MutableByteArray# s
    arr# Int#
    i# Word8#
    x# State# s
    s# of
        State# s
    s'# -> (# State# s
    s'#, () #))

    -- | Explode 'ByteArray' into a list of bytes.
    byteArrayToList :: ByteArray -> [Word8]
    {-# INLINE byteArrayToList #-}
    byteArrayToList :: ByteArray -> [Word8]
    byteArrayToList ByteArray
    arr = Int -> [Word8]
    go Int
    0
      where
        go :: Int -> [Word8]
    go Int
    i
          | Int
    i Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    maxI  = ByteArray -> Int -> Word8
    indexByteArray ByteArray
    arr Int
    i Word8 -> [Word8] -> [Word8]
    forall a. a -> [a] -> [a]
    : Int -> [Word8]
    go (Int
    iInt -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1)
          | Bool
    otherwise = []
        maxI :: Int
    maxI = ByteArray -> Int
    sizeofByteArray ByteArray
    arr

    -- | 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 :: Int -> [Word8] -> ByteArray
    byteArrayFromListN :: Int -> [Word8] -> ByteArray
    byteArrayFromListN Int
    n [Word8]
    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 s)
    forall s. Int -> ST s (MutableByteArray s)
    newByteArray Int
    n
        let go :: Int -> [Word8] -> ST s ()
    go !Int
    ix [] = if Int
    ix Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    n
              then () -> ST s ()
    forall a. a -> ST s a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
              else [Char] -> ST s ()
    forall a. HasCallStack => [Char] -> a
    error ([Char] -> ST s ()) -> [Char] -> ST s ()
    forall a b. (a -> b) -> a -> b
    $ [Char]
    "Data.Array.Byte.byteArrayFromListN: list length less than specified size"
            go !Int
    ix (Word8
    x : [Word8]
    xs) = if Int
    ix Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    n
              then do
                MutableByteArray s -> Int -> Word8 -> ST s ()
    forall s. MutableByteArray s -> Int -> Word8 -> ST s ()
    writeByteArray MutableByteArray s
    marr Int
    ix Word8
    x
                Int -> [Word8] -> ST s ()
    go (Int
    ix Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    1) [Word8]
    xs
              else [Char] -> ST s ()
    forall a. HasCallStack => [Char] -> a
    error ([Char] -> ST s ()) -> [Char] -> ST s ()
    forall a b. (a -> b) -> a -> b
    $ [Char]
    "Data.Array.Byte.byteArrayFromListN: list length greater than specified size"
        Int -> [Word8] -> ST s ()
    go Int
    0 [Word8]
    ys
        MutableByteArray s -> ST s ByteArray
    forall s. MutableByteArray s -> ST s ByteArray
    unsafeFreezeByteArray MutableByteArray s
    marr

    -- | Copy a slice of an immutable byte array to a mutable byte array.
    --
    -- /Note:/ this function does not do bounds or overlap checking.
    copyByteArray
      :: MutableByteArray s -- ^ destination array
      -> Int                -- ^ offset into destination array
      -> ByteArray          -- ^ source array
      -> Int                -- ^ offset into source array
      -> Int                -- ^ number of bytes to copy
      -> ST s ()
    {-# INLINE copyByteArray #-}
    copyByteArray :: forall s.
    MutableByteArray s -> Int -> ByteArray -> Int -> Int -> ST s ()
    copyByteArray (MutableByteArray MutableByteArray# s
    dst#) (I# Int#
    doff#) (ByteArray ByteArray#
    src#) (I# Int#
    soff#) (I# Int#
    sz#) =
      STRep s () -> ST s ()
    forall s a. STRep s a -> ST s a
    ST (\State# s
    s# -> case ByteArray#
    -> Int#
    -> MutableByteArray# s
    -> Int#
    -> Int#
    -> State# s
    -> State# s
    forall d.
    ByteArray#
    -> Int#
    -> MutableByteArray# d
    -> Int#
    -> Int#
    -> State# d
    -> State# d
    copyByteArray# ByteArray#
    src# Int#
    soff# MutableByteArray# s
    dst# Int#
    doff# Int#
    sz# State# s
    s# of
        State# s
    s'# -> (# State# s
    s'#, () #))

    instance Data ByteArray where
      toConstr :: ByteArray -> Constr
    toConstr ByteArray
    _ = [Char] -> Constr
    forall a. HasCallStack => [Char] -> a
    error [Char]
    "toConstr"
      gunfold :: forall (c :: * -> *).
    (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
    _ = [Char] -> Constr -> c ByteArray
    forall a. HasCallStack => [Char] -> a
    error [Char]
    "gunfold"
      dataTypeOf :: ByteArray -> DataType
    dataTypeOf ByteArray
    _ = [Char] -> DataType
    mkNoRepType [Char]
    "Data.Array.Byte.ByteArray"

    instance Typeable s => Data (MutableByteArray s) where
      toConstr :: MutableByteArray s -> Constr
    toConstr MutableByteArray s
    _ = [Char] -> Constr
    forall a. HasCallStack => [Char] -> a
    error [Char]
    "toConstr"
      gunfold :: forall (c :: * -> *).
    (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
    _ = [Char] -> Constr -> c (MutableByteArray s)
    forall a. HasCallStack => [Char] -> a
    error [Char]
    "gunfold"
      dataTypeOf :: MutableByteArray s -> DataType
    dataTypeOf MutableByteArray s
    _ = [Char] -> DataType
    mkNoRepType [Char]
    "Data.Array.Byte.MutableByteArray"

    instance Show ByteArray where
      showsPrec :: Int -> ByteArray -> ShowS
    showsPrec Int
    _ ByteArray
    ba =
          [Char] -> ShowS
    showString [Char]
    "[" 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 [Char]
    s =
              Char
    '0'
            Char -> ShowS
    forall a. a -> [a] -> [a]
    : Char
    'x'
            Char -> ShowS
    forall a. a -> [a] -> [a]
    : 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 a. a -> [a] -> [a]
    : 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 a. a -> [a] -> [a]
    : [Char]
    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
    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 = [Char] -> ShowS
    showString [Char]
    ", "

    -- | Compare prefixes of given length.
    compareByteArraysFromBeginning :: ByteArray -> ByteArray -> Int -> Ordering
    {-# INLINE compareByteArraysFromBeginning #-}
    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

    -- | Do two byte arrays share the same pointer?
    sameByteArray :: ByteArray# -> ByteArray# -> Bool
    sameByteArray :: ByteArray# -> ByteArray# -> Bool
    sameByteArray ByteArray#
    ba1 ByteArray#
    ba2 =
        case () -> () -> Int#
    forall a b. a -> b -> Int#
    reallyUnsafePtrEquality# (ByteArray# -> ()
    forall a b. a -> b
    unsafeCoerce# ByteArray#
    ba1 :: ()) (ByteArray# -> ()
    forall a b. a -> b
    unsafeCoerce# ByteArray#
    ba2 :: ()) of
          Int#
    r -> Int# -> Bool
    isTrue# Int#
    r

    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

    instance Eq (MutableByteArray s) where
      == :: MutableByteArray s -> MutableByteArray s -> Bool
    (==) (MutableByteArray MutableByteArray# s
    arr#) (MutableByteArray MutableByteArray# s
    brr#)
        = Int# -> Bool
    isTrue# (MutableByteArray# s -> MutableByteArray# s -> Int#
    forall s. MutableByteArray# s -> MutableByteArray# s -> Int#
    sameMutableByteArray# MutableByteArray# s
    arr# MutableByteArray# s
    brr#)

    -- | 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.
    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
    -- The primop compareByteArrays# (invoked from 'compareByteArraysFromBeginning')
    -- performs a check for pointer equality as well. 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.

    -- | Append two byte arrays.
    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 s)
    forall s. Int -> ST s (MutableByteArray s)
    newByteArray (ByteArray -> Int
    sizeofByteArray ByteArray
    a Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + ByteArray -> Int
    sizeofByteArray ByteArray
    b)
      MutableByteArray s -> Int -> ByteArray -> Int -> Int -> ST s ()
    forall s.
    MutableByteArray s -> Int -> ByteArray -> Int -> Int -> ST s ()
    copyByteArray MutableByteArray s
    marr Int
    0 ByteArray
    a Int
    0 (ByteArray -> Int
    sizeofByteArray ByteArray
    a)
      MutableByteArray s -> Int -> ByteArray -> Int -> Int -> ST s ()
    forall s.
    MutableByteArray s -> Int -> ByteArray -> Int -> Int -> ST s ()
    copyByteArray MutableByteArray s
    marr (ByteArray -> Int
    sizeofByteArray ByteArray
    a) ByteArray
    b Int
    0 (ByteArray -> Int
    sizeofByteArray ByteArray
    b)
      MutableByteArray s -> ST s ByteArray
    forall s. MutableByteArray s -> ST s ByteArray
    unsafeFreezeByteArray MutableByteArray s
    marr

    -- | Concatenate a list of 'ByteArray's.
    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 s)
    forall s. Int -> ST s (MutableByteArray s)
    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 s -> ST s ByteArray
    forall s. MutableByteArray s -> ST s ByteArray
    unsafeFreezeByteArray MutableByteArray s
    marr

    -- | Dump immutable 'ByteArray's into a mutable one, starting from a given offset.
    pasteByteArrays :: MutableByteArray s -> Int -> [ByteArray] -> ST s ()
    pasteByteArrays :: forall s. MutableByteArray s -> Int -> [ByteArray] -> ST s ()
    pasteByteArrays !MutableByteArray s
    _ !Int
    _ [] = () -> ST s ()
    forall a. a -> ST s a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
    pasteByteArrays !MutableByteArray s
    marr !Int
    ix (ByteArray
    x : [ByteArray]
    xs) = do
      MutableByteArray s -> Int -> ByteArray -> Int -> Int -> ST s ()
    forall s.
    MutableByteArray s -> Int -> ByteArray -> Int -> Int -> ST s ()
    copyByteArray MutableByteArray 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

    -- | Compute total length of 'ByteArray's, increased by accumulator.
    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)

    -- | An array of zero length.
    emptyByteArray :: ByteArray
    emptyByteArray :: ByteArray
    emptyByteArray = (forall s. ST s ByteArray) -> ByteArray
    forall a. (forall s. ST s a) -> a
    runST (Int -> ST s (MutableByteArray s)
    forall s. Int -> ST s (MutableByteArray s)
    newByteArray Int
    0 ST s (MutableByteArray s)
    -> (MutableByteArray s -> ST s ByteArray) -> ST s ByteArray
    forall a b. ST s a -> (a -> ST s b) -> ST s b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= MutableByteArray s -> ST s ByteArray
    forall s. MutableByteArray s -> ST s ByteArray
    unsafeFreezeByteArray)

    -- | Replicate 'ByteArray' given number of times and concatenate all together.
    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 s)
    forall s. Int -> ST s (MutableByteArray s)
    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 s -> Int -> ByteArray -> Int -> Int -> ST s ()
    forall s.
    MutableByteArray s -> Int -> ByteArray -> Int -> Int -> ST s ()
    copyByteArray MutableByteArray 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 a. a -> ST s a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
      Int -> ST s ()
    go Int
    0
      MutableByteArray s -> ST s ByteArray
    forall s. MutableByteArray s -> ST s ByteArray
    unsafeFreezeByteArray MutableByteArray s
    marr

    instance 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 a. NonEmpty a -> [a]
    forall (t :: * -> *) a. Foldable t => t a -> [a]
    F.toList
      stimes :: forall b. Integral b => 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 = [Char] -> ByteArray
    forall a. HasCallStack => [Char] -> a
    error [Char]
    "Data.Array.Byte#stimes: cannot allocate the requested amount of memory"
        where itgr :: Integer
    itgr = b -> Integer
    forall a. Integral a => a -> Integer
    toInteger b
    i :: Integer

    instance Monoid ByteArray where
      mempty :: ByteArray
    mempty = ByteArray
    emptyByteArray
      mconcat :: [ByteArray] -> ByteArray
    mconcat = [ByteArray] -> ByteArray
    concatByteArray

    instance IsList ByteArray where
      type Item ByteArray = Word8

      toList :: ByteArray -> [Item ByteArray]
    toList = ByteArray -> [Word8]
    ByteArray -> [Item ByteArray]
    byteArrayToList
      fromList :: [Item ByteArray] -> ByteArray
    fromList [Item ByteArray]
    xs = Int -> [Word8] -> ByteArray
    byteArrayFromListN ([Word8] -> Int
    forall a. [a] -> 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 -> [Word8] -> ByteArray
    Int -> [Item ByteArray] -> ByteArray
    byteArrayFromListN