{-# LANGUAGE OverloadedStrings #-}
module Snap.Types.Headers
(
Headers
, empty
, null
, member
, lookup
, lookupWithDefault
, insert
, unsafeInsert
, set
, delete
, foldl'
, foldr
, foldedFoldl'
, foldedFoldr
, toList
, fromList
, unsafeFromCaseFoldedList
, unsafeToCaseFoldedList
) where
import Control.Arrow (first)
import Data.ByteString.Char8 (ByteString)
import qualified Data.ByteString.Char8 as S
import Data.CaseInsensitive (CI)
import qualified Data.CaseInsensitive as CI
import qualified Data.CaseInsensitive.Unsafe as CI
import qualified Data.List as List
import Data.Maybe (fromMaybe)
import Prelude (Bool (..), Eq (..), Maybe (..), Show (..), fst, id, map, otherwise, uncurry, ($), ($!), (.))
newtype = H { Headers -> [(ByteString, ByteString)]
unH :: [(ByteString, ByteString)] }
deriving (Int -> Headers -> ShowS
[Headers] -> ShowS
Headers -> String
(Int -> Headers -> ShowS)
-> (Headers -> String) -> ([Headers] -> ShowS) -> Show Headers
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Headers] -> ShowS
$cshowList :: [Headers] -> ShowS
show :: Headers -> String
$cshow :: Headers -> String
showsPrec :: Int -> Headers -> ShowS
$cshowsPrec :: Int -> Headers -> ShowS
Show)
empty :: Headers
empty :: Headers
empty = [(ByteString, ByteString)] -> Headers
H []
null :: Headers -> Bool
null :: Headers -> Bool
null = [(ByteString, ByteString)] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
List.null ([(ByteString, ByteString)] -> Bool)
-> (Headers -> [(ByteString, ByteString)]) -> Headers -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Headers -> [(ByteString, ByteString)]
unH
{-# INLINE null #-}
member :: CI ByteString -> Headers -> Bool
member :: CI ByteString -> Headers -> Bool
member CI ByteString
k0 = [(ByteString, ByteString)] -> Bool
forall (t :: * -> *) b. Foldable t => t (ByteString, b) -> Bool
f ([(ByteString, ByteString)] -> Bool)
-> (Headers -> [(ByteString, ByteString)]) -> Headers -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Headers -> [(ByteString, ByteString)]
unH
where
k :: ByteString
k = CI ByteString -> ByteString
forall s. CI s -> s
CI.foldedCase CI ByteString
k0
f :: t (ByteString, b) -> Bool
f t (ByteString, b)
m = ((ByteString, b) -> Bool) -> t (ByteString, b) -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
List.any ((ByteString
k ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
==) (ByteString -> Bool)
-> ((ByteString, b) -> ByteString) -> (ByteString, b) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString, b) -> ByteString
forall a b. (a, b) -> a
fst) t (ByteString, b)
m
{-# INLINE member #-}
lookup :: CI ByteString -> Headers -> Maybe ByteString
lookup :: CI ByteString -> Headers -> Maybe ByteString
lookup CI ByteString
k (H [(ByteString, ByteString)]
m) = ByteString -> [(ByteString, ByteString)] -> Maybe ByteString
forall a b. Eq a => a -> [(a, b)] -> Maybe b
List.lookup (CI ByteString -> ByteString
forall s. CI s -> s
CI.foldedCase CI ByteString
k) [(ByteString, ByteString)]
m
{-# INLINE lookup #-}
lookupWithDefault :: ByteString -> CI ByteString -> Headers -> ByteString
lookupWithDefault :: ByteString -> CI ByteString -> Headers -> ByteString
lookupWithDefault ByteString
d CI ByteString
k Headers
m = ByteString -> Maybe ByteString -> ByteString
forall a. a -> Maybe a -> a
fromMaybe ByteString
d (Maybe ByteString -> ByteString) -> Maybe ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ CI ByteString -> Headers -> Maybe ByteString
lookup CI ByteString
k Headers
m
insert :: CI ByteString -> ByteString -> Headers -> Headers
insert :: CI ByteString -> ByteString -> Headers -> Headers
insert CI ByteString
k0 ByteString
v (H [(ByteString, ByteString)]
m) = [(ByteString, ByteString)] -> Headers
H ([(ByteString, ByteString)] -> Headers)
-> [(ByteString, ByteString)] -> Headers
forall a b. (a -> b) -> a -> b
$! ([(ByteString, ByteString)] -> [(ByteString, ByteString)])
-> [(ByteString, ByteString)] -> [(ByteString, ByteString)]
forall c.
([(ByteString, ByteString)] -> c)
-> [(ByteString, ByteString)] -> c
go [(ByteString, ByteString)] -> [(ByteString, ByteString)]
forall a. a -> a
id [(ByteString, ByteString)]
m
where
k :: ByteString
k = CI ByteString -> ByteString
forall s. CI s -> s
CI.foldedCase CI ByteString
k0
go :: ([(ByteString, ByteString)] -> c)
-> [(ByteString, ByteString)] -> c
go [(ByteString, ByteString)] -> c
dl [] = [(ByteString, ByteString)] -> c
dl [(ByteString
k, ByteString
v)]
go [(ByteString, ByteString)] -> c
dl (z :: (ByteString, ByteString)
z@(ByteString
x,ByteString
y):[(ByteString, ByteString)]
xs) | ByteString
k ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
x = [(ByteString, ByteString)] -> c
dl ((ByteString
k, ByteString -> ByteString -> ByteString
concatHeaderValues ByteString
v ByteString
y)(ByteString, ByteString)
-> [(ByteString, ByteString)] -> [(ByteString, ByteString)]
forall a. a -> [a] -> [a]
:[(ByteString, ByteString)]
xs)
| Bool
otherwise = ([(ByteString, ByteString)] -> c)
-> [(ByteString, ByteString)] -> c
go ([(ByteString, ByteString)] -> c
dl ([(ByteString, ByteString)] -> c)
-> ([(ByteString, ByteString)] -> [(ByteString, ByteString)])
-> [(ByteString, ByteString)]
-> c
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((ByteString, ByteString)
z(ByteString, ByteString)
-> [(ByteString, ByteString)] -> [(ByteString, ByteString)]
forall a. a -> [a] -> [a]
:)) [(ByteString, ByteString)]
xs
concatHeaderValues :: ByteString -> ByteString -> ByteString
concatHeaderValues :: ByteString -> ByteString -> ByteString
concatHeaderValues ByteString
new ByteString
old = [ByteString] -> ByteString
S.concat [ByteString
old, ByteString
",", ByteString
new]
unsafeInsert :: ByteString -> ByteString -> Headers -> Headers
unsafeInsert :: ByteString -> ByteString -> Headers -> Headers
unsafeInsert ByteString
k ByteString
v (H [(ByteString, ByteString)]
hdrs) = [(ByteString, ByteString)] -> Headers
H ((ByteString
k,ByteString
v)(ByteString, ByteString)
-> [(ByteString, ByteString)] -> [(ByteString, ByteString)]
forall a. a -> [a] -> [a]
:[(ByteString, ByteString)]
hdrs)
set :: CI ByteString -> ByteString -> Headers -> Headers
set :: CI ByteString -> ByteString -> Headers -> Headers
set CI ByteString
k0 ByteString
v (H [(ByteString, ByteString)]
m) = [(ByteString, ByteString)] -> Headers
H ([(ByteString, ByteString)] -> Headers)
-> [(ByteString, ByteString)] -> Headers
forall a b. (a -> b) -> a -> b
$ [(ByteString, ByteString)] -> [(ByteString, ByteString)]
go [(ByteString, ByteString)]
m
where
k :: ByteString
k = CI ByteString -> ByteString
forall s. CI s -> s
CI.foldedCase CI ByteString
k0
go :: [(ByteString, ByteString)] -> [(ByteString, ByteString)]
go [] = [(ByteString
k,ByteString
v)]
go (x :: (ByteString, ByteString)
x@(ByteString
k',ByteString
_):[(ByteString, ByteString)]
xs) | ByteString
k ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== ByteString
k' = (ByteString
k,ByteString
v) (ByteString, ByteString)
-> [(ByteString, ByteString)] -> [(ByteString, ByteString)]
forall a. a -> [a] -> [a]
: ((ByteString, ByteString) -> Bool)
-> [(ByteString, ByteString)] -> [(ByteString, ByteString)]
forall a. (a -> Bool) -> [a] -> [a]
List.filter ((ByteString
k ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
/=) (ByteString -> Bool)
-> ((ByteString, ByteString) -> ByteString)
-> (ByteString, ByteString)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString, ByteString) -> ByteString
forall a b. (a, b) -> a
fst) [(ByteString, ByteString)]
xs
| Bool
otherwise = (ByteString, ByteString)
x (ByteString, ByteString)
-> [(ByteString, ByteString)] -> [(ByteString, ByteString)]
forall a. a -> [a] -> [a]
: [(ByteString, ByteString)] -> [(ByteString, ByteString)]
go [(ByteString, ByteString)]
xs
delete :: CI ByteString -> Headers -> Headers
delete :: CI ByteString -> Headers -> Headers
delete CI ByteString
k (H [(ByteString, ByteString)]
m) = [(ByteString, ByteString)] -> Headers
H ([(ByteString, ByteString)] -> Headers)
-> [(ByteString, ByteString)] -> Headers
forall a b. (a -> b) -> a -> b
$ ((ByteString, ByteString) -> Bool)
-> [(ByteString, ByteString)] -> [(ByteString, ByteString)]
forall a. (a -> Bool) -> [a] -> [a]
List.filter ((ByteString
k' ByteString -> ByteString -> Bool
forall a. Eq a => a -> a -> Bool
/=) (ByteString -> Bool)
-> ((ByteString, ByteString) -> ByteString)
-> (ByteString, ByteString)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString, ByteString) -> ByteString
forall a b. (a, b) -> a
fst) [(ByteString, ByteString)]
m
where
k' :: ByteString
k' = CI ByteString -> ByteString
forall s. CI s -> s
CI.foldedCase CI ByteString
k
foldl' :: (a -> CI ByteString -> ByteString -> a)
-> a
-> Headers
-> a
foldl' :: (a -> CI ByteString -> ByteString -> a) -> a -> Headers -> a
foldl' a -> CI ByteString -> ByteString -> a
f a
a (H [(ByteString, ByteString)]
m) = (a -> (ByteString, ByteString) -> a)
-> a -> [(ByteString, ByteString)] -> a
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl' a -> (ByteString, ByteString) -> a
f' a
a [(ByteString, ByteString)]
m
where
f' :: a -> (ByteString, ByteString) -> a
f' a
v (ByteString
x,ByteString
y) = a -> CI ByteString -> ByteString -> a
f a
v (ByteString -> CI ByteString
forall s. FoldCase s => s -> CI s
CI.unsafeMk ByteString
x) ByteString
y
foldedFoldl' :: (a -> ByteString -> ByteString -> a)
-> a
-> Headers
-> a
foldedFoldl' :: (a -> ByteString -> ByteString -> a) -> a -> Headers -> a
foldedFoldl' a -> ByteString -> ByteString -> a
f a
a (H [(ByteString, ByteString)]
m) = (a -> (ByteString, ByteString) -> a)
-> a -> [(ByteString, ByteString)] -> a
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl' a -> (ByteString, ByteString) -> a
f' a
a [(ByteString, ByteString)]
m
where
f' :: a -> (ByteString, ByteString) -> a
f' a
v (ByteString
x,ByteString
y) = a -> ByteString -> ByteString -> a
f a
v ByteString
x ByteString
y
foldr :: (CI ByteString -> ByteString -> a -> a)
-> a
-> Headers
-> a
foldr :: (CI ByteString -> ByteString -> a -> a) -> a -> Headers -> a
foldr CI ByteString -> ByteString -> a -> a
f a
a (H [(ByteString, ByteString)]
m) = ((ByteString, ByteString) -> a -> a)
-> a -> [(ByteString, ByteString)] -> a
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
List.foldr (ByteString, ByteString) -> a -> a
f' a
a [(ByteString, ByteString)]
m
where
f' :: (ByteString, ByteString) -> a -> a
f' (ByteString
x, ByteString
y) a
v = CI ByteString -> ByteString -> a -> a
f (ByteString -> CI ByteString
forall s. FoldCase s => s -> CI s
CI.unsafeMk ByteString
x) ByteString
y a
v
foldedFoldr :: (ByteString -> ByteString -> a -> a)
-> a
-> Headers
-> a
foldedFoldr :: (ByteString -> ByteString -> a -> a) -> a -> Headers -> a
foldedFoldr ByteString -> ByteString -> a -> a
f a
a (H [(ByteString, ByteString)]
m) = ((ByteString, ByteString) -> a -> a)
-> a -> [(ByteString, ByteString)] -> a
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
List.foldr ((ByteString -> ByteString -> a -> a)
-> (ByteString, ByteString) -> a -> a
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry ByteString -> ByteString -> a -> a
f) a
a [(ByteString, ByteString)]
m
toList :: Headers -> [(CI ByteString, ByteString)]
toList :: Headers -> [(CI ByteString, ByteString)]
toList = ((ByteString, ByteString) -> (CI ByteString, ByteString))
-> [(ByteString, ByteString)] -> [(CI ByteString, ByteString)]
forall a b. (a -> b) -> [a] -> [b]
map ((ByteString -> CI ByteString)
-> (ByteString, ByteString) -> (CI ByteString, ByteString)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first ByteString -> CI ByteString
forall s. FoldCase s => s -> CI s
CI.unsafeMk) ([(ByteString, ByteString)] -> [(CI ByteString, ByteString)])
-> (Headers -> [(ByteString, ByteString)])
-> Headers
-> [(CI ByteString, ByteString)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Headers -> [(ByteString, ByteString)]
unH
fromList :: [(CI ByteString, ByteString)] -> Headers
fromList :: [(CI ByteString, ByteString)] -> Headers
fromList = [(ByteString, ByteString)] -> Headers
H ([(ByteString, ByteString)] -> Headers)
-> ([(CI ByteString, ByteString)] -> [(ByteString, ByteString)])
-> [(CI ByteString, ByteString)]
-> Headers
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((CI ByteString, ByteString) -> (ByteString, ByteString))
-> [(CI ByteString, ByteString)] -> [(ByteString, ByteString)]
forall a b. (a -> b) -> [a] -> [b]
map ((CI ByteString -> ByteString)
-> (CI ByteString, ByteString) -> (ByteString, ByteString)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first CI ByteString -> ByteString
forall s. CI s -> s
CI.foldedCase)
unsafeFromCaseFoldedList :: [(ByteString, ByteString)] -> Headers
unsafeFromCaseFoldedList :: [(ByteString, ByteString)] -> Headers
unsafeFromCaseFoldedList = [(ByteString, ByteString)] -> Headers
H
unsafeToCaseFoldedList :: Headers -> [(ByteString, ByteString)]
unsafeToCaseFoldedList :: Headers -> [(ByteString, ByteString)]
unsafeToCaseFoldedList = Headers -> [(ByteString, ByteString)]
unH