{-# LANGUAGE OverloadedStrings, BangPatterns #-}

module Network.HPACK.Token (
  -- * Data type
    Token(..)
  , tokenIx
  , tokenCIKey
  , tokenFoldedKey
  , toToken
  -- * Ix
  , minTokenIx
  , maxStaticTokenIx
  , maxTokenIx
  , cookieTokenIx
  -- * Utilities
  , isMaxTokenIx
  , isCookieTokenIx
  , isStaticTokenIx
  , isStaticToken
  -- * Defined tokens
  , tokenAuthority
  , tokenMethod
  , tokenPath
  , tokenScheme
  , tokenStatus
  , tokenAcceptCharset
  , tokenAcceptEncoding
  , tokenAcceptLanguage
  , tokenAcceptRanges
  , tokenAccept
  , tokenAccessControlAllowOrigin
  , tokenAge
  , tokenAllow
  , tokenAuthorization
  , tokenCacheControl
  , tokenContentDisposition
  , tokenContentEncoding
  , tokenContentLanguage
  , tokenContentLength
  , tokenContentLocation
  , tokenContentRange
  , tokenContentType
  , tokenCookie
  , tokenDate
  , tokenEtag
  , tokenExpect
  , tokenExpires
  , tokenFrom
  , tokenHost
  , tokenIfMatch
  , tokenIfModifiedSince
  , tokenIfNoneMatch
  , tokenIfRange
  , tokenIfUnmodifiedSince
  , tokenLastModified
  , tokenLink
  , tokenLocation
  , tokenMaxForwards
  , tokenProxyAuthenticate
  , tokenProxyAuthorization
  , tokenRange
  , tokenReferer
  , tokenRefresh
  , tokenRetryAfter
  , tokenServer
  , tokenSetCookie
  , tokenStrictTransportSecurity
  , tokenTransferEncoding
  , tokenUserAgent
  , tokenVary
  , tokenVia
  , tokenWwwAuthenticate
  , tokenConnection
  , tokenTE
  , tokenMax
  ) where

import qualified Data.ByteString as B
import Data.ByteString.Internal (ByteString(..), memcmp)
import Foreign.ForeignPtr (withForeignPtr)
import Foreign.Ptr (plusPtr)
import System.IO.Unsafe (unsafeDupablePerformIO)
import Data.CaseInsensitive (original, mk, CI(..))

-- $setup
-- >>> :set -XOverloadedStrings

-- | Internal representation for header keys.
data Token = Token {
    Token -> Int
ix :: !Int               -- ^ Index for value table
  , Token -> Bool
shouldBeIndexed :: !Bool -- ^ should be indexed in HPACK
  , Token -> Bool
isPseudo :: !Bool        -- ^ is this a pseudo header key?
  , Token -> CI ByteString
tokenKey :: !(CI ByteString) -- ^ Case insensitive header key
  } deriving (Token -> Token -> Bool
(Token -> Token -> Bool) -> (Token -> Token -> Bool) -> Eq Token
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Token -> Token -> Bool
$c/= :: Token -> Token -> Bool
== :: Token -> Token -> Bool
$c== :: Token -> Token -> Bool
Eq, Int -> Token -> ShowS
[Token] -> ShowS
Token -> String
(Int -> Token -> ShowS)
-> (Token -> String) -> ([Token] -> ShowS) -> Show Token
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Token] -> ShowS
$cshowList :: [Token] -> ShowS
show :: Token -> String
$cshow :: Token -> String
showsPrec :: Int -> Token -> ShowS
$cshowsPrec :: Int -> Token -> ShowS
Show)

-- | Extracting an index from a token.
{-# INLINE tokenIx #-}
tokenIx :: Token -> Int
tokenIx :: Token -> Int
tokenIx (Token Int
n Bool
_ Bool
_ CI ByteString
_) = Int
n

-- | Extracting a case insensitive header key from a token.
{-# INLINE tokenCIKey #-}
tokenCIKey :: Token -> ByteString
tokenCIKey :: Token -> ByteString
tokenCIKey (Token Int
_ Bool
_ Bool
_ CI ByteString
ci) = CI ByteString -> ByteString
forall s. CI s -> s
original CI ByteString
ci

-- | Extracting a folded header key from a token.
{-# INLINE tokenFoldedKey #-}
tokenFoldedKey :: Token -> ByteString
tokenFoldedKey :: Token -> ByteString
tokenFoldedKey (Token Int
_ Bool
_ Bool
_ CI ByteString
ci) = CI ByteString -> ByteString
forall s. CI s -> s
foldedCase CI ByteString
ci

tokenAuthority                :: Token
tokenMethod                   :: Token
tokenPath                     :: Token
tokenScheme                   :: Token
tokenStatus                   :: Token
tokenAcceptCharset            :: Token
tokenAcceptEncoding           :: Token
tokenAcceptLanguage           :: Token
tokenAcceptRanges             :: Token
tokenAccept                   :: Token
tokenAccessControlAllowOrigin :: Token
tokenAge                      :: Token
tokenAllow                    :: Token
tokenAuthorization            :: Token
tokenCacheControl             :: Token
tokenContentDisposition       :: Token
tokenContentEncoding          :: Token
tokenContentLanguage          :: Token
tokenContentLength            :: Token
tokenContentLocation          :: Token
tokenContentRange             :: Token
tokenContentType              :: Token
tokenCookie                   :: Token
tokenDate                     :: Token
tokenEtag                     :: Token
tokenExpect                   :: Token
tokenExpires                  :: Token
tokenFrom                     :: Token
tokenHost                     :: Token
tokenIfMatch                  :: Token
tokenIfModifiedSince          :: Token
tokenIfNoneMatch              :: Token
tokenIfRange                  :: Token
tokenIfUnmodifiedSince        :: Token
tokenLastModified             :: Token
tokenLink                     :: Token
tokenLocation                 :: Token
tokenMaxForwards              :: Token
tokenProxyAuthenticate        :: Token
tokenProxyAuthorization       :: Token
tokenRange                    :: Token
tokenReferer                  :: Token
tokenRefresh                  :: Token
tokenRetryAfter               :: Token
tokenServer                   :: Token
tokenSetCookie                :: Token
tokenStrictTransportSecurity  :: Token
tokenTransferEncoding         :: Token
tokenUserAgent                :: Token
tokenVary                     :: Token
tokenVia                      :: Token
tokenWwwAuthenticate          :: Token
tokenConnection               :: Token -- Original
tokenTE                       :: Token -- Original
tokenMax                      :: Token -- Other tokens

tokenAuthority :: Token
tokenAuthority                = Int -> Bool -> Bool -> CI ByteString -> Token
Token  Int
0  Bool
True  Bool
True CI ByteString
":authority"
tokenMethod :: Token
tokenMethod                   = Int -> Bool -> Bool -> CI ByteString -> Token
Token  Int
1  Bool
True  Bool
True CI ByteString
":method"
tokenPath :: Token
tokenPath                     = Int -> Bool -> Bool -> CI ByteString -> Token
Token  Int
2 Bool
False  Bool
True CI ByteString
":path"
tokenScheme :: Token
tokenScheme                   = Int -> Bool -> Bool -> CI ByteString -> Token
Token  Int
3  Bool
True  Bool
True CI ByteString
":scheme"
tokenStatus :: Token
tokenStatus                   = Int -> Bool -> Bool -> CI ByteString -> Token
Token  Int
4  Bool
True  Bool
True CI ByteString
":status"
tokenAcceptCharset :: Token
tokenAcceptCharset            = Int -> Bool -> Bool -> CI ByteString -> Token
Token  Int
5  Bool
True Bool
False CI ByteString
"Accept-Charset"
tokenAcceptEncoding :: Token
tokenAcceptEncoding           = Int -> Bool -> Bool -> CI ByteString -> Token
Token  Int
6  Bool
True Bool
False CI ByteString
"Accept-Encoding"
tokenAcceptLanguage :: Token
tokenAcceptLanguage           = Int -> Bool -> Bool -> CI ByteString -> Token
Token  Int
7  Bool
True Bool
False CI ByteString
"Accept-Language"
tokenAcceptRanges :: Token
tokenAcceptRanges             = Int -> Bool -> Bool -> CI ByteString -> Token
Token  Int
8  Bool
True Bool
False CI ByteString
"Accept-Ranges"
tokenAccept :: Token
tokenAccept                   = Int -> Bool -> Bool -> CI ByteString -> Token
Token  Int
9  Bool
True Bool
False CI ByteString
"Accept"
tokenAccessControlAllowOrigin :: Token
tokenAccessControlAllowOrigin = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
10  Bool
True Bool
False CI ByteString
"Access-Control-Allow-Origin"
tokenAge :: Token
tokenAge                      = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
11  Bool
True Bool
False CI ByteString
"Age"
tokenAllow :: Token
tokenAllow                    = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
12  Bool
True Bool
False CI ByteString
"Allow"
tokenAuthorization :: Token
tokenAuthorization            = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
13  Bool
True Bool
False CI ByteString
"Authorization"
tokenCacheControl :: Token
tokenCacheControl             = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
14  Bool
True Bool
False CI ByteString
"Cache-Control"
tokenContentDisposition :: Token
tokenContentDisposition       = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
15  Bool
True Bool
False CI ByteString
"Content-Disposition"
tokenContentEncoding :: Token
tokenContentEncoding          = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
16  Bool
True Bool
False CI ByteString
"Content-Encoding"
tokenContentLanguage :: Token
tokenContentLanguage          = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
17  Bool
True Bool
False CI ByteString
"Content-Language"
tokenContentLength :: Token
tokenContentLength            = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
18 Bool
False Bool
False CI ByteString
"Content-Length"
tokenContentLocation :: Token
tokenContentLocation          = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
19 Bool
False Bool
False CI ByteString
"Content-Location"
tokenContentRange :: Token
tokenContentRange             = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
20  Bool
True Bool
False CI ByteString
"Content-Range"
tokenContentType :: Token
tokenContentType              = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
21  Bool
True Bool
False CI ByteString
"Content-Type"
tokenCookie :: Token
tokenCookie                   = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
22  Bool
True Bool
False CI ByteString
"Cookie"
tokenDate :: Token
tokenDate                     = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
23  Bool
True Bool
False CI ByteString
"Date"
tokenEtag :: Token
tokenEtag                     = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
24 Bool
False Bool
False CI ByteString
"Etag"
tokenExpect :: Token
tokenExpect                   = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
25  Bool
True Bool
False CI ByteString
"Expect"
tokenExpires :: Token
tokenExpires                  = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
26  Bool
True Bool
False CI ByteString
"Expires"
tokenFrom :: Token
tokenFrom                     = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
27  Bool
True Bool
False CI ByteString
"From"
tokenHost :: Token
tokenHost                     = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
28  Bool
True Bool
False CI ByteString
"Host"
tokenIfMatch :: Token
tokenIfMatch                  = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
29  Bool
True Bool
False CI ByteString
"If-Match"
tokenIfModifiedSince :: Token
tokenIfModifiedSince          = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
30  Bool
True Bool
False CI ByteString
"If-Modified-Since"
tokenIfNoneMatch :: Token
tokenIfNoneMatch              = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
31  Bool
True Bool
False CI ByteString
"If-None-Match"
tokenIfRange :: Token
tokenIfRange                  = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
32  Bool
True Bool
False CI ByteString
"If-Range"
tokenIfUnmodifiedSince :: Token
tokenIfUnmodifiedSince        = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
33  Bool
True Bool
False CI ByteString
"If-Unmodified-Since"
tokenLastModified :: Token
tokenLastModified             = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
34  Bool
True Bool
False CI ByteString
"Last-Modified"
tokenLink :: Token
tokenLink                     = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
35  Bool
True Bool
False CI ByteString
"Link"
tokenLocation :: Token
tokenLocation                 = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
36  Bool
True Bool
False CI ByteString
"Location"
tokenMaxForwards :: Token
tokenMaxForwards              = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
37  Bool
True Bool
False CI ByteString
"Max-Forwards"
tokenProxyAuthenticate :: Token
tokenProxyAuthenticate        = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
38  Bool
True Bool
False CI ByteString
"Proxy-Authenticate"
tokenProxyAuthorization :: Token
tokenProxyAuthorization       = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
39  Bool
True Bool
False CI ByteString
"Proxy-Authorization"
tokenRange :: Token
tokenRange                    = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
40  Bool
True Bool
False CI ByteString
"Range"
tokenReferer :: Token
tokenReferer                  = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
41  Bool
True Bool
False CI ByteString
"Referer"
tokenRefresh :: Token
tokenRefresh                  = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
42  Bool
True Bool
False CI ByteString
"Refresh"
tokenRetryAfter :: Token
tokenRetryAfter               = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
43  Bool
True Bool
False CI ByteString
"Retry-After"
tokenServer :: Token
tokenServer                   = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
44  Bool
True Bool
False CI ByteString
"Server"
tokenSetCookie :: Token
tokenSetCookie                = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
45 Bool
False Bool
False CI ByteString
"Set-Cookie"
tokenStrictTransportSecurity :: Token
tokenStrictTransportSecurity  = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
46  Bool
True Bool
False CI ByteString
"Strict-Transport-Security"
tokenTransferEncoding :: Token
tokenTransferEncoding         = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
47  Bool
True Bool
False CI ByteString
"Transfer-Encoding"
tokenUserAgent :: Token
tokenUserAgent                = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
48  Bool
True Bool
False CI ByteString
"User-Agent"
tokenVary :: Token
tokenVary                     = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
49  Bool
True Bool
False CI ByteString
"Vary"
tokenVia :: Token
tokenVia                      = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
50  Bool
True Bool
False CI ByteString
"Via"
tokenWwwAuthenticate :: Token
tokenWwwAuthenticate          = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
51  Bool
True Bool
False CI ByteString
"Www-Authenticate"
-- | Not defined in the static table.
tokenConnection :: Token
tokenConnection               = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
52 Bool
False Bool
False CI ByteString
"Connection"
-- | Not defined in the static table.
tokenTE :: Token
tokenTE                       = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
53 Bool
False Bool
False CI ByteString
"TE"
-- | A place holder to hold header keys not defined in the static table.
tokenMax :: Token
tokenMax                      = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
54  Bool
True Bool
False CI ByteString
"for other tokens"

-- | Minimum token index.
minTokenIx :: Int
minTokenIx :: Int
minTokenIx = Int
0

-- | Maximun token index defined in the static table.
maxStaticTokenIx :: Int
maxStaticTokenIx :: Int
maxStaticTokenIx = Int
51

-- | Maximum token index.
maxTokenIx :: Int
maxTokenIx :: Int
maxTokenIx = Int
54

-- | Token index for 'tokenCookie'.
cookieTokenIx :: Int
cookieTokenIx :: Int
cookieTokenIx = Int
22

-- | Is this token ix for Cookie?
{-# INLINE isCookieTokenIx #-}
isCookieTokenIx :: Int -> Bool
isCookieTokenIx :: Int -> Bool
isCookieTokenIx Int
n = Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
cookieTokenIx

-- | Is this token ix to be held in the place holder?
{-# INLINE isMaxTokenIx #-}
isMaxTokenIx :: Int -> Bool
isMaxTokenIx :: Int -> Bool
isMaxTokenIx Int
n = Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
maxTokenIx

-- | Is this token ix for a header not defined in the static table?
{-# INLINE isStaticTokenIx #-}
isStaticTokenIx :: Int -> Bool
isStaticTokenIx :: Int -> Bool
isStaticTokenIx Int
n = Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
maxStaticTokenIx

-- | Is this token for a header not defined in the static table?
{-# INLINE isStaticToken #-}
isStaticToken :: Token -> Bool
isStaticToken :: Token -> Bool
isStaticToken Token
n = Token -> Int
tokenIx Token
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
maxStaticTokenIx

-- | Making a token from a header key.
--
-- >>> toToken ":authority" == tokenAuthority
-- True
-- >>> toToken "foo"
-- Token {ix = 54, shouldBeIndexed = True, isPseudo = False, tokenKey = "foo"}
-- >>> toToken ":bar"
-- Token {ix = 54, shouldBeIndexed = True, isPseudo = True, tokenKey = ":bar"}
toToken :: ByteString -> Token
toToken :: ByteString -> Token
toToken ByteString
bs = case Int
len of
    Int
2 -> if ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"te" then Token
tokenTE else ByteString -> Token
mkTokenMax ByteString
bs
    Int
3 -> case Word8
lst of
        Word8
97  | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"via" -> Token
tokenVia
        Word8
101 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"age" -> Token
tokenAge
        Word8
_                  -> ByteString -> Token
mkTokenMax ByteString
bs
    Int
4 -> case Word8
lst of
        Word8
101 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"date" -> Token
tokenDate
        Word8
103 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"etag" -> Token
tokenEtag
        Word8
107 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"link" -> Token
tokenLink
        Word8
109 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"from" -> Token
tokenFrom
        Word8
116 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"host" -> Token
tokenHost
        Word8
121 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"vary" -> Token
tokenVary
        Word8
_                   -> ByteString -> Token
mkTokenMax ByteString
bs
    Int
5 -> case Word8
lst of
        Word8
101 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"range" -> Token
tokenRange
        Word8
104 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
":path" -> Token
tokenPath
        Word8
119 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"allow" -> Token
tokenAllow
        Word8
_                    -> ByteString -> Token
mkTokenMax ByteString
bs
    Int
6 -> case Word8
lst of
        Word8
101 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"cookie" -> Token
tokenCookie
        Word8
114 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"server" -> Token
tokenServer
        Word8
116 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"expect" -> Token
tokenExpect
            | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"accept" -> Token
tokenAccept
        Word8
_                     -> ByteString -> Token
mkTokenMax ByteString
bs
    Int
7 -> case Word8
lst of
        Word8
100 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
":method" -> Token
tokenMethod
        Word8
101 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
":scheme" -> Token
tokenScheme
        Word8
104 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"refresh" -> Token
tokenRefresh
        Word8
114 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"referer" -> Token
tokenReferer
        Word8
115 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"expires" -> Token
tokenExpires
            | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
":status" -> Token
tokenStatus
        Word8
_                      -> ByteString -> Token
mkTokenMax ByteString
bs
    Int
8 -> case Word8
lst of
        Word8
101 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"if-range" -> Token
tokenIfRange
        Word8
104 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"if-match" -> Token
tokenIfMatch
        Word8
110 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"location" -> Token
tokenLocation
        Word8
_                       -> ByteString -> Token
mkTokenMax ByteString
bs
    Int
10 -> case Word8
lst of
        Word8
101 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"set-cookie" -> Token
tokenSetCookie
        Word8
110 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"connection" -> Token
tokenConnection
        Word8
116 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"user-agent" -> Token
tokenUserAgent
        Word8
121 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
":authority" -> Token
tokenAuthority
        Word8
_                         -> ByteString -> Token
mkTokenMax ByteString
bs
    Int
11 -> case Word8
lst of
        Word8
114 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"retry-after" -> Token
tokenRetryAfter
        Word8
_                          -> ByteString -> Token
mkTokenMax ByteString
bs
    Int
12 -> case Word8
lst of
        Word8
101 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"content-type" -> Token
tokenContentType
        Word8
115 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"max-forwards" -> Token
tokenMaxForwards
        Word8
_                           -> ByteString -> Token
mkTokenMax ByteString
bs
    Int
13 -> case Word8
lst of
        Word8
100 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"last-modified" -> Token
tokenLastModified
        Word8
101 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"content-range" -> Token
tokenContentRange
        Word8
104 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"if-none-match" -> Token
tokenIfNoneMatch
        Word8
108 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"cache-control" -> Token
tokenCacheControl
        Word8
110 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"authorization" -> Token
tokenAuthorization
        Word8
115 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"accept-ranges" -> Token
tokenAcceptRanges
        Word8
_                            -> ByteString -> Token
mkTokenMax ByteString
bs
    Int
14 -> case Word8
lst of
        Word8
104 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"content-length" -> Token
tokenContentLength
        Word8
116 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"accept-charset" -> Token
tokenAcceptCharset
        Word8
_                             -> ByteString -> Token
mkTokenMax ByteString
bs
    Int
15 -> case Word8
lst of
        Word8
101 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"accept-language" -> Token
tokenAcceptLanguage
        Word8
103 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"accept-encoding" -> Token
tokenAcceptEncoding
        Word8
_                              -> ByteString -> Token
mkTokenMax ByteString
bs
    Int
16 -> case Word8
lst of
        Word8
101 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"content-language" -> Token
tokenContentLanguage
            | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"www-authenticate" -> Token
tokenWwwAuthenticate
        Word8
103 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"content-encoding" -> Token
tokenContentEncoding
        Word8
110 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"content-location" -> Token
tokenContentLocation
        Word8
_                               -> ByteString -> Token
mkTokenMax ByteString
bs
    Int
17 -> case Word8
lst of
        Word8
101 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"if-modified-since" -> Token
tokenIfModifiedSince
        Word8
103 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"transfer-encoding" -> Token
tokenTransferEncoding
        Word8
_                                -> ByteString -> Token
mkTokenMax ByteString
bs
    Int
18 -> case Word8
lst of
        Word8
101 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"proxy-authenticate" -> Token
tokenProxyAuthenticate
        Word8
_                                 -> ByteString -> Token
mkTokenMax ByteString
bs
    Int
19 -> case Word8
lst of
        Word8
101 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"if-unmodified-since" -> Token
tokenIfUnmodifiedSince
        Word8
110 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"proxy-authorization" -> Token
tokenProxyAuthorization
            | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"content-disposition" -> Token
tokenContentDisposition
        Word8
_                                  -> ByteString -> Token
mkTokenMax ByteString
bs
    Int
25 -> case Word8
lst of
        Word8
121 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"strict-transport-security" -> Token
tokenStrictTransportSecurity
        Word8
_                                        -> ByteString -> Token
mkTokenMax ByteString
bs
    Int
27 -> case Word8
lst of
        Word8
110 | ByteString
bs ByteString -> ByteString -> Bool
=== ByteString
"access-control-allow-origin" -> Token
tokenAccessControlAllowOrigin
        Word8
_                                          -> ByteString -> Token
mkTokenMax ByteString
bs
    Int
_  -> ByteString -> Token
mkTokenMax ByteString
bs
  where
    len :: Int
len = ByteString -> Int
B.length ByteString
bs
    lst :: Word8
lst = ByteString -> Word8
B.last ByteString
bs
    PS ForeignPtr Word8
fp1 Int
off1 Int
siz === :: ByteString -> ByteString -> Bool
=== PS ForeignPtr Word8
fp2 Int
off2 Int
_ = IO Bool -> Bool
forall a. IO a -> a
unsafeDupablePerformIO (IO Bool -> Bool) -> IO Bool -> Bool
forall a b. (a -> b) -> a -> b
$
      ForeignPtr Word8 -> (Ptr Word8 -> IO Bool) -> IO Bool
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
fp1 ((Ptr Word8 -> IO Bool) -> IO Bool)
-> (Ptr Word8 -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
p1 ->
      ForeignPtr Word8 -> (Ptr Word8 -> IO Bool) -> IO Bool
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
fp2 ((Ptr Word8 -> IO Bool) -> IO Bool)
-> (Ptr Word8 -> IO Bool) -> IO Bool
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
p2 -> do
        CInt
i <- Ptr Word8 -> Ptr Word8 -> Int -> IO CInt
memcmp (Ptr Word8
p1 Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
off1) (Ptr Word8
p2 Ptr Word8 -> Int -> Ptr Word8
forall a b. Ptr a -> Int -> Ptr b
`plusPtr` Int
off2) Int
siz
        Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$! CInt
i CInt -> CInt -> Bool
forall a. Eq a => a -> a -> Bool
== CInt
0

mkTokenMax :: ByteString -> Token
mkTokenMax :: ByteString -> Token
mkTokenMax ByteString
bs = Int -> Bool -> Bool -> CI ByteString -> Token
Token Int
maxTokenIx Bool
True Bool
p (ByteString -> CI ByteString
forall s. FoldCase s => s -> CI s
mk ByteString
bs)
  where
    !p :: Bool
p | ByteString -> Int
B.length ByteString
bs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = Bool
False
       | ByteString -> Word8
B.head ByteString
bs Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
58  = Bool
True
       | Bool
otherwise        = Bool
False