use std::sync::OnceLock;
#[derive(Debug)]
pub(crate) struct OnceCache<T> {
value: OnceLock<T>,
}
impl<T> OnceCache<T> {
pub(crate) const fn new() -> Self {
Self {
value: OnceLock::new(),
}
}
pub(crate) fn with_value(value: T) -> Self {
let cache = Self::new();
let _ = cache.value.set(value);
cache
}
pub(crate) fn get(&self) -> Option<&T> {
self.value.get()
}
pub(crate) fn try_set(&self, value: T) -> Result<(), T> {
self.value.set(value)
}
pub(crate) fn get_or_compute<F>(&self, compute_fn: F) -> &T
where
F: FnOnce() -> T,
{
self.value.get_or_init(compute_fn)
}
}
impl<T> Default for OnceCache<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: Clone> Clone for OnceCache<T> {
fn clone(&self) -> Self {
self.value
.get()
.map_or_else(Self::new, |value| Self::with_value(value.clone()))
}
}