use alloc::boxed::Box; #[cfg(not(feature = "mock_data"))] pub struct CachedValue { init_fn: Box T>, value: Option, } #[cfg(not(feature = "mock_data"))] impl CachedValue { pub fn new(init_fn: Box T>) -> Self { Self { init_fn, value: None, } } #[inline(always)] fn init_if_empty(&self) { if self.value.is_none() { unsafe { let s = self as *const Self as *mut Self; s.as_mut().unwrap().value.replace((self.init_fn)()); } } } #[inline] pub fn value(&self) -> T where T: Clone, { self.init_if_empty(); self.value.as_ref().unwrap().clone() } #[inline] pub fn value_ref(&self) -> &T { self.init_if_empty(); self.value.as_ref().unwrap() } } #[cfg(feature = "mock_data")] pub struct CachedValue { value: T, } #[cfg(feature = "mock_data")] impl CachedValue { pub fn new(value: T) -> Self { Self { value } } #[inline] pub fn value(&self) -> T where T: Clone, { self.value.clone() } #[inline] pub fn value_ref(&self) -> &T { &self.value } } #[cfg(feature = "mock_data")] impl From for CachedValue { fn from(value: T) -> Self { Self::new(value) } } #[macro_export] macro_rules! cached_value { ($init: block) => { CachedValue::new(alloc::boxed::Box::new(move || unsafe { $init })) }; } #[macro_export] macro_rules! cached_value_getters { ( $( $(#[$attr:meta])* $v:vis fn $name:ident(&self) -> $type:ty; )* ) => { $( $(#[$attr])* $v fn $name(&self) -> $type { self.inner.$name.value() } )* }; }