simple_middleware/
manager.rs

1use std::sync::Arc;
2
3use futures::future::BoxFuture;
4use tokio::sync::{Mutex, RwLock};
5
6type Middleware<V, R> = Box<dyn FnMut(V, Next<V, R>) -> BoxFuture<'static, R> + Send>;
7type MiddlewareMutex<V, R> = Mutex<Middleware<V, R>>;
8type ListOfMiddlewares<V, R> = Vec<MiddlewareMutex<V, R>>;
9type SharableListOfMiddlewares<V, R> = Arc<RwLock<ListOfMiddlewares<V, R>>>;
10
11pub struct Manager<V, R> {
12    list: SharableListOfMiddlewares<V, R>,
13}
14
15impl<V: 'static, R: 'static> Manager<V, R> {
16    /// Create new instance
17    pub fn new() -> Self {
18        Self {
19            list: Arc::default(),
20        }
21    }
22
23    pub async fn last<F>(last: impl FnMut(V, Next<V, R>) -> F + Send + 'static) -> Self
24    where
25        F: Future<Output = R> + Send + 'static,
26    {
27        let s = Self::new();
28        s.next(last).await;
29
30        s
31    }
32
33    /// Start processing the value
34    pub async fn send(&self, value: V) -> R {
35        let total = self.list.read().await.len();
36
37        let qq = Arc::clone(&self.list);
38        let next = Next {
39            list: Arc::clone(&qq),
40            next: total - 1,
41        };
42
43        let lock = self.list.read().await;
44        let mut callback = lock.last().unwrap().lock().await;
45        (callback)(value, next).await
46    }
47
48    pub async fn next<F>(&self, mut m: impl FnMut(V, Next<V, R>) -> F + Send + 'static) -> &Self
49    where
50        F: Future<Output = R> + Send + 'static,
51    {
52        let list = Arc::clone(&self.list);
53        let mut lock = list.write().await;
54        lock.push(Mutex::new(Box::new(move |v, next| {
55            let cb = (m)(v, next);
56            Box::pin(async move { cb.await })
57        })));
58
59        self
60    }
61}
62
63impl<V: 'static, R: 'static> Default for Manager<V, R> {
64    fn default() -> Self {
65        Self::new()
66    }
67}
68
69pub struct Next<V, R> {
70    list: SharableListOfMiddlewares<V, R>,
71    next: usize,
72}
73
74impl<V, R> Next<V, R> {
75    pub async fn call(mut self, value: V) -> R {
76        let list = Arc::clone(&self.list);
77        let lock = list.read().await;
78        if (self.next as isize) - 1 < 0 {
79            panic!("There must be a default")
80        }
81
82        self.next -= 1;
83        if let Some(next) = lock.get(self.next) {
84            let mut callback = next.lock().await;
85            return callback(value, self).await;
86        }
87        panic!("There must be a default")
88    }
89}
90
91#[cfg(test)]
92mod test {
93    use super::*;
94
95    #[tokio::test]
96    pub async fn test_last() {
97        let result_str = "This is the end of the row";
98        let manager = Manager::last(move |_v, _n| async move { result_str.to_string() }).await;
99
100        assert_eq!(&manager.send(()).await, result_str);
101    }
102
103    #[tokio::test]
104    pub async fn test_calling() {
105        let manager = Manager {
106            list: Arc::default(),
107        };
108
109        manager
110            .next(|value, _next| async move { value })
111            .await
112            .next(|value, next| async move { next.call(value * 2).await })
113            .await
114            .next(|value, next| async move { next.call(value + 2).await })
115            .await;
116
117        let result: i32 = manager.send(10).await;
118
119        assert_eq!(result, 24);
120    }
121}