use std::marker::PhantomData; use graphene_core::Node; use once_cell::sync::OnceCell; /// Caches the output of a given Node and acts as a proxy #[derive(Default)] pub struct CacheNode { cache: OnceCell, } impl<'i, T: 'i> Node<'i, T> for CacheNode { type Output = &'i T; fn eval<'s: 'i>(&'s self, input: T) -> Self::Output { self.cache.get_or_init(|| { trace!("Creating new cache node"); input }) } } impl CacheNode { pub const fn new() -> CacheNode { CacheNode { cache: OnceCell::new() } } } /// Caches the output of a given Node and acts as a proxy #[derive(Debug, Clone, PartialEq, Eq, Default)] pub struct LetNode { cache: OnceCell, } impl<'i, T: 'i> Node<'i, Option> for LetNode { type Output = &'i T; fn eval<'s: 'i>(&'s self, input: Option) -> Self::Output { match input { Some(input) => { self.cache.set(input).unwrap_or_else(|_| error!("Let node was set twice but is not mutable")); self.cache.get().unwrap() } None => self.cache.get().expect("Let node was not initialized"), } } } impl LetNode { pub const fn new() -> LetNode { LetNode { cache: OnceCell::new() } } } /// Caches the output of a given Node and acts as a proxy #[derive(Debug, Clone, PartialEq, Eq, Default)] pub struct EndLetNode { input: Input, } impl<'i, T: 'i, Input> Node<'i, &'i T> for EndLetNode where Input: Node<'i, ()>, { type Output = ::Output; fn eval<'s: 'i>(&'s self, _: &'i T) -> Self::Output { self.input.eval(()) } } impl EndLetNode { pub const fn new(input: Input) -> EndLetNode { EndLetNode { input } } } pub use graphene_core::ops::SomeNode as InitNode; #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct RefNode { let_node: Let, _t: PhantomData, } impl<'i, T: 'i, Let> Node<'i, ()> for RefNode where Let: for<'a> Node<'a, Option, Output = &'a T>, { type Output = &'i T; fn eval<'s: 'i>(&'s self, _: ()) -> Self::Output { self.let_node.eval(None) } } impl RefNode { pub const fn new(let_node: Let) -> RefNode { RefNode { let_node, _t: PhantomData } } }