{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}

module Df1.Parse
 ( log
 ) where

import Control.Applicative ((<|>), many, empty)
import Data.Bits (shiftL)
import qualified Data.Sequence as Seq
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as BL
import Data.Function (fix)
import Data.Functor (($>))
import qualified Data.Attoparsec.ByteString as AB
import qualified Data.Attoparsec.ByteString.Lazy as ABL
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Encoding as TL
import qualified Data.Time as Time
import qualified Data.Time.Clock.System as Time
import Data.Word (Word8, Word16, Word32)
import Prelude hiding (log)

import Df1.Render () -- To make sure module instances are available here too.

import Df1.Types
 (Log(Log, log_time, log_level, log_path, log_message),
  Level(Debug, Info, Notice, Warning, Error, Critical, Alert, Emergency),
  Path(Attr, Push),
  Segment, segment,
  Key, key,
  Value, value,
  Message, message)

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

-- | If sucessful, parsing will stop after the first CR or LF newline marker if
-- any, otherwise it will consume all input.
log :: AB.Parser Log
{-# INLINABLE log #-}
log :: Parser Log
log = (forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"log") forall a b. (a -> b) -> a -> b
$ do
  UTCTime
t <- (Word8 -> Bool) -> Parser ()
AB.skipWhile (forall a. Eq a => a -> a -> Bool
== Word8
32) forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser ByteString UTCTime
pIso8601 -- :space:
  Seq Path
p <- (Word8 -> Bool) -> Parser ()
AB.skipWhile (forall a. Eq a => a -> a -> Bool
== Word8
32) forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser ByteString (Seq Path)
pPath
  Level
l <- (Word8 -> Bool) -> Parser ()
AB.skipWhile (forall a. Eq a => a -> a -> Bool
== Word8
32) forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser ByteString Level
pLevel
  Message
m <- (Word8 -> Bool) -> Parser ()
AB.skip (forall a. Eq a => a -> a -> Bool
== Word8
32) forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser ByteString Message
pMessage
  forall (f :: * -> *) a. Applicative f => a -> f a
pure (Log { log_time :: SystemTime
log_time = UTCTime -> SystemTime
Time.utcToSystemTime UTCTime
t
            , log_level :: Level
log_level = Level
l, log_path :: Seq Path
log_path = Seq Path
p, log_message :: Message
log_message = Message
m })

pIso8601 :: AB.Parser Time.UTCTime
{-# INLINABLE pIso8601 #-}
pIso8601 :: Parser ByteString UTCTime
pIso8601 = (forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"pIso8601") forall a b. (a -> b) -> a -> b
$ do
  Word16
year <- (Parser ByteString Word16
pNum4Digits forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"year") forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ((Word8 -> Bool) -> Parser ()
AB.skip (forall a. Eq a => a -> a -> Bool
== Word8
45) forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"-")
  Word8
month <- (Parser ByteString Word8
pNum2Digits forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"month") forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ((Word8 -> Bool) -> Parser ()
AB.skip (forall a. Eq a => a -> a -> Bool
== Word8
45) forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"-")
  Word8
day <- (Parser ByteString Word8
pNum2Digits forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"day") forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ((Word8 -> Bool) -> Parser ()
AB.skip (forall a. Eq a => a -> a -> Bool
== Word8
84) forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"T")
  Just Day
tday <- forall (f :: * -> *) a. Applicative f => a -> f a
pure (Year -> MonthOfYear -> MonthOfYear -> Maybe Day
Time.fromGregorianValid
     (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
year) (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
month) (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
day))
  Word8
hour <- (Parser ByteString Word8
pNum2Digits forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"hour") forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ((Word8 -> Bool) -> Parser ()
AB.skip (forall a. Eq a => a -> a -> Bool
== Word8
58) forall i a. Parser i a -> String -> Parser i a
AB.<?> String
":")
  Word8
min' <- (Parser ByteString Word8
pNum2Digits forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"minute") forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ((Word8 -> Bool) -> Parser ()
AB.skip (forall a. Eq a => a -> a -> Bool
== Word8
58) forall i a. Parser i a -> String -> Parser i a
AB.<?> String
":")
  Word8
sec <- (Parser ByteString Word8
pNum2Digits forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"second") forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ((Word8 -> Bool) -> Parser ()
AB.skip (forall a. Eq a => a -> a -> Bool
== Word8
46) forall i a. Parser i a -> String -> Parser i a
AB.<?> String
".")
  Word32
nsec <- (Parser ByteString Word32
pNum9Digits forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"nanosecond") forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ((Word8 -> Bool) -> Parser ()
AB.skip (forall a. Eq a => a -> a -> Bool
== Word8
90) forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"Z")
  Just TimeOfDay
ttod <- forall (f :: * -> *) a. Applicative f => a -> f a
pure (MonthOfYear -> MonthOfYear -> Pico -> Maybe TimeOfDay
Time.makeTimeOfDayValid
     (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
hour) (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
min')
     (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
sec forall a. Num a => a -> a -> a
+ (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
nsec forall a. Fractional a => a -> a -> a
/ Pico
1000000000)))
  forall (f :: * -> *) a. Applicative f => a -> f a
pure (Day -> DiffTime -> UTCTime
Time.UTCTime Day
tday (TimeOfDay -> DiffTime
Time.timeOfDayToTime TimeOfDay
ttod))

pNum1Digit :: AB.Parser Word8
{-# INLINE pNum1Digit #-}
pNum1Digit :: Parser ByteString Word8
pNum1Digit = forall a. (Word8 -> a) -> (a -> Bool) -> Parser a
AB.satisfyWith (forall a. Num a => a -> a -> a
subtract Word8
48) (forall a. Ord a => a -> a -> Bool
< Word8
10) forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"pNum1Digit"

pNum2Digits :: AB.Parser Word8
{-# INLINE pNum2Digits #-}
pNum2Digits :: Parser ByteString Word8
pNum2Digits = (forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"pNum2Digits") forall a b. (a -> b) -> a -> b
$ do
  forall a. Num a => a -> a -> a
(+) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a. Num a => a -> a -> a
* Word8
10) Parser ByteString Word8
pNum1Digit forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser ByteString Word8
pNum1Digit

pNum4Digits :: AB.Parser Word16
{-# INLINE pNum4Digits #-}
pNum4Digits :: Parser ByteString Word16
pNum4Digits = (forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"pNum4Digits") forall a b. (a -> b) -> a -> b
$ do
  (\Word16
a Word16
b Word16
c Word16
d -> Word16
a forall a. Num a => a -> a -> a
+ Word16
b forall a. Num a => a -> a -> a
+ Word16
c forall a. Num a => a -> a -> a
+ Word16
d)
     forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((forall a. Num a => a -> a -> a
* Word16
1000) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) Parser ByteString Word8
pNum1Digit
     forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((forall a. Num a => a -> a -> a
* Word16
100) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) Parser ByteString Word8
pNum1Digit
     forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((forall a. Num a => a -> a -> a
* Word16
10) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) Parser ByteString Word8
pNum1Digit
          forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (Integral a, Num b) => a -> b
fromIntegral Parser ByteString Word8
pNum1Digit

pNum9Digits :: AB.Parser Word32
{-# INLINE pNum9Digits #-}
pNum9Digits :: Parser ByteString Word32
pNum9Digits = (forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"pNum9Digits") forall a b. (a -> b) -> a -> b
$ do
  (\Word32
a Word32
b Word32
c Word32
d Word32
e Word32
f Word32
g Word32
h Word32
i -> Word32
a forall a. Num a => a -> a -> a
+ Word32
b forall a. Num a => a -> a -> a
+ Word32
c forall a. Num a => a -> a -> a
+ Word32
d forall a. Num a => a -> a -> a
+ Word32
e forall a. Num a => a -> a -> a
+ Word32
f forall a. Num a => a -> a -> a
+ Word32
g forall a. Num a => a -> a -> a
+ Word32
h forall a. Num a => a -> a -> a
+ Word32
i)
     forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((forall a. Num a => a -> a -> a
* Word32
100000000) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) Parser ByteString Word8
pNum1Digit
     forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((forall a. Num a => a -> a -> a
* Word32
10000000) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) Parser ByteString Word8
pNum1Digit
     forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((forall a. Num a => a -> a -> a
* Word32
1000000) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) Parser ByteString Word8
pNum1Digit
     forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((forall a. Num a => a -> a -> a
* Word32
100000) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) Parser ByteString Word8
pNum1Digit
     forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((forall a. Num a => a -> a -> a
* Word32
10000) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) Parser ByteString Word8
pNum1Digit
     forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((forall a. Num a => a -> a -> a
* Word32
1000) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) Parser ByteString Word8
pNum1Digit
     forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((forall a. Num a => a -> a -> a
* Word32
100) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) Parser ByteString Word8
pNum1Digit
     forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((forall a. Num a => a -> a -> a
* Word32
10) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Integral a, Num b) => a -> b
fromIntegral) Parser ByteString Word8
pNum1Digit
     forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (Integral a, Num b) => a -> b
fromIntegral Parser ByteString Word8
pNum1Digit

pLevel :: AB.Parser Level
{-# INLINE pLevel #-}
pLevel :: Parser ByteString Level
pLevel = (forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"pLevel")
  -- In decreasing frequency we expect logs to happen.
  -- We expect 'Debug' to mostly be muted, so 'Info' is prefered.
  (ByteString -> Parser ByteString
AB.string ByteString
"INFO"      forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Level
Info)     forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
  (ByteString -> Parser ByteString
AB.string ByteString
"DEBUG"     forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Level
Debug)    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
  (ByteString -> Parser ByteString
AB.string ByteString
"NOTICE"    forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Level
Notice)   forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
  (ByteString -> Parser ByteString
AB.string ByteString
"WARNING"   forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Level
Warning)  forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
  (ByteString -> Parser ByteString
AB.string ByteString
"ERROR"     forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Level
Error)    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
  (ByteString -> Parser ByteString
AB.string ByteString
"CRITICAL"  forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Level
Critical) forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
  (ByteString -> Parser ByteString
AB.string ByteString
"ALERT"     forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Level
Alert)    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
  (ByteString -> Parser ByteString
AB.string ByteString
"EMERGENCY" forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Level
Emergency)

pPath :: AB.Parser (Seq.Seq Path)
{-# INLINABLE pPath #-}
pPath :: Parser ByteString (Seq Path)
pPath = (forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"pPath") forall a b. (a -> b) -> a -> b
$ do
    forall a. (a -> a) -> a
fix (\Seq Path -> Parser ByteString (Seq Path)
k Seq Path
ps -> ((Parser ByteString Path
pPush forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser ByteString Path
pAttr) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Path
p -> Seq Path -> Parser ByteString (Seq Path)
k (Seq Path
ps forall a. Seq a -> a -> Seq a
Seq.|> Path
p)) forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall (f :: * -> *) a. Applicative f => a -> f a
pure Seq Path
ps)
        forall a. Monoid a => a
mempty
  where
    {-# INLINE pPush #-}
    pPush :: AB.Parser Path
    pPush :: Parser ByteString Path
pPush = (forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"pPush") forall a b. (a -> b) -> a -> b
$ do
      Segment
seg <- Parser ByteString Segment
pSegment forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* (Word8 -> Bool) -> Parser ()
AB.skipWhile (forall a. Eq a => a -> a -> Bool
== Word8
32)
      forall (f :: * -> *) a. Applicative f => a -> f a
pure (Segment -> Path
Push Segment
seg)
    {-# INLINE pAttr #-}
    pAttr :: AB.Parser Path
    pAttr :: Parser ByteString Path
pAttr = do
      Key
k <- Parser ByteString Key
pKey forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* (Word8 -> Bool) -> Parser ()
AB.skip (forall a. Eq a => a -> a -> Bool
== Word8
61)
      Value
v <- Parser ByteString Value
pValue forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* (Word8 -> Bool) -> Parser ()
AB.skipWhile (forall a. Eq a => a -> a -> Bool
== Word8
32)
      forall (f :: * -> *) a. Applicative f => a -> f a
pure (Key -> Value -> Path
Attr Key
k Value
v)

pSegment :: AB.Parser Segment
pSegment :: Parser ByteString Segment
pSegment = (forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"pSegment") forall a b. (a -> b) -> a -> b
$ do
  (Word8 -> Bool) -> Parser ()
AB.skip (forall a. Eq a => a -> a -> Bool
== Word8
47) forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"/"
  Text
bl <- ByteString -> Parser ByteString Text
pUtf8LtoL forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< ByteString -> Parser ByteString ByteString
pDecodePercents forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (Word8 -> Bool) -> Parser ByteString
AB.takeWhile (forall a. Eq a => a -> a -> Bool
/= Word8
32) -- :space:
  forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a. ToSegment a => a -> Segment
segment Text
bl)

pKey :: AB.Parser Key
pKey :: Parser ByteString Key
pKey = (forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"pKey") forall a b. (a -> b) -> a -> b
$ do
  Text
bl <- ByteString -> Parser ByteString Text
pUtf8LtoL forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< ByteString -> Parser ByteString ByteString
pDecodePercents
          forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (Word8 -> Bool) -> Parser ByteString
AB.takeWhile (\Word8
w -> Word8
w forall a. Eq a => a -> a -> Bool
/= Word8
61 Bool -> Bool -> Bool
&& Word8
w forall a. Eq a => a -> a -> Bool
/= Word8
32) -- '=' or :space:
  forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a. ToKey a => a -> Key
key Text
bl)

pValue :: AB.Parser Value
pValue :: Parser ByteString Value
pValue = (forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"pValue") forall a b. (a -> b) -> a -> b
$ do
  Text
bl <- ByteString -> Parser ByteString Text
pUtf8LtoL forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< ByteString -> Parser ByteString ByteString
pDecodePercents forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (Word8 -> Bool) -> Parser ByteString
AB.takeWhile (forall a. Eq a => a -> a -> Bool
/= Word8
32) -- :space:
  forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a. ToValue a => a -> Value
value Text
bl)

pMessage :: AB.Parser Message
{-# INLINE pMessage #-}
pMessage :: Parser ByteString Message
pMessage = (forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"pMessage") forall a b. (a -> b) -> a -> b
$ do
  ByteString
b <- (Word8 -> Bool) -> Parser ByteString
AB.takeWhile (\Word8
w -> Word8
w forall a. Eq a => a -> a -> Bool
/= Word8
10 Bool -> Bool -> Bool
&& Word8
w forall a. Eq a => a -> a -> Bool
/= Word8
13) -- CR and LF
  Text
tl <- ByteString -> Parser ByteString Text
pUtf8LtoL forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< ByteString -> Parser ByteString ByteString
pDecodePercents ByteString
b
  forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a. ToMessage a => a -> Message
message Text
tl)

pUtf8LtoL :: BL.ByteString -> AB.Parser TL.Text
{-# INLINE pUtf8LtoL #-}
pUtf8LtoL :: ByteString -> Parser ByteString Text
pUtf8LtoL = \ByteString
bl -> case ByteString -> Either UnicodeException Text
TL.decodeUtf8' ByteString
bl of
   Right Text
x -> forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
x
   Left UnicodeException
e -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail (forall a. Show a => a -> String
show UnicodeException
e) forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"pUtf8LtoL"

-- | Parse @\"%FF\"@. Always consumes 3 bytes from the input, if successful.
pNumPercent :: AB.Parser Word8
{-# INLINE pNumPercent #-}
pNumPercent :: Parser ByteString Word8
pNumPercent = (forall i a. Parser i a -> String -> Parser i a
AB.<?> String
"pNum2Nibbles") forall a b. (a -> b) -> a -> b
$ do
   (Word8 -> Bool) -> Parser ()
AB.skip (forall a. Eq a => a -> a -> Bool
== Word8
37) -- percent
   Word8
wh <- Parser ByteString Word8
pHexDigit
   Word8
wl <- Parser ByteString Word8
pHexDigit
   forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a. Bits a => a -> MonthOfYear -> a
shiftL Word8
wh MonthOfYear
4 forall a. Num a => a -> a -> a
+ Word8
wl)

pHexDigit :: AB.Parser Word8
{-# INLINE pHexDigit #-}
pHexDigit :: Parser ByteString Word8
pHexDigit = forall a. (Word8 -> a) -> (a -> Bool) -> Parser a
AB.satisfyWith
  (\case Word8
w | Word8
w forall a. Ord a => a -> a -> Bool
>= Word8
48 Bool -> Bool -> Bool
&& Word8
w forall a. Ord a => a -> a -> Bool
<=  Word8
57 -> Word8
w forall a. Num a => a -> a -> a
- Word8
48
           | Word8
w forall a. Ord a => a -> a -> Bool
>= Word8
65 Bool -> Bool -> Bool
&& Word8
w forall a. Ord a => a -> a -> Bool
<=  Word8
70 -> Word8
w forall a. Num a => a -> a -> a
- Word8
55
           | Word8
w forall a. Ord a => a -> a -> Bool
>= Word8
97 Bool -> Bool -> Bool
&& Word8
w forall a. Ord a => a -> a -> Bool
<= Word8
102 -> Word8
w forall a. Num a => a -> a -> a
- Word8
87
           | Bool
otherwise -> Word8
99)
  (\Word8
w -> Word8
w forall a. Eq a => a -> a -> Bool
/= Word8
99)

-- | Like 'pDecodePercentsL' but takes strict bytes.
pDecodePercents :: B.ByteString -> AB.Parser BL.ByteString
{-# INLINE pDecodePercents #-}
pDecodePercents :: ByteString -> Parser ByteString ByteString
pDecodePercents = ByteString -> Parser ByteString ByteString
pDecodePercentsL forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
BL.fromStrict

-- | Decodes all 'pNumPercent' occurences from the given input.
--
-- TODO: Make faster and more space efficient.
pDecodePercentsL :: BL.ByteString -> AB.Parser BL.ByteString
{-# INLINABLE pDecodePercentsL #-}
pDecodePercentsL :: ByteString -> Parser ByteString ByteString
pDecodePercentsL = \ByteString
bl ->
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall r. Result r -> Either String r
ABL.eitherResult (forall a. Parser a -> ByteString -> Result a
ABL.parse Parser ByteString ByteString
p ByteString
bl))
  where
    p :: AB.Parser BL.ByteString
    p :: Parser ByteString ByteString
p = forall t. Chunk t => Parser t Bool
AB.atEnd forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
          Bool
True -> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. Monoid a => a
mempty
          Bool
False -> forall a. (a -> a) -> a
fix forall a b. (a -> b) -> a -> b
$ \Parser ByteString ByteString
k -> do
             ByteString
b <- Parser (Maybe Word8)
AB.peekWord8 forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
                Maybe Word8
Nothing -> forall (f :: * -> *) a. Alternative f => f a
empty
                Just Word8
37 -> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Word8 -> ByteString
B.singleton Parser ByteString Word8
pNumPercent
                Just Word8
_  -> (Word8 -> Bool) -> Parser ByteString
AB.takeWhile1 (\Word8
w -> Word8
w forall a. Eq a => a -> a -> Bool
/= Word8
37)
             [ByteString]
bls <- forall (f :: * -> *) a. Alternative f => f a -> f [a]
many Parser ByteString ByteString
k forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall t. Chunk t => Parser t ()
AB.endOfInput
             forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall a. Monoid a => [a] -> a
mconcat (ByteString -> ByteString
BL.fromStrict ByteString
b forall a. a -> [a] -> [a]
: [ByteString]
bls))