ware/
lib.rs

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