Skip to main content

lgui_core/command/
contract.rs

1use std::{future::Future, pin::Pin};
2
3use super::CommandContext;
4
5pub type CommandFuture<C> = Pin<
6    Box<
7        dyn Future<Output = Result<<C as Command>::Output, <C as Command>::Error>> + Send + 'static,
8    >,
9>;
10
11/// A typed application command contract.
12///
13/// `NAME` is used only for diagnostics. Commands are registered and resolved by
14/// their Rust type, so arguments and results never pass through serialization.
15pub trait Command: Send + Sync + 'static {
16    type Args: Send + 'static;
17    type Output: Send + 'static;
18    type Error: Send + 'static;
19
20    const NAME: &'static str;
21}
22
23pub trait CommandHandler<C>: Send + Sync + 'static
24where
25    C: Command,
26{
27    fn call(&self, context: CommandContext, args: C::Args) -> CommandFuture<C>;
28}
29
30impl<C, F, Fut> CommandHandler<C> for F
31where
32    C: Command,
33    F: Fn(CommandContext, C::Args) -> Fut + Send + Sync + 'static,
34    Fut: Future<Output = Result<C::Output, C::Error>> + Send + 'static,
35{
36    fn call(&self, context: CommandContext, args: C::Args) -> CommandFuture<C> {
37        Box::pin((self)(context, args))
38    }
39}