servant-routes-0.1.1.0: src/Servant/API/Routes/Internal/Header.hs
{-# OPTIONS_HADDOCK not-home #-}
{- |
Module : Servant.API.Routes.Internal.Header
Copyright : (c) Frederick Pringle, 2025
License : BSD-3-Clause
Maintainer : frederick.pringle@fpringle.com
Internal module, subject to change.
-}
module Servant.API.Routes.Internal.Header
( HeaderRep (..)
, mkHeaderRep
, GetHeaderReps (..)
)
where
import Data.Aeson
import Data.Kind (Type)
import Data.Text
import Data.Typeable
import GHC.TypeLits
import Servant.API
import "this" Servant.API.Routes.Utils
-- | Convenience function to construct a 'HeaderRep' from @sym :: 'Symbol'@ and @a :: Type'@.
mkHeaderRep ::
forall sym a.
(KnownSymbol sym, Typeable a) =>
HeaderRep
mkHeaderRep =
HeaderRep
{ _hName = knownSymbolT @sym
, _hType = typeRepOf @a
}
{- | Simple term-level representation of a 'Servant.API.Header.Header'.
A type-level @'Servant.API.Header.Header' (sym :: 'GHC.TypeLits.Symbol') typ@ should correspond to
@'HeaderRep' { _hName = str, _hType = typRep }@, where @str@ is the term-level equivalent
of @sym@ and @typRep@ is the term-level representation of @typ@.
-}
data HeaderRep = HeaderRep
{ _hName :: Text
, _hType :: TypeRep
}
deriving (Show, Eq, Ord)
instance ToJSON HeaderRep where
toJSON HeaderRep {..} =
object
[ "name" .= _hName
, "type" .= typeRepToJSON _hType
]
{- | Utility class to let us get a value-level list of 'HeaderRep's from a
type-level list of 'Servant.API.Header.Header's. See the implementation of
@'Servant.API.Route.HasRoutes' ('Verb' method status ctypes ('Headers' hs a))@ for an example.
-}
class GetHeaderReps (hs :: [Type]) where
getHeaderReps :: [HeaderRep]
instance GetHeaderReps '[] where
getHeaderReps = []
instance
(GetHeaderReps rest, KnownSymbol h, Typeable v) =>
GetHeaderReps (Header h v ': rest)
where
getHeaderReps = header : getHeaderReps @rest
where
header = mkHeaderRep @h @v