1mod command_handler;
2mod dispatched_command;
3
4use std::sync::Arc;
5
6pub use command_handler::CommandHandler;
7pub use dispatched_command::DispatchedCommand;
8use futures::future::BoxFuture;
9use simple_middleware::{Manager as MiddlewareManager, Next};
10
11use crate::Busstop;
12
13pub type NextCommandMiddleware = Next<DispatchedCommand, DispatchedCommand>;
15
16pub type CommandMiddleware = Box<
18 dyn FnMut(DispatchedCommand, NextCommandMiddleware) -> BoxFuture<'static, DispatchedCommand>
19 + Send
20 + Sync,
21>;
22
23#[async_trait::async_trait]
27pub trait DispatchableCommand: Send + Sync {
28 async fn dispatch_command(self) -> bool
30 where
31 Self: Sized + 'static,
32 {
33 Busstop::instance().dispatch_command(self).await
34 }
35
36 async fn command_handler<H: CommandHandler + Default + 'static>()
38 where
39 Self: Sized,
40 {
41 Busstop::instance()
42 .register_command::<Self>(H::default())
43 .await;
44 }
45
46 async fn command_middleware<M: 'static>(middleware: M)
48 where
49 Self: Sized,
50 M: FnMut(
51 DispatchedCommand,
52 Next<DispatchedCommand, DispatchedCommand>,
53 ) -> BoxFuture<'static, DispatchedCommand>
54 + Send
55 + Sync,
56 {
57 Busstop::instance()
58 .register_command_middleware::<Self, M>(middleware)
59 .await;
60 }
61
62 async fn soft_command_handler<H: CommandHandler + Default + 'static>()
64 where
65 Self: Sized,
66 {
67 let bus = Busstop::instance();
68 if !bus.command_has_handler::<Self>().await {
69 bus.register_command::<Self>(H::default()).await;
70 }
71 }
72
73 async fn register_command_handler<H: CommandHandler + 'static>(handler: H)
75 where
76 Self: Sized,
77 {
78 Busstop::instance().register_command::<Self>(handler).await;
79 }
80
81 async fn register_soft_command_handler<H: CommandHandler + 'static>(handler: H)
83 where
84 Self: Sized,
85 {
86 let bus = Busstop::instance();
87 if !bus.command_has_handler::<Self>().await {
88 bus.register_command::<Self>(handler).await;
89 }
90 }
91}
92
93pub struct CommandHandlerManager {
95 name: String,
96 middleware: MiddlewareManager<DispatchedCommand, DispatchedCommand>,
97}
98
99impl CommandHandlerManager {
100 pub async fn new(handler: impl CommandHandler + 'static) -> Self {
102 let handler = Arc::new(Box::new(handler));
103 Self {
104 name: handler.command_handler_name().to_string(),
105 middleware: MiddlewareManager::last(move |dispatched, _| {
106 let instance = handler.clone();
107 Box::pin(async move { instance.clone().handle_command(dispatched).await })
108 })
109 .await,
110 }
111 }
112
113 pub fn name(&self) -> &String {
115 &self.name
116 }
117
118 pub async fn next<M>(&self, middleware: M) -> &Self
119 where
120 M: FnMut(DispatchedCommand, NextCommandMiddleware) -> BoxFuture<'static, DispatchedCommand>
121 + Send
122 + 'static,
123 {
124 self.middleware.next(middleware).await;
125 self
126 }
127
128 pub async fn handle(&self, dispatched: DispatchedCommand) -> DispatchedCommand {
129 let mut result = self.middleware.send(dispatched).await;
130 result.handled = true;
131
132 result
133 }
134
135 pub async fn handle_command<C: Send + Sync + 'static>(&self, command: C) -> DispatchedCommand {
136 self.handle(DispatchedCommand::new(
137 Box::new(command),
138 std::any::type_name::<C>(),
139 ))
140 .await
141 }
142}
143
144#[cfg(test)]
145mod test {
146 use super::*;
147
148 struct Cmd;
149 impl DispatchableCommand for Cmd {}
150
151 #[derive(Default)]
152 struct CmdHandler;
153
154 #[async_trait::async_trait]
155 impl CommandHandler for CmdHandler {
156 async fn handle_command(&self, c: DispatchedCommand) -> DispatchedCommand {
157 c
158 }
159 }
160
161 #[tokio::test]
162 async fn test_command_handler_manager() {
163 let manager = CommandHandlerManager::new(CmdHandler).await;
164
165 manager
166 .next(|c, n| Box::pin(async move { n.call(c).await }))
167 .await;
168 manager
169 .next(|c, n| Box::pin(async move { n.call(c).await }))
170 .await;
171
172 assert_eq!(manager.handle_command(Cmd).await.handled(), true)
173 }
174}