capnp-0.11.0.0: lib/Capnp/Rpc/Invoke.hs
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TypeFamilies #-}
-- |
-- Module: Capnp.Rpc.Invoke
-- Description: Invoke remote methods
--
-- Support for invoking 'Server.MethodHandler's
module Capnp.Rpc.Invoke
(
-- * Using high-level representations
invokePurePromise
, (?)
, invokePure
, InvokePureCtx
-- * Using low level representations
, invokeRaw
) where
import Control.Monad.STM.Class
import Control.Monad.Catch (MonadThrow)
import Control.Monad.Primitive (PrimMonad, PrimState)
import Capnp.Classes
( Cerialize(cerialize)
, Decerialize(Cerial, decerialize)
, FromPtr(fromPtr)
, ToStruct(toStruct)
)
import Capnp.Message (Mutability(..))
import Capnp.TraversalLimit (defaultLimit, evalLimitT)
import Data.Mutable (freeze)
import qualified Capnp.Message as M
import qualified Capnp.Rpc.Promise as Promise
import qualified Capnp.Rpc.Server as Server
import qualified Capnp.Untyped as U
-- | Invoke a method by passing it the low-level representation of its parameter,
-- and a 'Fulfiller' that can be used to supply (the low-level representation of)
-- its return value.
invokeRaw ::
( MonadThrow m
, MonadSTM m
, PrimMonad m
, Decerialize r
, Decerialize p
, ToStruct 'Const (Cerial 'Const p)
, FromPtr 'Const (Cerial 'Const r)
) =>
Server.MethodHandler m p r
-> Cerial 'Const p
-> Promise.Fulfiller (Cerial 'Const r)
-> m ()
invokeRaw method params typedFulfiller = do
(_, untypedFulfiller) <- liftSTM $ Promise.newPromiseWithCallback $ \case
Left e -> Promise.breakPromise typedFulfiller e
Right v -> evalLimitT defaultLimit (fromPtr M.empty v) >>= Promise.fulfill typedFulfiller
Server.invoke
(Server.toUntypedHandler method)
(Just (U.PtrStruct (toStruct params)))
untypedFulfiller
-- | Shorthand for class contstraints needed to invoke a method using
-- the high-level API.
type InvokePureCtx m p r =
( MonadThrow m
, MonadSTM m
, PrimMonad m
, Decerialize r
, ToStruct 'Const (Cerial 'Const p)
, ToStruct ('Mut (PrimState m)) (Cerial ('Mut (PrimState m)) p)
, Cerialize (PrimState m) p
, FromPtr 'Const (Cerial 'Const r)
)
-- | Like 'invokeRaw', but uses the high-level representations of the data
-- types.
invokePure
:: InvokePureCtx m p r
=> Server.MethodHandler m p r
-> p
-> Promise.Fulfiller r
-> m ()
invokePure method params pureFulfiller = do
struct <- evalLimitT defaultLimit $ do
msg <- M.newMessage Nothing
cerialize msg params >>= freeze . toStruct
(_, untypedFulfiller) <- liftSTM $ Promise.newPromiseWithCallback $ \case
Left e -> Promise.breakPromise pureFulfiller e
Right v ->
evalLimitT defaultLimit (fromPtr M.empty v >>= decerialize)
>>= Promise.fulfill pureFulfiller
Server.invoke
(Server.toUntypedHandler method)
(Just (U.PtrStruct struct))
untypedFulfiller
-- | Like 'invokePure', but returns a promise instead of accepting a fulfiller.
invokePurePromise
:: InvokePureCtx m p r
=> Server.MethodHandler m p r
-> p
-> m (Promise.Promise r)
invokePurePromise method params = do
(promise, fulfiller) <- Promise.newPromise
invokePure method params fulfiller
pure promise
-- | Alias for 'invokePurePromise'
(?) :: InvokePureCtx m p r
=> Server.MethodHandler m p r
-> p
-> m (Promise.Promise r)
(?) = invokePurePromise