grapesy-1.0.0: proto/Proto/API/Interop.hs
{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module Proto.API.Interop (
-- * TestService
-- ** Endpoints
EmptyCall
, UnaryCall
, StreamingInputCall
, StreamingOutputCall
, FullDuplexCall
, UnimplementedCall
-- ** Metadata
, InteropReqMeta(..)
, InteropRespInitMeta(..)
, InteropRespTrailMeta(..)
-- * UnimplementedService
, UnimplementedServiceCall
-- * Re-exports
, module Proto.Empty
, module Proto.Messages
, module Proto.Test
) where
import Data.ByteString qualified as Strict (ByteString)
import Control.Monad.Catch (MonadThrow(throwM))
import Control.Monad.State (StateT, execStateT, modify)
import Network.GRPC.Common
import Network.GRPC.Common.Protobuf
import Proto.Empty
import Proto.Messages
import Proto.Test
{-------------------------------------------------------------------------------
Endpoints
-------------------------------------------------------------------------------}
type EmptyCall = Protobuf TestService "emptyCall"
type UnaryCall = Protobuf TestService "unaryCall"
type StreamingInputCall = Protobuf TestService "streamingInputCall"
type StreamingOutputCall = Protobuf TestService "streamingOutputCall"
type FullDuplexCall = Protobuf TestService "fullDuplexCall"
type UnimplementedCall = Protobuf TestService "unimplementedCall"
{-------------------------------------------------------------------------------
Metadata
-------------------------------------------------------------------------------}
type instance RequestMetadata (Protobuf TestService meth) = InteropReqMeta
type instance ResponseInitialMetadata (Protobuf TestService meth) = InteropRespInitMeta
type instance ResponseTrailingMetadata (Protobuf TestService meth) = InteropRespTrailMeta
data InteropReqMeta = InteropReqMeta {
-- | Header we expect the server to include in the initial metadata
interopExpectInit :: Maybe Strict.ByteString
-- | Header we expect the server to include in the trailng metadata
, interopExpectTrail :: Maybe Strict.ByteString
}
deriving (Show, Eq)
newtype InteropRespInitMeta = InteropRespInitMeta {
-- | Metadata the server /actually/ included in the initial metadata
--
-- See also 'interopExpectInit'
interopActualInit :: Maybe Strict.ByteString
}
deriving (Show, Eq)
newtype InteropRespTrailMeta = InteropRespTrailMeta {
-- | Metadata the server /actually/ included in the trailing metadata
--
-- See also 'interopExpectTrail'
interopActualTrail :: Maybe Strict.ByteString
}
deriving (Show, Eq)
grpcTestEchoInitial :: HeaderName
grpcTestEchoInitial = "x-grpc-test-echo-initial"
grpcTestEchoTrailingBin :: HeaderName
grpcTestEchoTrailingBin = "x-grpc-test-echo-trailing-bin"
{-------------------------------------------------------------------------------
Client instances
-------------------------------------------------------------------------------}
instance Default InteropReqMeta where
def = InteropReqMeta {
interopExpectInit = Nothing
, interopExpectTrail = Nothing
}
instance BuildMetadata InteropReqMeta where
buildMetadata md = concat [
[ CustomMetadata grpcTestEchoInitial val
| Just val <- [interopExpectInit md]
]
, [ CustomMetadata grpcTestEchoTrailingBin val
| Just val <- [interopExpectTrail md]
]
]
instance ParseMetadata InteropRespInitMeta where
parseMetadata headers =
case headers of
[] ->
return $ InteropRespInitMeta $ Nothing
[md] | customMetadataName md == grpcTestEchoInitial ->
return $ InteropRespInitMeta $ Just (customMetadataValue md)
_otherwise ->
throwM $ UnexpectedMetadata headers
instance ParseMetadata InteropRespTrailMeta where
parseMetadata headers =
case headers of
[] ->
return $ InteropRespTrailMeta $ Nothing
[md] | customMetadataName md == grpcTestEchoTrailingBin ->
return $ InteropRespTrailMeta $ Just (customMetadataValue md)
_otherwise ->
throwM $ UnexpectedMetadata headers
{-------------------------------------------------------------------------------
Server instances
-------------------------------------------------------------------------------}
instance Default InteropRespInitMeta where
def = InteropRespInitMeta Nothing
instance Default InteropRespTrailMeta where
def = InteropRespTrailMeta Nothing
instance ParseMetadata InteropReqMeta where
parseMetadata = flip execStateT def . mapM go
where
go :: MonadThrow m => CustomMetadata -> StateT InteropReqMeta m ()
go md
| customMetadataName md == grpcTestEchoInitial
= modify $ \x -> x{interopExpectInit = Just $ customMetadataValue md}
| customMetadataName md == grpcTestEchoTrailingBin
= modify $ \x -> x{interopExpectTrail = Just $ customMetadataValue md}
| otherwise
= throwM $ UnexpectedMetadata [md]
instance BuildMetadata InteropRespInitMeta where
buildMetadata md = concat [
[ CustomMetadata grpcTestEchoInitial val
| Just val <- [interopActualInit md]
]
]
instance BuildMetadata InteropRespTrailMeta where
buildMetadata md = concat [
[ CustomMetadata grpcTestEchoTrailingBin val
| Just val <- [interopActualTrail md]
]
]
instance StaticMetadata InteropRespTrailMeta where
metadataHeaderNames _ = [grpcTestEchoTrailingBin]
{-------------------------------------------------------------------------------
UnimplementedService service
-------------------------------------------------------------------------------}
type UnimplementedServiceCall = Protobuf UnimplementedService "unimplementedCall"
type instance RequestMetadata (Protobuf UnimplementedService meth) = NoMetadata
type instance ResponseInitialMetadata (Protobuf UnimplementedService meth) = NoMetadata
type instance ResponseTrailingMetadata (Protobuf UnimplementedService meth) = NoMetadata