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
//! An immutable version of ware. Does not use RefCells, instead //! relying on the user to return the modified variable in the closure. //! //! ## Example //! ``` //! use ware::im::Ware; //! //! fn main() { //! let mut chain: Ware<i32> = Ware::new(); //! chain.wrap(Box::new(|num| num * 10)); //! chain.wrap(Box::new(|num| num - 2)); //! let result = chain.run(5); //! assert_eq!(result, 48); //! } //! ``` /// A middleware chain. pub struct Ware<T> { /// The internal list of middleware functions. pub fns: Vec<Box<dyn Fn(T) -> T>>, } impl<T> Ware<T> { /// Create a new middleware chain with a given type. /// /// # Example /// ``` /// use ware::im::Ware; /// let mut chain: Ware<String> = Ware::new(); /// ``` pub fn new() -> Ware<T> { let vec: Vec<Box<dyn Fn(T) -> 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 the specified type and return the same /// specified type. It also has to be boxed for memory safety reasons. /// /// # Example /// ``` /// use ware::im::Ware; /// let mut chain: Ware<String> = Ware::new(); /// chain.wrap(Box::new(|st| { /// let mut s = st.clone(); /// s.push('a'); /// s /// })) /// ``` pub fn wrap(&mut self, func: Box<dyn Fn(T) -> T>) { self.fns.push(func); } /// Run the registered middleware functions with the given value to pass /// through. Returns whatever the last registered middleware function /// returns. pub fn run(&self, arg: T) -> T { self.fns.iter().fold(arg, |acc, func| func(acc)) } } #[cfg(test)] mod tests { use super::*; #[test] fn it_works() { let value = 1; let mut w: Ware<i32> = Ware::new(); w.wrap(Box::new(|num| num + 1)); assert_eq!(w.run(value), 2); } #[test] fn it_is_immutable() { let value = 1; let closure = |num| { let num = num + 1; num }; let mut w: Ware<i32> = Ware::new(); w.wrap(Box::new(closure)); assert_eq!(w.run(value), 2); assert_eq!(value, 1); } }