    {-# LANGUAGE OverloadedStrings #-}

    module Network.Wreq.Internal.Link
           (
             links
           ) where

    import Control.Applicative ((<$>), (<*>), (*>), (<*), many)
    import Data.Attoparsec.ByteString.Char8 as A8
    import Data.ByteString (ByteString)
    import Network.Wreq.Types (Link(..))
    import qualified Data.Attoparsec.ByteString as A
    import qualified Data.ByteString as B
    import qualified Data.ByteString.Char8 as B8

    links :: B.ByteString -> [Link]
    links :: ByteString -> [Link]
    links ByteString
    hdr = case Parser [Link] -> ByteString -> Either String [Link]
    forall a. Parser a -> ByteString -> Either String a
    parseOnly Parser [Link]
    f ByteString
    hdr of
                  Left String
    _   -> []
                  Right [Link]
    xs -> [Link]
    xs
      where f :: Parser [Link]
    f = Parser ByteString Link -> Parser ByteString () -> Parser [Link]
    forall (f :: * -> *) a s. Alternative f => f a -> f s -> f [a]
    sepBy1 (Parser ByteString Link
    link Parser ByteString Link
    -> Parser ByteString () -> Parser ByteString Link
    forall a b.
    Parser ByteString a -> Parser ByteString b -> Parser ByteString a
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* Parser ByteString ()
    skipSpace) (Char -> Parser Word8
    char8 Char
    ',' Parser Word8 -> Parser ByteString () -> Parser ByteString ()
    forall a b.
    Parser ByteString a -> Parser ByteString b -> Parser ByteString b
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
    *> Parser ByteString ()
    skipSpace) Parser [Link] -> Parser ByteString () -> Parser [Link]
    forall a b.
    Parser ByteString a -> Parser ByteString b -> Parser ByteString a
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* Parser ByteString ()
    forall t. Chunk t => Parser t ()
    endOfInput

    link :: Parser Link
    link :: Parser ByteString Link
    link = ByteString -> [(ByteString, ByteString)] -> Link
    Link (ByteString -> [(ByteString, ByteString)] -> Link)
    -> Parser ByteString ByteString
    -> Parser ByteString ([(ByteString, ByteString)] -> Link)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Parser ByteString ByteString
    url Parser ByteString ([(ByteString, ByteString)] -> Link)
    -> Parser ByteString [(ByteString, ByteString)]
    -> Parser ByteString Link
    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
    <*> Parser ByteString (ByteString, ByteString)
    -> Parser ByteString [(ByteString, ByteString)]
    forall a. Parser ByteString a -> Parser ByteString [a]
    forall (f :: * -> *) a. Alternative f => f a -> f [a]
    many (Char -> Parser Word8
    char8 Char
    ';' Parser Word8 -> Parser ByteString () -> Parser ByteString ()
    forall a b.
    Parser ByteString a -> Parser ByteString b -> Parser ByteString b
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
    *> Parser ByteString ()
    skipSpace Parser ByteString ()
    -> Parser ByteString (ByteString, ByteString)
    -> Parser ByteString (ByteString, ByteString)
    forall a b.
    Parser ByteString a -> Parser ByteString b -> Parser ByteString b
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
    *> Parser ByteString (ByteString, ByteString)
    param)
      where url :: Parser ByteString ByteString
    url = Char -> Parser Word8
    char8 Char
    '<' Parser Word8
    -> Parser ByteString ByteString -> Parser ByteString ByteString
    forall a b.
    Parser ByteString a -> Parser ByteString b -> Parser ByteString b
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
    *> (Char -> Bool) -> Parser ByteString ByteString
    A8.takeTill (Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    ==Char
    '>') Parser ByteString ByteString
    -> Parser Word8 -> Parser ByteString ByteString
    forall a b.
    Parser ByteString a -> Parser ByteString b -> Parser ByteString a
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* Char -> Parser Word8
    char8 Char
    '>' Parser ByteString ByteString
    -> Parser ByteString () -> Parser ByteString ByteString
    forall a b.
    Parser ByteString a -> Parser ByteString b -> Parser ByteString a
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* Parser ByteString ()
    skipSpace

    param :: Parser (ByteString, ByteString)
    param :: Parser ByteString (ByteString, ByteString)
    param = do
      ByteString
    name <- Parser ByteString ByteString
    paramName
      Parser ByteString ()
    skipSpace Parser ByteString ()
    -> Parser ByteString ByteString -> Parser ByteString ByteString
    forall a b.
    Parser ByteString a -> Parser ByteString b -> Parser ByteString b
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
    *> Parser ByteString ByteString
    "=" Parser ByteString ByteString
    -> Parser ByteString () -> Parser ByteString ()
    forall a b.
    Parser ByteString a -> Parser ByteString b -> Parser ByteString b
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
    *> Parser ByteString ()
    skipSpace
      Char
    c <- Parser Char
    peekChar'
      let isTokenChar :: Word8 -> Bool
    isTokenChar = String -> Word8 -> Bool
    A.inClass String
    "!#$%&'()*+./0-9:<=>?@a-zA-Z[]^_`{|}~-"
      ByteString
    val <- case Char
    c of
               Char
    '"' -> Parser ByteString ByteString
    quotedString
               Char
    _   -> (Word8 -> Bool) -> Parser ByteString ByteString
    A.takeWhile Word8 -> Bool
    isTokenChar
      Parser ByteString ()
    skipSpace
      (ByteString, ByteString)
    -> Parser ByteString (ByteString, ByteString)
    forall a. a -> Parser ByteString a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (ByteString
    name, ByteString
    val)

    data Quot = Literal | Backslash

    quotedString :: Parser ByteString
    quotedString :: Parser ByteString ByteString
    quotedString = Char -> Parser Char
    char Char
    '"' Parser Char
    -> Parser ByteString ByteString -> Parser ByteString ByteString
    forall a b.
    Parser ByteString a -> Parser ByteString b -> Parser ByteString b
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
    *> (ByteString -> ByteString
    fixup (ByteString -> ByteString)
    -> Parser ByteString ByteString -> Parser ByteString ByteString
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Parser ByteString ByteString
    body) Parser ByteString ByteString
    -> Parser Char -> Parser ByteString ByteString
    forall a b.
    Parser ByteString a -> Parser ByteString b -> Parser ByteString a
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* Char -> Parser Char
    char Char
    '"'
      where body :: Parser ByteString ByteString
    body = Quot
    -> (Quot -> Char -> Maybe Quot) -> Parser ByteString ByteString
    forall s.
    s -> (s -> Char -> Maybe s) -> Parser ByteString ByteString
    A8.scan Quot
    Literal ((Quot -> Char -> Maybe Quot) -> Parser ByteString ByteString)
    -> (Quot -> Char -> Maybe Quot) -> Parser ByteString ByteString
    forall a b. (a -> b) -> a -> b
    $ \Quot
    s Char
    c ->
              case (Quot
    s,Char
    c) of
                (Quot
    Literal,  Char
    '\\') -> Maybe Quot
    backslash
                (Quot
    Literal,  Char
    '"')  -> Maybe Quot
    forall a. Maybe a
    Nothing
                (Quot, Char)
    _                -> Maybe Quot
    literal
            literal :: Maybe Quot
    literal   = Quot -> Maybe Quot
    forall a. a -> Maybe a
    Just Quot
    Literal
            backslash :: Maybe Quot
    backslash = Quot -> Maybe Quot
    forall a. a -> Maybe a
    Just Quot
    Backslash
            fixup :: ByteString -> ByteString
    fixup = String -> ByteString
    B8.pack (String -> ByteString)
    -> (ByteString -> String) -> ByteString -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> String
    go (String -> String)
    -> (ByteString -> String) -> ByteString -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> String
    B8.unpack
              where go :: String -> String
    go (Char
    '\\' : x :: Char
    x@Char
    '\\' : String
    xs) = Char
    x Char -> String -> String
    forall a. a -> [a] -> [a]
    : String -> String
    go String
    xs
                    go (Char
    '\\' : x :: Char
    x@Char
    '"' : String
    xs)  = Char
    x Char -> String -> String
    forall a. a -> [a] -> [a]
    : String -> String
    go String
    xs
                    go (Char
    x : String
    xs)             = Char
    x Char -> String -> String
    forall a. a -> [a] -> [a]
    : String -> String
    go String
    xs
                    go String
    xs                   = String
    xs

    paramName :: Parser ByteString
    paramName :: Parser ByteString ByteString
    paramName = do
      ByteString
    name <- (Word8 -> Bool) -> Parser ByteString ByteString
    A.takeWhile1 ((Word8 -> Bool) -> Parser ByteString ByteString)
    -> (Word8 -> Bool) -> Parser ByteString ByteString
    forall a b. (a -> b) -> a -> b
    $ String -> Word8 -> Bool
    A.inClass String
    "a-zA-Z0-9!#$&+-.^_`|~"
      Maybe Char
    c <- Parser (Maybe Char)
    peekChar
      ByteString -> Parser ByteString ByteString
    forall a. a -> Parser ByteString a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (ByteString -> Parser ByteString ByteString)
    -> ByteString -> Parser ByteString ByteString
    forall a b. (a -> b) -> a -> b
    $ case Maybe Char
    c of
                 Just Char
    '*' -> ByteString -> Char -> ByteString
    B8.snoc ByteString
    name Char
    '*'
                 Maybe Char
    _        -> ByteString
    name