icmd 0.1.0

A command-line software framework
Documentation
use std::{fmt::Debug, sync::Arc};

use parking_lot::RwLock;

use crate::node::Node;

pub type NodeRef = Arc<dyn Node>;

/// A lazy evaluation wrapper that allows for deferred computation of a value.
/// It can be used to create a value that is computed only when needed.
pub struct Lazy<'a, T> {
    inner: RwLock<LazyInner<'a, T>>,
}

enum LazyInner<'a, T> {
    Lazy(Box<dyn Fn() -> T + Send + Sync + 'a>),
    Value(T),
}

/// A type alias for a lazy measure that can be used to defer the computation of a value.
pub type LazyMeasure = Lazy<'static, i32>;

impl<'a, T> Lazy<'a, T> {
    /// Creates a new `Lazy` instance with a closure that computes the value.
    pub fn new(f: impl Fn() -> T + Send + Sync + 'a) -> Self {
        Self {
            inner: RwLock::new(LazyInner::Lazy(Box::new(f))),
        }
    }

    /// Creates a new `Lazy` instance with a value that is already computed.
    /// This is useful when you want to create a `Lazy` instance without a closure.
    pub fn lazy(v: T) -> Self {
        Self {
            inner: RwLock::new(LazyInner::Value(v)),
        }
    }

    /// Evaluates the lazy value, replacing the closure with the computed value.
    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);
            }
        }
    }

    /// Evaluates the lazy value without replacing the closure.
    /// This is useful when you want to keep the closure for future evaluations.
    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),
        }
    }
}