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
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}