#![warn(missing_docs)]
#![warn(missing_debug_implementations)]
#![deny(unsafe_code)]
use async_trait::async_trait;
use std::fmt::Debug;
use std::{
any::{Any, TypeId},
collections::HashMap,
error::Error,
};
mod error;
pub use self::error::MediatorError;
pub type Result<T> = core::result::Result<T, Box<dyn Error>>;
pub trait Request<TResponse>: 'static {}
#[async_trait]
pub trait RequestHandler<TRequest, TResponse>
where
TRequest: Request<TResponse>,
{
async fn handle(&mut self, request: TRequest) -> Result<TResponse>;
}
#[derive(Debug)]
pub struct Mediator(TypeMap);
impl Mediator {
pub fn new() -> Self {
Mediator(TypeMap::new())
}
pub fn register_handler<TRequest, TRequestHandler, TResponse>(
&mut self,
handler: TRequestHandler,
) -> &mut Self
where
TRequest: Request<TResponse>,
TRequestHandler: RequestHandler<TRequest, TResponse> + 'static,
TResponse: 'static,
{
self.0
.set::<TRequest, Box<dyn RequestHandler<TRequest, TResponse>>>(Box::new(handler));
self
}
pub async fn send<TRequest, TResponse>(&mut self, request: TRequest) -> Result<TResponse>
where
TRequest: Request<TResponse>,
TResponse: 'static,
{
match self
.0
.get_mut::<TRequest, Box<dyn RequestHandler<TRequest, TResponse>>>()
{
Some(h) => h.handle(request).await,
None => Err(Box::new(error::MediatorError::HandlerNotRegisteredError)),
}
}
}
#[derive(Debug)]
struct TypeMap(HashMap<TypeId, Box<dyn Any>>);
impl TypeMap {
fn new() -> Self {
TypeMap(HashMap::new())
}
pub fn set<TKey: 'static, TValue: Any + 'static>(&mut self, value: TValue) {
self.0.insert(TypeId::of::<TKey>(), Box::new(value));
}
pub fn get_mut<TKey: 'static, TValue: Any + 'static>(&mut self) -> Option<&mut TValue> {
self.0
.get_mut(&TypeId::of::<TKey>())
.and_then(|v| v.downcast_mut::<TValue>())
}
}
#[cfg(test)]
mod test {
use super::*;
#[derive(Debug)]
pub struct TestRequest {}
#[derive(Debug)]
pub struct TestRequestHandler;
impl Request<i64> for TestRequest {}
#[async_trait]
impl RequestHandler<TestRequest, i64> for TestRequestHandler {
async fn handle(&mut self, _request: TestRequest) -> Result<i64> {
Ok(42)
}
}
#[tokio::test]
async fn test_mediator_register_handler() {
let mut m = Mediator::new();
m.register_handler(TestRequestHandler);
assert_eq!(m.send(TestRequest {}).await.unwrap(), 42);
}
#[tokio::test]
async fn test_mediator_no_handler_registered() {
let mut m = Mediator::new();
match m.send(TestRequest {}).await {
Ok(_) => assert!(false),
Err(err) => {
if let Some(e) = err.downcast_ref::<MediatorError>() {
assert_eq!(e, &error::MediatorError::HandlerNotRegisteredError);
} else {
assert!(false);
}
}
}
}
}