1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
//! Ware provides mutable and immutable middleware abstractions. Basically, it means that
//! you can pass one variable through a series of functions that all have the
//! ability to modify this variable, therefore sending this modified version of
//! it further down the chain.
//!
//! Ware is used like this:
//!
//! ```
//! use ware::Ware;
//! use std::ops::{Mul, Sub};
//!
//! fn main() {
//! let mut chain: Ware<i32> = Ware::new();
//! chain.wrap(Box::new(|mut num| {
//! *num = num.mul(5);
//! }));
//! chain.wrap(Box::new(|mut num| {
//! *num = num.sub(2);
//! }));
//! let result = chain.run(5);
//! assert_eq!(result, 23);
//! }
//! ```
use std::cell::{RefCell, RefMut};
pub mod im;
/// Shorthand version of `RefMut<T>`, if you don't want to import `RefMut`.
pub type WareArg<'a, T> = RefMut<'a, T>;
/// A middleware chain.
pub struct Ware<T> {
/// The internal list of middleware functions.
pub fns: Vec<Box<dyn Fn(WareArg<T>) -> ()>>,
}
impl<T> Ware<T> {
/// Create a new middleware chain with a given type.
///
/// # Example
/// ```
/// use ware::Ware;
/// let mut chain: Ware<String> = Ware::new();
/// ```
pub fn new() -> Ware<T> {
let vec: Vec<Box<dyn Fn(WareArg<T>) -> ()>> = Vec::new();
Ware { fns: vec }
}
/// Add a new middleware function to the internal function list. This function
/// must be of the `Fn` trait, take a `WareArg<T>` and return a unit struct (aka. nothing).
/// It also has to be boxed for memory safety reasons.
///
/// # Example
/// ```
/// use ware::Ware;
/// let mut chain: Ware<String> = Ware::new();
/// chain.wrap(Box::new(|mut st| {
/// st.push('a');
/// }))
/// ```
pub fn wrap(&mut self, func: Box<dyn Fn(WareArg<T>) -> ()>) {
self.fns.push(func);
}
/// Run the registered middleware functions with the given value to pass
/// through. Returns whatever the passed value will be after the last
/// middleware function runs.
pub fn run(&self, arg: T) -> T {
let ware_arg = RefCell::new(arg);
self.fns.iter().for_each(|func| func(ware_arg.borrow_mut()));
ware_arg.into_inner()
}
}
#[cfg(test)]
mod tests {
use std::ops::Add;
use super::*;
#[test]
fn it_works() {
let value = 1;
let mut w: Ware<i32> = Ware::new();
w.wrap(Box::new(|mut num| {
*num = num.add(1);
}));
assert_eq!(w.run(value), 2);
}
}