studiole_command/services/
command_registry.rs1use crate::prelude::*;
2
3pub struct CommandRegistry<T: ICommandInfo> {
5 handlers: HashMap<TypeId, T::Handler>,
6}
7
8impl<T: ICommandInfo> CommandRegistry<T> {
9 #[must_use]
11 pub fn new() -> Self {
12 Self {
13 handlers: HashMap::default(),
14 }
15 }
16
17 #[allow(clippy::as_conversions)]
19 pub fn register<
20 R: Executable + Send + Sync + 'static,
21 H: Execute<R, R::Response, R::ExecutionError>,
22 >(
23 &mut self,
24 handler: Arc<H>,
25 ) where
26 Arc<H>: Into<T::Handler>,
27 {
28 let request_type = TypeId::of::<R>();
29 self.handlers.insert(request_type, handler.into());
30 }
31
32 #[allow(clippy::as_conversions)]
34 pub fn resolve<R: Executable + Send + Sync + 'static>(
35 &self,
36 request: R,
37 ) -> Result<T::Command, Report<QueueError>> {
38 let request_type = TypeId::of::<R>();
39 let handler = self
40 .handlers
41 .get(&request_type)
42 .ok_or_else(|| {
43 Report::new(QueueError::NoMatch)
44 .attach_with("request_type", || String::from(type_name::<R>()))
45 .attach("request", request.to_string())
46 })?
47 .clone();
48 let command = T::Command::new(request, handler);
49 Ok(command)
50 }
51}
52
53impl<T: ICommandInfo + 'static> Service for CommandRegistry<T> {
54 type Error = ServiceError;
55
56 async fn from_services(_services: &ServiceProvider) -> Result<Self, Report<Self::Error>> {
57 let registry = CommandRegistry::new();
58 Ok(registry)
59 }
60}
61
62#[derive(Debug, Error)]
64pub enum QueueError {
65 #[error("Unable to match request to command")]
66 NoMatch,
67 #[error("Unable to match request to command")]
68 IncorrectCommandType,
69}