another_rxrust/internals/
function_wrapper.rs

1use std::sync::{Arc, RwLock};
2
3#[derive(Clone)]
4struct FunctionWrapperInner<'a, In, Out>
5where
6  In: Clone + Send + Sync + 'a,
7  Out: Clone + Send + Sync + 'a,
8{
9  pub func: Arc<Box<dyn Fn(In) -> Out + Send + Sync + 'a>>,
10}
11
12#[derive(Clone)]
13pub struct FunctionWrapper<'a, In, Out>
14where
15  In: Clone + Send + Sync + 'a,
16  Out: Clone + Send + Sync + 'a,
17{
18  inner: Arc<RwLock<Option<FunctionWrapperInner<'a, In, Out>>>>,
19}
20
21impl<'a, In, Out> FunctionWrapper<'a, In, Out>
22where
23  In: Clone + Send + Sync + 'a,
24  Out: Clone + Send + Sync + 'a,
25{
26  pub fn new<F>(func: F) -> FunctionWrapper<'a, In, Out>
27  where
28    F: Fn(In) -> Out + Send + Sync + 'a,
29    In: Clone + Send + Sync + 'a,
30    Out: Clone + Send + Sync + 'a,
31  {
32    FunctionWrapper {
33      inner: Arc::new(RwLock::new(Some(
34        FunctionWrapperInner { func: Arc::new(Box::new(func)) },
35      ))),
36    }
37  }
38  pub fn clear(&self) {
39    *self.inner.write().unwrap() = None;
40  }
41  pub fn empty(&self) -> bool {
42    self.inner.read().unwrap().is_none()
43  }
44  pub fn exists(&self) -> bool {
45    !self.empty()
46  }
47
48  fn fetch_function(&self) -> Option<FunctionWrapperInner<In, Out>> {
49    if let Some(x) = &*self.inner.read().unwrap() {
50      Some(x.clone())
51    } else {
52      None
53    }
54  }
55
56  pub fn call(&self, indata: In) -> Out {
57    if let Some(ff) = self.fetch_function() {
58      (ff.func)(indata)
59    } else {
60      panic!("no func")
61    }
62  }
63  pub fn call_if_available(&self, indata: In) -> Option<Out> {
64    if let Some(ff) = self.fetch_function() {
65      Some((ff.func)(indata))
66    } else {
67      None
68    }
69  }
70  pub fn call_and_clear_if_available(&self, indata: In) -> Option<Out> {
71    let f = {
72      let mut f = self.inner.write().unwrap();
73      if let Some(x) = &*f {
74        let x = x.clone();
75        *f = None;
76        Some(x)
77      } else {
78        None
79      }
80    };
81    if let Some(f) = f {
82      Some((f.func)(indata))
83    } else {
84      None
85    }
86  }
87}
88
89#[cfg(test)]
90mod tset {
91  use super::FunctionWrapper;
92
93  #[test]
94  fn basic() {
95    let f = FunctionWrapper::new(|x| x * x);
96    assert_eq!(f.call(10), 100);
97    assert_eq!(f.call(10), 100);
98  }
99
100  #[test]
101  fn call_if_available() {
102    let f = FunctionWrapper::new(|x| x * x);
103    assert_eq!(f.call_if_available(10), Some(100));
104    assert_eq!(f.empty(), false);
105    f.clear();
106    assert_eq!(f.empty(), true);
107    assert_eq!(f.call_if_available(10), None);
108  }
109
110  #[test]
111  fn call_and_clear_if_available() {
112    let f = FunctionWrapper::new(|x| x * x);
113    assert_eq!(
114      f.call_and_clear_if_available(10),
115      Some(100)
116    );
117    assert_eq!(f.empty(), true);
118    assert_eq!(f.call_and_clear_if_available(10), None);
119  }
120
121  #[test]
122  #[should_panic]
123  fn call_and_clear_if_available_panic() {
124    let f = FunctionWrapper::new(|x| x * x);
125    assert_eq!(
126      f.call_and_clear_if_available(10),
127      Some(100)
128    );
129    f.call(10); // should be panic
130  }
131
132  #[test]
133  fn borrow() {
134    let a = 10;
135    {
136      let ff = |x| x * x; // static
137      let f = FunctionWrapper::new(ff);
138      assert_eq!(f.call(&a), 100);
139      assert_eq!(f.call(&a), 100);
140    }
141  }
142
143  #[test]
144  fn borrow2() {
145    let a = 10;
146    let b = 1;
147    {
148      let ff = |x| x * x + b; // non static
149      let f = FunctionWrapper::new(ff);
150      assert_eq!(f.call(&a), 101);
151      assert_eq!(f.call(&a), 101);
152    }
153  }
154}