mirror of
https://github.com/zap-proto/haskell.git
synced 2026-10-30 15:05:00 +00:00
120 lines
3.5 KiB
Haskell
120 lines
3.5 KiB
Haskell
{-# 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
|