{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Servant.API.UVerb
( UVerb,
HasStatus (StatusOf),
statusOf,
HasStatuses (Statuses, statuses),
WithStatus (..),
module Servant.API.UVerb.Union,
)
where
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 :: *) where
type StatusOf (a :: *) :: Nat
statusOf :: forall a proxy. HasStatus a => proxy a -> Status
statusOf :: forall a (proxy :: * -> *). HasStatus a => proxy a -> Status
statusOf = forall a b. a -> b -> a
const (forall (n :: Nat) (proxy :: Nat -> *).
KnownStatus n =>
proxy n -> Status
statusVal (forall {k} (t :: k). Proxy t
Proxy :: Proxy (StatusOf a)))
instance HasStatus NoContent where
type StatusOf NoContent = 204
class HasStatuses (as :: [*]) where
type Statuses (as :: [*]) :: [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)
_ = forall a (proxy :: * -> *). HasStatus a => proxy a -> Status
statusOf (forall {k} (t :: k). Proxy t
Proxy :: Proxy a) forall a. a -> [a] -> [a]
: forall (as :: [*]). HasStatuses as => Proxy as -> [Status]
statuses (forall {k} (t :: k). Proxy t
Proxy :: Proxy as)
newtype WithStatus (k :: Nat) a = WithStatus a
deriving (WithStatus k a -> WithStatus k a -> Bool
forall (k :: Nat) a.
Eq a =>
WithStatus k a -> WithStatus k a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: 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
$c== :: forall (k :: Nat) a.
Eq a =>
WithStatus k a -> WithStatus k a -> Bool
Eq, Int -> WithStatus k a -> ShowS
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
showList :: [WithStatus k a] -> ShowS
$cshowList :: forall (k :: Nat) a. Show a => [WithStatus k a] -> ShowS
show :: WithStatus k a -> String
$cshow :: forall (k :: Nat) a. Show a => WithStatus k a -> String
showsPrec :: Int -> WithStatus k a -> ShowS
$cshowsPrec :: forall (k :: Nat) a. Show a => Int -> 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 :: [*]) (as :: [*])
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) = 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) = 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) = 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) = 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 = forall (k :: Nat) a. a -> WithStatus k a
WithStatus forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> 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 = forall (k :: Nat) a. a -> WithStatus k a
WithStatus forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> 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 = forall (k :: Nat) a. a -> WithStatus k a
WithStatus forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> 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 = forall (k :: Nat) a. a -> WithStatus k a
WithStatus forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall {k} (ctype :: k) a.
MimeUnrender ctype a =>
Proxy ctype -> ByteString -> Either String a
mimeUnrender Proxy OctetStream
contentTypeProxy ByteString
input