bloom_core/
effect.rs

1use std::hash::{DefaultHasher, Hash, Hasher};
2
3use async_context::with_async_context_mut;
4
5use crate::hook::Hook;
6
7pub struct Cleanup(Box<dyn FnOnce()>);
8
9impl From<()> for Cleanup {
10    fn from(_: ()) -> Self {
11        Self(Box::new(|| {}))
12    }
13}
14
15impl<C> From<C> for Cleanup
16where
17    C: FnOnce() + 'static,
18{
19    fn from(cleanup: C) -> Self {
20        Self(Box::new(cleanup))
21    }
22}
23
24impl Cleanup {
25    pub(crate) fn run(self) {
26        let cleanup = self.0;
27        cleanup()
28    }
29}
30
31pub(crate) struct Effect(Box<dyn FnOnce() -> Cleanup + Send + Sync + 'static>);
32
33impl Effect {
34    pub(crate) fn run(self) -> Cleanup {
35        let effect = self.0;
36        effect()
37    }
38}
39
40pub fn use_effect<A, C>(arg: A, effect: fn(A) -> C)
41where
42    A: Hash + Send + Sync + 'static,
43    C: Into<Cleanup> + 'static,
44{
45    with_async_context_mut(|hook: Option<&mut Hook>| {
46        if let Some(hook) = hook {
47            let mut hasher = DefaultHasher::new();
48            arg.hash(&mut hasher);
49            let arg_hash = hasher.finish();
50
51            hook.effects
52                .push((arg_hash, Effect(Box::new(move || effect(arg).into()))));
53        }
54    })
55}