{-# LANGUAGE CPP               #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE Rank2Types        #-}

{- |
Module      : Network.Socks5.Parse
License     : BSD-style
Copyright   : (c) 2010-2019 Vincent Hanquez <vincent@snarc.org>
Stability   : experimental
Portability : portable

A very simple bytestring parser related to Parsec and Attoparsec.

Simple example:

> > parse ((,) <$> take 2 <*> byte 0x20 <*> (bytes "abc" *> anyByte)) "xx abctest"
> ParseOK "est" ("xx", 116)
-}

module Network.Socks5.Parse
  ( Parser
  , Result (..)
    -- * run the Parser

  , parse
  , parseFeed
    -- * Parser methods

  , byte
  , anyByte
  , bytes
  , take
  , takeWhile
  , takeAll
  , skip
  , skipWhile
  , skipAll
  , takeStorable
  ) where

import           Control.Applicative ( Alternative (..) )
import           Control.Monad ( MonadPlus (..) )
import           Data.ByteString ( ByteString )
import qualified Data.ByteString as B
import qualified Data.ByteString.Internal as B ( toForeignPtr )
import           Data.Word ( Word8 )
import           Foreign.ForeignPtr ( withForeignPtr )
import           Foreign.Storable ( Storable, peekByteOff, sizeOf )
import           Prelude hiding ( take, takeWhile )
import           System.IO.Unsafe ( unsafePerformIO )

-- | Simple parsing result, that represent respectively:

--

-- * failure: with the error message

--

-- * continuation: that need for more input data

--

-- * success: the remaining unparsed data and the parser value

data Result a =
    ParseFail String
  | ParseMore (ByteString -> Result a)
  | ParseOK   ByteString a

instance Show a => Show (Result a) where
  show :: Result a -> String
show (ParseFail String
err) = String
"ParseFailure: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
err
  show (ParseMore ByteString -> Result a
_)   = String
"ParseMore _"
  show (ParseOK ByteString
b a
a)   = String
"ParseOK " String -> ShowS
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
a String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" " String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
forall a. Show a => a -> String
show ByteString
b

type Failure r = ByteString -> String -> Result r

type Success a r = ByteString -> a -> Result r

-- | Simple ByteString parser structure.

newtype Parser a = Parser
  { forall a.
Parser a
-> forall r. ByteString -> Failure r -> Success a r -> Result r
runParser :: forall r . ByteString -> Failure r -> Success a r -> Result r
  }

instance Monad Parser where
  Parser a
m >>= :: forall a b. Parser a -> (a -> Parser b) -> Parser b
>>= a -> Parser b
k = (forall r. ByteString -> Failure r -> Success b r -> Result r)
-> Parser b
forall a.
(forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
Parser ((forall r. ByteString -> Failure r -> Success b r -> Result r)
 -> Parser b)
-> (forall r. ByteString -> Failure r -> Success b r -> Result r)
-> Parser b
forall a b. (a -> b) -> a -> b
$ \ByteString
buf Failure r
err Success b r
ok ->
    Parser a
-> forall r. ByteString -> Failure r -> Success a r -> Result r
forall a.
Parser a
-> forall r. ByteString -> Failure r -> Success a r -> Result r
runParser Parser a
m ByteString
buf Failure r
err (\ByteString
buf' a
a -> Parser b
-> forall r. ByteString -> Failure r -> Success b r -> Result r
forall a.
Parser a
-> forall r. ByteString -> Failure r -> Success a r -> Result r
runParser (a -> Parser b
k a
a) ByteString
buf' Failure r
err Success b r
ok)

#if MIN_VERSION_base(4,13,0)
instance MonadFail Parser where
#endif
  fail :: forall a. String -> Parser a
fail String
errorMsg = (forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
forall a.
(forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
Parser ((forall r. ByteString -> Failure r -> Success a r -> Result r)
 -> Parser a)
-> (forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
forall a b. (a -> b) -> a -> b
$ \ByteString
buf Failure r
err Success a r
_ -> Failure r
err ByteString
buf (String
"failed: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
errorMsg)

instance MonadPlus Parser where
  mzero :: forall a. Parser a
mzero = String -> Parser a
forall a. String -> Parser a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Parser.MonadPlus.mzero"
  mplus :: forall a. Parser a -> Parser a -> Parser a
mplus Parser a
f Parser a
g = (forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
forall a.
(forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
Parser ((forall r. ByteString -> Failure r -> Success a r -> Result r)
 -> Parser a)
-> (forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
forall a b. (a -> b) -> a -> b
$ \ByteString
buf Failure r
err Success a r
ok ->
    -- rewrite the err callback of @f to call @g

    Parser a
-> forall r. ByteString -> Failure r -> Success a r -> Result r
forall a.
Parser a
-> forall r. ByteString -> Failure r -> Success a r -> Result r
runParser Parser a
f ByteString
buf (\ByteString
_ String
_ -> Parser a
-> forall r. ByteString -> Failure r -> Success a r -> Result r
forall a.
Parser a
-> forall r. ByteString -> Failure r -> Success a r -> Result r
runParser Parser a
g ByteString
buf Failure r
err Success a r
ok) Success a r
ok

instance Functor Parser where
  fmap :: forall a b. (a -> b) -> Parser a -> Parser b
fmap a -> b
f Parser a
p = (forall r. ByteString -> Failure r -> Success b r -> Result r)
-> Parser b
forall a.
(forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
Parser ((forall r. ByteString -> Failure r -> Success b r -> Result r)
 -> Parser b)
-> (forall r. ByteString -> Failure r -> Success b r -> Result r)
-> Parser b
forall a b. (a -> b) -> a -> b
$ \ByteString
buf Failure r
err Success b r
ok ->
    Parser a
-> forall r. ByteString -> Failure r -> Success a r -> Result r
forall a.
Parser a
-> forall r. ByteString -> Failure r -> Success a r -> Result r
runParser Parser a
p ByteString
buf Failure r
err (\ByteString
b a
a -> Success b r
ok ByteString
b (a -> b
f a
a))

instance Applicative Parser where
  pure :: forall a. a -> Parser a
pure a
v = (forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
forall a.
(forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
Parser ((forall r. ByteString -> Failure r -> Success a r -> Result r)
 -> Parser a)
-> (forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
forall a b. (a -> b) -> a -> b
$ \ByteString
buf Failure r
_ Success a r
ok -> Success a r
ok ByteString
buf a
v
  <*> :: forall a b. Parser (a -> b) -> Parser a -> Parser b
(<*>) Parser (a -> b)
d Parser a
e = Parser (a -> b)
d Parser (a -> b) -> ((a -> b) -> Parser b) -> Parser b
forall a b. Parser a -> (a -> Parser b) -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \a -> b
b -> Parser a
e Parser a -> (a -> Parser b) -> Parser b
forall a b. Parser a -> (a -> Parser b) -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \a
a -> b -> Parser b
forall a. a -> Parser a
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> b
b a
a)

instance Alternative Parser where
  empty :: forall a. Parser a
empty = String -> Parser a
forall a. String -> Parser a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Parser.Alternative.empty"
  <|> :: forall a. Parser a -> Parser a -> Parser a
(<|>) = Parser a -> Parser a -> Parser a
forall a. Parser a -> Parser a -> Parser a
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
mplus

-- | Run a parser on an @initial ByteString.

--

-- If the Parser needs more data than available, the @feeder function is

-- automatically called and fed to the More continuation.

parseFeed ::
     Monad m
  => m B.ByteString
  -> Parser a
  -> B.ByteString
  -> m (Result a)
parseFeed :: forall (m :: * -> *) a.
Monad m =>
m ByteString -> Parser a -> ByteString -> m (Result a)
parseFeed m ByteString
feeder Parser a
p ByteString
initial = Result a -> m (Result a)
forall {a}. Result a -> m (Result a)
loop (Result a -> m (Result a)) -> Result a -> m (Result a)
forall a b. (a -> b) -> a -> b
$ Parser a -> ByteString -> Result a
forall a. Parser a -> ByteString -> Result a
parse Parser a
p ByteString
initial
 where
  loop :: Result a -> m (Result a)
loop (ParseMore ByteString -> Result a
k) = m ByteString
feeder m ByteString -> (ByteString -> m (Result a)) -> m (Result a)
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Result a -> m (Result a)
loop (Result a -> m (Result a))
-> (ByteString -> Result a) -> ByteString -> m (Result a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Result a
k)
  loop Result a
r             = Result a -> m (Result a)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Result a
r

-- | Run a Parser on a ByteString and return a 'Result'.

parse :: Parser a -> ByteString -> Result a
parse :: forall a. Parser a -> ByteString -> Result a
parse Parser a
p ByteString
s = Parser a
-> forall r. ByteString -> Failure r -> Success a r -> Result r
forall a.
Parser a
-> forall r. ByteString -> Failure r -> Success a r -> Result r
runParser Parser a
p ByteString
s (\ByteString
_ String
msg -> String -> Result a
forall a. String -> Result a
ParseFail String
msg) Success a a
forall a. ByteString -> a -> Result a
ParseOK

--------------------------------------------------------------------------------


getMore :: Parser ()
getMore :: Parser ()
getMore = (forall r. ByteString -> Failure r -> Success () r -> Result r)
-> Parser ()
forall a.
(forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
Parser ((forall r. ByteString -> Failure r -> Success () r -> Result r)
 -> Parser ())
-> (forall r. ByteString -> Failure r -> Success () r -> Result r)
-> Parser ()
forall a b. (a -> b) -> a -> b
$ \ByteString
buf Failure r
err Success () r
ok -> (ByteString -> Result r) -> Result r
forall a. (ByteString -> Result a) -> Result a
ParseMore ((ByteString -> Result r) -> Result r)
-> (ByteString -> Result r) -> Result r
forall a b. (a -> b) -> a -> b
$ \ByteString
nextChunk ->
  if ByteString -> Bool
B.null ByteString
nextChunk
    then Failure r
err ByteString
buf String
"EOL: need more data"
    else Success () r
ok (ByteString -> ByteString -> ByteString
B.append ByteString
buf ByteString
nextChunk) ()

getAll :: Parser ()
getAll :: Parser ()
getAll = (forall r. ByteString -> Failure r -> Success () r -> Result r)
-> Parser ()
forall a.
(forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
Parser ((forall r. ByteString -> Failure r -> Success () r -> Result r)
 -> Parser ())
-> (forall r. ByteString -> Failure r -> Success () r -> Result r)
-> Parser ()
forall a b. (a -> b) -> a -> b
$ \ByteString
buf Failure r
err Success () r
ok -> (ByteString -> Result r) -> Result r
forall a. (ByteString -> Result a) -> Result a
ParseMore ((ByteString -> Result r) -> Result r)
-> (ByteString -> Result r) -> Result r
forall a b. (a -> b) -> a -> b
$ \ByteString
nextChunk ->
  if ByteString -> Bool
B.null ByteString
nextChunk
    then Success () r
ok ByteString
buf ()
    else Parser ()
-> forall r. ByteString -> Failure r -> Success () r -> Result r
forall a.
Parser a
-> forall r. ByteString -> Failure r -> Success a r -> Result r
runParser Parser ()
getAll (ByteString -> ByteString -> ByteString
B.append ByteString
buf ByteString
nextChunk) Failure r
err Success () r
ok

flushAll :: Parser ()
flushAll :: Parser ()
flushAll = (forall r. ByteString -> Failure r -> Success () r -> Result r)
-> Parser ()
forall a.
(forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
Parser ((forall r. ByteString -> Failure r -> Success () r -> Result r)
 -> Parser ())
-> (forall r. ByteString -> Failure r -> Success () r -> Result r)
-> Parser ()
forall a b. (a -> b) -> a -> b
$ \ByteString
buf Failure r
err Success () r
ok -> (ByteString -> Result r) -> Result r
forall a. (ByteString -> Result a) -> Result a
ParseMore ((ByteString -> Result r) -> Result r)
-> (ByteString -> Result r) -> Result r
forall a b. (a -> b) -> a -> b
$ \ByteString
nextChunk ->
  if ByteString -> Bool
B.null ByteString
nextChunk
    then Success () r
ok ByteString
buf ()
    else Parser ()
-> forall r. ByteString -> Failure r -> Success () r -> Result r
forall a.
Parser a
-> forall r. ByteString -> Failure r -> Success a r -> Result r
runParser Parser ()
getAll ByteString
B.empty Failure r
err Success () r
ok

--------------------------------------------------------------------------------


-- | Get the next byte from the parser.

anyByte :: Parser Word8
anyByte :: Parser Word8
anyByte = (forall r. ByteString -> Failure r -> Success Word8 r -> Result r)
-> Parser Word8
forall a.
(forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
Parser ((forall r. ByteString -> Failure r -> Success Word8 r -> Result r)
 -> Parser Word8)
-> (forall r.
    ByteString -> Failure r -> Success Word8 r -> Result r)
-> Parser Word8
forall a b. (a -> b) -> a -> b
$ \ByteString
buf Failure r
err Success Word8 r
ok ->
  case ByteString -> Maybe (Word8, ByteString)
B.uncons ByteString
buf of
    Maybe (Word8, ByteString)
Nothing -> Parser Word8
-> forall r. ByteString -> Failure r -> Success Word8 r -> Result r
forall a.
Parser a
-> forall r. ByteString -> Failure r -> Success a r -> Result r
runParser (Parser ()
getMore Parser () -> Parser Word8 -> Parser Word8
forall a b. Parser a -> Parser b -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser Word8
anyByte) ByteString
buf Failure r
err Success Word8 r
ok
    Just (Word8
c1,ByteString
b2) -> Success Word8 r
ok ByteString
b2 Word8
c1

-- | Parse a specific byte at current position.

--

-- If the byte is different than the expected one, this parser will raise a

-- failure.

byte :: Word8 -> Parser ()
byte :: Word8 -> Parser ()
byte Word8
w = (forall r. ByteString -> Failure r -> Success () r -> Result r)
-> Parser ()
forall a.
(forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
Parser ((forall r. ByteString -> Failure r -> Success () r -> Result r)
 -> Parser ())
-> (forall r. ByteString -> Failure r -> Success () r -> Result r)
-> Parser ()
forall a b. (a -> b) -> a -> b
$ \ByteString
buf Failure r
err Success () r
ok ->
  case ByteString -> Maybe (Word8, ByteString)
B.uncons ByteString
buf of
    Maybe (Word8, ByteString)
Nothing -> Parser ()
-> forall r. ByteString -> Failure r -> Success () r -> Result r
forall a.
Parser a
-> forall r. ByteString -> Failure r -> Success a r -> Result r
runParser (Parser ()
getMore Parser () -> Parser () -> Parser ()
forall a b. Parser a -> Parser b -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Word8 -> Parser ()
byte Word8
w) ByteString
buf Failure r
err Success () r
ok
    Just (Word8
c1,ByteString
b2)
      | Word8
c1 Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
w -> Success () r
ok ByteString
b2 ()
      | Bool
otherwise -> Failure r
err ByteString
buf (String
"byte " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Word8 -> String
forall a. Show a => a -> String
show Word8
w String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" : failed")

-- | Parse a sequence of bytes from current position.

--

-- If the following bytes don't match the expected bytestring completely, the

-- parser will raise a failure.

bytes :: ByteString -> Parser ()
bytes :: ByteString -> Parser ()
bytes ByteString
allExpected = ByteString -> Parser ()
consumeEq ByteString
allExpected
 where
  errMsg :: String
errMsg = String
"bytes " String -> ShowS
forall a. [a] -> [a] -> [a]
++ ByteString -> String
forall a. Show a => a -> String
show ByteString
allExpected String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" : failed"

  -- Partially consume as much as possible or raise an error.

  consumeEq :: ByteString -> Parser ()
consumeEq ByteString
expected = (forall r. ByteString -> Failure r -> Success () r -> Result r)
-> Parser ()
forall a.
(forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
Parser ((forall r. ByteString -> Failure r -> Success () r -> Result r)
 -> Parser ())
-> (forall r. ByteString -> Failure r -> Success () r -> Result r)
-> Parser ()
forall a b. (a -> b) -> a -> b
$ \ByteString
actual Failure r
err Success () r
ok ->
    let eLen :: Int
eLen = ByteString -> Int
B.length ByteString
expected
    in  if ByteString -> Int
B.length ByteString
actual Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
eLen
          then -- enough data for doing a full match

            let (ByteString
aMatch,ByteString
aRem) = Int -> ByteString -> (ByteString, ByteString)
B.splitAt Int
eLen ByteString
actual
            in  if ByteString
aMatch ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
expected
                  then Success () r
ok ByteString
aRem ()
                  else Failure r
err ByteString
actual String
errMsg
          else -- not enough data, match as much as we have, and then recurse.

            let (ByteString
eMatch, ByteString
eRem) = Int -> ByteString -> (ByteString, ByteString)
B.splitAt (ByteString -> Int
B.length ByteString
actual) ByteString
expected
            in  if ByteString
actual ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
eMatch
                  then Parser ()
-> forall r. ByteString -> Failure r -> Success () r -> Result r
forall a.
Parser a
-> forall r. ByteString -> Failure r -> Success a r -> Result r
runParser (Parser ()
getMore Parser () -> Parser () -> Parser ()
forall a b. Parser a -> Parser b -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ByteString -> Parser ()
consumeEq ByteString
eRem) ByteString
B.empty Failure r
err Success () r
ok
                  else Failure r
err ByteString
actual String
errMsg

--------------------------------------------------------------------------------


-- | Take a storable from the current position in the stream.

takeStorable :: Storable d => Parser d
takeStorable :: forall d. Storable d => Parser d
takeStorable = d -> Parser d
forall d. Storable d => d -> Parser d
anyStorable d
forall a. HasCallStack => a
undefined
 where
  anyStorable :: Storable d => d -> Parser d
  anyStorable :: forall d. Storable d => d -> Parser d
anyStorable d
a = do
    (fptr, off, _) <- ByteString -> (ForeignPtr Word8, Int, Int)
B.toForeignPtr (ByteString -> (ForeignPtr Word8, Int, Int))
-> Parser ByteString -> Parser (ForeignPtr Word8, Int, Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Parser ByteString
take (d -> Int
forall a. Storable a => a -> Int
sizeOf d
a)
    return $ unsafePerformIO $ withForeignPtr fptr $ \Ptr Word8
ptr -> Ptr Word8 -> Int -> IO d
forall b. Ptr b -> Int -> IO d
forall a b. Storable a => Ptr b -> Int -> IO a
peekByteOff Ptr Word8
ptr Int
off

-- | Take @n@ bytes from the current position in the stream.

take :: Int -> Parser ByteString
take :: Int -> Parser ByteString
take Int
n = (forall r.
 ByteString -> Failure r -> Success ByteString r -> Result r)
-> Parser ByteString
forall a.
(forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
Parser ((forall r.
  ByteString -> Failure r -> Success ByteString r -> Result r)
 -> Parser ByteString)
-> (forall r.
    ByteString -> Failure r -> Success ByteString r -> Result r)
-> Parser ByteString
forall a b. (a -> b) -> a -> b
$ \ByteString
buf Failure r
err Success ByteString r
ok ->
  if ByteString -> Int
B.length ByteString
buf Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
n
    then
      let (ByteString
b1,ByteString
b2) = Int -> ByteString -> (ByteString, ByteString)
B.splitAt Int
n ByteString
buf
      in  Success ByteString r
ok ByteString
b2 ByteString
b1
    else Parser ByteString
-> forall r.
   ByteString -> Failure r -> Success ByteString r -> Result r
forall a.
Parser a
-> forall r. ByteString -> Failure r -> Success a r -> Result r
runParser (Parser ()
getMore Parser () -> Parser ByteString -> Parser ByteString
forall a b. Parser a -> Parser b -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Int -> Parser ByteString
take Int
n) ByteString
buf Failure r
err Success ByteString r
ok

-- | Take bytes while the @predicate hold from the current position in the

-- stream.

takeWhile :: (Word8 -> Bool) -> Parser ByteString
takeWhile :: (Word8 -> Bool) -> Parser ByteString
takeWhile Word8 -> Bool
predicate = (forall r.
 ByteString -> Failure r -> Success ByteString r -> Result r)
-> Parser ByteString
forall a.
(forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
Parser ((forall r.
  ByteString -> Failure r -> Success ByteString r -> Result r)
 -> Parser ByteString)
-> (forall r.
    ByteString -> Failure r -> Success ByteString r -> Result r)
-> Parser ByteString
forall a b. (a -> b) -> a -> b
$ \ByteString
buf Failure r
err Success ByteString r
ok ->
  case (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
B.span Word8 -> Bool
predicate ByteString
buf of
    (ByteString
_, ByteString
b2) | ByteString -> Bool
B.null ByteString
b2 -> Parser ByteString
-> forall r.
   ByteString -> Failure r -> Success ByteString r -> Result r
forall a.
Parser a
-> forall r. ByteString -> Failure r -> Success a r -> Result r
runParser (Parser ()
getMore Parser () -> Parser ByteString -> Parser ByteString
forall a b. Parser a -> Parser b -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (Word8 -> Bool) -> Parser ByteString
takeWhile Word8 -> Bool
predicate) ByteString
buf Failure r
err Success ByteString r
ok
    (ByteString
b1, ByteString
b2) -> Success ByteString r
ok ByteString
b2 ByteString
b1

-- | Take the remaining bytes from the current position in the stream.

takeAll :: Parser ByteString
takeAll :: Parser ByteString
takeAll = (forall r.
 ByteString -> Failure r -> Success ByteString r -> Result r)
-> Parser ByteString
forall a.
(forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
Parser ((forall r.
  ByteString -> Failure r -> Success ByteString r -> Result r)
 -> Parser ByteString)
-> (forall r.
    ByteString -> Failure r -> Success ByteString r -> Result r)
-> Parser ByteString
forall a b. (a -> b) -> a -> b
$ \ByteString
buf Failure r
err Success ByteString r
ok ->
  Parser ByteString
-> forall r.
   ByteString -> Failure r -> Success ByteString r -> Result r
forall a.
Parser a
-> forall r. ByteString -> Failure r -> Success a r -> Result r
runParser (Parser ()
getAll Parser () -> Parser ByteString -> Parser ByteString
forall a b. Parser a -> Parser b -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser ByteString
returnBuffer) ByteString
buf Failure r
err Success ByteString r
ok
 where
  returnBuffer :: Parser ByteString
returnBuffer = (forall r.
 ByteString -> Failure r -> Success ByteString r -> Result r)
-> Parser ByteString
forall a.
(forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
Parser ((forall r.
  ByteString -> Failure r -> Success ByteString r -> Result r)
 -> Parser ByteString)
-> (forall r.
    ByteString -> Failure r -> Success ByteString r -> Result r)
-> Parser ByteString
forall a b. (a -> b) -> a -> b
$ \ByteString
buf Failure r
_ Success ByteString r
ok -> Success ByteString r
ok ByteString
B.empty ByteString
buf

-- | Skip @n@ bytes from the current position in the stream.

skip :: Int -> Parser ()
skip :: Int -> Parser ()
skip Int
n = (forall r. ByteString -> Failure r -> Success () r -> Result r)
-> Parser ()
forall a.
(forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
Parser ((forall r. ByteString -> Failure r -> Success () r -> Result r)
 -> Parser ())
-> (forall r. ByteString -> Failure r -> Success () r -> Result r)
-> Parser ()
forall a b. (a -> b) -> a -> b
$ \ByteString
buf Failure r
err Success () r
ok ->
  if ByteString -> Int
B.length ByteString
buf Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
n
    then Success () r
ok (Int -> ByteString -> ByteString
B.drop Int
n ByteString
buf) ()
    else Parser ()
-> forall r. ByteString -> Failure r -> Success () r -> Result r
forall a.
Parser a
-> forall r. ByteString -> Failure r -> Success a r -> Result r
runParser (Parser ()
getMore Parser () -> Parser () -> Parser ()
forall a b. Parser a -> Parser b -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Int -> Parser ()
skip (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- ByteString -> Int
B.length ByteString
buf)) ByteString
B.empty Failure r
err Success () r
ok

-- | Skip bytes while the @predicate@ holds from the current position in the

-- stream.

skipWhile :: (Word8 -> Bool) -> Parser ()
skipWhile :: (Word8 -> Bool) -> Parser ()
skipWhile Word8 -> Bool
p = (forall r. ByteString -> Failure r -> Success () r -> Result r)
-> Parser ()
forall a.
(forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
Parser ((forall r. ByteString -> Failure r -> Success () r -> Result r)
 -> Parser ())
-> (forall r. ByteString -> Failure r -> Success () r -> Result r)
-> Parser ()
forall a b. (a -> b) -> a -> b
$ \ByteString
buf Failure r
err Success () r
ok ->
  case (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
B.span Word8 -> Bool
p ByteString
buf of
    (ByteString
_, ByteString
b2) | ByteString -> Bool
B.null ByteString
b2 -> Parser ()
-> forall r. ByteString -> Failure r -> Success () r -> Result r
forall a.
Parser a
-> forall r. ByteString -> Failure r -> Success a r -> Result r
runParser (Parser ()
getMore Parser () -> Parser () -> Parser ()
forall a b. Parser a -> Parser b -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (Word8 -> Bool) -> Parser ()
skipWhile Word8 -> Bool
p) ByteString
B.empty Failure r
err Success () r
ok
    (ByteString
_, ByteString
b2) -> Success () r
ok ByteString
b2 ()

-- | Skip all the remaining bytes from the current position in the stream.

skipAll :: Parser ()
skipAll :: Parser ()
skipAll = (forall r. ByteString -> Failure r -> Success () r -> Result r)
-> Parser ()
forall a.
(forall r. ByteString -> Failure r -> Success a r -> Result r)
-> Parser a
Parser ((forall r. ByteString -> Failure r -> Success () r -> Result r)
 -> Parser ())
-> (forall r. ByteString -> Failure r -> Success () r -> Result r)
-> Parser ()
forall a b. (a -> b) -> a -> b
$ \ByteString
buf Failure r
err Success () r
ok -> Parser ()
-> forall r. ByteString -> Failure r -> Success () r -> Result r
forall a.
Parser a
-> forall r. ByteString -> Failure r -> Success a r -> Result r
runParser Parser ()
flushAll ByteString
buf Failure r
err Success () r
ok