mediator/lib.rs
1#![allow(clippy::needless_doctest_main)]
2//! # mediator-rs
3//!
4//! 
5//! 
6//! 
7//! 
8//!
9//! An implementation of the Mediator pattern in Rust
10//! inspired in C# [MediatR](https://github.com/jbogard/MediatR).
11//!
12//! ## Mediator Pattern
13//! https://en.wikipedia.org/wiki/Mediator_pattern
14//!
15//! ## Usage
16//! ```toml
17//! [dependencies]
18//! mediator = "0.2"
19//! ```
20//!
21//! ## Tests
22//! To run the tests use the following command:
23//! ```bash
24//! cargo test --all-features
25//! ```
26//!
27//! ## Examples
28//!
29//! ### Basic usage
30//! ```rust
31//! use mediator::{DefaultMediator, Mediator, Request, Event, RequestHandler, EventHandler};
32//!
33//! #[derive(Clone, Debug)]
34//! enum Op {
35//! Add(f32, f32),
36//! Sub(f32, f32),
37//! Mul(f32, f32),
38//! Div(f32, f32),
39//! }
40//!
41//! struct MathRequest(Op);
42//! impl Request<Option<f32>> for MathRequest {}
43//!
44//! #[derive(Clone, Debug)]
45//! struct MathEvent(Op, Option<f32>);
46//! impl Event for MathEvent {}
47//!
48//! struct MathRequestHandler(DefaultMediator);
49//! impl RequestHandler<MathRequest, Option<f32>> for MathRequestHandler {
50//! fn handle(&mut self, req: MathRequest) -> Option<f32> {
51//! let result = match req.0 {
52//! Op::Add(a, b) => Some(a + b),
53//! Op::Sub(a, b) => Some(a - b),
54//! Op::Mul(a, b) => Some(a * b),
55//! Op::Div(a, b) => {
56//! if b == 0.0 { None } else { Some(a / b) }
57//! }
58//! };
59//!
60//! self.0.publish(MathEvent(req.0, result)).expect("publish failed");
61//! result
62//! }
63//! }
64//!
65//! fn main() {
66//! let mut mediator = DefaultMediator::builder()
67//! .add_handler_deferred(MathRequestHandler)
68//! .subscribe_fn(|event: MathEvent| {
69//! println!("{:?}", event);
70//! })
71//! .build();
72//!
73//! let result = mediator.send(MathRequest(Op::Add(1.0, 2.0))).expect("send failed");
74//! assert_eq!(result, Some(3.0));
75//! }
76//! ```
77//!
78//! ### Async
79//! Require the `async` feature enable.
80//!
81//! ```rust
82//! use mediator::{DefaultAsyncMediator, AsyncMediator, Request};
83//!
84//! struct MulRequest(f32, f32);
85//! impl Request<f32> for MulRequest {}
86//!
87//! #[tokio::main]
88//! async fn main() {
89//! let mut mediator = DefaultAsyncMediator::builder()
90//! .add_handler(|req: MulRequest| async move {
91//! tokio::time::sleep(std::time::Duration::from_secs(1)).await;
92//! req.0 * req.1
93//! })
94//! .build();
95//!
96//! let result = mediator.send(MulRequest(2.0, 3.0)).await.expect("send failed");
97//! assert_eq!(result, 6.0);
98//! }
99//! ```
100//!
101//! ### Streams
102//! Require the `streams` feature enable.
103//!
104//! ```rust
105//! use mediator::{StreamRequest, Event, DefaultAsyncMediator, AsyncMediator, box_stream};
106//! use mediator::futures::{StreamExt, BoxStream};
107//!
108//! struct CountdownRequest(u32);
109//! impl StreamRequest for CountdownRequest {
110//! type Stream = BoxStream<'static, u32>;
111//! type Item = u32;
112//! }
113//!
114//! #[tokio::main]
115//! async fn main() {
116//! let mut mediator = DefaultAsyncMediator::builder()
117//! .add_stream_handler_fn(|req: CountdownRequest| box_stream! { yx move =>
118//! let mut count = req.0;
119//! while count > 0 {
120//! tokio::time::sleep(std::time::Duration::from_secs(1)).await;
121//! yx.yield_one(count);
122//! count -= 1;
123//! }
124//! })
125//! .build();
126//!
127//! let mut stream = mediator.stream(CountdownRequest(3)).await.expect("stream failed");
128//! assert_eq!(stream.next().await.unwrap(), 3);
129//! assert_eq!(stream.next().await.unwrap(), 2);
130//! assert_eq!(stream.next().await.unwrap(), 1);
131//! assert_eq!(stream.next().await, None);
132//! }
133//! ```
134
135/// A convenient result type.
136pub type Result<T> = std::result::Result<T, error::Error>;
137
138/// Module for the mediator request-response.
139mod request;
140pub use request::*;
141
142/// Module for the mediator events.
143mod event;
144pub use event::*;
145
146/// Module for the mediator.
147mod mediator;
148pub use crate::mediator::*;
149
150/// Module for the errors.
151pub mod error;
152
153/// Module for streams.
154#[cfg(feature = "streams")]
155mod streams;
156
157#[cfg(feature = "streams")]
158pub use streams::*;
159
160#[cfg(feature = "interceptors")]
161mod interceptor;
162
163#[cfg(feature = "interceptors")]
164pub use interceptor::*;
165
166/// Re-exports for futures/stream utilities.
167#[cfg(feature = "async")]
168pub mod futures;
169
170#[cfg(feature = "async")]
171pub use async_trait::async_trait;
172
173// Default implementations.
174#[cfg(feature = "impls")]
175mod default_impls;
176
177// Default exports
178#[cfg(feature = "impls")]
179pub use default_impls::mediator_impl::DefaultMediator;
180
181#[cfg(all(feature = "impls", feature = "async"))]
182pub use default_impls::async_mediator_impl::DefaultAsyncMediator;
183
184/// Provides default implementations.
185#[cfg(feature = "impls")]
186pub mod impls {
187 pub use crate::default_impls::mediator_impl::Builder;
188 pub use crate::default_impls::mediator_impl::DefaultMediator;
189}
190
191/// Provides async default implementations.
192#[cfg(all(feature = "impls", feature = "async"))]
193pub mod impls_async {
194 pub use crate::default_impls::async_mediator_impl::Builder;
195 pub use crate::default_impls::async_mediator_impl::DefaultAsyncMediator;
196}