use core::marker::PhantomData; use crate::Node; #[derive(Clone)] pub struct ComposeNode { first: First, second: Second, phantom: PhantomData, } impl<'i, 'f: 'i, 's: 'i, Input: 'i, First, Second> Node<'i, Input> for ComposeNode where First: Node<'i, Input>, Second: Node<'i, >::Output> + 'i, { type Output = >::Output>>::Output; fn eval(&'i self, input: Input) -> Self::Output { let arg = self.first.eval(input); let second = &self.second; second.eval(arg) } } impl<'i, First, Second, Input: 'i> ComposeNode where First: Node<'i, Input>, Second: Node<'i, >::Output>, { pub const fn new(first: First, second: Second) -> Self { ComposeNode:: { first, second, phantom: PhantomData } } } pub trait Then<'i, Input: 'i>: Sized { fn then(self, second: Second) -> ComposeNode where Self: Node<'i, Input>, Second: Node<'i, >::Output>, { ComposeNode::new(self, second) } } impl<'i, First: Node<'i, Input>, Input: 'i> Then<'i, Input> for First {} pub struct ConsNode, Root>(pub Root, PhantomData); impl<'i, Root, Input: 'i, I: 'i + From<()>> Node<'i, Input> for ConsNode where Root: Node<'i, I>, { type Output = (Input, Root::Output); fn eval(&'i self, input: Input) -> Self::Output { let arg = self.0.eval(I::from(())); (input, arg) } } impl<'i, Root: Node<'i, I>, I: 'i + From<()>> ConsNode { pub fn new(root: Root) -> Self { ConsNode(root, PhantomData) } } #[cfg(test)] mod test { use crate::{ops::IdNode, value::ValueNode}; use super::*; #[test] fn compose() { let value = ValueNode::new(4u32); let compose = value.then(IdNode::new()); assert_eq!(compose.eval(()), &4u32); let type_erased = &compose as &dyn for<'i> Node<'i, (), Output = &'i u32>; assert_eq!(type_erased.eval(()), &4u32); } #[test] fn test_ref_eval() { let value = ValueNode::new(5); assert_eq!(value.eval(()), &5); let id = IdNode::new(); let compose = ComposeNode::new(&value, &id); assert_eq!(compose.eval(()), &5); } }