    -- | Fast not-backtracking incremental scanner for bytestrings
    --
    -- Unlike attoparsec or most of other parser combinator libraries,
    -- scanner doesn't support backtracking. But you probably don't need it
    -- anyway, at least if you need fast parser.
    --
    -- Scanner processes input incrementally. When more input is needed, scanner
    -- returns `More` continuation. All the already processed input is discarded.

    module Scanner
    ( Scanner
    , Result (..)
    , scan
    , scanOnly
    , scanLazy
    , scanWith
    , anyWord8
    , anyChar8
    , word8
    , char8
    , take
    , takeWhile
    , takeWhileChar8
    , string
    , skipWhile
    , skipSpace
    , lookAhead
    , lookAheadChar8
    , foldlWhile
    , foldlWhile1
    , satisfy
    , satisfyMaybe
    , decimal
    )
    where

    import Scanner.Internal

    import Prelude hiding (take, takeWhile)
    import Data.Word
    import qualified Data.Char as Char
    import Data.ByteString (ByteString)
    import qualified Data.ByteString as ByteString
    import qualified Data.ByteString.Lazy as Lazy (ByteString)
    import qualified Data.ByteString.Lazy as Lazy.ByteString
    import Control.Monad
    import GHC.Base (unsafeChr)

    -- | Scan the complete input, without resupplying
    scanOnly :: Scanner a -> ByteString -> Either String a
    scanOnly :: Scanner a -> ByteString -> Either String a
    scanOnly s :: Scanner a
    s bs :: ByteString
    bs = Result a -> Either String a
    forall b. Result b -> Either String b
    go (Scanner a -> ByteString -> Result a
    forall r. Scanner r -> ByteString -> Result r
    scan Scanner a
    s ByteString
    bs)
      where
      go :: Result b -> Either String b
    go res :: Result b
    res = case Result b
    res of
        Done _ r :: b
    r -> b -> Either String b
    forall a b. b -> Either a b
    Right b
    r
        Fail _ err :: String
    err -> String -> Either String b
    forall a b. a -> Either a b
    Left String
    err
        More more :: ByteString -> Result b
    more -> Result b -> Either String b
    go (ByteString -> Result b
    more ByteString
    ByteString.empty)

    -- | Scan lazy bytestring by resupplying scanner with chunks
    scanLazy :: Scanner a -> Lazy.ByteString -> Either String a
    scanLazy :: Scanner a -> ByteString -> Either String a
    scanLazy s :: Scanner a
    s lbs :: ByteString
    lbs = (ByteString -> Result a) -> [ByteString] -> Either String a
    forall b.
    (ByteString -> Result b) -> [ByteString] -> Either String b
    go (Scanner a -> ByteString -> Result a
    forall r. Scanner r -> ByteString -> Result r
    scan Scanner a
    s) (ByteString -> [ByteString]
    Lazy.ByteString.toChunks ByteString
    lbs)
      where
      go :: (ByteString -> Result b) -> [ByteString] -> Either String b
    go more :: ByteString -> Result b
    more chunks :: [ByteString]
    chunks =
        let (chunk :: ByteString
    chunk, chunks' :: [ByteString]
    chunks') = case [ByteString]
    chunks of
              [] -> (ByteString
    ByteString.empty, [])
              (c:cs) -> (ByteString
    c, [ByteString]
    cs)
        in case ByteString -> Result b
    more ByteString
    chunk of
          Done _ r :: b
    r -> b -> Either String b
    forall a b. b -> Either a b
    Right b
    r
          Fail _ err :: String
    err -> String -> Either String b
    forall a b. a -> Either a b
    Left String
    err
          More more' :: ByteString -> Result b
    more' -> (ByteString -> Result b) -> [ByteString] -> Either String b
    go ByteString -> Result b
    more' [ByteString]
    chunks'

    -- | Scan with the provided resupply action
    scanWith :: Monad m => m ByteString -> Scanner a -> ByteString -> m (Result a)
    scanWith :: m ByteString -> Scanner a -> ByteString -> m (Result a)
    scanWith more :: m ByteString
    more s :: Scanner a
    s input :: ByteString
    input = ByteString -> (ByteString -> Result a) -> m (Result a)
    forall r. ByteString -> (ByteString -> Result r) -> m (Result r)
    go ByteString
    input (Scanner a -> ByteString -> Result a
    forall r. Scanner r -> ByteString -> Result r
    scan Scanner a
    s)
      where
      go :: ByteString -> (ByteString -> Result r) -> m (Result r)
    go bs :: ByteString
    bs next :: ByteString -> Result r
    next = case ByteString -> Result r
    next ByteString
    bs of
        More next' :: ByteString -> Result r
    next' -> do
          ByteString
    bs' <- m ByteString
    more
          ByteString -> (ByteString -> Result r) -> m (Result r)
    go ByteString
    bs' ByteString -> Result r
    next'
        res :: Result r
    res -> Result r -> m (Result r)
    forall (m :: * -> *) a. Monad m => a -> m a
    return Result r
    res

    -- | Consume the next 8-bit char
    --
    -- It fails if end of input
    {-# INLINE anyChar8 #-}
    anyChar8 :: Scanner Char
    anyChar8 :: Scanner Char
    anyChar8 = Word8 -> Char
    w2c (Word8 -> Char) -> Scanner Word8 -> Scanner Char
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Scanner Word8
    anyWord8

    -- | Consume the specified word or fail
    {-# INLINE word8 #-}
    word8 :: Word8 -> Scanner ()
    word8 :: Word8 -> Scanner ()
    word8 w :: Word8
    w = do
      Word8
    w' <- Scanner Word8
    anyWord8
      Bool -> Scanner () -> Scanner ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    unless (Word8
    w' Word8 -> Word8 -> Bool
    forall a. Eq a => a -> a -> Bool
    == Word8
    w) (Scanner () -> Scanner ()) -> Scanner () -> Scanner ()
    forall a b. (a -> b) -> a -> b
    $
        String -> Scanner ()
    forall (m :: * -> *) a. MonadFail m => String -> m a
    fail "unexpected word"

    -- | Consume the specified 8-bit char or fail
    {-# INLINE char8 #-}
    char8 :: Char -> Scanner ()
    char8 :: Char -> Scanner ()
    char8 = Word8 -> Scanner ()
    word8 (Word8 -> Scanner ()) -> (Char -> Word8) -> Char -> Scanner ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> Word8
    c2w

    -- | Take input while the predicate is `True`
    {-# INLINE takeWhileChar8 #-}
    takeWhileChar8 :: (Char -> Bool) -> Scanner ByteString
    takeWhileChar8 :: (Char -> Bool) -> Scanner ByteString
    takeWhileChar8 p :: Char -> Bool
    p = (Word8 -> Bool) -> Scanner ByteString
    takeWhile (Char -> Bool
    p (Char -> Bool) -> (Word8 -> Char) -> Word8 -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Char
    w2c)

    -- | Return the next byte, if any, without consuming it
    {-# INLINE lookAheadChar8 #-}
    lookAheadChar8 :: Scanner (Maybe Char)
    lookAheadChar8 :: Scanner (Maybe Char)
    lookAheadChar8 = (Word8 -> Char) -> Maybe Word8 -> Maybe Char
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Word8 -> Char
    w2c (Maybe Word8 -> Maybe Char)
    -> Scanner (Maybe Word8) -> Scanner (Maybe Char)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Scanner (Maybe Word8)
    lookAhead

    -- | Skip any input while the preducate is `True`
    {-# INLINE skipWhile #-}
    skipWhile :: (Word8 -> Bool) -> Scanner ()
    skipWhile :: (Word8 -> Bool) -> Scanner ()
    skipWhile = Scanner ByteString -> Scanner ()
    forall (f :: * -> *) a. Functor f => f a -> f ()
    void (Scanner ByteString -> Scanner ())
    -> ((Word8 -> Bool) -> Scanner ByteString)
    -> (Word8 -> Bool)
    -> Scanner ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Word8 -> Bool) -> Scanner ByteString
    takeWhile

    -- | Skip space
    {-# INLINE skipSpace #-}
    skipSpace :: Scanner ()
    skipSpace :: Scanner ()
    skipSpace = (Word8 -> Bool) -> Scanner ()
    skipWhile Word8 -> Bool
    isSpaceWord8

    {-# INLINE isSpaceWord8 #-}
    isSpaceWord8 :: Word8 -> Bool
    isSpaceWord8 :: Word8 -> Bool
    isSpaceWord8 w :: Word8
    w = Word8
    w Word8 -> Word8 -> Bool
    forall a. Eq a => a -> a -> Bool
    == 32 Bool -> Bool -> Bool
    || Word8
    w Word8 -> Word8 -> Bool
    forall a. Ord a => a -> a -> Bool
    <= 13

    {-# INLINE w2c #-}
    w2c :: Word8 -> Char
    w2c :: Word8 -> Char
    w2c = Int -> Char
    unsafeChr (Int -> Char) -> (Word8 -> Int) -> Word8 -> Char
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral

    {-# INLINE c2w #-}
    c2w :: Char -> Word8
    c2w :: Char -> Word8
    c2w = Int -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Int -> Word8) -> (Char -> Int) -> Char -> Word8
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Char -> Int
    Char.ord