{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_GHC -Wwarn=missing-import-lists #-}
module Network.HTTP.Grammar (
UserAgent(..),
Product(..),
userAgent,
product,
comment,
ctext,
quotedPair,
text,
char,
ctl,
token,
separators,
lws,
crlf,
) where
import Prelude hiding (product)
import Control.Applicative (many, (<|>))
import Control.Monad (void)
import Data.Attoparsec.ByteString (Parser, word8, takeWhile1, satisfy,
inClass, option, string, many1)
import Data.ByteString (ByteString)
import Data.Word (Word8)
import qualified Data.ByteString as BS
data UserAgent
= UAProduct Product
| ByteString
data Product = Product {
Product -> ByteString
productName :: ByteString,
Product -> Maybe ByteString
productVersion :: Maybe ByteString
}
userAgent :: Parser [UserAgent]
userAgent :: Parser [UserAgent]
userAgent = Parser ByteString UserAgent -> Parser [UserAgent]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many1 (
(Product -> UserAgent
UAProduct (Product -> UserAgent)
-> Parser ByteString Product -> Parser ByteString UserAgent
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ByteString Product
product)
Parser ByteString UserAgent
-> Parser ByteString UserAgent -> Parser ByteString UserAgent
forall a.
Parser ByteString a -> Parser ByteString a -> Parser ByteString a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (ByteString -> UserAgent
UAComment (ByteString -> UserAgent)
-> Parser ByteString ByteString -> Parser ByteString UserAgent
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ByteString ByteString
comment)
)
product :: Parser Product
product :: Parser ByteString Product
product =
ByteString -> Maybe ByteString -> Product
Product
(ByteString -> Maybe ByteString -> Product)
-> Parser ByteString ByteString
-> Parser ByteString (Maybe ByteString -> Product)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ByteString ByteString
token
Parser ByteString (Maybe ByteString -> Product)
-> Parser ByteString (Maybe ByteString)
-> Parser ByteString Product
forall a b.
Parser ByteString (a -> b)
-> Parser ByteString a -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe ByteString
-> Parser ByteString (Maybe ByteString)
-> Parser ByteString (Maybe ByteString)
forall (f :: * -> *) a. Alternative f => a -> f a -> f a
option Maybe ByteString
forall a. Maybe a
Nothing Parser ByteString (Maybe ByteString)
versionParser
where
versionParser :: Parser ByteString (Maybe ByteString)
versionParser = do
Parser ByteString ByteString -> Parser ByteString ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Parser ByteString ByteString -> Parser ByteString ())
-> Parser ByteString ByteString -> Parser ByteString ()
forall a b. (a -> b) -> a -> b
$ ByteString -> Parser ByteString ByteString
string ByteString
"/"
ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just (ByteString -> Maybe ByteString)
-> Parser ByteString ByteString
-> Parser ByteString (Maybe ByteString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ByteString ByteString
token
comment :: Parser ByteString
= do
Parser ByteString Word8 -> Parser ByteString ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Parser ByteString Word8 -> Parser ByteString ())
-> Parser ByteString Word8 -> Parser ByteString ()
forall a b. (a -> b) -> a -> b
$ Word8 -> Parser ByteString Word8
word8 Word8
40
segments <- Parser ByteString ByteString -> Parser ByteString [ByteString]
forall a. Parser ByteString a -> Parser ByteString [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many (
(Word8 -> Bool) -> Parser ByteString ByteString
takeWhile1 Word8 -> Bool
ctext
Parser ByteString ByteString
-> Parser ByteString ByteString -> Parser ByteString ByteString
forall a.
Parser ByteString a -> Parser ByteString a -> Parser ByteString a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Word8 -> ByteString
BS.singleton (Word8 -> ByteString)
-> Parser ByteString Word8 -> Parser ByteString ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ByteString Word8
quotedPair)
Parser ByteString ByteString
-> Parser ByteString ByteString -> Parser ByteString ByteString
forall a.
Parser ByteString a -> Parser ByteString a -> Parser ByteString a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser ByteString ByteString
comment
)
void $ word8 41
return (mconcat segments)
ctext :: Word8 -> Bool
ctext :: Word8 -> Bool
ctext Word8
x = Word8 -> Bool
text Word8
x Bool -> Bool -> Bool
&& Word8
x Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word8
40 Bool -> Bool -> Bool
&& Word8
x Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
/= Word8
41
quotedPair :: Parser Word8
quotedPair :: Parser ByteString Word8
quotedPair = do
Parser ByteString Word8 -> Parser ByteString ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Parser ByteString Word8 -> Parser ByteString ())
-> Parser ByteString Word8 -> Parser ByteString ()
forall a b. (a -> b) -> a -> b
$ Word8 -> Parser ByteString Word8
word8 Word8
92
(Word8 -> Bool) -> Parser ByteString Word8
satisfy Word8 -> Bool
char
text :: Word8 -> Bool
text :: Word8 -> Bool
text = Bool -> Bool
not (Bool -> Bool) -> (Word8 -> Bool) -> Word8 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Bool
ctl
char :: Word8 -> Bool
char :: Word8 -> Bool
char Word8
x = Word8
x Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word8
0 Bool -> Bool -> Bool
&& Word8
x Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
127
ctl :: Word8 -> Bool
ctl :: Word8 -> Bool
ctl Word8
x = (Word8
x Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
>= Word8
0 Bool -> Bool -> Bool
&& Word8
x Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
<= Word8
31) Bool -> Bool -> Bool
|| Word8
x Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
127
token :: Parser ByteString
token :: Parser ByteString ByteString
token = do
() -> Parser ByteString () -> Parser ByteString ()
forall (f :: * -> *) a. Alternative f => a -> f a -> f a
option () Parser ByteString ()
lws
t <- (Word8 -> Bool) -> Parser ByteString ByteString
takeWhile1 (\Word8
x -> Word8 -> Bool
char Word8
x Bool -> Bool -> Bool
&& Bool -> Bool
not (Word8 -> Bool
separators Word8
x) Bool -> Bool -> Bool
&& Bool -> Bool
not (Word8 -> Bool
ctl Word8
x))
option () lws
return t
separators :: Word8 -> Bool
separators :: Word8 -> Bool
separators = String -> Word8 -> Bool
inClass String
"()<>@,;:\\\"/[]?={} \t"
lws :: Parser ()
lws :: Parser ByteString ()
lws = do
() -> Parser ByteString () -> Parser ByteString ()
forall (f :: * -> *) a. Alternative f => a -> f a -> f a
option () Parser ByteString ()
crlf
Parser ByteString ByteString -> Parser ByteString ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Parser ByteString ByteString -> Parser ByteString ())
-> Parser ByteString ByteString -> Parser ByteString ()
forall a b. (a -> b) -> a -> b
$ (Word8 -> Bool) -> Parser ByteString ByteString
takeWhile1 (\Word8
x -> Word8
x Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
32 Bool -> Bool -> Bool
|| Word8
x Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
9)
crlf :: Parser ()
crlf :: Parser ByteString ()
crlf = Parser ByteString ByteString -> Parser ByteString ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Parser ByteString ByteString -> Parser ByteString ())
-> Parser ByteString ByteString -> Parser ByteString ()
forall a b. (a -> b) -> a -> b
$ ByteString -> Parser ByteString ByteString
string ByteString
"\r\n"