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    /// 依赖缓存,只有依赖变化时才重新计算,适合性能优化。
12    fn use_memo<F, D, T>(&mut self, f: F, deps: D) -> T
13    where
14        F: FnOnce() -> T,
15        D: Hash,
16        T: Clone + Send + Unpin + 'static;
17}
18
19pub(crate) fn hash_deps<D: Hash>(deps: D) -> u64 {
20    let mut hasher = DefaultHasher::new();
21    deps.hash(&mut hasher);
22    hasher.finish()
23}
24
25pub struct UseMemoImpl<T> {
26    memoized_value: Option<T>,
27    deps_hash: u64,
28}
29
30impl<T> Default for UseMemoImpl<T> {
31    fn default() -> Self {
32        UseMemoImpl {
33            memoized_value: None,
34            deps_hash: 0,
35        }
36    }
37}
38
39impl<T: Send + Unpin> Hook for UseMemoImpl<T> {}
40
41impl UseMemo for Hooks<'_, '_> {
42    fn use_memo<F, D, T>(&mut self, f: F, deps: D) -> T
43    where
44        F: FnOnce() -> T,
45        D: Hash,
46        T: Clone + Send + Unpin + 'static,
47    {
48        let dep_hash = hash_deps(deps);
49        let hook = self.use_hook(UseMemoImpl::<T>::default);
50        if hook.deps_hash != dep_hash || hook.memoized_value.is_none() {
51            hook.memoized_value = Some(f());
52            hook.deps_hash = dep_hash;
53        }
54        hook.memoized_value.clone().unwrap()
55    }
56}