penumbra_sdk_tct/internal/hash/
cache.rs1use std::fmt::Debug;
4
5use parking_lot::Mutex;
6
7use crate::prelude::*;
8
9#[derive(Default, Derivative)]
11pub struct CachedHash {
12 mutex: Mutex<OptionHash>,
13}
14
15impl Debug for CachedHash {
16 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17 if let Some(hash) = <Option<Hash>>::from(*self.mutex.lock()) {
18 write!(f, "{hash:?}")
19 } else {
20 write!(f, "_")
21 }
22 }
23}
24
25impl Clone for CachedHash {
26 fn clone(&self) -> Self {
27 Self {
28 mutex: Mutex::new(*self.mutex.lock()),
29 }
30 }
31}
32
33impl CachedHash {
34 pub fn get(&self) -> Option<Hash> {
36 (*self.mutex.lock()).into()
37 }
38
39 pub fn set_if_empty(&self, new: impl FnOnce() -> Hash) -> Hash {
41 let mut guard = self.mutex.lock();
42 if let Some(hash) = Option::from(*guard) {
43 hash
44 } else {
45 let new = new();
46 *guard = OptionHash::from(Some(new));
47 new
48 }
49 }
50
51 pub fn clear(&self) {
53 *self.mutex.lock() = OptionHash::from(None);
54 }
55}
56
57impl From<Hash> for CachedHash {
58 fn from(hash: Hash) -> Self {
59 Self {
60 mutex: Mutex::new(OptionHash::from(Some(hash))),
61 }
62 }
63}
64
65#[cfg(test)]
66mod test {
67 use super::*;
68
69 #[test]
70 fn cached_hash_size() {
71 static_assertions::assert_eq_size!(CachedHash, [u8; 40]);
72 }
73}