studiole_command/macros/
server_macro.rs1use crate::prelude::*;
2
3#[macro_export]
4macro_rules! define_commands_server {
5 ($($kind:ident($req:ty, $handler:ty)),* $(,)?) => {
6 #[derive(Clone)]
7 pub enum CommandHandler {
8 $(
9 $kind(Arc<$handler>),
10 )*
11 }
12
13 impl IHandler for CommandHandler {}
14
15 pub enum Command {
16 $(
17 $kind($req, Arc<$handler>),
18 )*
19 }
20
21 #[async_trait]
22 impl ICommand<CommandHandler, CommandSuccess, CommandFailure> for Command {
23 fn new<T: Executable + Send + Sync + 'static>(
24 request: T,
25 handler: CommandHandler,
26 ) -> Self {
27 let request_any: Box<dyn Any> = Box::new(request);
28 match handler {
29 $(
30 CommandHandler::$kind(handler) => {
31 let request = request_any
32 .downcast::<$req>()
33 .expect("Request type should match handler");
34 Self::$kind(*request, handler)
35 },
36 )*
37 }
38 }
39
40 async fn execute(self) -> Result<CommandSuccess, CommandFailure> {
41 match self {
42 $(
43 Self::$kind(request, handler) => {
44 match handler.execute(&request).await {
45 Ok(result) => Ok(CommandSuccess::$kind(result)),
46 Err(e) => Err(CommandFailure::$kind(e)),
47 }
48 },
49 )*
50 }
51 }
52 }
53
54 impl Display for Command {
55 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
56 let name = match &self {
57 $(
58 Self::$kind(request, _) => request.to_string(),
59 )*
60 };
61 f.write_str(&name)
62 }
63 }
64
65 $(
66 impl From<Arc<$handler>> for CommandHandler {
67 fn from(handler: Arc<$handler>) -> Self {
68 Self::$kind(handler)
69 }
70 }
71 )*
72
73 impl RegisterHandlers for CommandInfo {
74 async fn register_handlers(
75 services: &ServiceProvider,
76 ) -> Result<CommandRegistry<Self>, Report<ResolveError>> {
77 let mut registry = CommandRegistry::new();
78 $(
79 let handler = services.get_async::<$handler>().await?;
80 registry.register::<$req, $handler>(handler);
81 )*
82 Ok(registry)
83 }
84 }
85
86 pub trait WithCommands: Sized {
87 fn with_commands(self) -> Self;
88 }
89
90 impl WithCommands for ServiceBuilder {
91 fn with_commands(self) -> Self {
92 self
93 $(
94 .with_type_async::<$handler>()
95 )*
96 .with_type_async::<CommandRegistry<CommandInfo>>()
97 .with_type_async::<CommandRunner<CommandInfo>>()
98 .with_type::<CommandMediator<CommandInfo>>()
99 .with_type::<WorkerPool<CommandInfo>>()
100 .with_type::<CommandEvents<CommandInfo>>()
101 .with_type::<CliProgress<CommandInfo>>()
102 }
103 }
104 };
105}
106
107pub trait IHandler: Clone + Send + Sync {}
109
110#[async_trait]
112pub trait ICommand<H: IHandler, S: ISuccess, F: IFailure>: Display + Send + Sync {
113 fn new<T: Executable + Send + Sync + 'static>(request: T, handler: H) -> Self;
115 async fn execute(self) -> Result<S, F>;
117}