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);
    }
}