    -- |
    -- Module      : Data.ByteArray.Methods
    -- License     : BSD-style
    -- Maintainer  : Vincent Hanquez <vincent@snarc.org>
    -- Stability   : stable
    -- Portability : Good
    --
    {-# LANGUAGE CPP #-}
    {-# LANGUAGE BangPatterns #-}
    module Data.ByteArray.Methods
        ( alloc
        , allocAndFreeze
        , create
        , unsafeCreate
        , pack
        , unpack
        , uncons
        , empty
        , singleton
        , cons
        , snoc
        , null
        , replicate
        , zero
        , copy
        , take
        , drop
        , span
        , reverse
        , convert
        , copyRet
        , copyAndFreeze
        , splitAt
        , xor
        , index
        , eq
        , constEq
        , any
        , all
        , append
        , concat
        ) where

    import           Data.ByteArray.Types
    import           Data.Memory.Internal.Compat
    import           Data.Memory.Internal.Imports hiding (empty)
    import           Data.Memory.PtrMethods
    import           Data.Monoid
    import           Foreign.Storable
    import           Foreign.Ptr

    import           Prelude hiding (length, take, drop, span, reverse, concat, replicate, splitAt, null, pred, last, any, all)
    import qualified Prelude

    #if defined(WITH_BYTESTRING_SUPPORT) && defined(WITH_BASEMENT_SUPPORT)
    import qualified Data.ByteString as SPE (ByteString)
    import qualified Basement.UArray as SPE (UArray)
    import qualified Basement.Block  as SPE (Block)
    #endif

    -- | Allocate a new bytearray of specific size, and run the initializer on this memory
    alloc :: ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
    alloc :: forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
    alloc Int
    n Ptr p -> IO ()
    f
        | Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    0     = Int -> (Ptr p -> IO ()) -> IO ba
    forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
    alloc Int
    0 Ptr p -> IO ()
    f
        | Bool
    otherwise = ((), ba) -> ba
    forall a b. (a, b) -> b
    snd (((), ba) -> ba) -> IO ((), ba) -> IO ba
    forall a b. (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` Int -> (Ptr p -> IO ()) -> IO ((), ba)
    forall ba p a. ByteArray ba => Int -> (Ptr p -> IO a) -> IO (a, ba)
    forall p a. Int -> (Ptr p -> IO a) -> IO (a, ba)
    allocRet Int
    n Ptr p -> IO ()
    f
    {-# INLINE alloc #-}

    -- | Allocate a new bytearray of specific size, and run the initializer on this memory
    create :: ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
    create :: forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
    create Int
    n Ptr p -> IO ()
    f = Int -> (Ptr p -> IO ()) -> IO ba
    forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
    alloc Int
    n Ptr p -> IO ()
    f

    -- | similar to 'alloc' but hide the allocation and initializer in a pure context
    allocAndFreeze :: ByteArray a => Int -> (Ptr p -> IO ()) -> a
    allocAndFreeze :: forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    allocAndFreeze Int
    sz Ptr p -> IO ()
    f = IO a -> a
    forall a. IO a -> a
    unsafeDoIO (Int -> (Ptr p -> IO ()) -> IO a
    forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
    alloc Int
    sz Ptr p -> IO ()
    f)
    {-# NOINLINE allocAndFreeze #-}

    -- | similar to 'create' but hide the allocation and initializer in a pure context
    unsafeCreate :: ByteArray a => Int -> (Ptr p -> IO ()) -> a
    unsafeCreate :: forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    unsafeCreate Int
    sz Ptr p -> IO ()
    f = IO a -> a
    forall a. IO a -> a
    unsafeDoIO (Int -> (Ptr p -> IO ()) -> IO a
    forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
    alloc Int
    sz Ptr p -> IO ()
    f)
    {-# NOINLINE unsafeCreate #-}

    inlineUnsafeCreate :: ByteArray a => Int -> (Ptr p -> IO ()) -> a
    inlineUnsafeCreate :: forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    inlineUnsafeCreate !Int
    sz Ptr p -> IO ()
    f = IO a -> a
    forall a. IO a -> a
    unsafeDoIO (Int -> (Ptr p -> IO ()) -> IO a
    forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
    alloc Int
    sz Ptr p -> IO ()
    f)
    {-# INLINE inlineUnsafeCreate #-}

    -- | Create an empty byte array
    empty :: ByteArray a => a
    empty :: forall a. ByteArray a => a
    empty = IO a -> a
    forall a. IO a -> a
    unsafeDoIO (Int -> (Ptr (ZonkAny 9) -> IO ()) -> IO a
    forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
    alloc Int
    0 ((Ptr (ZonkAny 9) -> IO ()) -> IO a)
    -> (Ptr (ZonkAny 9) -> IO ()) -> IO a
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 9)
    _ -> () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ())

    -- | Check if a byte array is empty
    null :: ByteArrayAccess a => a -> Bool
    null :: forall a. ByteArrayAccess a => a -> Bool
    null a
    b = a -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    length a
    b Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    0

    -- | Pack a list of bytes into a bytearray
    pack :: ByteArray a => [Word8] -> a
    pack :: forall a. ByteArray a => [Word8] -> a
    pack [Word8]
    l = Int -> (Ptr Word8 -> IO ()) -> a
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    inlineUnsafeCreate ([Word8] -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    Prelude.length [Word8]
    l) ([Word8] -> Ptr Word8 -> IO ()
    forall {b}. Storable b => [b] -> Ptr b -> IO ()
    fill [Word8]
    l)
      where fill :: [b] -> Ptr b -> IO ()
    fill []     Ptr b
    _  = () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
            fill (b
    x:[b]
    xs) !Ptr b
    p = Ptr b -> b -> IO ()
    forall a. Storable a => Ptr a -> a -> IO ()
    poke Ptr b
    p b
    x IO () -> IO () -> IO ()
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> [b] -> Ptr b -> IO ()
    fill [b]
    xs (Ptr b
    p Ptr b -> Int -> Ptr b
    forall a b. Ptr a -> Int -> Ptr b
    `plusPtr` Int
    1)
            {-# INLINE fill #-}
    {-# NOINLINE pack #-}

    -- | Un-pack a bytearray into a list of bytes
    unpack :: ByteArrayAccess a => a -> [Word8]
    unpack :: forall a. ByteArrayAccess a => a -> [Word8]
    unpack a
    bs = Int -> [Word8]
    forall {a}. Storable a => Int -> [a]
    loop Int
    0
      where !len :: Int
    len = a -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    length a
    bs
            loop :: Int -> [a]
    loop Int
    i
                | Int
    i Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    len  = []
                | Bool
    otherwise =
                    let !v :: a
    v = IO a -> a
    forall a. IO a -> a
    unsafeDoIO (IO a -> a) -> IO a -> a
    forall a b. (a -> b) -> a -> b
    $ a -> (Ptr (ZonkAny 2) -> IO a) -> IO a
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. a -> (Ptr p -> IO a) -> IO a
    withByteArray a
    bs (\Ptr (ZonkAny 2)
    p -> Ptr (ZonkAny 2) -> Int -> IO a
    forall b. Ptr b -> Int -> IO a
    forall a b. Storable a => Ptr b -> Int -> IO a
    peekByteOff Ptr (ZonkAny 2)
    p Int
    i)
                     in a
    v a -> [a] -> [a]
    forall a. a -> [a] -> [a]
    : Int -> [a]
    loop (Int
    iInt -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1)

    -- | returns the first byte, and the remaining bytearray if the bytearray is not null
    uncons :: ByteArray a => a -> Maybe (Word8, a)
    uncons :: forall a. ByteArray a => a -> Maybe (Word8, a)
    uncons a
    a
        | a -> Bool
    forall a. ByteArrayAccess a => a -> Bool
    null a
    a    = Maybe (Word8, a)
    forall a. Maybe a
    Nothing
        | Bool
    otherwise = (Word8, a) -> Maybe (Word8, a)
    forall a. a -> Maybe a
    Just (a -> Int -> Word8
    forall a. ByteArrayAccess a => a -> Int -> Word8
    index a
    a Int
    0, Int -> a -> a
    forall bs. ByteArray bs => Int -> bs -> bs
    drop Int
    1 a
    a)

    -- | Create a byte array from a single byte
    singleton :: ByteArray a => Word8 -> a
    singleton :: forall a. ByteArray a => Word8 -> a
    singleton Word8
    b = Int -> (Ptr (ZonkAny 4) -> IO ()) -> a
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    unsafeCreate Int
    1 (\Ptr (ZonkAny 4)
    p -> Ptr (ZonkAny 4) -> Int -> Word8 -> IO ()
    forall b. Ptr b -> Int -> Word8 -> IO ()
    forall a b. Storable a => Ptr b -> Int -> a -> IO ()
    pokeByteOff Ptr (ZonkAny 4)
    p Int
    0 Word8
    b)

    -- | prepend a single byte to a byte array
    cons :: ByteArray a => Word8 -> a -> a
    cons :: forall a. ByteArray a => Word8 -> a -> a
    cons Word8
    b a
    ba = Int -> (Ptr (ZonkAny 5) -> IO ()) -> a
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    unsafeCreate (Int
    len Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    1) ((Ptr (ZonkAny 5) -> IO ()) -> a)
    -> (Ptr (ZonkAny 5) -> IO ()) -> a
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 5)
    d -> a -> (Ptr Word8 -> IO ()) -> IO ()
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. a -> (Ptr p -> IO a) -> IO a
    withByteArray a
    ba ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    s -> do
        Ptr (ZonkAny 5) -> Int -> Word8 -> IO ()
    forall b. Ptr b -> Int -> Word8 -> IO ()
    forall a b. Storable a => Ptr b -> Int -> a -> IO ()
    pokeByteOff Ptr (ZonkAny 5)
    d Int
    0 Word8
    b
        Ptr Word8 -> Ptr Word8 -> Int -> IO ()
    memCopy (Ptr (ZonkAny 5)
    d Ptr (ZonkAny 5) -> Int -> Ptr Word8
    forall a b. Ptr a -> Int -> Ptr b
    `plusPtr` Int
    1) Ptr Word8
    s Int
    len
      where len :: Int
    len = a -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    length a
    ba

    -- | append a single byte to a byte array
    snoc :: ByteArray a =>  a -> Word8 -> a
    snoc :: forall a. ByteArray a => a -> Word8 -> a
    snoc a
    ba Word8
    b = Int -> (Ptr Word8 -> IO ()) -> a
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    unsafeCreate (Int
    len Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    1) ((Ptr Word8 -> IO ()) -> a) -> (Ptr Word8 -> IO ()) -> a
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    d -> a -> (Ptr Word8 -> IO ()) -> IO ()
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. a -> (Ptr p -> IO a) -> IO a
    withByteArray a
    ba ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    s -> do
        Ptr Word8 -> Ptr Word8 -> Int -> IO ()
    memCopy Ptr Word8
    d Ptr Word8
    s Int
    len
        Ptr Word8 -> Int -> Word8 -> IO ()
    forall b. Ptr b -> Int -> Word8 -> IO ()
    forall a b. Storable a => Ptr b -> Int -> a -> IO ()
    pokeByteOff Ptr Word8
    d Int
    len Word8
    b
      where len :: Int
    len = a -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    length a
    ba

    -- | Create a xor of bytes between a and b.
    --
    -- the returns byte array is the size of the smallest input.
    xor :: (ByteArrayAccess a, ByteArrayAccess b, ByteArray c) => a -> b -> c
    xor :: forall a b c.
    (ByteArrayAccess a, ByteArrayAccess b, ByteArray c) =>
    a -> b -> c
    xor a
    a b
    b =
        Int -> (Ptr Word8 -> IO ()) -> c
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    unsafeCreate Int
    n ((Ptr Word8 -> IO ()) -> c) -> (Ptr Word8 -> IO ()) -> c
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    pc ->
        a -> (Ptr Word8 -> IO ()) -> IO ()
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. a -> (Ptr p -> IO a) -> IO a
    withByteArray a
    a  ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    pa ->
        b -> (Ptr Word8 -> IO ()) -> IO ()
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. b -> (Ptr p -> IO a) -> IO a
    withByteArray b
    b  ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    pb ->
            Ptr Word8 -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
    memXor Ptr Word8
    pc Ptr Word8
    pa Ptr Word8
    pb Int
    n
      where
            n :: Int
    n  = Int -> Int -> Int
    forall a. Ord a => a -> a -> a
    min Int
    la Int
    lb
            la :: Int
    la = a -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    length a
    a
            lb :: Int
    lb = b -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    length b
    b

    -- | return a specific byte indexed by a number from 0 in a bytearray
    --
    -- unsafe, no bound checking are done
    index :: ByteArrayAccess a => a -> Int -> Word8
    index :: forall a. ByteArrayAccess a => a -> Int -> Word8
    index a
    b Int
    i = IO Word8 -> Word8
    forall a. IO a -> a
    unsafeDoIO (IO Word8 -> Word8) -> IO Word8 -> Word8
    forall a b. (a -> b) -> a -> b
    $ a -> (Ptr (ZonkAny 1) -> IO Word8) -> IO Word8
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. a -> (Ptr p -> IO a) -> IO a
    withByteArray a
    b ((Ptr (ZonkAny 1) -> IO Word8) -> IO Word8)
    -> (Ptr (ZonkAny 1) -> IO Word8) -> IO Word8
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 1)
    p -> Ptr Word8 -> IO Word8
    forall a. Storable a => Ptr a -> IO a
    peek (Ptr (ZonkAny 1)
    p Ptr (ZonkAny 1) -> Int -> Ptr Word8
    forall a b. Ptr a -> Int -> Ptr b
    `plusPtr` Int
    i)

    -- | Split a bytearray at a specific length in two bytearray
    splitAt :: ByteArray bs => Int -> bs -> (bs, bs)
    splitAt :: forall bs. ByteArray bs => Int -> bs -> (bs, bs)
    splitAt Int
    n bs
    bs
        | Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    0    = (bs
    forall a. ByteArray a => a
    empty, bs
    bs)
        | Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    len  = (bs
    bs, bs
    forall a. ByteArray a => a
    empty)
        | Bool
    otherwise = IO (bs, bs) -> (bs, bs)
    forall a. IO a -> a
    unsafeDoIO (IO (bs, bs) -> (bs, bs)) -> IO (bs, bs) -> (bs, bs)
    forall a b. (a -> b) -> a -> b
    $ do
            bs -> (Ptr Word8 -> IO (bs, bs)) -> IO (bs, bs)
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. bs -> (Ptr p -> IO a) -> IO a
    withByteArray bs
    bs ((Ptr Word8 -> IO (bs, bs)) -> IO (bs, bs))
    -> (Ptr Word8 -> IO (bs, bs)) -> IO (bs, bs)
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    p -> do
                b1 <- Int -> (Ptr Word8 -> IO ()) -> IO bs
    forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
    alloc Int
    n ((Ptr Word8 -> IO ()) -> IO bs) -> (Ptr Word8 -> IO ()) -> IO bs
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    r -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
    memCopy Ptr Word8
    r Ptr Word8
    p Int
    n
                b2 <- alloc (len - n) $ \Ptr Word8
    r -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
    memCopy Ptr Word8
    r (Ptr Word8
    p Ptr Word8 -> Int -> Ptr Word8
    forall a b. Ptr a -> Int -> Ptr b
    `plusPtr` Int
    n) (Int
    len Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    n)
                return (b1, b2)
      where len :: Int
    len = bs -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    length bs
    bs

    -- | Take the first @n@ byte of a bytearray
    take :: ByteArray bs => Int -> bs -> bs
    take :: forall bs. ByteArray bs => Int -> bs -> bs
    take Int
    n bs
    bs
        | Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    0    = bs
    forall a. ByteArray a => a
    empty
        | Bool
    otherwise = Int -> (Ptr Word8 -> IO ()) -> bs
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    unsafeCreate Int
    m ((Ptr Word8 -> IO ()) -> bs) -> (Ptr Word8 -> IO ()) -> bs
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    d -> bs -> (Ptr Word8 -> IO ()) -> IO ()
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. bs -> (Ptr p -> IO a) -> IO a
    withByteArray bs
    bs ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    s -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
    memCopy Ptr Word8
    d Ptr Word8
    s Int
    m
      where
        !m :: Int
    m   = Int -> Int -> Int
    forall a. Ord a => a -> a -> a
    min Int
    len Int
    n
        !len :: Int
    len = bs -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    length bs
    bs

    -- | drop the first @n@ byte of a bytearray
    drop :: ByteArray bs => Int -> bs -> bs
    drop :: forall bs. ByteArray bs => Int -> bs -> bs
    drop Int
    n bs
    bs
        | Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    0    = bs
    bs
        | Int
    nb Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    0   = bs
    forall a. ByteArray a => a
    empty
        | Bool
    otherwise = Int -> (Ptr Word8 -> IO ()) -> bs
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    unsafeCreate Int
    nb ((Ptr Word8 -> IO ()) -> bs) -> (Ptr Word8 -> IO ()) -> bs
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    d -> bs -> (Ptr (ZonkAny 10) -> IO ()) -> IO ()
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. bs -> (Ptr p -> IO a) -> IO a
    withByteArray bs
    bs ((Ptr (ZonkAny 10) -> IO ()) -> IO ())
    -> (Ptr (ZonkAny 10) -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 10)
    s -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
    memCopy Ptr Word8
    d (Ptr (ZonkAny 10)
    s Ptr (ZonkAny 10) -> Int -> Ptr Word8
    forall a b. Ptr a -> Int -> Ptr b
    `plusPtr` Int
    ofs) Int
    nb
      where
        ofs :: Int
    ofs = Int -> Int -> Int
    forall a. Ord a => a -> a -> a
    min Int
    len Int
    n
        nb :: Int
    nb  = Int
    len Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    ofs
        len :: Int
    len = bs -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    length bs
    bs

    -- | Split a bytearray at the point where @pred@ becomes invalid
    span :: ByteArray bs => (Word8 -> Bool) -> bs -> (bs, bs)
    span :: forall bs. ByteArray bs => (Word8 -> Bool) -> bs -> (bs, bs)
    span Word8 -> Bool
    pred bs
    bs
        | bs -> Bool
    forall a. ByteArrayAccess a => a -> Bool
    null bs
    bs   = (bs
    bs, bs
    bs)
        | Bool
    otherwise = let n :: Int
    n = Int -> Int
    loop Int
    0 in (Int -> bs -> bs
    forall bs. ByteArray bs => Int -> bs -> bs
    take Int
    n bs
    bs, Int -> bs -> bs
    forall bs. ByteArray bs => Int -> bs -> bs
    drop Int
    n bs
    bs)
      where loop :: Int -> Int
    loop !Int
    i
                | Int
    i Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    len          = Int
    len
                | Word8 -> Bool
    pred (bs -> Int -> Word8
    forall a. ByteArrayAccess a => a -> Int -> Word8
    index bs
    bs Int
    i) = Int -> Int
    loop (Int
    iInt -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1)
                | Bool
    otherwise         = Int
    i
            len :: Int
    len = bs -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    length bs
    bs

    -- | Reverse a bytearray
    reverse :: ByteArray bs => bs -> bs
    reverse :: forall bs. ByteArray bs => bs -> bs
    reverse bs
    bs = Int -> (Ptr Word8 -> IO ()) -> bs
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    unsafeCreate Int
    n ((Ptr Word8 -> IO ()) -> bs) -> (Ptr Word8 -> IO ()) -> bs
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    d -> bs -> (Ptr Word8 -> IO ()) -> IO ()
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. bs -> (Ptr p -> IO a) -> IO a
    withByteArray bs
    bs ((Ptr Word8 -> IO ()) -> IO ()) -> (Ptr Word8 -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    s -> Ptr Word8 -> Ptr Word8 -> Int -> IO ()
    memReverse Ptr Word8
    d Ptr Word8
    s Int
    n
      where n :: Int
    n = bs -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    length bs
    bs

    -- | Concatenate bytearray into a larger bytearray
    concat :: (ByteArrayAccess bin, ByteArray bout) => [bin] -> bout
    concat :: forall bin bout.
    (ByteArrayAccess bin, ByteArray bout) =>
    [bin] -> bout
    concat [bin]
    l = Int -> (Ptr (ZonkAny 6) -> IO ()) -> bout
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    unsafeCreate Int
    retLen ([bin] -> Ptr (ZonkAny 6) -> IO ()
    forall {ba} {b}. ByteArrayAccess ba => [ba] -> Ptr b -> IO ()
    loopCopy [bin]
    l)
      where
        retLen :: Int
    retLen = [Int] -> Int
    forall a. Num a => [a] -> a
    forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
    sum ([Int] -> Int) -> [Int] -> Int
    forall a b. (a -> b) -> a -> b
    $ (bin -> Int) -> [bin] -> [Int]
    forall a b. (a -> b) -> [a] -> [b]
    map bin -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    length [bin]
    l

        loopCopy :: [ba] -> Ptr b -> IO ()
    loopCopy []     Ptr b
    _   = () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
        loopCopy (ba
    x:[ba]
    xs) Ptr b
    dst = do
            ba -> Ptr b -> IO ()
    forall p. ba -> Ptr p -> IO ()
    forall ba p. ByteArrayAccess ba => ba -> Ptr p -> IO ()
    copyByteArrayToPtr ba
    x Ptr b
    dst
            [ba] -> Ptr b -> IO ()
    loopCopy [ba]
    xs (Ptr b
    dst Ptr b -> Int -> Ptr b
    forall a b. Ptr a -> Int -> Ptr b
    `plusPtr` Int
    chunkLen)
          where
            !chunkLen :: Int
    chunkLen = ba -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    length ba
    x

    -- | append one bytearray to the other
    append :: ByteArray bs => bs -> bs -> bs
    append :: forall bs. ByteArray bs => bs -> bs -> bs
    append = bs -> bs -> bs
    forall a. Monoid a => a -> a -> a
    mappend

    -- | Duplicate a bytearray into another bytearray, and run an initializer on it
    copy :: (ByteArrayAccess bs1, ByteArray bs2) => bs1 -> (Ptr p -> IO ()) -> IO bs2
    copy :: forall bs1 bs2 p.
    (ByteArrayAccess bs1, ByteArray bs2) =>
    bs1 -> (Ptr p -> IO ()) -> IO bs2
    copy bs1
    bs Ptr p -> IO ()
    f =
        Int -> (Ptr (ZonkAny 11) -> IO ()) -> IO bs2
    forall ba p. ByteArray ba => Int -> (Ptr p -> IO ()) -> IO ba
    alloc (bs1 -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    length bs1
    bs) ((Ptr (ZonkAny 11) -> IO ()) -> IO bs2)
    -> (Ptr (ZonkAny 11) -> IO ()) -> IO bs2
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 11)
    d -> do
            bs1 -> Ptr (ZonkAny 11) -> IO ()
    forall p. bs1 -> Ptr p -> IO ()
    forall ba p. ByteArrayAccess ba => ba -> Ptr p -> IO ()
    copyByteArrayToPtr bs1
    bs Ptr (ZonkAny 11)
    d
            Ptr p -> IO ()
    f (Ptr (ZonkAny 11) -> Ptr p
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (ZonkAny 11)
    d)

    -- | Similar to 'copy' but also provide a way to return a value from the initializer
    copyRet :: (ByteArrayAccess bs1, ByteArray bs2) => bs1 -> (Ptr p -> IO a) -> IO (a, bs2)
    copyRet :: forall bs1 bs2 p a.
    (ByteArrayAccess bs1, ByteArray bs2) =>
    bs1 -> (Ptr p -> IO a) -> IO (a, bs2)
    copyRet bs1
    bs Ptr p -> IO a
    f =
        Int -> (Ptr (ZonkAny 0) -> IO a) -> IO (a, bs2)
    forall ba p a. ByteArray ba => Int -> (Ptr p -> IO a) -> IO (a, ba)
    forall p a. Int -> (Ptr p -> IO a) -> IO (a, bs2)
    allocRet (bs1 -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    length bs1
    bs) ((Ptr (ZonkAny 0) -> IO a) -> IO (a, bs2))
    -> (Ptr (ZonkAny 0) -> IO a) -> IO (a, bs2)
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 0)
    d -> do
            bs1 -> Ptr (ZonkAny 0) -> IO ()
    forall p. bs1 -> Ptr p -> IO ()
    forall ba p. ByteArrayAccess ba => ba -> Ptr p -> IO ()
    copyByteArrayToPtr bs1
    bs Ptr (ZonkAny 0)
    d
            Ptr p -> IO a
    f (Ptr (ZonkAny 0) -> Ptr p
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (ZonkAny 0)
    d)

    -- | Similiar to 'copy' but expect the resulting bytearray in a pure context
    copyAndFreeze :: (ByteArrayAccess bs1, ByteArray bs2) => bs1 -> (Ptr p -> IO ()) -> bs2
    copyAndFreeze :: forall bs1 bs2 p.
    (ByteArrayAccess bs1, ByteArray bs2) =>
    bs1 -> (Ptr p -> IO ()) -> bs2
    copyAndFreeze bs1
    bs Ptr p -> IO ()
    f =
        Int -> (Ptr (ZonkAny 7) -> IO ()) -> bs2
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    inlineUnsafeCreate (bs1 -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    length bs1
    bs) ((Ptr (ZonkAny 7) -> IO ()) -> bs2)
    -> (Ptr (ZonkAny 7) -> IO ()) -> bs2
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 7)
    d -> do
            bs1 -> Ptr (ZonkAny 7) -> IO ()
    forall p. bs1 -> Ptr p -> IO ()
    forall ba p. ByteArrayAccess ba => ba -> Ptr p -> IO ()
    copyByteArrayToPtr bs1
    bs Ptr (ZonkAny 7)
    d
            Ptr p -> IO ()
    f (Ptr (ZonkAny 7) -> Ptr p
    forall a b. Ptr a -> Ptr b
    castPtr Ptr (ZonkAny 7)
    d)
    {-# NOINLINE copyAndFreeze #-}

    -- | Create a bytearray of a specific size containing a repeated byte value
    replicate :: ByteArray ba => Int -> Word8 -> ba
    replicate :: forall ba. ByteArray ba => Int -> Word8 -> ba
    replicate Int
    0 Word8
    _ = ba
    forall a. ByteArray a => a
    empty
    replicate Int
    n Word8
    b
        | Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    0     = ba
    forall a. ByteArray a => a
    empty
        | Bool
    otherwise = Int -> (Ptr Word8 -> IO ()) -> ba
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    inlineUnsafeCreate Int
    n ((Ptr Word8 -> IO ()) -> ba) -> (Ptr Word8 -> IO ()) -> ba
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    ptr -> Ptr Word8 -> Word8 -> Int -> IO ()
    memSet Ptr Word8
    ptr Word8
    b Int
    n
    {-# NOINLINE replicate #-}

    -- | Create a bytearray of a specific size initialized to 0
    zero :: ByteArray ba => Int -> ba
    zero :: forall ba. ByteArray ba => Int -> ba
    zero Int
    0 = ba
    forall a. ByteArray a => a
    empty
    zero Int
    n
        | Int
    n Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    0     = ba
    forall a. ByteArray a => a
    empty
        | Bool
    otherwise = Int -> (Ptr Word8 -> IO ()) -> ba
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    unsafeCreate Int
    n ((Ptr Word8 -> IO ()) -> ba) -> (Ptr Word8 -> IO ()) -> ba
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    ptr -> Ptr Word8 -> Word8 -> Int -> IO ()
    memSet Ptr Word8
    ptr Word8
    0 Int
    n
    {-# NOINLINE zero #-}

    -- | Check if two bytearray are equals
    --
    -- This is not constant time, as soon some byte differs the function will
    -- returns. use 'constEq' in sensitive context where timing matters.
    eq :: (ByteArrayAccess bs1, ByteArrayAccess bs2) => bs1 -> bs2 -> Bool
    eq :: forall bs1 bs2.
    (ByteArrayAccess bs1, ByteArrayAccess bs2) =>
    bs1 -> bs2 -> Bool
    eq bs1
    b1 bs2
    b2
        | Int
    l1 Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Int
    l2  = Bool
    False
        | Bool
    otherwise = IO Bool -> Bool
    forall a. IO a -> a
    unsafeDoIO (IO Bool -> Bool) -> IO Bool -> Bool
    forall a b. (a -> b) -> a -> b
    $ bs1 -> (Ptr Word8 -> IO Bool) -> IO Bool
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. bs1 -> (Ptr p -> IO a) -> IO a
    withByteArray bs1
    b1 ((Ptr Word8 -> IO Bool) -> IO Bool)
    -> (Ptr Word8 -> IO Bool) -> IO Bool
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    p1 -> bs2 -> (Ptr Word8 -> IO Bool) -> IO Bool
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. bs2 -> (Ptr p -> IO a) -> IO a
    withByteArray bs2
    b2 ((Ptr Word8 -> IO Bool) -> IO Bool)
    -> (Ptr Word8 -> IO Bool) -> IO Bool
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    p2 -> Ptr Word8 -> Ptr Word8 -> Int -> IO Bool
    memEqual Ptr Word8
    p1 Ptr Word8
    p2 Int
    l1
      where
        l1 :: Int
    l1 = bs1 -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    length bs1
    b1
        l2 :: Int
    l2 = bs2 -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    length bs2
    b2

    -- | A constant time equality test for 2 ByteArrayAccess values.
    --
    -- If values are of 2 different sizes, the function will abort early
    -- without comparing any bytes.
    --
    -- compared to == , this function will go over all the bytes
    -- present before yielding a result even when knowing the
    -- overall result early in the processing.
    constEq :: (ByteArrayAccess bs1, ByteArrayAccess bs2) => bs1 -> bs2 -> Bool
    constEq :: forall bs1 bs2.
    (ByteArrayAccess bs1, ByteArrayAccess bs2) =>
    bs1 -> bs2 -> Bool
    constEq bs1
    b1 bs2
    b2
        | Int
    l1 Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Int
    l2  = Bool
    False
        | Bool
    otherwise = IO Bool -> Bool
    forall a. IO a -> a
    unsafeDoIO (IO Bool -> Bool) -> IO Bool -> Bool
    forall a b. (a -> b) -> a -> b
    $ bs1 -> (Ptr Word8 -> IO Bool) -> IO Bool
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. bs1 -> (Ptr p -> IO a) -> IO a
    withByteArray bs1
    b1 ((Ptr Word8 -> IO Bool) -> IO Bool)
    -> (Ptr Word8 -> IO Bool) -> IO Bool
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    p1 -> bs2 -> (Ptr Word8 -> IO Bool) -> IO Bool
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. bs2 -> (Ptr p -> IO a) -> IO a
    withByteArray bs2
    b2 ((Ptr Word8 -> IO Bool) -> IO Bool)
    -> (Ptr Word8 -> IO Bool) -> IO Bool
    forall a b. (a -> b) -> a -> b
    $ \Ptr Word8
    p2 -> Ptr Word8 -> Ptr Word8 -> Int -> IO Bool
    memConstEqual Ptr Word8
    p1 Ptr Word8
    p2 Int
    l1
      where
        !l1 :: Int
    l1 = bs1 -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    length bs1
    b1
        !l2 :: Int
    l2 = bs2 -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    length bs2
    b2

    -- | Check if any element of a byte array satisfies a predicate
    any :: (ByteArrayAccess ba) => (Word8 -> Bool) -> ba -> Bool
    any :: forall ba. ByteArrayAccess ba => (Word8 -> Bool) -> ba -> Bool
    any Word8 -> Bool
    f ba
    b
        | ba -> Bool
    forall a. ByteArrayAccess a => a -> Bool
    null ba
    b    = Bool
    False
        | Bool
    otherwise = IO Bool -> Bool
    forall a. IO a -> a
    unsafeDoIO (IO Bool -> Bool) -> IO Bool -> Bool
    forall a b. (a -> b) -> a -> b
    $ ba -> (Ptr (ZonkAny 3) -> IO Bool) -> IO Bool
    forall ba p a. ByteArrayAccess ba => ba -> (Ptr p -> IO a) -> IO a
    forall p a. ba -> (Ptr p -> IO a) -> IO a
    withByteArray ba
    b ((Ptr (ZonkAny 3) -> IO Bool) -> IO Bool)
    -> (Ptr (ZonkAny 3) -> IO Bool) -> IO Bool
    forall a b. (a -> b) -> a -> b
    $ \Ptr (ZonkAny 3)
    p -> Ptr (ZonkAny 3) -> Int -> IO Bool
    forall {b}. Ptr b -> Int -> IO Bool
    loop Ptr (ZonkAny 3)
    p Int
    0
      where
        len :: Int
    len = ba -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    length ba
    b
        loop :: Ptr b -> Int -> IO Bool
    loop Ptr b
    p Int
    i
            | Int
    i Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    len  = Bool -> IO Bool
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Bool
    False
            | Bool
    otherwise = do
                w <- Ptr b -> Int -> IO Word8
    forall b. Ptr b -> Int -> IO Word8
    forall a b. Storable a => Ptr b -> Int -> IO a
    peekByteOff Ptr b
    p Int
    i
                if f w then return True else loop p (i+1)

    -- | Check if all elements of a byte array satisfy a predicate
    all :: (ByteArrayAccess ba) => (Word8 -> Bool) -> ba -> Bool
    all :: forall ba. ByteArrayAccess ba => (Word8 -> Bool) -> ba -> Bool
    all Word8 -> Bool
    f ba
    b = Bool -> Bool
    not ((Word8 -> Bool) -> ba -> Bool
    forall ba. ByteArrayAccess ba => (Word8 -> Bool) -> ba -> Bool
    any (Bool -> Bool
    not (Bool -> Bool) -> (Word8 -> Bool) -> Word8 -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Bool
    f) ba
    b)

    -- | Convert a bytearray to another type of bytearray
    convert :: (ByteArrayAccess bin, ByteArray bout) => bin -> bout
    convert :: forall bin bout.
    (ByteArrayAccess bin, ByteArray bout) =>
    bin -> bout
    convert bin
    bs = Int -> (Ptr (ZonkAny 8) -> IO ()) -> bout
    forall a p. ByteArray a => Int -> (Ptr p -> IO ()) -> a
    inlineUnsafeCreate (bin -> Int
    forall ba. ByteArrayAccess ba => ba -> Int
    length bin
    bs) (bin -> Ptr (ZonkAny 8) -> IO ()
    forall p. bin -> Ptr p -> IO ()
    forall ba p. ByteArrayAccess ba => ba -> Ptr p -> IO ()
    copyByteArrayToPtr bin
    bs)
    #if defined(WITH_BYTESTRING_SUPPORT) && defined(WITH_BASEMENT_SUPPORT)
    {-# SPECIALIZE convert :: SPE.ByteString -> SPE.UArray Word8 #-}
    {-# SPECIALIZE convert :: SPE.UArray Word8 -> SPE.ByteString #-}
    {-# SPECIALIZE convert :: SPE.ByteString -> SPE.Block Word8 #-}
    {-# SPECIALIZE convert :: SPE.Block Word8 -> SPE.ByteString #-}
    #endif