    -- |
    -- Module    : Replace.Megaparsec.Internal.ByteString
    -- Copyright : ©2019 James Brock
    -- License   : BSD2
    -- Maintainer: James Brock <jamesbrock@gmail.com>
    --
    -- This internal module is for 'Data.ByteString.ByteString' specializations.
    --
    -- The functions in this module are intended to be chosen automatically
    -- by rewrite rules in the "Replace.Megaparsec" module, so you should never
    -- need to import this module.
    --
    -- Names in this module may change without a major version increment.

    {-# LANGUAGE RankNTypes #-}
    {-# LANGUAGE TypeFamilies #-}
    {-# LANGUAGE TypeOperators #-}

    module Replace.Megaparsec.Internal.ByteString
      (
        -- * Parser combinator
        sepCapByteString
      , anyTillByteString
      )
    where

    import Control.Monad
    import qualified Data.ByteString as B
    import Text.Megaparsec

    {-# INLINE [1] sepCapByteString #-}
    sepCapByteString
        :: forall e s m a. (MonadParsec e s m, s ~ B.ByteString)
        => m a -- ^ The pattern matching parser @sep@
        -> m [Either (Tokens s) a]
    sepCapByteString :: forall e s (m :: * -> *) a.
    (MonadParsec e s m, s ~ ByteString) =>
    m a -> m [Either (Tokens s) a]
    sepCapByteString m a
    sep = m ByteString
    forall e s (m :: * -> *). MonadParsec e s m => m s
    getInput m ByteString
    -> (ByteString -> m [Either ByteString a])
    -> m [Either ByteString a]
    forall a b. m a -> (a -> m b) -> m b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= ByteString -> m [Either ByteString a]
    go
      where
        -- the go function will search for the first pattern match,
        -- and then capture the pattern match along with the preceding
        -- unmatched string, and then recurse.
        -- restBegin is the rest of the buffer after the last pattern
        -- match.
        go :: ByteString -> m [Either ByteString a]
    go ByteString
    restBegin = do
            m [Either ByteString a]
    -> m [Either ByteString a] -> m [Either ByteString a]
    forall a. m a -> m a -> m a
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
    (<|>)
                ( do
                    restThis <- m ByteString
    forall e s (m :: * -> *). MonadParsec e s m => m s
    getInput
                    -- About 'thisiter':
                    -- It looks stupid and introduces a completely unnecessary
                    -- Maybe, but when I refactor to eliminate 'thisiter' and
                    -- the Maybe then the benchmarks get dramatically worse.
                    thisiter <- (<|>)
                        ( do
                            x <- try sep
                            restAfter <- getInput
                            -- Don't allow a match of a zero-width pattern
                            when (B.length restAfter >= B.length restThis) empty
                            pure $ Just (x, restAfter)
                        )
                        (anySingle >> pure Nothing)
                    case thisiter of
                        (Just (a
    x, ByteString
    restAfter)) | ByteString -> Int
    B.length ByteString
    restThis Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < ByteString -> Int
    B.length ByteString
    restBegin -> do
                            -- we've got a match with some preceding unmatched string
                            let unmatched :: ByteString
    unmatched = Int -> ByteString -> ByteString
    B.take (ByteString -> Int
    B.length ByteString
    restBegin Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - ByteString -> Int
    B.length ByteString
    restThis) ByteString
    restBegin
                            (ByteString -> Either ByteString a
    forall a b. a -> Either a b
    Left ByteString
    unmatchedEither ByteString a
    -> [Either ByteString a] -> [Either ByteString a]
    forall a. a -> [a] -> [a]
    :) ([Either ByteString a] -> [Either ByteString a])
    -> ([Either ByteString a] -> [Either ByteString a])
    -> [Either ByteString a]
    -> [Either ByteString a]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (a -> Either ByteString a
    forall a b. b -> Either a b
    Right a
    xEither ByteString a
    -> [Either ByteString a] -> [Either ByteString a]
    forall a. a -> [a] -> [a]
    :) ([Either ByteString a] -> [Either ByteString a])
    -> m [Either ByteString a] -> m [Either ByteString a]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> ByteString -> m [Either ByteString a]
    go ByteString
    restAfter
                        (Just (a
    x, ByteString
    restAfter)) -> do
                            -- we're got a match with no preceding unmatched string
                            (a -> Either ByteString a
    forall a b. b -> Either a b
    Right a
    xEither ByteString a
    -> [Either ByteString a] -> [Either ByteString a]
    forall a. a -> [a] -> [a]
    :) ([Either ByteString a] -> [Either ByteString a])
    -> m [Either ByteString a] -> m [Either ByteString a]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> ByteString -> m [Either ByteString a]
    go ByteString
    restAfter
                        Maybe (a, ByteString)
    Nothing -> ByteString -> m [Either ByteString a]
    go ByteString
    restBegin -- no match, try again
                )
                ( do
                    -- We're at the end of the input, so return
                    -- whatever unmatched string we've got since offsetBegin
                    if ByteString -> Int
    B.length ByteString
    restBegin Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > Int
    0 then
                        [Either ByteString a] -> m [Either ByteString a]
    forall a. a -> m a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure [ByteString -> Either ByteString a
    forall a b. a -> Either a b
    Left ByteString
    restBegin]
                    else [Either ByteString a] -> m [Either ByteString a]
    forall a. a -> m a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure []
                )

    {-# INLINE [1] anyTillByteString #-}
    anyTillByteString
        :: forall e s m a. (MonadParsec e s m, s ~ B.ByteString)
        => m a -- ^ The pattern matching parser @sep@
        -> m (Tokens s, a)
    anyTillByteString :: forall e s (m :: * -> *) a.
    (MonadParsec e s m, s ~ ByteString) =>
    m a -> m (Tokens s, a)
    anyTillByteString m a
    sep = do
        begin <- m ByteString
    forall e s (m :: * -> *). MonadParsec e s m => m s
    getInput
        (end, x) <- go
        pure (B.take (B.length begin - B.length end) begin, x)
      where
        go :: m (ByteString, a)
    go = do
          end <- m ByteString
    forall e s (m :: * -> *). MonadParsec e s m => m s
    getInput
          r <- optional $ try sep
          case r of
            Maybe a
    Nothing -> m (Token ByteString)
    forall e s (m :: * -> *). MonadParsec e s m => m (Token s)
    anySingle m (Token ByteString) -> m (ByteString, a) -> m (ByteString, a)
    forall a b. m a -> m b -> m b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> m (ByteString, a)
    go
            Just a
    x -> (ByteString, a) -> m (ByteString, a)
    forall a. a -> m a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (ByteString
    end, a
    x)