use crate::Node; use std::cell::{Cell, RefCell, RefMut}; use std::marker::PhantomData; #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] pub struct IntNode; impl<'i, const N: u32, I> Node<'i, I> for IntNode { type Output = u32; #[inline(always)] fn eval(&'i self, _input: I) -> Self::Output { N } } #[derive(Default, Debug, Clone, Copy)] pub struct ValueNode(pub T); impl<'i, T: 'i, I> Node<'i, I> for ValueNode { type Output = &'i T; #[inline(always)] fn eval(&'i self, _input: I) -> Self::Output { &self.0 } } impl ValueNode { pub const fn new(value: T) -> ValueNode { ValueNode(value) } } impl From for ValueNode { fn from(value: T) -> Self { ValueNode::new(value) } } #[derive(Default, Debug, Clone, Copy)] pub struct AsRefNode, U>(pub T, PhantomData); impl<'i, T: 'i + AsRef, U: 'i> Node<'i, ()> for AsRefNode { type Output = &'i U; #[inline(always)] fn eval(&'i self, _input: ()) -> Self::Output { self.0.as_ref() } } impl, U> AsRefNode { pub const fn new(value: T) -> AsRefNode { AsRefNode(value, PhantomData) } } #[derive(Default, Debug, Clone)] pub struct RefCellMutNode(pub RefCell); impl<'i, T: 'i> Node<'i, ()> for RefCellMutNode { type Output = RefMut<'i, T>; #[inline(always)] fn eval(&'i self, _input: ()) -> Self::Output { let a = self.0.borrow_mut(); a } } impl RefCellMutNode { pub const fn new(value: T) -> RefCellMutNode { RefCellMutNode(RefCell::new(value)) } } #[derive(Default)] pub struct OnceCellNode(pub Cell); impl<'i, T: Default + 'i, I> Node<'i, I> for OnceCellNode { type Output = T; #[inline(always)] fn eval(&'i self, _input: I) -> Self::Output { self.0.replace(T::default()) } } impl OnceCellNode { pub const fn new(value: T) -> OnceCellNode { OnceCellNode(Cell::new(value)) } } #[derive(Clone, Copy)] pub struct ClonedNode(pub T); impl<'i, T: Clone + 'i, I> Node<'i, I> for ClonedNode { type Output = T; #[inline(always)] fn eval(&'i self, _input: I) -> Self::Output { self.0.clone() } } impl ClonedNode { pub const fn new(value: T) -> ClonedNode { ClonedNode(value) } } impl From for ClonedNode { fn from(value: T) -> Self { ClonedNode::new(value) } } #[derive(Clone, Copy)] /// The DebugClonedNode logs every time it is evaluated. /// This is useful for debugging. pub struct DebugClonedNode(pub T); impl<'i, T: Clone + 'i> Node<'i, ()> for DebugClonedNode { type Output = T; #[inline(always)] fn eval(&'i self, _input: ()) -> Self::Output { #[cfg(not(target_arch = "spirv"))] // KEEP THIS `debug!()` - It acts as the output for the debug node itself log::debug!("DebugClonedNode::eval"); self.0.clone() } } impl DebugClonedNode { pub const fn new(value: T) -> DebugClonedNode { DebugClonedNode(value) } } #[derive(Clone, Copy)] pub struct CopiedNode(pub T); impl<'i, T: Copy + 'i, I> Node<'i, I> for CopiedNode { type Output = T; #[inline(always)] fn eval(&'i self, _input: I) -> Self::Output { self.0 } } impl CopiedNode { pub const fn new(value: T) -> CopiedNode { CopiedNode(value) } } #[derive(Default)] pub struct DefaultNode(PhantomData); impl<'i, T: Default + 'i, I> Node<'i, I> for DefaultNode { type Output = T; fn eval(&'i self, _input: I) -> Self::Output { T::default() } } impl DefaultNode { pub fn new() -> Self { Self(PhantomData) } } #[repr(C)] /// Return the unit value #[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] pub struct ForgetNode; impl<'i, T: 'i> Node<'i, T> for ForgetNode { type Output = (); fn eval(&'i self, _input: T) -> Self::Output {} } impl ForgetNode { pub const fn new() -> Self { ForgetNode } } #[cfg(test)] mod test { use super::*; #[test] fn test_int_node() { let node = IntNode::<5>; assert_eq!(node.eval(()), 5); } #[test] fn test_value_node() { let node = ValueNode::new(5); assert_eq!(node.eval(()), &5); let type_erased = &node as &dyn for<'a> Node<'a, (), Output = &'a i32>; assert_eq!(type_erased.eval(()), &5); } #[test] fn test_default_node() { let node = DefaultNode::::new(); assert_eq!(node.eval(42), 0); } #[test] #[allow(clippy::unit_cmp)] fn test_unit_node() { let node = ForgetNode::new(); assert_eq!(node.eval(()), ()); } }