37 lines
744 B
Rust
37 lines
744 B
Rust
use alloc::boxed::Box;
|
|
|
|
pub struct CachedValue<T> {
|
|
init_fn: Box<dyn Fn() -> T>,
|
|
value: Option<T>,
|
|
}
|
|
|
|
impl<T> CachedValue<T>
|
|
where
|
|
T: Clone,
|
|
{
|
|
pub fn new(init_fn: Box<dyn Fn() -> T>) -> Self {
|
|
Self {
|
|
init_fn,
|
|
value: None,
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn value(&self) -> T {
|
|
if self.value.is_none() {
|
|
unsafe {
|
|
let s = self as *const Self as *mut Self;
|
|
s.as_mut().unwrap().value.replace((self.init_fn)());
|
|
}
|
|
}
|
|
self.value.as_ref().unwrap().clone()
|
|
}
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! cached_value {
|
|
($init: block) => {
|
|
CachedValue::new(alloc::boxed::Box::new(move || unsafe { $init }))
|
|
};
|
|
}
|