use core::marker::PhantomData; use crate::{AsRefNode, Node, RefNode}; #[derive(Debug)] pub struct ComposeNode { first: First, second: Second, _phantom: PhantomData, } impl Node for ComposeNode where First: Node, Second: Node, { type Output = >::Output; fn eval(self, input: Input) -> Self::Output { // evaluate the first node with the given input // and then pipe the result from the first computation // into the second node let arg: Inter = self.first.eval(input); self.second.eval(arg) } } impl<'n, Input, Inter, First, Second> Node for &'n ComposeNode where First: AsRefNode<'n, Input, Output = Inter>, Second: AsRefNode<'n, Inter>, &'n First: Node, &'n Second: Node, { type Output = >::Output; fn eval(self, input: Input) -> Self::Output { // evaluate the first node with the given input // and then pipe the result from the first computation // into the second node let arg: Inter = (self.first).eval_box(input); (self.second).eval_box(arg) } } impl RefNode for ComposeNode where First: RefNode + Copy, Second: RefNode + Copy, { type Output = >::Output; fn eval_ref(&self, input: Input) -> Self::Output { // evaluate the first node with the given input // and then pipe the result from the first computation // into the second node let arg: Inter = (self.first).eval_ref(input); (self.second).eval_ref(arg) } } #[cfg(feature = "std")] impl dyn_any::StaticType for ComposeNode { type Static = ComposeNode; } impl<'n, Input, First: 'n, Second: 'n> ComposeNode { pub const fn new(first: First, second: Second) -> Self { ComposeNode:: { first, second, _phantom: PhantomData } } } pub trait Then: Sized { fn then(self, second: Second) -> ComposeNode where Self: Node, Second: Node, { ComposeNode:: { first: self, second, _phantom: PhantomData, } } } impl, Inter, Input> Then for First {} pub trait ThenRef: Sized { fn after<'n, Second: 'n>(&'n self, second: Second) -> ComposeNode<&'n Self, Second, Input> where &'n Self: Node + Copy, Second: Node, Self: 'n, { ComposeNode::<&'n Self, Second, Input> { first: self, second, _phantom: PhantomData, } } } impl<'n, First: 'n, Inter, Input> ThenRef for First where &'n First: Node {} #[cfg(feature = "async")] pub trait ThenBox { fn then<'n, Second: 'n>(self, second: Second) -> ComposeNode where alloc::boxed::Box: Node, Second: Node + Copy, Self: Sized, { ComposeNode:: { first: self, second, _phantom: PhantomData, } } } #[cfg(feature = "async")] impl<'n, First: 'n, Inter, Input> ThenBox for alloc::boxed::Box where &'n alloc::boxed::Box: Node {} pub struct ConsNode>(pub Root, pub PhantomData); impl> Node for ConsNode where Root: Node, { type Output = (Input, >::Output); fn eval(self, input: Input) -> Self::Output { let arg = self.0.eval(().into()); (input, arg) } } impl<'n, Root: Node + Copy, T: From<()>, Input> Node for &'n ConsNode { type Output = (Input, Root::Output); fn eval(self, input: Input) -> Self::Output { let arg = self.0.eval(().into()); (input, arg) } } impl> ConsNode { pub fn new(root: Root) -> Self { ConsNode(root, PhantomData) } }