use std::{fmt::Debug, sync::Arc};
use parking_lot::RwLock;
use crate::node::Node;
pub type NodeRef = Arc<dyn Node>;
pub struct Lazy<'a, T> {
inner: RwLock<LazyInner<'a, T>>,
}
enum LazyInner<'a, T> {
Lazy(Box<dyn Fn() -> T + Send + Sync + 'a>),
Value(T),
}
pub type LazyMeasure = Lazy<'static, i32>;
impl<'a, T> Lazy<'a, T> {
pub fn new(f: impl Fn() -> T + Send + Sync + 'a) -> Self {
Self {
inner: RwLock::new(LazyInner::Lazy(Box::new(f))),
}
}
pub fn lazy(v: T) -> Self {
Self {
inner: RwLock::new(LazyInner::Value(v)),
}
}
pub fn eval(&self) {
let is_lazy = {
let inner = self.inner.read();
matches!(*inner, LazyInner::Lazy(_))
};
if is_lazy {
let mut inner_mut = self.inner.write();
if let LazyInner::Lazy(ref mut f) = *inner_mut {
let value = f();
*inner_mut = LazyInner::Value(value);
}
}
}
pub fn get(&self) -> T
where
T: Clone,
{
match *self.inner.read() {
LazyInner::Lazy(ref f) => f(),
LazyInner::Value(ref v) => v.clone(),
}
}
}
impl<'a, T: Debug> Debug for Lazy<'a, T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match *self.inner.read() {
LazyInner::Lazy(_) => write!(f, "Lazy"),
LazyInner::Value(ref v) => write!(f, "{:?}", v),
}
}
}