{-# 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
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 = forall (t :: * -> *) a. Foldable t => t a -> Bool
List.null 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 = forall {t :: * -> *} {b}. Foldable t => t (ByteString, b) -> Bool
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. Headers -> [(ByteString, ByteString)]
unH
where
k :: ByteString
k = forall s. CI s -> s
CI.foldedCase CI ByteString
k0
f :: t (ByteString, b) -> Bool
f t (ByteString, b)
m = forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
List.any ((ByteString
k forall a. Eq a => a -> a -> Bool
==) forall b c a. (b -> c) -> (a -> b) -> a -> c
. 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) = forall a b. Eq a => a -> [(a, b)] -> Maybe b
List.lookup (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 = forall a. a -> Maybe a -> a
fromMaybe ByteString
d 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 forall a b. (a -> b) -> a -> b
$! forall {c}.
([(ByteString, ByteString)] -> c)
-> [(ByteString, ByteString)] -> c
go forall a. a -> a
id [(ByteString, ByteString)]
m
where
k :: ByteString
k = 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 forall a. Eq a => a -> a -> Bool
== ByteString
x = [(ByteString, ByteString)] -> c
dl ((ByteString
k, ByteString -> ByteString -> ByteString
concatHeaderValues ByteString
v ByteString
y)forall a. a -> [a] -> [a]
:[(ByteString, ByteString)]
xs)
| Bool
otherwise = ([(ByteString, ByteString)] -> c)
-> [(ByteString, ByteString)] -> c
go ([(ByteString, ByteString)] -> c
dl forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((ByteString, ByteString)
zforall 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)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 forall a b. (a -> b) -> a -> b
$ [(ByteString, ByteString)] -> [(ByteString, ByteString)]
go [(ByteString, ByteString)]
m
where
k :: ByteString
k = 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 forall a. Eq a => a -> a -> Bool
== ByteString
k' = (ByteString
k,ByteString
v) forall a. a -> [a] -> [a]
: forall a. (a -> Bool) -> [a] -> [a]
List.filter ((ByteString
k forall a. Eq a => a -> a -> Bool
/=) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst) [(ByteString, ByteString)]
xs
| Bool
otherwise = (ByteString, ByteString)
x 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 forall a b. (a -> b) -> a -> b
$ forall a. (a -> Bool) -> [a] -> [a]
List.filter ((ByteString
k' forall a. Eq a => a -> a -> Bool
/=) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst) [(ByteString, ByteString)]
m
where
k' :: ByteString
k' = forall s. CI s -> s
CI.foldedCase CI ByteString
k
foldl' :: (a -> CI ByteString -> ByteString -> a)
-> a
-> Headers
-> a
foldl' :: forall a.
(a -> CI ByteString -> ByteString -> a) -> a -> Headers -> a
foldl' a -> CI ByteString -> ByteString -> a
f a
a (H [(ByteString, ByteString)]
m) = 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 (forall s. FoldCase s => s -> CI s
CI.unsafeMk ByteString
x) ByteString
y
foldedFoldl' :: (a -> ByteString -> ByteString -> a)
-> a
-> Headers
-> a
foldedFoldl' :: forall a. (a -> ByteString -> ByteString -> a) -> a -> Headers -> a
foldedFoldl' a -> ByteString -> ByteString -> a
f a
a (H [(ByteString, ByteString)]
m) = 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 :: forall a.
(CI ByteString -> ByteString -> a -> a) -> a -> Headers -> a
foldr CI ByteString -> ByteString -> a -> a
f a
a (H [(ByteString, ByteString)]
m) = 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 (forall s. FoldCase s => s -> CI s
CI.unsafeMk ByteString
x) ByteString
y a
v
foldedFoldr :: (ByteString -> ByteString -> a -> a)
-> a
-> Headers
-> a
foldedFoldr :: forall a. (ByteString -> ByteString -> a -> a) -> a -> Headers -> a
foldedFoldr ByteString -> ByteString -> a -> a
f a
a (H [(ByteString, ByteString)]
m) = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
List.foldr (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 = forall a b. (a -> b) -> [a] -> [b]
map (forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first forall s. FoldCase s => s -> CI s
CI.unsafeMk) 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 forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map (forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first 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