nitinol_resolver/
mapping.rs

1#[cfg(feature = "process")]
2pub mod process;
3
4use std::collections::HashMap;
5use std::sync::Arc;
6
7use nitinol_core::event::Event;
8
9use crate::resolver::{ResolveHandler, ResolveType, Resolver, ResolverType, TypedResolver};
10
11/// ResolveMapping is a trait that defines the mapping of event types to their respective handlers.
12///
13/// ## Example
14/// ```rust
15/// # use async_trait::async_trait;
16/// # use serde::{Deserialize, Serialize};
17/// # use nitinol_core::errors::{DeserializeError, SerializeError};
18/// # use nitinol_core::event::Event;
19/// # use nitinol_resolver::resolver::ResolveHandler;
20/// #
21/// # pub struct Entity;
22/// #
23/// # #[derive(Debug, Deserialize, Serialize)]
24/// # pub enum EntityEvent {}
25/// #
26/// # impl Event for EntityEvent {
27/// #     const EVENT_TYPE: &'static str = "entity-event";
28/// #
29/// #     fn as_bytes(&self) -> Result<Vec<u8>, SerializeError> {
30/// #         Ok(serde_json::to_vec(self)?)
31/// #     }
32/// #     fn from_bytes(bytes: &[u8]) -> Result<Self, DeserializeError> {
33/// #         Ok(serde_json::from_slice(bytes)?)
34/// #     }
35/// # }
36/// #
37/// # pub struct Subscribe;
38/// #
39/// # #[async_trait]
40/// # pub trait SubscribeHandler<E: Event>: 'static + Sync + Send + Sized {
41/// #     type Rejection: std::fmt::Debug + Sync + Send + 'static;
42/// #     async fn on(&mut self, event: E) -> Result<(), Self::Rejection>;
43/// # }
44/// #
45/// # #[async_trait]
46/// # impl<E: Event, T> ResolveHandler<E, T> for Subscribe
47/// # where
48/// #     T: SubscribeHandler<E>,
49/// # {
50/// #     const HANDLER_TYPE: &'static str = "subscribe";
51/// #     type Error = T::Rejection;
52/// #
53/// #     async fn apply(entity: &mut Option<T>, event: E) -> Result<(), Self::Error> {
54/// #         let Some(entity) = entity else {
55/// #             panic!("Entity must exist in this process.");
56/// #         };
57/// #
58/// #         entity.on(event).await?;
59/// #
60/// #         Ok(())
61/// #     }
62/// # }
63/// #
64/// use nitinol_resolver::mapping::{Mapper, ResolveMapping};
65///
66/// #[async_trait]
67/// impl SubscribeHandler<EntityEvent> for Entity {
68///     type Rejection = String;
69///     async fn on(&mut self, event: EntityEvent) -> Result<(), Self::Rejection> {
70///         // something process...
71///         Ok(())
72///     }
73/// }
74///
75/// impl ResolveMapping for Entity {
76///     fn mapping(mapper: &mut Mapper<Self>) {
77///         // Register the event type and its handler
78///         // This `Subscribe` shown as an example points out a compile error,
79///         // if the above `SubscribeHandler` is not implemented for the Entity type.
80///         mapper.register::<EntityEvent, Subscribe>();
81///     }
82/// }
83/// ```
84pub trait ResolveMapping: 'static + Sync + Send + Sized {
85    fn mapping(mapper: &mut Mapper<Self>);
86}
87
88pub struct Mapper<T> {
89    map: HashMap<ResolveType, Arc<dyn Resolver<T>>>,
90}
91
92impl<T> Mapper<T> 
93where
94    T: 'static + Sync + Send,
95{
96    pub fn register<E: Event, H>(&mut self) -> &mut Self
97    where
98        H: ResolveHandler<E, T>,
99    {
100        self.map.insert(
101            ResolveType::new(E::EVENT_TYPE, H::HANDLER_TYPE),
102            Arc::new(TypedResolver::<E, T, H>::default()),
103        );
104        self
105    }
106    
107    pub fn register_with<E: Event, R>(&mut self, resolver: R) -> &mut Self 
108    where
109        R: ResolverType<T>
110    {
111        self.map.insert(
112            ResolveType::new(E::EVENT_TYPE, R::RESOLVE_TYPE),
113            Arc::new(resolver),
114        );
115        self
116    }
117
118    pub fn find(&self, mut f: impl FnMut(&ResolveType) -> bool) -> Option<Arc<dyn Resolver<T>>> {
119        self.map
120            .iter()
121            .find(|(key, _)| f(key))
122            .map(|(_, handler)| handler)
123            .cloned()
124    }
125    
126    pub fn filter(self, mut f: impl FnMut(&ResolveType) -> bool) -> Self {
127        Self {
128            map: self.map.into_iter()
129                .filter(|(key, _)| f(key))
130                .collect(),
131        }
132    }
133}
134
135impl<T> Default for Mapper<T> {
136    fn default() -> Self {
137        Self {
138            map: HashMap::default(),
139        }
140    }
141}