module Ptr.Parse where

import qualified Data.ByteString.Char8 as B
import qualified Data.ByteString.Short.Internal as E
import qualified Ptr.IO as D
import qualified Ptr.PokeAndPeek as A
import Ptr.Prelude hiding (peek, take)
import qualified Ptr.Prelude as C

newtype Parse output
  = Parse (Int -> Ptr Word8 -> forall result. (Int -> IO result) -> (Text -> IO result) -> (output -> Int -> Ptr Word8 -> IO result) -> IO result)

deriving instance Functor Parse

instance Applicative Parse where
  pure :: forall a. a -> Parse a
pure a
x =
    forall output.
(Int
 -> Ptr Word8
 -> forall result.
    (Int -> IO result)
    -> (Text -> IO result)
    -> (output -> Int -> Ptr Word8 -> IO result)
    -> IO result)
-> Parse output
Parse (\Int
availableAmount Ptr Word8
ptr Int -> IO result
_ Text -> IO result
_ a -> Int -> Ptr Word8 -> IO result
succeed -> a -> Int -> Ptr Word8 -> IO result
succeed a
x Int
availableAmount Ptr Word8
ptr)
  {-# INLINE (<*>) #-}
  <*> :: forall a b. Parse (a -> b) -> Parse a -> Parse b
(<*>) (Parse Int
-> Ptr Word8
-> forall result.
   (Int -> IO result)
   -> (Text -> IO result)
   -> ((a -> b) -> Int -> Ptr Word8 -> IO result)
   -> IO result
left) (Parse Int
-> Ptr Word8
-> forall result.
   (Int -> IO result)
   -> (Text -> IO result)
   -> (a -> Int -> Ptr Word8 -> IO result)
   -> IO result
right) =
    forall output.
(Int
 -> Ptr Word8
 -> forall result.
    (Int -> IO result)
    -> (Text -> IO result)
    -> (output -> Int -> Ptr Word8 -> IO result)
    -> IO result)
-> Parse output
Parse forall a b. (a -> b) -> a -> b
$ \ !Int
availableAmount !Ptr Word8
ptr Int -> IO result
failWithEOI Text -> IO result
failWithMessage b -> Int -> Ptr Word8 -> IO result
succeed ->
      Int
-> Ptr Word8
-> forall result.
   (Int -> IO result)
   -> (Text -> IO result)
   -> ((a -> b) -> Int -> Ptr Word8 -> IO result)
   -> IO result
left Int
availableAmount Ptr Word8
ptr Int -> IO result
failWithEOI Text -> IO result
failWithMessage forall a b. (a -> b) -> a -> b
$ \a -> b
leftOutput !Int
leftAvailableAmount !Ptr Word8
leftPtr ->
        Int
-> Ptr Word8
-> forall result.
   (Int -> IO result)
   -> (Text -> IO result)
   -> (a -> Int -> Ptr Word8 -> IO result)
   -> IO result
right Int
leftAvailableAmount Ptr Word8
leftPtr Int -> IO result
failWithEOI Text -> IO result
failWithMessage forall a b. (a -> b) -> a -> b
$ \a
rightOutput !Int
rightAvailableAmount !Ptr Word8
rightPtr ->
          b -> Int -> Ptr Word8 -> IO result
succeed (a -> b
leftOutput a
rightOutput) Int
rightAvailableAmount Ptr Word8
rightPtr

instance Alternative Parse where
  empty :: forall a. Parse a
empty =
    forall output.
(Int
 -> Ptr Word8
 -> forall result.
    (Int -> IO result)
    -> (Text -> IO result)
    -> (output -> Int -> Ptr Word8 -> IO result)
    -> IO result)
-> Parse output
Parse (\Int
_ Ptr Word8
_ Int -> IO result
failWithEOI Text -> IO result
_ a -> Int -> Ptr Word8 -> IO result
_ -> Int -> IO result
failWithEOI Int
0)
  {-# INLINE (<|>) #-}
  <|> :: forall a. Parse a -> Parse a -> Parse a
(<|>) (Parse Int
-> Ptr Word8
-> forall result.
   (Int -> IO result)
   -> (Text -> IO result)
   -> (a -> Int -> Ptr Word8 -> IO result)
   -> IO result
left) (Parse Int
-> Ptr Word8
-> forall result.
   (Int -> IO result)
   -> (Text -> IO result)
   -> (a -> Int -> Ptr Word8 -> IO result)
   -> IO result
right) =
    forall output.
(Int
 -> Ptr Word8
 -> forall result.
    (Int -> IO result)
    -> (Text -> IO result)
    -> (output -> Int -> Ptr Word8 -> IO result)
    -> IO result)
-> Parse output
Parse forall a b. (a -> b) -> a -> b
$ \ !Int
availableAmount !Ptr Word8
ptr Int -> IO result
failWithEOI Text -> IO result
failWithMessage a -> Int -> Ptr Word8 -> IO result
succeed ->
      Int
-> Ptr Word8
-> forall result.
   (Int -> IO result)
   -> (Text -> IO result)
   -> (a -> Int -> Ptr Word8 -> IO result)
   -> IO result
left
        Int
availableAmount
        Ptr Word8
ptr
        (\Int
_ -> Int
-> Ptr Word8
-> forall result.
   (Int -> IO result)
   -> (Text -> IO result)
   -> (a -> Int -> Ptr Word8 -> IO result)
   -> IO result
right Int
availableAmount Ptr Word8
ptr Int -> IO result
failWithEOI Text -> IO result
failWithMessage a -> Int -> Ptr Word8 -> IO result
succeed)
        Text -> IO result
failWithMessage
        a -> Int -> Ptr Word8 -> IO result
succeed

instance Monad Parse where
  return :: forall a. a -> Parse a
return = forall (f :: * -> *) a. Applicative f => a -> f a
pure
  {-# INLINE (>>=) #-}
  >>= :: forall a b. Parse a -> (a -> Parse b) -> Parse b
(>>=) (Parse Int
-> Ptr Word8
-> forall result.
   (Int -> IO result)
   -> (Text -> IO result)
   -> (a -> Int -> Ptr Word8 -> IO result)
   -> IO result
left) a -> Parse b
rightK =
    forall output.
(Int
 -> Ptr Word8
 -> forall result.
    (Int -> IO result)
    -> (Text -> IO result)
    -> (output -> Int -> Ptr Word8 -> IO result)
    -> IO result)
-> Parse output
Parse forall a b. (a -> b) -> a -> b
$ \ !Int
availableAmount !Ptr Word8
ptr Int -> IO result
failWithEOI Text -> IO result
failWithMessage b -> Int -> Ptr Word8 -> IO result
succeed ->
      Int
-> Ptr Word8
-> forall result.
   (Int -> IO result)
   -> (Text -> IO result)
   -> (a -> Int -> Ptr Word8 -> IO result)
   -> IO result
left Int
availableAmount Ptr Word8
ptr Int -> IO result
failWithEOI Text -> IO result
failWithMessage forall a b. (a -> b) -> a -> b
$ \a
leftOutput !Int
leftAvailableAmount !Ptr Word8
leftPtr ->
        case a -> Parse b
rightK a
leftOutput of
          Parse Int
-> Ptr Word8
-> forall result.
   (Int -> IO result)
   -> (Text -> IO result)
   -> (b -> Int -> Ptr Word8 -> IO result)
   -> IO result
right ->
            Int
-> Ptr Word8
-> forall result.
   (Int -> IO result)
   -> (Text -> IO result)
   -> (b -> Int -> Ptr Word8 -> IO result)
   -> IO result
right Int
leftAvailableAmount Ptr Word8
leftPtr Int -> IO result
failWithEOI Text -> IO result
failWithMessage b -> Int -> Ptr Word8 -> IO result
succeed

instance MonadPlus Parse where
  mzero :: forall a. Parse a
mzero = forall (f :: * -> *) a. Alternative f => f a
empty
  mplus :: forall a. Parse a -> Parse a -> Parse a
mplus = forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
(<|>)

instance MonadIO Parse where
  {-# INLINE liftIO #-}
  liftIO :: forall a. IO a -> Parse a
liftIO IO a
io =
    forall output.
(Int
 -> Ptr Word8
 -> forall result.
    (Int -> IO result)
    -> (Text -> IO result)
    -> (output -> Int -> Ptr Word8 -> IO result)
    -> IO result)
-> Parse output
Parse forall a b. (a -> b) -> a -> b
$ \Int
availableAmount Ptr Word8
ptr Int -> IO result
_ Text -> IO result
_ a -> Int -> Ptr Word8 -> IO result
succeed -> IO a
io forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \a
output -> a -> Int -> Ptr Word8 -> IO result
succeed a
output Int
availableAmount Ptr Word8
ptr

{-# INLINE fail #-}
fail :: Text -> Parse output
fail :: forall output. Text -> Parse output
fail Text
message =
  forall output.
(Int
 -> Ptr Word8
 -> forall result.
    (Int -> IO result)
    -> (Text -> IO result)
    -> (output -> Int -> Ptr Word8 -> IO result)
    -> IO result)
-> Parse output
Parse forall a b. (a -> b) -> a -> b
$ \Int
_ Ptr Word8
_ Int -> IO result
_ Text -> IO result
failWithMessage output -> Int -> Ptr Word8 -> IO result
_ -> Text -> IO result
failWithMessage Text
message

{-# INLINE io #-}
io :: Int -> (Ptr Word8 -> IO output) -> Parse output
io :: forall output. Int -> (Ptr Word8 -> IO output) -> Parse output
io !Int
requiredAmount Ptr Word8 -> IO output
ptrIO =
  {-# SCC "io" #-}
  forall output.
(Int
 -> Ptr Word8
 -> forall result.
    (Int -> IO result)
    -> (Text -> IO result)
    -> (output -> Int -> Ptr Word8 -> IO result)
    -> IO result)
-> Parse output
Parse forall a b. (a -> b) -> a -> b
$ \ !Int
availableAmount !Ptr Word8
ptr Int -> IO result
failWithEOI Text -> IO result
failWithMessage output -> Int -> Ptr Word8 -> IO result
succeed ->
    if Int
availableAmount forall a. Ord a => a -> a -> Bool
>= Int
requiredAmount
      then do
        !output
result <- Ptr Word8 -> IO output
ptrIO Ptr Word8
ptr
        output -> Int -> Ptr Word8 -> IO result
succeed output
result (Int
availableAmount forall a. Num a => a -> a -> a
- Int
requiredAmount) (forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
ptr Int
requiredAmount)
      else Int -> IO result
failWithEOI (Int
requiredAmount forall a. Num a => a -> a -> a
- Int
availableAmount)

{-# INLINE mapInIO #-}
mapInIO :: (output -> IO newOutput) -> Parse output -> Parse newOutput
mapInIO :: forall output newOutput.
(output -> IO newOutput) -> Parse output -> Parse newOutput
mapInIO output -> IO newOutput
io (Parse Int
-> Ptr Word8
-> forall result.
   (Int -> IO result)
   -> (Text -> IO result)
   -> (output -> Int -> Ptr Word8 -> IO result)
   -> IO result
parseIO) =
  forall output.
(Int
 -> Ptr Word8
 -> forall result.
    (Int -> IO result)
    -> (Text -> IO result)
    -> (output -> Int -> Ptr Word8 -> IO result)
    -> IO result)
-> Parse output
Parse forall a b. (a -> b) -> a -> b
$ \ !Int
availableAmount !Ptr Word8
ptr Int -> IO result
failWithEOI Text -> IO result
failWithMessage newOutput -> Int -> Ptr Word8 -> IO result
succeed ->
    Int
-> Ptr Word8
-> forall result.
   (Int -> IO result)
   -> (Text -> IO result)
   -> (output -> Int -> Ptr Word8 -> IO result)
   -> IO result
parseIO
      Int
availableAmount
      Ptr Word8
ptr
      Int -> IO result
failWithEOI
      Text -> IO result
failWithMessage
      (\output
output Int
newAvailableAmount Ptr Word8
newPtr -> output -> IO newOutput
io output
output forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \newOutput
newOutput -> newOutput -> Int -> Ptr Word8 -> IO result
succeed newOutput
newOutput Int
newAvailableAmount Ptr Word8
newPtr)

{-# INLINE pokeAndPeek #-}
pokeAndPeek :: A.PokeAndPeek input output -> Parse output
pokeAndPeek :: forall input output. PokeAndPeek input output -> Parse output
pokeAndPeek (A.PokeAndPeek Int
requiredAmount Ptr Word8 -> input -> IO ()
_ Ptr Word8 -> IO output
ptrIO) =
  forall output.
(Int
 -> Ptr Word8
 -> forall result.
    (Int -> IO result)
    -> (Text -> IO result)
    -> (output -> Int -> Ptr Word8 -> IO result)
    -> IO result)
-> Parse output
Parse forall a b. (a -> b) -> a -> b
$ \ !Int
availableAmount !Ptr Word8
ptr Int -> IO result
failWithEOI Text -> IO result
failWithMessage output -> Int -> Ptr Word8 -> IO result
succeed ->
    if Int
availableAmount forall a. Ord a => a -> a -> Bool
>= Int
requiredAmount
      then do
        !output
result <- Ptr Word8 -> IO output
ptrIO Ptr Word8
ptr
        output -> Int -> Ptr Word8 -> IO result
succeed output
result (Int
availableAmount forall a. Num a => a -> a -> a
- Int
requiredAmount) (forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
ptr Int
requiredAmount)
      else Int -> IO result
failWithEOI (Int
requiredAmount forall a. Num a => a -> a -> a
- Int
availableAmount)

{-# INLINE limiting #-}
limiting :: Int -> Parse output -> Parse output
limiting :: forall output. Int -> Parse output -> Parse output
limiting Int
limitAmount (Parse Int
-> Ptr Word8
-> forall result.
   (Int -> IO result)
   -> (Text -> IO result)
   -> (output -> Int -> Ptr Word8 -> IO result)
   -> IO result
io) =
  forall output.
(Int
 -> Ptr Word8
 -> forall result.
    (Int -> IO result)
    -> (Text -> IO result)
    -> (output -> Int -> Ptr Word8 -> IO result)
    -> IO result)
-> Parse output
Parse forall a b. (a -> b) -> a -> b
$ \ !Int
availableAmount !Ptr Word8
ptr Int -> IO result
failWithEOI Text -> IO result
failWithMessage output -> Int -> Ptr Word8 -> IO result
succeed ->
    if Int
availableAmount forall a. Ord a => a -> a -> Bool
>= Int
limitAmount
      then Int
-> Ptr Word8
-> forall result.
   (Int -> IO result)
   -> (Text -> IO result)
   -> (output -> Int -> Ptr Word8 -> IO result)
   -> IO result
io Int
limitAmount Ptr Word8
ptr Int -> IO result
failWithEOI Text -> IO result
failWithMessage output -> Int -> Ptr Word8 -> IO result
succeed
      else Int -> IO result
failWithEOI (Int
limitAmount forall a. Num a => a -> a -> a
- Int
availableAmount)

-- |
-- Decode the remaining bytes, whithout moving the parser's cursor.
-- Useful for debugging.
{-# INLINE peekRemainders #-}
peekRemainders :: Parse ByteString
peekRemainders :: Parse ByteString
peekRemainders =
  {-# SCC "peekRemainders" #-}
  forall output.
(Int
 -> Ptr Word8
 -> forall result.
    (Int -> IO result)
    -> (Text -> IO result)
    -> (output -> Int -> Ptr Word8 -> IO result)
    -> IO result)
-> Parse output
Parse forall a b. (a -> b) -> a -> b
$ \ !Int
availableAmount !Ptr Word8
ptr Int -> IO result
failWithEOI Text -> IO result
failWithMessage ByteString -> Int -> Ptr Word8 -> IO result
succeed -> do
    !ByteString
bytes <- Ptr Word8 -> Int -> IO ByteString
D.peekBytes Ptr Word8
ptr Int
availableAmount
    ByteString -> Int -> Ptr Word8 -> IO result
succeed ByteString
bytes Int
availableAmount Ptr Word8
ptr

{-# INLINE word8 #-}
word8 :: Parse Word8
word8 :: Parse Word8
word8 =
  {-# SCC "word8" #-}
  forall output. Int -> (Ptr Word8 -> IO output) -> Parse output
io Int
1 Ptr Word8 -> IO Word8
D.peekWord8

{-# INLINE beWord16 #-}
beWord16 :: Parse Word16
beWord16 :: Parse Word16
beWord16 =
  {-# SCC "beWord16" #-}
  forall output. Int -> (Ptr Word8 -> IO output) -> Parse output
io Int
2 Ptr Word8 -> IO Word16
D.peekBEWord16

{-# INLINE beWord32 #-}
beWord32 :: Parse Word32
beWord32 :: Parse Word32
beWord32 =
  {-# SCC "beWord32" #-}
  forall output. Int -> (Ptr Word8 -> IO output) -> Parse output
io Int
4 Ptr Word8 -> IO Word32
D.peekBEWord32

{-# INLINE beWord64 #-}
beWord64 :: Parse Word64
beWord64 :: Parse Word64
beWord64 =
  {-# SCC "beWord64" #-}
  forall output. Int -> (Ptr Word8 -> IO output) -> Parse output
io Int
8 Ptr Word8 -> IO Word64
D.peekBEWord64

{-# INLINE bytes #-}
bytes :: Int -> Parse ByteString
bytes :: Int -> Parse ByteString
bytes Int
amount =
  {-# SCC "bytes" #-}
  forall output. Int -> (Ptr Word8 -> IO output) -> Parse output
io Int
amount (\Ptr Word8
ptr -> Ptr Word8 -> Int -> IO ByteString
D.peekBytes Ptr Word8
ptr Int
amount)

{-# INLINE allBytes #-}
allBytes :: Parse ByteString
allBytes :: Parse ByteString
allBytes =
  {-# SCC "allBytes" #-}
  forall output.
(Int
 -> Ptr Word8
 -> forall result.
    (Int -> IO result)
    -> (Text -> IO result)
    -> (output -> Int -> Ptr Word8 -> IO result)
    -> IO result)
-> Parse output
Parse forall a b. (a -> b) -> a -> b
$ \ !Int
availableAmount !Ptr Word8
ptr Int -> IO result
failWithEOI Text -> IO result
failWithMessage ByteString -> Int -> Ptr Word8 -> IO result
succeed -> do
    !ByteString
bytes <- Ptr Word8 -> Int -> IO ByteString
D.peekBytes Ptr Word8
ptr Int
availableAmount
    ByteString -> Int -> Ptr Word8 -> IO result
succeed ByteString
bytes Int
0 (forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
ptr Int
availableAmount)

{-# INLINE nullTerminatedBytes #-}
nullTerminatedBytes :: Parse ByteString
nullTerminatedBytes :: Parse ByteString
nullTerminatedBytes =
  {-# SCC "nullTerminatedBytes" #-}
  forall output.
(Int
 -> Ptr Word8
 -> forall result.
    (Int -> IO result)
    -> (Text -> IO result)
    -> (output -> Int -> Ptr Word8 -> IO result)
    -> IO result)
-> Parse output
Parse forall a b. (a -> b) -> a -> b
$ \ !Int
availableAmount !Ptr Word8
ptr Int -> IO result
failWithEOI Text -> IO result
failWithMessage ByteString -> Int -> Ptr Word8 -> IO result
succeed -> do
    !ByteString
bytes <- CString -> IO ByteString
B.packCString (forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
ptr)
    case forall a. Enum a => a -> a
succ (ByteString -> Int
B.length ByteString
bytes) of
      Int
consumedAmount ->
        if Int
consumedAmount forall a. Ord a => a -> a -> Bool
<= Int
availableAmount
          then ByteString -> Int -> Ptr Word8 -> IO result
succeed ByteString
bytes (Int
availableAmount forall a. Num a => a -> a -> a
- Int
consumedAmount) (forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
ptr Int
consumedAmount)
          else Int -> IO result
failWithEOI (Int
consumedAmount forall a. Num a => a -> a -> a
- Int
availableAmount)

{-# INLINE nullTerminatedShortByteString #-}
nullTerminatedShortByteString :: Parse ShortByteString
nullTerminatedShortByteString :: Parse ShortByteString
nullTerminatedShortByteString =
  {-# SCC "nullTerminatedShortByteString" #-}
  forall output.
(Int
 -> Ptr Word8
 -> forall result.
    (Int -> IO result)
    -> (Text -> IO result)
    -> (output -> Int -> Ptr Word8 -> IO result)
    -> IO result)
-> Parse output
Parse forall a b. (a -> b) -> a -> b
$ \ !Int
availableAmount !Ptr Word8
ptr Int -> IO result
failWithEOI Text -> IO result
failWithMessage ShortByteString -> Int -> Ptr Word8 -> IO result
succeed ->
    forall a. Ptr Word8 -> (Int -> IO ShortByteString -> IO a) -> IO a
D.peekNullTerminatedShortByteString Ptr Word8
ptr forall a b. (a -> b) -> a -> b
$ \Int
length IO ShortByteString
create ->
      if Int
length forall a. Ord a => a -> a -> Bool
<= Int
availableAmount
        then do
          !ShortByteString
result <- IO ShortByteString
create
          ShortByteString -> Int -> Ptr Word8 -> IO result
succeed ShortByteString
result (Int
availableAmount forall a. Num a => a -> a -> a
- Int
length) (forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
ptr Int
length)
        else Int -> IO result
failWithEOI (Int
length forall a. Num a => a -> a -> a
- Int
availableAmount)

{-# INLINE bytesWhile #-}
bytesWhile :: (Word8 -> Bool) -> Parse ByteString
bytesWhile :: (Word8 -> Bool) -> Parse ByteString
bytesWhile Word8 -> Bool
predicate =
  {-# SCC "bytesWhile" #-}
  forall output.
(Int
 -> Ptr Word8
 -> forall result.
    (Int -> IO result)
    -> (Text -> IO result)
    -> (output -> Int -> Ptr Word8 -> IO result)
    -> IO result)
-> Parse output
Parse forall a b. (a -> b) -> a -> b
$ \ !Int
availableAmount !Ptr Word8
ptr Int -> IO result
failWithEOI Text -> IO result
failWithMessage ByteString -> Int -> Ptr Word8 -> IO result
succeed ->
    let iterate :: Int -> Int -> Ptr Word8 -> IO result
iterate !Int
availableAmount !Int
unconsumedAmount !Ptr Word8
currentPtr =
          if Int
unconsumedAmount forall a. Ord a => a -> a -> Bool
> Int
0
            then do
              Word8
byte <- forall a. Storable a => Ptr a -> IO a
C.peek Ptr Word8
currentPtr
              if Word8 -> Bool
predicate Word8
byte
                then Int -> Int -> Ptr Word8 -> IO result
iterate Int
availableAmount (forall a. Enum a => a -> a
pred Int
unconsumedAmount) (forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
currentPtr Int
1)
                else do
                  ByteString
bytes <- CStringLen -> IO ByteString
B.packCStringLen (forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
ptr, Int
availableAmount forall a. Num a => a -> a -> a
- Int
unconsumedAmount)
                  ByteString -> Int -> Ptr Word8 -> IO result
succeed ByteString
bytes Int
unconsumedAmount Ptr Word8
currentPtr
            else do
              ByteString
bytes <- CStringLen -> IO ByteString
B.packCStringLen (forall a b. Ptr a -> Ptr b
castPtr Ptr Word8
ptr, Int
availableAmount forall a. Num a => a -> a -> a
- Int
unconsumedAmount)
              ByteString -> Int -> Ptr Word8 -> IO result
succeed ByteString
bytes Int
unconsumedAmount Ptr Word8
currentPtr
     in Int -> Int -> Ptr Word8 -> IO result
iterate Int
availableAmount Int
availableAmount Ptr Word8
ptr

{-# INLINE skipWhile #-}
skipWhile :: (Word8 -> Bool) -> Parse ()
skipWhile :: (Word8 -> Bool) -> Parse ()
skipWhile Word8 -> Bool
predicate =
  {-# SCC "skipWhile" #-}
  forall output.
(Int
 -> Ptr Word8
 -> forall result.
    (Int -> IO result)
    -> (Text -> IO result)
    -> (output -> Int -> Ptr Word8 -> IO result)
    -> IO result)
-> Parse output
Parse forall a b. (a -> b) -> a -> b
$ \ !Int
availableAmount !Ptr Word8
ptr Int -> IO result
failWithEOI Text -> IO result
failWithMessage () -> Int -> Ptr Word8 -> IO result
succeed ->
    let iterate :: Int -> Int -> Ptr Word8 -> IO result
iterate !Int
availableAmount !Int
unconsumedAmount !Ptr Word8
ptr =
          if Int
unconsumedAmount forall a. Ord a => a -> a -> Bool
> Int
0
            then do
              Word8
byte <- forall a. Storable a => Ptr a -> IO a
C.peek Ptr Word8
ptr
              if Word8 -> Bool
predicate Word8
byte
                then Int -> Int -> Ptr Word8 -> IO result
iterate Int
availableAmount (forall a. Enum a => a -> a
pred Int
unconsumedAmount) (forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
ptr Int
1)
                else () -> Int -> Ptr Word8 -> IO result
succeed () Int
unconsumedAmount Ptr Word8
ptr
            else () -> Int -> Ptr Word8 -> IO result
succeed () Int
unconsumedAmount Ptr Word8
ptr
     in Int -> Int -> Ptr Word8 -> IO result
iterate Int
availableAmount Int
availableAmount Ptr Word8
ptr

{-# INLINE foldWhile #-}
foldWhile :: (Word8 -> Bool) -> (state -> Word8 -> state) -> state -> Parse state
foldWhile :: forall state.
(Word8 -> Bool)
-> (state -> Word8 -> state) -> state -> Parse state
foldWhile Word8 -> Bool
predicate state -> Word8 -> state
step state
start =
  {-# SCC "foldWhile" #-}
  forall output.
(Int
 -> Ptr Word8
 -> forall result.
    (Int -> IO result)
    -> (Text -> IO result)
    -> (output -> Int -> Ptr Word8 -> IO result)
    -> IO result)
-> Parse output
Parse forall a b. (a -> b) -> a -> b
$ \ !Int
availableAmount !Ptr Word8
ptr Int -> IO result
failWithEOI Text -> IO result
failWithMessage state -> Int -> Ptr Word8 -> IO result
succeed ->
    let iterate :: state -> Int -> Ptr Word8 -> IO result
iterate !state
state !Int
unconsumedAmount !Ptr Word8
ptr =
          if Int
unconsumedAmount forall a. Ord a => a -> a -> Bool
> Int
0
            then do
              Word8
byte <- forall a. Storable a => Ptr a -> IO a
C.peek Ptr Word8
ptr
              if Word8 -> Bool
predicate Word8
byte
                then state -> Int -> Ptr Word8 -> IO result
iterate (state -> Word8 -> state
step state
state Word8
byte) (forall a. Enum a => a -> a
pred Int
unconsumedAmount) (forall a b. Ptr a -> Int -> Ptr b
plusPtr Ptr Word8
ptr Int
1)
                else state -> Int -> Ptr Word8 -> IO result
succeed state
state Int
unconsumedAmount Ptr Word8
ptr
            else Int -> IO result
failWithEOI Int
0
     in state -> Int -> Ptr Word8 -> IO result
iterate state
start Int
availableAmount Ptr Word8
ptr

-- |
-- Unsigned integral number encoded in ASCII.
{-# INLINE unsignedASCIIIntegral #-}
unsignedASCIIIntegral :: Integral a => Parse a
unsignedASCIIIntegral :: forall a. Integral a => Parse a
unsignedASCIIIntegral =
  {-# SCC "unsignedASCIIIntegral" #-}
  forall state.
(Word8 -> Bool)
-> (state -> Word8 -> state) -> state -> Parse state
foldWhile forall {a}. (Ord a, Num a) => a -> Bool
byteIsDigit forall {a} {a}. (Integral a, Num a) => a -> a -> a
step a
0
  where
    byteIsDigit :: a -> Bool
byteIsDigit a
byte =
      a
byte forall a. Num a => a -> a -> a
- a
48 forall a. Ord a => a -> a -> Bool
<= a
9
    step :: a -> a -> a
step !a
state !a
byte =
      a
state forall a. Num a => a -> a -> a
* a
10 forall a. Num a => a -> a -> a
+ forall a b. (Integral a, Num b) => a -> b
fromIntegral a
byte forall a. Num a => a -> a -> a
- a
48