{-# OPTIONS_HADDOCK not-home        #-}
{-# OPTIONS_GHC -Wno-redundant-constraints #-}
module Servant.API.ResponseHeaders
    ( Headers(..)
    , ResponseHeader (..)
    , AddHeader
    , addHeader
    , addHeader'
    , noHeader
    , noHeader'
    , HasResponseHeader
    , lookupResponseHeader
    , BuildHeadersTo(buildHeadersTo)
    , GetHeaders(getHeaders)
    , GetHeaders'
    , HeaderValMap
    , HList(..)
    ) where
import           Control.DeepSeq
                 (NFData (..))
import           Data.ByteString.Char8     as BS
                 (ByteString, pack)
import qualified Data.CaseInsensitive      as CI
import           Data.Kind
                 (Type)
import qualified Data.List                 as L
import           Data.Proxy
import           Data.Typeable
                 (Typeable)
import           GHC.TypeLits
                 (KnownSymbol, Symbol, symbolVal)
import qualified Network.HTTP.Types.Header as HTTP
import           Web.HttpApiData
                 (FromHttpApiData, ToHttpApiData, parseHeader, toHeader)
import           Servant.API.Header
                 (Header')
import           Servant.API.Modifiers
                 (Optional, Strict)
import           Servant.API.UVerb.Union
import qualified Data.SOP.BasicFunctors as SOP
import qualified Data.SOP.NS as SOP
data  ls a =  {  :: a
                            
                            ,  :: HList ls
                            
                            } deriving ((forall a b. (a -> b) -> Headers ls a -> Headers ls b)
-> (forall a b. a -> Headers ls b -> Headers ls a)
-> Functor (Headers ls)
forall (ls :: [Type]) a b. a -> Headers ls b -> Headers ls a
forall (ls :: [Type]) a b. (a -> b) -> Headers ls a -> Headers ls b
forall a b. a -> Headers ls b -> Headers ls a
forall a b. (a -> b) -> Headers ls a -> Headers ls b
forall (f :: Type -> Type).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall (ls :: [Type]) a b. (a -> b) -> Headers ls a -> Headers ls b
fmap :: forall a b. (a -> b) -> Headers ls a -> Headers ls b
$c<$ :: forall (ls :: [Type]) a b. a -> Headers ls b -> Headers ls a
<$ :: forall a b. a -> Headers ls b -> Headers ls a
Functor)
instance (NFDataHList ls, NFData a) => NFData (Headers ls a) where
    rnf :: Headers ls a -> ()
rnf (Headers a
x HList ls
hdrs) = a -> ()
forall a. NFData a => a -> ()
rnf a
x () -> () -> ()
forall a b. a -> b -> b
`seq` HList ls -> ()
forall a. NFData a => a -> ()
rnf HList ls
hdrs
data  (sym :: Symbol) a
    =  a
    | 
    |  ByteString
  deriving (Typeable, ResponseHeader sym a -> ResponseHeader sym a -> Bool
(ResponseHeader sym a -> ResponseHeader sym a -> Bool)
-> (ResponseHeader sym a -> ResponseHeader sym a -> Bool)
-> Eq (ResponseHeader sym a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (sym :: Symbol) a.
Eq a =>
ResponseHeader sym a -> ResponseHeader sym a -> Bool
$c== :: forall (sym :: Symbol) a.
Eq a =>
ResponseHeader sym a -> ResponseHeader sym a -> Bool
== :: ResponseHeader sym a -> ResponseHeader sym a -> Bool
$c/= :: forall (sym :: Symbol) a.
Eq a =>
ResponseHeader sym a -> ResponseHeader sym a -> Bool
/= :: ResponseHeader sym a -> ResponseHeader sym a -> Bool
Eq, Int -> ResponseHeader sym a -> ShowS
[ResponseHeader sym a] -> ShowS
ResponseHeader sym a -> String
(Int -> ResponseHeader sym a -> ShowS)
-> (ResponseHeader sym a -> String)
-> ([ResponseHeader sym a] -> ShowS)
-> Show (ResponseHeader sym a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (sym :: Symbol) a.
Show a =>
Int -> ResponseHeader sym a -> ShowS
forall (sym :: Symbol) a. Show a => [ResponseHeader sym a] -> ShowS
forall (sym :: Symbol) a. Show a => ResponseHeader sym a -> String
$cshowsPrec :: forall (sym :: Symbol) a.
Show a =>
Int -> ResponseHeader sym a -> ShowS
showsPrec :: Int -> ResponseHeader sym a -> ShowS
$cshow :: forall (sym :: Symbol) a. Show a => ResponseHeader sym a -> String
show :: ResponseHeader sym a -> String
$cshowList :: forall (sym :: Symbol) a. Show a => [ResponseHeader sym a] -> ShowS
showList :: [ResponseHeader sym a] -> ShowS
Show, (forall a b.
 (a -> b) -> ResponseHeader sym a -> ResponseHeader sym b)
-> (forall a b. a -> ResponseHeader sym b -> ResponseHeader sym a)
-> Functor (ResponseHeader sym)
forall a b. a -> ResponseHeader sym b -> ResponseHeader sym a
forall a b.
(a -> b) -> ResponseHeader sym a -> ResponseHeader sym b
forall (sym :: Symbol) a b.
a -> ResponseHeader sym b -> ResponseHeader sym a
forall (sym :: Symbol) a b.
(a -> b) -> ResponseHeader sym a -> ResponseHeader sym b
forall (f :: Type -> Type).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall (sym :: Symbol) a b.
(a -> b) -> ResponseHeader sym a -> ResponseHeader sym b
fmap :: forall a b.
(a -> b) -> ResponseHeader sym a -> ResponseHeader sym b
$c<$ :: forall (sym :: Symbol) a b.
a -> ResponseHeader sym b -> ResponseHeader sym a
<$ :: forall a b. a -> ResponseHeader sym b -> ResponseHeader sym a
Functor)
instance NFData a => NFData (ResponseHeader sym a) where
    rnf :: ResponseHeader sym a -> ()
rnf ResponseHeader sym a
MissingHeader          = ()
    rnf (UndecodableHeader ByteString
bs) = ByteString -> ()
forall a. NFData a => a -> ()
rnf ByteString
bs
    rnf (Header a
x)             = a -> ()
forall a. NFData a => a -> ()
rnf a
x
data HList a where
    HNil  :: HList '[]
    HCons :: ResponseHeader h x -> HList xs -> HList (Header' mods h x ': xs)
class NFDataHList xs where rnfHList :: HList xs -> ()
instance NFDataHList '[] where rnfHList :: HList '[] -> ()
rnfHList HList '[]
HNil = ()
instance (y ~ Header' mods h x, NFData x, NFDataHList xs) => NFDataHList (y ': xs) where
    rnfHList :: HList (y : xs) -> ()
rnfHList (HCons ResponseHeader h x
h HList xs
xs) = ResponseHeader h x -> ()
forall a. NFData a => a -> ()
rnf ResponseHeader h x
h () -> () -> ()
forall a b. a -> b -> b
`seq` HList xs -> ()
forall (xs :: [Type]). NFDataHList xs => HList xs -> ()
rnfHList HList xs
xs
instance NFDataHList xs => NFData (HList xs) where
    rnf :: HList xs -> ()
rnf = HList xs -> ()
forall (xs :: [Type]). NFDataHList xs => HList xs -> ()
rnfHList
type family  (f :: Type -> Type) (xs :: [Type]) where
     f '[]                = '[]
     f (Header' mods h x ': xs) = Header' mods h (f x) ': HeaderValMap f xs
class  hs where
     :: [HTTP.Header] -> HList hs
instance {-# OVERLAPPING #-} BuildHeadersTo '[] where
    buildHeadersTo :: [Header] -> HList '[]
buildHeadersTo [Header]
_ = HList '[]
HNil
instance {-# OVERLAPPABLE #-} ( FromHttpApiData v, BuildHeadersTo xs, KnownSymbol h )
         => BuildHeadersTo (Header' mods h v ': xs) where
    buildHeadersTo :: [Header] -> HList (Header' mods h v : xs)
buildHeadersTo [Header]
headers = case (Header -> Bool) -> [Header] -> Maybe Header
forall (t :: Type -> Type) a.
Foldable t =>
(a -> Bool) -> t a -> Maybe a
L.find Header -> Bool
wantedHeader [Header]
headers of
      Maybe Header
Nothing -> ResponseHeader h v
forall (sym :: Symbol) a. ResponseHeader sym a
MissingHeader ResponseHeader h v -> HList xs -> HList (Header' mods h v : xs)
forall (h :: Symbol) x (xs :: [Type]) (mods :: [Type]).
ResponseHeader h x -> HList xs -> HList (Header' mods h x : xs)
`HCons` [Header] -> HList xs
forall (hs :: [Type]). BuildHeadersTo hs => [Header] -> HList hs
buildHeadersTo [Header]
headers
      Just header :: Header
header@(CI ByteString
_, ByteString
val) -> case ByteString -> Either Text v
forall a. FromHttpApiData a => ByteString -> Either Text a
parseHeader ByteString
val of
        Left Text
_err -> ByteString -> ResponseHeader h v
forall (sym :: Symbol) a. ByteString -> ResponseHeader sym a
UndecodableHeader ByteString
val ResponseHeader h v -> HList xs -> HList (Header' mods h v : xs)
forall (h :: Symbol) x (xs :: [Type]) (mods :: [Type]).
ResponseHeader h x -> HList xs -> HList (Header' mods h x : xs)
`HCons` [Header] -> HList xs
forall (hs :: [Type]). BuildHeadersTo hs => [Header] -> HList hs
buildHeadersTo (Header -> [Header] -> [Header]
forall a. Eq a => a -> [a] -> [a]
L.delete Header
header [Header]
headers)
        Right v
h   -> v -> ResponseHeader h v
forall (sym :: Symbol) a. a -> ResponseHeader sym a
Header v
h ResponseHeader h v -> HList xs -> HList (Header' mods h v : xs)
forall (h :: Symbol) x (xs :: [Type]) (mods :: [Type]).
ResponseHeader h x -> HList xs -> HList (Header' mods h x : xs)
`HCons` [Header] -> HList xs
forall (hs :: [Type]). BuildHeadersTo hs => [Header] -> HList hs
buildHeadersTo (Header -> [Header] -> [Header]
forall a. Eq a => a -> [a] -> [a]
L.delete Header
header [Header]
headers)
      where wantedHeader :: Header -> Bool
wantedHeader (CI ByteString
h, ByteString
_) = CI ByteString
h CI ByteString -> CI ByteString -> Bool
forall a. Eq a => a -> a -> Bool
== CI ByteString
wantedHeaderName
            wantedHeaderName :: CI ByteString
wantedHeaderName = ByteString -> CI ByteString
forall s. FoldCase s => s -> CI s
CI.mk (ByteString -> CI ByteString)
-> (String -> ByteString) -> String -> CI ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ByteString
pack (String -> CI ByteString) -> String -> CI ByteString
forall a b. (a -> b) -> a -> b
$ Proxy h -> String
forall (n :: Symbol) (proxy :: Symbol -> Type).
KnownSymbol n =>
proxy n -> String
symbolVal (Proxy h
forall {k} (t :: k). Proxy t
Proxy :: Proxy h)
class  ls where
     :: ls -> [HTTP.Header]
class  hs where
     :: HList hs  -> [HTTP.Header]
instance GetHeadersFromHList hs => GetHeaders (HList hs) where
    getHeaders :: HList hs -> [Header]
getHeaders = HList hs -> [Header]
forall (hs :: [Type]).
GetHeadersFromHList hs =>
HList hs -> [Header]
getHeadersFromHList
instance GetHeadersFromHList '[] where
    getHeadersFromHList :: HList '[] -> [Header]
getHeadersFromHList HList '[]
_ = []
instance (KnownSymbol h, ToHttpApiData x, GetHeadersFromHList xs)
    => GetHeadersFromHList (Header' mods h x ': xs)
  where
    getHeadersFromHList :: HList (Header' mods h x : xs) -> [Header]
getHeadersFromHList HList (Header' mods h x : xs)
hdrs = case HList (Header' mods h x : xs)
hdrs of
        Header x
val `HCons` HList xs
rest          -> (CI ByteString
headerName , x -> ByteString
forall a. ToHttpApiData a => a -> ByteString
toHeader x
val) Header -> [Header] -> [Header]
forall a. a -> [a] -> [a]
: HList xs -> [Header]
forall (hs :: [Type]).
GetHeadersFromHList hs =>
HList hs -> [Header]
getHeadersFromHList HList xs
rest
        UndecodableHeader ByteString
h `HCons` HList xs
rest -> (CI ByteString
headerName,  ByteString
h) Header -> [Header] -> [Header]
forall a. a -> [a] -> [a]
: HList xs -> [Header]
forall (hs :: [Type]).
GetHeadersFromHList hs =>
HList hs -> [Header]
getHeadersFromHList HList xs
rest
        ResponseHeader h x
MissingHeader `HCons` HList xs
rest       -> HList xs -> [Header]
forall (hs :: [Type]).
GetHeadersFromHList hs =>
HList hs -> [Header]
getHeadersFromHList HList xs
rest
      where
        headerName :: CI ByteString
headerName = ByteString -> CI ByteString
forall s. FoldCase s => s -> CI s
CI.mk (ByteString -> CI ByteString)
-> (String -> ByteString) -> String -> CI ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ByteString
pack (String -> CI ByteString) -> String -> CI ByteString
forall a b. (a -> b) -> a -> b
$ Proxy h -> String
forall (n :: Symbol) (proxy :: Symbol -> Type).
KnownSymbol n =>
proxy n -> String
symbolVal (Proxy h
forall {k} (t :: k). Proxy t
Proxy :: Proxy h)
class  hs where
     :: Headers hs a -> [HTTP.Header]
instance GetHeaders' hs => GetHeaders (Headers hs a) where
    getHeaders :: Headers hs a -> [Header]
getHeaders = Headers hs a -> [Header]
forall (hs :: [Type]) a. GetHeaders' hs => Headers hs a -> [Header]
forall a. Headers hs a -> [Header]
getHeaders'
instance GetHeaders' '[] where
    getHeaders' :: forall a. Headers '[] a -> [Header]
getHeaders' Headers '[] a
_ = []
instance (KnownSymbol h, GetHeadersFromHList rest, ToHttpApiData v)
    => GetHeaders' (Header' mods h v ': rest)
  where
    getHeaders' :: forall a. Headers (Header' mods h v : rest) a -> [Header]
getHeaders' Headers (Header' mods h v : rest) a
hs = HList (Header' mods h v : rest) -> [Header]
forall (hs :: [Type]).
GetHeadersFromHList hs =>
HList hs -> [Header]
getHeadersFromHList (HList (Header' mods h v : rest) -> [Header])
-> HList (Header' mods h v : rest) -> [Header]
forall a b. (a -> b) -> a -> b
$ Headers (Header' mods h v : rest) a
-> HList (Header' mods h v : rest)
forall (ls :: [Type]) a. Headers ls a -> HList ls
getHeadersHList Headers (Header' mods h v : rest) a
hs
class  (mods :: [Type]) h v orig new
    | mods h v orig -> new, new -> mods, new -> h, new -> v, new -> orig where
   :: ResponseHeader h v -> orig -> new  
instance {-# OVERLAPPING #-} ( KnownSymbol h, ToHttpApiData v )
         => AddHeader mods h v (Headers (fst ': rest)  a) (Headers (Header' mods h v  ': fst ': rest) a) where
    addOptionalHeader :: ResponseHeader h v
-> Headers (fst : rest) a
-> Headers (Header' mods h v : fst : rest) a
addOptionalHeader ResponseHeader h v
hdr (Headers a
resp HList (fst : rest)
heads) = a
-> HList (Header' mods h v : fst : rest)
-> Headers (Header' mods h v : fst : rest) a
forall (ls :: [Type]) a. a -> HList ls -> Headers ls a
Headers a
resp (ResponseHeader h v
-> HList (fst : rest) -> HList (Header' mods h v : fst : rest)
forall (h :: Symbol) x (xs :: [Type]) (mods :: [Type]).
ResponseHeader h x -> HList xs -> HList (Header' mods h x : xs)
HCons ResponseHeader h v
hdr HList (fst : rest)
heads)
instance {-# OVERLAPPABLE #-} ( KnownSymbol h, ToHttpApiData v , new ~ Headers '[Header' mods h v] a)
         => AddHeader mods h v a new where
    addOptionalHeader :: ResponseHeader h v -> a -> new
addOptionalHeader ResponseHeader h v
hdr a
resp = a -> HList '[Header' mods h v] -> Headers '[Header' mods h v] a
forall (ls :: [Type]) a. a -> HList ls -> Headers ls a
Headers a
resp (ResponseHeader h v -> HList '[] -> HList '[Header' mods h v]
forall (h :: Symbol) x (xs :: [Type]) (mods :: [Type]).
ResponseHeader h x -> HList xs -> HList (Header' mods h x : xs)
HCons ResponseHeader h v
hdr HList '[]
HNil)
instance (AddHeader mods h v old new) => AddHeader mods h v (Union '[old]) (Union '[new]) where
  addOptionalHeader :: ResponseHeader h v -> Union '[old] -> Union '[new]
addOptionalHeader ResponseHeader h v
hdr Union '[old]
resp =
    I new -> Union '[new]
forall {k} (a :: k -> Type) (x :: k) (xs :: [k]).
a x -> NS a (x : xs)
SOP.Z (I new -> Union '[new]) -> I new -> Union '[new]
forall a b. (a -> b) -> a -> b
$ new -> I new
forall a. a -> I a
SOP.I (new -> I new) -> new -> I new
forall a b. (a -> b) -> a -> b
$ ResponseHeader h v -> old -> new
forall (mods :: [Type]) (h :: Symbol) v orig new.
AddHeader mods h v orig new =>
ResponseHeader h v -> orig -> new
addOptionalHeader ResponseHeader h v
hdr (old -> new) -> old -> new
forall a b. (a -> b) -> a -> b
$ I old -> old
forall a. I a -> a
SOP.unI (I old -> old) -> I old -> old
forall a b. (a -> b) -> a -> b
$ Union '[old] -> I old
forall {k} (f :: k -> Type) (x :: k). NS f '[x] -> f x
SOP.unZ Union '[old]
resp
instance
  ( AddHeader mods h v old new, AddHeader mods h v (Union oldrest) (Union newrest)
  
  
  
  , oldrest ~ (a ': as), newrest ~ (b ': bs))
  => AddHeader mods h v (Union (old ': (a ': as))) (Union (new ': (b ': bs))) where
  addOptionalHeader :: ResponseHeader h v -> Union (old : a : as) -> Union (new : b : bs)
addOptionalHeader ResponseHeader h v
hdr Union (old : a : as)
resp = case Union (old : a : as)
resp of
    SOP.Z (SOP.I x
rHead) -> I new -> Union (new : b : bs)
forall {k} (a :: k -> Type) (x :: k) (xs :: [k]).
a x -> NS a (x : xs)
SOP.Z (I new -> Union (new : b : bs)) -> I new -> Union (new : b : bs)
forall a b. (a -> b) -> a -> b
$ new -> I new
forall a. a -> I a
SOP.I (new -> I new) -> new -> I new
forall a b. (a -> b) -> a -> b
$ ResponseHeader h v -> x -> new
forall (mods :: [Type]) (h :: Symbol) v orig new.
AddHeader mods h v orig new =>
ResponseHeader h v -> orig -> new
addOptionalHeader ResponseHeader h v
hdr x
rHead
    SOP.S NS I xs
rOthers -> Union (b : bs) -> Union (new : b : bs)
forall {k} (a :: k -> Type) (xs :: [k]) (x :: k).
NS a xs -> NS a (x : xs)
SOP.S (Union (b : bs) -> Union (new : b : bs))
-> Union (b : bs) -> Union (new : b : bs)
forall a b. (a -> b) -> a -> b
$ ResponseHeader h v -> NS I xs -> Union (b : bs)
forall (mods :: [Type]) (h :: Symbol) v orig new.
AddHeader mods h v orig new =>
ResponseHeader h v -> orig -> new
addOptionalHeader ResponseHeader h v
hdr NS I xs
rOthers
addHeader :: AddHeader '[Optional, Strict] h v orig new => v -> orig -> new
 = ResponseHeader h v -> orig -> new
forall (mods :: [Type]) (h :: Symbol) v orig new.
AddHeader mods h v orig new =>
ResponseHeader h v -> orig -> new
addOptionalHeader (ResponseHeader h v -> orig -> new)
-> (v -> ResponseHeader h v) -> v -> orig -> new
forall b c a. (b -> c) -> (a -> b) -> a -> c
. v -> ResponseHeader h v
forall (sym :: Symbol) a. a -> ResponseHeader sym a
Header
addHeader' :: AddHeader mods h v orig new => v -> orig -> new
 = ResponseHeader h v -> orig -> new
forall (mods :: [Type]) (h :: Symbol) v orig new.
AddHeader mods h v orig new =>
ResponseHeader h v -> orig -> new
addOptionalHeader (ResponseHeader h v -> orig -> new)
-> (v -> ResponseHeader h v) -> v -> orig -> new
forall b c a. (b -> c) -> (a -> b) -> a -> c
. v -> ResponseHeader h v
forall (sym :: Symbol) a. a -> ResponseHeader sym a
Header
noHeader :: AddHeader '[Optional, Strict] h v orig new => orig -> new
 = ResponseHeader h v -> orig -> new
forall (mods :: [Type]) (h :: Symbol) v orig new.
AddHeader mods h v orig new =>
ResponseHeader h v -> orig -> new
addOptionalHeader ResponseHeader h v
forall (sym :: Symbol) a. ResponseHeader sym a
MissingHeader
noHeader' :: AddHeader mods h v orig new => orig -> new
 = ResponseHeader h v -> orig -> new
forall (mods :: [Type]) (h :: Symbol) v orig new.
AddHeader mods h v orig new =>
ResponseHeader h v -> orig -> new
addOptionalHeader ResponseHeader h v
forall (sym :: Symbol) a. ResponseHeader sym a
MissingHeader
class  h a headers where
   :: HList headers -> ResponseHeader h a
instance {-# OVERLAPPING #-} HasResponseHeader h a (Header' mods h a ': rest) where
  hlistLookupHeader :: HList (Header' mods h a : rest) -> ResponseHeader h a
hlistLookupHeader (HCons ResponseHeader h x
ha HList xs
_) = ResponseHeader h a
ResponseHeader h x
ha
instance {-# OVERLAPPABLE #-} (HasResponseHeader h a rest) => HasResponseHeader h a (first ': rest) where
  hlistLookupHeader :: HList (first : rest) -> ResponseHeader h a
hlistLookupHeader (HCons ResponseHeader h x
_ HList xs
hs) = HList xs -> ResponseHeader h a
forall (h :: Symbol) a (headers :: [Type]).
HasResponseHeader h a headers =>
HList headers -> ResponseHeader h a
hlistLookupHeader HList xs
hs
lookupResponseHeader :: (HasResponseHeader h a headers)
  => Headers headers r -> ResponseHeader h a
 = HList headers -> ResponseHeader h a
forall (h :: Symbol) a (headers :: [Type]).
HasResponseHeader h a headers =>
HList headers -> ResponseHeader h a
hlistLookupHeader (HList headers -> ResponseHeader h a)
-> (Headers headers r -> HList headers)
-> Headers headers r
-> ResponseHeader h a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Headers headers r -> HList headers
forall (ls :: [Type]) a. Headers ls a -> HList ls
getHeadersHList