ratatui_kit/hooks/
use_memo.rs1use 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
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}