mediator/
lib.rs

1#![allow(clippy::needless_doctest_main)]
2//! # mediator-rs
3//!
4//! ![https://github.com/Neo-Ciber94/mediator-rs/blob/main/LICENSE](https://img.shields.io/badge/license-MIT-blue)
5//! ![https://docs.rs/mediator/latest/mediator/](https://img.shields.io/badge/docs-passing-brightgreen)
6//! ![https://crates.io/crates/mediator](https://img.shields.io/badge/crates.io-v0.1-brightgreen)
7//! ![https://github.com/Neo-Ciber94/mediator-rs/actions/workflows/ci.yml](https://github.com/Neo-Ciber94/mediator-rs/actions/workflows/ci.yml/badge.svg)
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}