#[non_exhaustive]pub struct ClosureHandler<B: Send + Sync + 'static, C: Clone + Send + 'static> { /* private fields */ }Expand description
A JmapHandler that wraps an async closure over a shared backend and
forwards CallerCtx to it.
Use this when your handler closures need per-request context — for
example, an auth identity that controls which data the handler can
access. Closures that don’t need the context can simply ignore the
ctx parameter.
§Usage
use jmap_server::{ClosureHandler, Dispatcher};
use std::sync::Arc;
#[derive(Clone)]
struct AuthCtx { user_id: String }
let handler: Arc<ClosureHandler<MyBackend, AuthCtx>> =
Arc::new(ClosureHandler::new(
Arc::new(my_backend),
|b, call_id, args, ctx| {
Box::pin(async move {
// ctx.user_id is available here
handle_something(&*b, args, &ctx.user_id).await
})
},
));
let mut dispatcher: Dispatcher<AuthCtx> = Dispatcher::new();
dispatcher.register("MyMethod/get", handler);A JmapHandler handle wrapping a shared backend + an async
closure. Construct via ClosureHandler::new — the fields are
crate-private (bd:JMAP-jfia.5) to keep the handle opaque, prevent
post-construction hot-swap of the closure or backend, and let the
constructor remain the sole site that enforces invariants when
future fields (per-handler tracing context, metrics handle, etc.)
are added.
Implementations§
Source§impl<B: Send + Sync + 'static, C: Clone + Send + 'static> ClosureHandler<B, C>
impl<B: Send + Sync + 'static, C: Clone + Send + 'static> ClosureHandler<B, C>
Sourcepub fn new<F>(backend: Arc<B>, call_fn: F) -> Self
pub fn new<F>(backend: Arc<B>, call_fn: F) -> Self
Construct a ClosureHandler wrapping a shared backend and an
async closure (bd:JMAP-wlip.17).
This is the supported construction path. The struct is
#[non_exhaustive] so future fields (per-handler tracing
context, metrics handle, timeout, etc.) can be added without a
major-version bump — external callers MUST go through new
rather than struct-literal syntax.
The call_fn parameter is generic over
F: Fn(...) + Send + Sync + 'static (bd:JMAP-jfia.40), so
callers can pass a closure directly without wrapping it in
Box::new. Existing callers that already wrap in
Box::new(...) continue to compile unchanged:
Box<dyn Fn(...) + Send + Sync + 'static> itself implements
Fn(...) via the blanket
impl<F: Fn(...)> Fn(...) for Box<F>, so the boxed form
satisfies the generic bound. Internally, the closure is boxed
once at construction and stored as
Box<BackendCallFn<B, C>>.
Trait Implementations§
Source§impl<B: Send + Sync + 'static, C: Clone + Send + 'static> JmapHandler<C> for ClosureHandler<B, C>
impl<B: Send + Sync + 'static, C: Clone + Send + 'static> JmapHandler<C> for ClosureHandler<B, C>
Source§fn call(
&self,
_method: String,
call_id: String,
args: Value,
caller: C,
) -> HandlerFuture
fn call( &self, _method: String, call_id: String, args: Value, caller: C, ) -> HandlerFuture
method is the registered method name for this call. A single handler
instance may be registered under multiple names (e.g. both "Foo/get" and
"Bar/get"); this parameter lets the handler distinguish between them. Read more