use std::collections::HashMap;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum DispatcherError {
#[error("error while sending message: {0}")]
SendError(String),
#[error("error while receinging message: {0}")]
RecvError(String),
}
pub trait MessageType {
fn message_type(&self) -> &str;
}
pub trait Observer<M> {
fn call(&self, message: &M);
}
pub type LocalObserverRef<'a, M> = Box<dyn Observer<M> + 'a>;
pub type ObserverRef<M> = Box<dyn Observer<M> + Send + Sync>;
#[derive(Default)]
pub struct LocalDispatcher<'a, M> {
handlers: HashMap<String, HashMap<String, LocalObserverRef<'a, M>>>,
}
#[derive(Default)]
pub struct Dispatcher<M> {
handlers: HashMap<String, HashMap<String, ObserverRef<M>>>,
}
impl<'a, M> LocalDispatcher<'a, M>
where
M: MessageType,
{
pub fn register_handler(
&mut self,
message_type: &str,
observer: LocalObserverRef<'a, M>,
tag: &str,
) {
match self.handlers.get_mut(message_type) {
Some(observers) => {
observers.insert(tag.to_owned(), observer);
}
None => {
let mut observers = HashMap::new();
observers.insert(tag.to_owned(), observer);
self.handlers.insert(message_type.to_owned(), observers);
}
}
}
pub fn unregister_handler(&mut self, message_type: &str, tag: &str) {
if let Some(observers) = self.handlers.get_mut(message_type) {
observers.remove(tag);
}
}
pub fn dispatch(&self, message: &M) -> Result<usize, DispatcherError> {
let message_type = message.message_type();
if let Some(observers) = self.handlers.get(message_type) {
for observer in observers.values() {
observer.call(message);
}
return Ok(observers.len());
}
Ok(0usize)
}
}
impl<M> Dispatcher<M>
where
M: MessageType,
{
pub fn register_handler(&mut self, message_type: &str, observer: ObserverRef<M>, tag: &str) {
match self.handlers.get_mut(message_type) {
Some(observers) => {
observers.insert(tag.to_owned(), observer);
}
None => {
let mut observers = HashMap::new();
observers.insert(tag.to_owned(), observer);
self.handlers.insert(message_type.to_owned(), observers);
}
}
}
pub fn unregister_handler(&mut self, message_type: &str, tag: &str) {
if let Some(observers) = self.handlers.get_mut(message_type) {
observers.remove(tag);
}
}
pub fn dispatch(&self, message: &M) -> Result<usize, DispatcherError> {
let message_type = message.message_type();
if let Some(observers) = self.handlers.get(message_type) {
for observer in observers.values() {
observer.call(message);
}
return Ok(observers.len());
}
Ok(0usize)
}
}