{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Servant.API.UVerb
( UVerb,
HasStatus (StatusOf),
statusOf,
HasStatuses (Statuses, statuses),
WithStatus (..),
module Servant.API.UVerb.Union,
)
where
import Data.Kind (Type)
import Data.Proxy (Proxy (Proxy))
import GHC.TypeLits (Nat)
import Network.HTTP.Types (Status, StdMethod)
import Servant.API.ContentTypes (JSON, PlainText, FormUrlEncoded, OctetStream, NoContent, MimeRender(mimeRender), MimeUnrender(mimeUnrender))
import Servant.API.Status (KnownStatus, statusVal)
import Servant.API.ResponseHeaders (Headers)
import Servant.API.UVerb.Union
class KnownStatus (StatusOf a) => HasStatus (a :: Type) where
type StatusOf (a :: Type) :: Nat
statusOf :: forall a proxy. HasStatus a => proxy a -> Status
statusOf :: forall a (proxy :: Type -> Type). HasStatus a => proxy a -> Status
statusOf = Status -> proxy a -> Status
forall a b. a -> b -> a
const (Proxy (StatusOf a) -> Status
forall (n :: Nat) (proxy :: Nat -> Type).
KnownStatus n =>
proxy n -> Status
forall (proxy :: Nat -> Type). proxy (StatusOf a) -> Status
statusVal (Proxy (StatusOf a)
forall {k} (t :: k). Proxy t
Proxy :: Proxy (StatusOf a)))
instance HasStatus NoContent where
type StatusOf NoContent = 204
class HasStatuses (as :: [Type]) where
type Statuses (as :: [Type]) :: [Nat]
statuses :: Proxy as -> [Status]
instance HasStatuses '[] where
type Statuses '[] = '[]
statuses :: Proxy '[] -> [Status]
statuses Proxy '[]
_ = []
instance (HasStatus a, HasStatuses as) => HasStatuses (a ': as) where
type Statuses (a ': as) = StatusOf a ': Statuses as
statuses :: Proxy (a : as) -> [Status]
statuses Proxy (a : as)
_ = Proxy a -> Status
forall a (proxy :: Type -> Type). HasStatus a => proxy a -> Status
statusOf (Proxy a
forall {k} (t :: k). Proxy t
Proxy :: Proxy a) Status -> [Status] -> [Status]
forall a. a -> [a] -> [a]
: Proxy as -> [Status]
forall (as :: [Type]). HasStatuses as => Proxy as -> [Status]
statuses (Proxy as
forall {k} (t :: k). Proxy t
Proxy :: Proxy as)
newtype WithStatus (k :: Nat) a = WithStatus a
deriving (WithStatus k a -> WithStatus k a -> Bool
(WithStatus k a -> WithStatus k a -> Bool)
-> (WithStatus k a -> WithStatus k a -> Bool)
-> Eq (WithStatus k a)
forall (k :: Nat) a.
Eq a =>
WithStatus k a -> WithStatus k a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall (k :: Nat) a.
Eq a =>
WithStatus k a -> WithStatus k a -> Bool
== :: WithStatus k a -> WithStatus k a -> Bool
$c/= :: forall (k :: Nat) a.
Eq a =>
WithStatus k a -> WithStatus k a -> Bool
/= :: WithStatus k a -> WithStatus k a -> Bool
Eq, Int -> WithStatus k a -> ShowS
[WithStatus k a] -> ShowS
WithStatus k a -> String
(Int -> WithStatus k a -> ShowS)
-> (WithStatus k a -> String)
-> ([WithStatus k a] -> ShowS)
-> Show (WithStatus k a)
forall (k :: Nat) a. Show a => Int -> WithStatus k a -> ShowS
forall (k :: Nat) a. Show a => [WithStatus k a] -> ShowS
forall (k :: Nat) a. Show a => WithStatus k a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall (k :: Nat) a. Show a => Int -> WithStatus k a -> ShowS
showsPrec :: Int -> WithStatus k a -> ShowS
$cshow :: forall (k :: Nat) a. Show a => WithStatus k a -> String
show :: WithStatus k a -> String
$cshowList :: forall (k :: Nat) a. Show a => [WithStatus k a] -> ShowS
showList :: [WithStatus k a] -> ShowS
Show)
instance KnownStatus n => HasStatus (WithStatus n a) where
type StatusOf (WithStatus n a) = n
instance HasStatus a => HasStatus (Headers ls a) where
type StatusOf (Headers ls a) = StatusOf a
data UVerb (method :: StdMethod) (contentTypes :: [Type]) (as :: [Type])
instance {-# OVERLAPPING #-} MimeRender JSON a => MimeRender JSON (WithStatus _status a) where
mimeRender :: Proxy JSON -> WithStatus _status a -> ByteString
mimeRender Proxy JSON
contentTypeProxy (WithStatus a
a) = Proxy JSON -> a -> ByteString
forall {k} (ctype :: k) a.
MimeRender ctype a =>
Proxy ctype -> a -> ByteString
mimeRender Proxy JSON
contentTypeProxy a
a
instance {-# OVERLAPPING #-} MimeRender PlainText a => MimeRender PlainText (WithStatus _status a) where
mimeRender :: Proxy PlainText -> WithStatus _status a -> ByteString
mimeRender Proxy PlainText
contentTypeProxy (WithStatus a
a) = Proxy PlainText -> a -> ByteString
forall {k} (ctype :: k) a.
MimeRender ctype a =>
Proxy ctype -> a -> ByteString
mimeRender Proxy PlainText
contentTypeProxy a
a
instance {-# OVERLAPPING #-} MimeRender FormUrlEncoded a => MimeRender FormUrlEncoded (WithStatus _status a) where
mimeRender :: Proxy FormUrlEncoded -> WithStatus _status a -> ByteString
mimeRender Proxy FormUrlEncoded
contentTypeProxy (WithStatus a
a) = Proxy FormUrlEncoded -> a -> ByteString
forall {k} (ctype :: k) a.
MimeRender ctype a =>
Proxy ctype -> a -> ByteString
mimeRender Proxy FormUrlEncoded
contentTypeProxy a
a
instance {-# OVERLAPPING #-} MimeRender OctetStream a => MimeRender OctetStream (WithStatus _status a) where
mimeRender :: Proxy OctetStream -> WithStatus _status a -> ByteString
mimeRender Proxy OctetStream
contentTypeProxy (WithStatus a
a) = Proxy OctetStream -> a -> ByteString
forall {k} (ctype :: k) a.
MimeRender ctype a =>
Proxy ctype -> a -> ByteString
mimeRender Proxy OctetStream
contentTypeProxy a
a
instance {-# OVERLAPPING #-} MimeUnrender JSON a => MimeUnrender JSON (WithStatus _status a) where
mimeUnrender :: Proxy JSON -> ByteString -> Either String (WithStatus _status a)
mimeUnrender Proxy JSON
contentTypeProxy ByteString
input = a -> WithStatus _status a
forall (k :: Nat) a. a -> WithStatus k a
WithStatus (a -> WithStatus _status a)
-> Either String a -> Either String (WithStatus _status a)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Proxy JSON -> ByteString -> Either String a
forall {k} (ctype :: k) a.
MimeUnrender ctype a =>
Proxy ctype -> ByteString -> Either String a
mimeUnrender Proxy JSON
contentTypeProxy ByteString
input
instance {-# OVERLAPPING #-} MimeUnrender PlainText a => MimeUnrender PlainText (WithStatus _status a) where
mimeUnrender :: Proxy PlainText
-> ByteString -> Either String (WithStatus _status a)
mimeUnrender Proxy PlainText
contentTypeProxy ByteString
input = a -> WithStatus _status a
forall (k :: Nat) a. a -> WithStatus k a
WithStatus (a -> WithStatus _status a)
-> Either String a -> Either String (WithStatus _status a)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Proxy PlainText -> ByteString -> Either String a
forall {k} (ctype :: k) a.
MimeUnrender ctype a =>
Proxy ctype -> ByteString -> Either String a
mimeUnrender Proxy PlainText
contentTypeProxy ByteString
input
instance {-# OVERLAPPING #-} MimeUnrender FormUrlEncoded a => MimeUnrender FormUrlEncoded (WithStatus _status a) where
mimeUnrender :: Proxy FormUrlEncoded
-> ByteString -> Either String (WithStatus _status a)
mimeUnrender Proxy FormUrlEncoded
contentTypeProxy ByteString
input = a -> WithStatus _status a
forall (k :: Nat) a. a -> WithStatus k a
WithStatus (a -> WithStatus _status a)
-> Either String a -> Either String (WithStatus _status a)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Proxy FormUrlEncoded -> ByteString -> Either String a
forall {k} (ctype :: k) a.
MimeUnrender ctype a =>
Proxy ctype -> ByteString -> Either String a
mimeUnrender Proxy FormUrlEncoded
contentTypeProxy ByteString
input
instance {-# OVERLAPPING #-} MimeUnrender OctetStream a => MimeUnrender OctetStream (WithStatus _status a) where
mimeUnrender :: Proxy OctetStream
-> ByteString -> Either String (WithStatus _status a)
mimeUnrender Proxy OctetStream
contentTypeProxy ByteString
input = a -> WithStatus _status a
forall (k :: Nat) a. a -> WithStatus k a
WithStatus (a -> WithStatus _status a)
-> Either String a -> Either String (WithStatus _status a)
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> Proxy OctetStream -> ByteString -> Either String a
forall {k} (ctype :: k) a.
MimeUnrender ctype a =>
Proxy ctype -> ByteString -> Either String a
mimeUnrender Proxy OctetStream
contentTypeProxy ByteString
input