    -- | Folds for byte streams

    module Control.Foldl.ByteString (
        -- * Folding
          fold
        , foldM

        -- * Folds
        , head
        , last
        , null
        , length
        , any
        , all
        , maximum
        , minimum
        , elem
        , notElem
        , find
        , index
        , elemIndex
        , findIndex
        , count
        , lazy

        -- * Re-exports
        -- $reexports
        , module Control.Foldl
        , module Data.ByteString
        , module Data.Word
        ) where

    import Control.Foldl (Fold, FoldM)
    import Control.Foldl.Internal (Maybe'(..), strict, Either'(..), hush)
    import Data.ByteString (ByteString)
    import Data.Word (Word8)
    import Prelude hiding (
        head, last, null, length, any, all, maximum, minimum, elem, notElem )

    import qualified Control.Foldl
    import qualified Control.Foldl.Internal
    import qualified Data.ByteString
    import qualified Data.ByteString.Lazy.Internal
    import qualified Data.ByteString.Unsafe
    import qualified Data.ByteString.Lazy

    -- | Apply a strict left 'Fold' to a lazy bytestring
    fold :: Fold ByteString a -> Data.ByteString.Lazy.ByteString -> a
    fold :: forall a. Fold ByteString a -> ByteString -> a
    fold (Control.Foldl.Fold x -> ByteString -> x
    step x
    begin x -> a
    done) ByteString
    as =
        x -> a
    done ((x -> ByteString -> x) -> x -> ByteString -> x
    forall a. (a -> ByteString -> a) -> a -> ByteString -> a
    Data.ByteString.Lazy.Internal.foldlChunks x -> ByteString -> x
    step x
    begin ByteString
    as)
    {-# INLINABLE fold #-}

    -- | Apply a strict monadic left 'FoldM' to a lazy bytestring
    foldM
        :: Monad m => FoldM m ByteString a -> Data.ByteString.Lazy.ByteString -> m a
    foldM :: forall (m :: * -> *) a.
    Monad m =>
    FoldM m ByteString a -> ByteString -> m a
    foldM (Control.Foldl.FoldM x -> ByteString -> m x
    step m x
    begin x -> m a
    done) ByteString
    as = do
        x <- (m x -> ByteString -> m x) -> m x -> ByteString -> m x
    forall a. (a -> ByteString -> a) -> a -> ByteString -> a
    Data.ByteString.Lazy.Internal.foldlChunks m x -> ByteString -> m x
    step' m x
    begin ByteString
    as
        done x
      where
        step' :: m x -> ByteString -> m x
    step' m x
    mx ByteString
    bs = do
          x <- m x
    mx
          x `seq` step x bs
    {-# INLINABLE foldM #-}

    {-| Get the first byte of a byte stream or return 'Nothing' if the stream is
        empty
    -}
    head :: Fold ByteString (Maybe Word8)
    head :: Fold ByteString (Maybe Word8)
    head = (Maybe' Word8 -> ByteString -> Maybe' Word8)
    -> Maybe' Word8
    -> (Maybe' Word8 -> Maybe Word8)
    -> Fold ByteString (Maybe Word8)
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold Maybe' Word8 -> ByteString -> Maybe' Word8
    step Maybe' Word8
    forall a. Maybe' a
    Nothing' Maybe' Word8 -> Maybe Word8
    forall a. Maybe' a -> Maybe a
    Control.Foldl.Internal.lazy
      where
        step :: Maybe' Word8 -> ByteString -> Maybe' Word8
    step Maybe' Word8
    mw8 ByteString
    bs =
            if ByteString -> Bool
    Data.ByteString.null ByteString
    bs
            then Maybe' Word8
    mw8
            else case Maybe' Word8
    mw8 of
                Just' Word8
    _  -> Maybe' Word8
    mw8
                Maybe' Word8
    Nothing' -> Word8 -> Maybe' Word8
    forall a. a -> Maybe' a
    Just' (ByteString -> Word8
    Data.ByteString.Unsafe.unsafeHead ByteString
    bs)
    {-# INLINABLE head #-}

    {-| Get the last byte of a byte stream or return 'Nothing' if the byte stream is
        empty
    -}
    last :: Fold ByteString (Maybe Word8)
    last :: Fold ByteString (Maybe Word8)
    last = (Maybe' Word8 -> ByteString -> Maybe' Word8)
    -> Maybe' Word8
    -> (Maybe' Word8 -> Maybe Word8)
    -> Fold ByteString (Maybe Word8)
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold Maybe' Word8 -> ByteString -> Maybe' Word8
    step Maybe' Word8
    forall a. Maybe' a
    Nothing' Maybe' Word8 -> Maybe Word8
    forall a. Maybe' a -> Maybe a
    Control.Foldl.Internal.lazy
      where
        step :: Maybe' Word8 -> ByteString -> Maybe' Word8
    step Maybe' Word8
    mw8 ByteString
    bs =
            if ByteString -> Bool
    Data.ByteString.null ByteString
    bs
            then Maybe' Word8
    mw8
            else Word8 -> Maybe' Word8
    forall a. a -> Maybe' a
    Just' (HasCallStack => ByteString -> Word8
    ByteString -> Word8
    Data.ByteString.last ByteString
    bs)
            -- TODO: Use `unsafeLast` when Debian Stable Haskell Platform has it
    {-# INLINABLE last #-}

    -- | Returns 'True' if the byte stream is empty, 'False' otherwise
    null :: Fold ByteString Bool
    null :: Fold ByteString Bool
    null = (Bool -> ByteString -> Bool)
    -> Bool -> (Bool -> Bool) -> Fold ByteString Bool
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold Bool -> ByteString -> Bool
    step Bool
    True Bool -> Bool
    forall a. a -> a
    id
      where
        step :: Bool -> ByteString -> Bool
    step Bool
    isNull ByteString
    bs = Bool
    isNull Bool -> Bool -> Bool
    && ByteString -> Bool
    Data.ByteString.null ByteString
    bs
    {-# INLINABLE null #-}

    -- | Return the length of the byte stream in bytes
    length :: Num n => Fold ByteString n
    length :: forall n. Num n => Fold ByteString n
    length = (n -> ByteString -> n) -> n -> (n -> n) -> Fold ByteString n
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold n -> ByteString -> n
    forall {a}. Num a => a -> ByteString -> a
    step n
    0 n -> n
    forall a. a -> a
    id
      where
        step :: a -> ByteString -> a
    step a
    n ByteString
    bs = a
    n a -> a -> a
    forall a. Num a => a -> a -> a
    + Int -> a
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (ByteString -> Int
    Data.ByteString.length ByteString
    bs)
    {-# INLINABLE length #-}

    {-| @(all predicate)@ returns 'True' if all bytes satisfy the predicate, 'False'
        otherwise
    -}
    all :: (Word8 -> Bool) -> Fold ByteString Bool
    all :: (Word8 -> Bool) -> Fold ByteString Bool
    all Word8 -> Bool
    predicate =
        (Bool -> ByteString -> Bool)
    -> Bool -> (Bool -> Bool) -> Fold ByteString Bool
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold (\Bool
    b ByteString
    bs -> Bool
    b Bool -> Bool -> Bool
    && (Word8 -> Bool) -> ByteString -> Bool
    Data.ByteString.all Word8 -> Bool
    predicate ByteString
    bs) Bool
    True Bool -> Bool
    forall a. a -> a
    id
    {-# INLINABLE all #-}

    {-| @(any predicate)@ returns 'True' if any byte satisfies the predicate,
        'False' otherwise
    -}
    any :: (Word8 -> Bool) -> Fold ByteString Bool
    any :: (Word8 -> Bool) -> Fold ByteString Bool
    any Word8 -> Bool
    predicate =
        (Bool -> ByteString -> Bool)
    -> Bool -> (Bool -> Bool) -> Fold ByteString Bool
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold (\Bool
    b ByteString
    bs -> Bool
    b Bool -> Bool -> Bool
    || (Word8 -> Bool) -> ByteString -> Bool
    Data.ByteString.any Word8 -> Bool
    predicate ByteString
    bs) Bool
    False Bool -> Bool
    forall a. a -> a
    id
    {-# INLINABLE any #-}

    -- | Computes the maximum byte
    maximum :: Fold ByteString (Maybe Word8)
    maximum :: Fold ByteString (Maybe Word8)
    maximum = (Maybe' Word8 -> ByteString -> Maybe' Word8)
    -> Maybe' Word8
    -> (Maybe' Word8 -> Maybe Word8)
    -> Fold ByteString (Maybe Word8)
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold Maybe' Word8 -> ByteString -> Maybe' Word8
    step Maybe' Word8
    forall a. Maybe' a
    Nothing' Maybe' Word8 -> Maybe Word8
    forall a. Maybe' a -> Maybe a
    Control.Foldl.Internal.lazy
      where
        step :: Maybe' Word8 -> ByteString -> Maybe' Word8
    step Maybe' Word8
    mw8 ByteString
    bs =
            if ByteString -> Bool
    Data.ByteString.null ByteString
    bs
            then Maybe' Word8
    mw8
            else Word8 -> Maybe' Word8
    forall a. a -> Maybe' a
    Just' (case Maybe' Word8
    mw8 of
                Maybe' Word8
    Nothing' -> HasCallStack => ByteString -> Word8
    ByteString -> Word8
    Data.ByteString.maximum ByteString
    bs
                Just' Word8
    w8 -> Word8 -> Word8 -> Word8
    forall a. Ord a => a -> a -> a
    max Word8
    w8 (HasCallStack => ByteString -> Word8
    ByteString -> Word8
    Data.ByteString.maximum ByteString
    bs) )
    {-# INLINABLE maximum #-}

    -- | Computes the minimum byte
    minimum :: Fold ByteString (Maybe Word8)
    minimum :: Fold ByteString (Maybe Word8)
    minimum = (Maybe' Word8 -> ByteString -> Maybe' Word8)
    -> Maybe' Word8
    -> (Maybe' Word8 -> Maybe Word8)
    -> Fold ByteString (Maybe Word8)
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold Maybe' Word8 -> ByteString -> Maybe' Word8
    step Maybe' Word8
    forall a. Maybe' a
    Nothing' Maybe' Word8 -> Maybe Word8
    forall a. Maybe' a -> Maybe a
    Control.Foldl.Internal.lazy
      where
        step :: Maybe' Word8 -> ByteString -> Maybe' Word8
    step Maybe' Word8
    mw8 ByteString
    bs =
            if ByteString -> Bool
    Data.ByteString.null ByteString
    bs
            then Maybe' Word8
    mw8
            else Word8 -> Maybe' Word8
    forall a. a -> Maybe' a
    Just' (case Maybe' Word8
    mw8 of
                Maybe' Word8
    Nothing' -> HasCallStack => ByteString -> Word8
    ByteString -> Word8
    Data.ByteString.minimum ByteString
    bs
                Just' Word8
    w8 -> Word8 -> Word8 -> Word8
    forall a. Ord a => a -> a -> a
    min Word8
    w8 (HasCallStack => ByteString -> Word8
    ByteString -> Word8
    Data.ByteString.minimum ByteString
    bs) )
    {-# INLINABLE minimum #-}

    {-| @(elem w8)@ returns 'True' if the byte stream has a byte equal to @w8@,
        'False' otherwise
    -}
    elem :: Word8 -> Fold ByteString Bool
    elem :: Word8 -> Fold ByteString Bool
    elem Word8
    w8 = (Word8 -> Bool) -> Fold ByteString Bool
    any (Word8
    w8 Word8 -> Word8 -> Bool
    forall a. Eq a => a -> a -> Bool
    ==)
    {-# INLINABLE elem #-}

    {-| @(notElem w8)@ returns 'False' if the byte stream has a byte equal to @w8@,
        'True' otherwise
    -}
    notElem :: Word8 -> Fold ByteString Bool
    notElem :: Word8 -> Fold ByteString Bool
    notElem Word8
    w8 = (Word8 -> Bool) -> Fold ByteString Bool
    all (Word8
    w8 Word8 -> Word8 -> Bool
    forall a. Eq a => a -> a -> Bool
    /=)
    {-# INLINABLE notElem #-}

    {-| @(find predicate)@ returns the first byte that satisfies the predicate or
        'Nothing' if no byte satisfies the predicate
    -}
    find :: (Word8 -> Bool) -> Fold ByteString (Maybe Word8)
    find :: (Word8 -> Bool) -> Fold ByteString (Maybe Word8)
    find Word8 -> Bool
    predicate = (Maybe' Word8 -> ByteString -> Maybe' Word8)
    -> Maybe' Word8
    -> (Maybe' Word8 -> Maybe Word8)
    -> Fold ByteString (Maybe Word8)
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold Maybe' Word8 -> ByteString -> Maybe' Word8
    step Maybe' Word8
    forall a. Maybe' a
    Nothing' Maybe' Word8 -> Maybe Word8
    forall a. Maybe' a -> Maybe a
    Control.Foldl.Internal.lazy
      where
        step :: Maybe' Word8 -> ByteString -> Maybe' Word8
    step Maybe' Word8
    mw8 ByteString
    bs = case Maybe' Word8
    mw8 of
            Maybe' Word8
    Nothing' -> Maybe Word8 -> Maybe' Word8
    forall a. Maybe a -> Maybe' a
    strict ((Word8 -> Bool) -> ByteString -> Maybe Word8
    Data.ByteString.find Word8 -> Bool
    predicate ByteString
    bs)
            Just' Word8
    _  -> Maybe' Word8
    mw8
    {-# INLINABLE find #-}

    {-| @(index n)@ returns the @n@th byte of the byte stream, or 'Nothing' if the
        stream has an insufficient number of bytes
    -}
    index :: Integral n => n -> Fold ByteString (Maybe Word8)
    index :: forall n. Integral n => n -> Fold ByteString (Maybe Word8)
    index n
    i = (Either' Int Word8 -> ByteString -> Either' Int Word8)
    -> Either' Int Word8
    -> (Either' Int Word8 -> Maybe Word8)
    -> Fold ByteString (Maybe Word8)
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold Either' Int Word8 -> ByteString -> Either' Int Word8
    step (Int -> Either' Int Word8
    forall a b. a -> Either' a b
    Left' (n -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral n
    i)) Either' Int Word8 -> Maybe Word8
    forall a b. Either' a b -> Maybe b
    hush
      where
        step :: Either' Int Word8 -> ByteString -> Either' Int Word8
    step Either' Int Word8
    x ByteString
    bs = case Either' Int Word8
    x of
            Left' Int
    remainder ->
                let len :: Int
    len = ByteString -> Int
    Data.ByteString.length ByteString
    bs
                in  if Int
    remainder Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    len
                    then Word8 -> Either' Int Word8
    forall a b. b -> Either' a b
    Right' (ByteString -> Int -> Word8
    Data.ByteString.Unsafe.unsafeIndex ByteString
    bs Int
    remainder)
                    else Int -> Either' Int Word8
    forall a b. a -> Either' a b
    Left'  (Int
    remainder Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    len)
            Either' Int Word8
    _               -> Either' Int Word8
    x
    {-# INLINABLE index #-}

    {-| @(elemIndex w8)@ returns the index of the first byte that equals @w8@, or
        'Nothing' if no byte matches
    -}
    elemIndex :: Num n => Word8 -> Fold ByteString (Maybe n)
    elemIndex :: forall n. Num n => Word8 -> Fold ByteString (Maybe n)
    elemIndex Word8
    w8 = (Word8 -> Bool) -> Fold ByteString (Maybe n)
    forall n. Num n => (Word8 -> Bool) -> Fold ByteString (Maybe n)
    findIndex (Word8
    w8 Word8 -> Word8 -> Bool
    forall a. Eq a => a -> a -> Bool
    ==)
    {-# INLINABLE elemIndex #-}

    {-| @(findIndex predicate)@ returns the index of the first byte that satisfies
        the predicate, or 'Nothing' if no byte satisfies the predicate
    -}
    findIndex :: Num n => (Word8 -> Bool) -> Fold ByteString (Maybe n)
    findIndex :: forall n. Num n => (Word8 -> Bool) -> Fold ByteString (Maybe n)
    findIndex Word8 -> Bool
    predicate = (Either' n n -> ByteString -> Either' n n)
    -> Either' n n
    -> (Either' n n -> Maybe n)
    -> Fold ByteString (Maybe n)
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold Either' n n -> ByteString -> Either' n n
    forall {b}. Num b => Either' b b -> ByteString -> Either' b b
    step (n -> Either' n n
    forall a b. a -> Either' a b
    Left' n
    0) Either' n n -> Maybe n
    forall a b. Either' a b -> Maybe b
    hush
      where
        step :: Either' b b -> ByteString -> Either' b b
    step Either' b b
    x ByteString
    bs = case Either' b b
    x of
            Left' b
    m -> case (Word8 -> Bool) -> ByteString -> Maybe Int
    Data.ByteString.findIndex Word8 -> Bool
    predicate ByteString
    bs of
                Maybe Int
    Nothing -> b -> Either' b b
    forall a b. a -> Either' a b
    Left'  (b
    m b -> b -> b
    forall a. Num a => a -> a -> a
    + Int -> b
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (ByteString -> Int
    Data.ByteString.length ByteString
    bs))
                Just Int
    n  -> b -> Either' b b
    forall a b. b -> Either' a b
    Right' (b
    m b -> b -> b
    forall a. Num a => a -> a -> a
    + Int -> b
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Int
    n)
            Either' b b
    _       -> Either' b b
    x
    {-# INLINABLE findIndex #-}

    -- | @count w8@ returns the number of times @w8@ appears
    count :: Num n => Word8 -> Fold ByteString n
    count :: forall n. Num n => Word8 -> Fold ByteString n
    count Word8
    w8 = (n -> ByteString -> n) -> n -> (n -> n) -> Fold ByteString n
    forall a b x. (x -> a -> x) -> x -> (x -> b) -> Fold a b
    Control.Foldl.Fold n -> ByteString -> n
    forall {a}. Num a => a -> ByteString -> a
    step n
    0 n -> n
    forall a. a -> a
    id
      where
        step :: a -> ByteString -> a
    step a
    n ByteString
    bs = a
    n a -> a -> a
    forall a. Num a => a -> a -> a
    + Int -> a
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Word8 -> ByteString -> Int
    Data.ByteString.count Word8
    w8 ByteString
    bs)
    {-# INLINABLE count #-}

    -- | Combine all the strict `ByteString` chunks to build a lazy `ByteString`
    lazy :: Fold ByteString Data.ByteString.Lazy.ByteString
    lazy :: Fold ByteString ByteString
    lazy = ([ByteString] -> ByteString)
    -> Fold ByteString [ByteString] -> Fold ByteString ByteString
    forall a b. (a -> b) -> Fold ByteString a -> Fold ByteString b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap [ByteString] -> ByteString
    Data.ByteString.Lazy.fromChunks Fold ByteString [ByteString]
    forall a. Fold a [a]
    Control.Foldl.list
    {-# INLINABLE lazy #-}

    -- |

    {- $reexports

        "Control.Foldl" re-exports the 'Fold' type

        @Data.ByteString@ re-exports the 'ByteString' type

        @Data.Word@ re-exports the 'Word8' type
    -}