ratatui_kit/hooks/
use_memo.rs

1use std::hash::{DefaultHasher, Hash, Hasher};
2
3use crate::{Hook, Hooks};
4
5mod private {
6    pub trait Sealed {}
7    impl Sealed for crate::Hooks<'_, '_> {}
8}
9
10pub trait UseMemo: private::Sealed {
11    fn use_memo<F, D, T>(&mut self, f: F, deps: D) -> T
12    where
13        F: FnOnce() -> T,
14        D: Hash,
15        T: Clone + Send + Unpin + 'static;
16}
17
18pub(crate) fn hash_deps<D: Hash>(deps: D) -> u64 {
19    let mut hasher = DefaultHasher::new();
20    deps.hash(&mut hasher);
21    hasher.finish()
22}
23
24pub struct UseMemoImpl<T> {
25    memoized_value: Option<T>,
26    deps_hash: u64,
27}
28
29impl<T> Default for UseMemoImpl<T> {
30    fn default() -> Self {
31        UseMemoImpl {
32            memoized_value: None,
33            deps_hash: 0,
34        }
35    }
36}
37
38impl<T: Send + Unpin> Hook for UseMemoImpl<T> {}
39
40impl UseMemo for Hooks<'_, '_> {
41    fn use_memo<F, D, T>(&mut self, f: F, deps: D) -> T
42    where
43        F: FnOnce() -> T,
44        D: Hash,
45        T: Clone + Send + Unpin + 'static,
46    {
47        let dep_hash = hash_deps(deps);
48        let hook = self.use_hook(UseMemoImpl::<T>::default);
49        if hook.deps_hash != dep_hash || hook.memoized_value.is_none() {
50            hook.memoized_value = Some(f());
51            hook.deps_hash = dep_hash;
52        }
53        hook.memoized_value.clone().unwrap()
54    }
55}