Make node trait consume self

This commit is contained in:
Dennis
2022-08-19 18:58:17 +02:00
committed by Keavon Chambers
parent 12b33da083
commit bdad7aca47
10 changed files with 286 additions and 188 deletions

View File

@@ -1,31 +1,45 @@
use core::marker::PhantomData;
use crate::Node;
pub struct FnNode<'n, T: Fn(I) -> O, I, O>(T, PhantomData<&'n (I, O)>);
impl<'n, T: Fn(I) -> O, O, I> Node<'n, I> for FnNode<'n, T, I, O> {
pub struct FnNode<T: Fn(I) -> O, I, O>(T, PhantomData<(I, O)>);
impl<T: Fn(I) -> O, O, I> Node<I> for FnNode<T, I, O> {
type Output = O;
fn eval(&'n self, input: I) -> Self::Output {
fn eval(self, input: I) -> Self::Output {
self.0(input)
}
}
impl<'n, T: Fn(I) -> O, O, I> Node<I> for &'n FnNode<T, I, O> {
type Output = O;
fn eval(self, input: I) -> Self::Output {
self.0(input)
}
}
impl<'n, T: Fn(I) -> O, I, O> FnNode<'n, T, I, O> {
impl<T: Fn(I) -> O, I, O> FnNode<T, I, O> {
pub fn new(f: T) -> Self {
FnNode(f, PhantomData)
}
}
pub struct FnNodeWithState<'n, T: Fn(I, &'n State) -> O, I, O, State: 'n>(T, State, PhantomData<&'n (O, I)>);
impl<'n, T: Fn(I, &'n State) -> O, I, O: 'n, State: 'n> Node<'n, I> for FnNodeWithState<'n, T, I, O, State> {
pub struct FnNodeWithState<'n, T: Fn(I, &'n State) -> O, I, O: 'n, State: 'n>(T, State, PhantomData<&'n (O, I)>);
impl<'n, T: Fn(I, &State) -> O, I, O: 'n, State: 'n> Node<I> for &'n FnNodeWithState<'n, T, I, O, State> {
type Output = O;
fn eval(&'n self, input: I) -> Self::Output {
fn eval(self, input: I) -> Self::Output {
self.0(input, &self.1)
}
}
impl<'n, T: Fn(I, &State) -> O, I, O: 'n, State: 'n> Node<I> for FnNodeWithState<'n, T, I, O, State> {
type Output = O;
fn eval(self, input: I) -> Self::Output {
self.0(input, &self.1)
}
}
impl<'n, T: Fn(I, &'n State) -> O, I, O: 'n, State: 'n> FnNodeWithState<'n, T, I, O, State> {
impl<'n, T: Fn(I, &State) -> O, I, O, State> FnNodeWithState<'n, T, I, O, State> {
pub fn new(f: T, state: State) -> Self {
FnNodeWithState(f, state, PhantomData)
}

View File

@@ -14,18 +14,10 @@ pub mod raster;
pub mod structural;
pub mod value;
pub trait Node<'n, T> {
type Output; // TODO: replace with generic associated type
pub trait Node<T> {
type Output;
fn eval(&'n self, input: T) -> Self::Output;
}
impl<'n, N: Node<'n, T>, T> Node<'n, T> for &'n N {
type Output = N::Output;
fn eval(&'n self, input: T) -> Self::Output {
Node::eval(*self, input)
}
fn eval(self, input: T) -> Self::Output;
}
trait Input<I> {
@@ -34,21 +26,21 @@ trait Input<I> {
#[cfg(feature = "async")]
#[async_trait]
pub trait AsyncNode<'n, T> {
type Output; // TODO: replace with generic associated type
pub trait AsyncNode<T> {
type Output;
async fn eval_async(&'n self, input: T) -> Self::Output;
async fn eval_async(self, input: T) -> Self::Output;
}
#[cfg(feature = "async")]
/*#[cfg(feature = "async")]
#[async_trait]
impl<'n, N: Node<'n, T> + Sync, T: Send + 'n> AsyncNode<'n, T> for N {
impl<'n, N: Node<T> + Send + Sync + 'n, T: Send + 'n> AsyncNode<T> for N {
type Output = N::Output;
async fn eval_async(&'n self, input: T) -> Self::Output {
async fn eval_async(self, input: T) -> Self::Output {
Node::eval(self, input)
}
}
}*/
pub trait Cache {
fn clear(&mut self);

View File

@@ -3,111 +3,124 @@ use core::ops::Add;
use crate::Node;
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct AddNode;
impl<'n, L: Add<R, Output = O> + 'n, R, O: 'n> Node<'n, (L, R)> for AddNode {
impl<'n, L: Add<R, Output = O> + 'n, R, O: 'n> Node<(L, R)> for AddNode {
type Output = <L as Add<R>>::Output;
fn eval(&'n self, input: (L, R)) -> Self::Output {
fn eval(self, input: (L, R)) -> Self::Output {
input.0 + input.1
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CloneNode;
impl<'n, O: Clone> Node<'n, &'n O> for CloneNode {
impl<'n, O: Clone> Node<&'n O> for CloneNode {
type Output = O;
fn eval(&'n self, input: &'n O) -> Self::Output {
fn eval(self, input: &'n O) -> Self::Output {
input.clone()
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FstNode;
impl<'n, T: 'n, U> Node<'n, (T, U)> for FstNode {
impl<'n, T: 'n, U> Node<(T, U)> for FstNode {
type Output = T;
fn eval(&'n self, input: (T, U)) -> Self::Output {
fn eval(self, input: (T, U)) -> Self::Output {
let (a, _) = input;
a
}
}
impl<'n, T: 'n, U> Node<'n, &'n (T, U)> for FstNode {
impl<'n, T: 'n, U> Node<&'n (T, U)> for FstNode {
type Output = &'n T;
fn eval(&'n self, input: &'n (T, U)) -> Self::Output {
fn eval(self, input: &'n (T, U)) -> Self::Output {
let (a, _) = input;
a
}
}
/// Destructures a Tuple of two values and returns the first one
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SndNode;
impl<'n, T, U: 'n> Node<'n, (T, U)> for SndNode {
impl<'n, T, U: 'n> Node<(T, U)> for SndNode {
type Output = U;
fn eval(&'n self, input: (T, U)) -> Self::Output {
fn eval(self, input: (T, U)) -> Self::Output {
let (_, b) = input;
b
}
}
impl<'n, T, U: 'n> Node<'n, &'n (T, U)> for SndNode {
impl<'n, T, U: 'n> Node<&'n (T, U)> for SndNode {
type Output = &'n U;
fn eval(&'n self, input: &'n (T, U)) -> Self::Output {
fn eval(self, input: &'n (T, U)) -> Self::Output {
let (_, b) = input;
b
}
}
/// Destructures a Tuple of two values and returns them in reverse order
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SwapNode;
impl<'n, T: 'n, U: 'n> Node<'n, (T, U)> for SwapNode {
impl<'n, T: 'n, U: 'n> Node<(T, U)> for SwapNode {
type Output = (U, T);
fn eval(&'n self, input: (T, U)) -> Self::Output {
fn eval(self, input: (T, U)) -> Self::Output {
let (a, b) = input;
(b, a)
}
}
impl<'n, T, U: 'n> Node<'n, &'n (T, U)> for SwapNode {
impl<'n, T, U: 'n> Node<&'n (T, U)> for SwapNode {
type Output = (&'n U, &'n T);
fn eval(&'n self, input: &'n (T, U)) -> Self::Output {
fn eval(self, input: &'n (T, U)) -> Self::Output {
let (a, b) = input;
(b, a)
}
}
/// Return a tuple with two instances of the input argument
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DupNode;
impl<'n, T: Clone + 'n> Node<'n, T> for DupNode {
impl<'n, T: Clone + 'n> Node<T> for DupNode {
type Output = (T, T);
fn eval(&'n self, input: T) -> Self::Output {
fn eval(self, input: T) -> Self::Output {
(input.clone(), input) //TODO: use Copy/Clone implementation
}
}
/// Return the Input Argument
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct IdNode;
impl<'n, T: 'n> Node<'n, T> for IdNode {
impl<'n, T: 'n> Node<T> for IdNode {
type Output = T;
fn eval(&'n self, input: T) -> Self::Output {
fn eval(self, input: T) -> Self::Output {
input
}
}
pub struct MapResultNode<'n, MN: Node<'n, I>, I, E>(pub MN, pub PhantomData<&'n (I, E)>);
pub struct MapResultNode<MN, I, E>(pub MN, pub PhantomData<(I, E)>);
impl<'n, MN: Node<'n, I>, I, E> Node<'n, Result<I, E>> for MapResultNode<'n, MN, I, E> {
impl<MN: Node<I>, I, E> Node<Result<I, E>> for MapResultNode<MN, I, E> {
type Output = Result<MN::Output, E>;
fn eval(&'n self, input: Result<I, E>) -> Self::Output {
fn eval(self, input: Result<I, E>) -> Self::Output {
input.map(|x| self.0.eval(x))
}
}
impl<'n, MN: Node<I> + Copy, I, E> Node<Result<I, E>> for &'n MapResultNode<MN, I, E> {
type Output = Result<MN::Output, E>;
fn eval(self, input: Result<I, E>) -> Self::Output {
input.map(|x| (&self.0).eval(x))
}
}
impl<'n, MN: Node<'n, I>, I, E> MapResultNode<'n, MN, I, E> {
impl<MN, I, E> MapResultNode<MN, I, E> {
pub const fn new(mn: MN) -> Self {
Self(mn, PhantomData)
}
}
pub struct FlatMapResultNode<'n, MN: Node<'n, I>, I, E>(pub MN, pub PhantomData<&'n (I, E)>);
pub struct FlatMapResultNode<MN: Node<I>, I, E>(pub MN, pub PhantomData<(I, E)>);
impl<'n, MN: Node<'n, I, Output = Result<O, E>>, I, O: 'n, E: 'n> Node<'n, Result<I, E>> for FlatMapResultNode<'n, MN, I, E> {
impl<'n, MN: Node<I, Output = Result<O, E>>, I, O: 'n, E: 'n> Node<Result<I, E>> for FlatMapResultNode<MN, I, E> {
type Output = Result<O, E>;
fn eval(&'n self, input: Result<I, E>) -> Self::Output {
fn eval(self, input: Result<I, E>) -> Self::Output {
match input.map(|x| self.0.eval(x)) {
Ok(Ok(x)) => Ok(x),
Ok(Err(e)) => Err(e),
@@ -116,7 +129,7 @@ impl<'n, MN: Node<'n, I, Output = Result<O, E>>, I, O: 'n, E: 'n> Node<'n, Resul
}
}
impl<'n, MN: Node<'n, I>, I, E> FlatMapResultNode<'n, MN, I, E> {
impl<MN: Node<I>, I, E> FlatMapResultNode<MN, I, E> {
pub const fn new(mn: MN) -> Self {
Self(mn, PhantomData)
}
@@ -131,26 +144,26 @@ mod test {
pub fn dup_node() {
let value = ValueNode(4u32);
let dup = DupNode.after(value);
assert_eq!(dup.eval(()), (&4, &4));
assert_eq!(dup.eval(()), (4, 4));
}
#[test]
pub fn id_node() {
let value = IdNode.after(ValueNode(4u32));
assert_eq!(value.eval(()), &4);
assert_eq!(value.eval(()), 4);
}
#[test]
pub fn clone_node() {
let cloned = CloneNode.after(ValueNode(4u32));
let cloned = CloneNode.after(&ValueNode(4u32));
assert_eq!(cloned.eval(()), 4);
}
#[test]
pub fn fst_node() {
let fst = FstNode.after(ValueNode((4u32, "a")).clone());
let fst = FstNode.after(ValueNode((4u32, "a")));
assert_eq!(fst.eval(()), 4);
}
#[test]
pub fn snd_node() {
let fst = SndNode.after(ValueNode((4u32, "a")).clone());
let fst = SndNode.after(ValueNode((4u32, "a")));
assert_eq!(fst.eval(()), "a");
}
#[test]
@@ -164,8 +177,8 @@ mod test {
}
#[test]
pub fn foo() {
fn int(_: (), state: &u32) -> &u32 {
state
fn int(_: (), state: &u32) -> u32 {
*state
}
fn swap(input: (u32, u32)) -> (u32, u32) {
(input.1, input.0)
@@ -173,6 +186,7 @@ mod test {
let fnn = FnNode::new(&swap);
let fns = FnNodeWithState::new(int, 42u32);
assert_eq!(fnn.eval((1u32, 2u32)), (2, 1));
assert_eq!(fns.eval(()), &42);
let result: u32 = (&fns).eval(());
assert_eq!(result, 42);
}
}

View File

@@ -1,36 +1,48 @@
use core::marker::PhantomData;
use crate::Node;
use self::color::Color;
pub mod color;
#[derive(Debug, Clone, Copy)]
pub struct GrayscaleNode;
impl<'n> Node<'n, Color> for GrayscaleNode {
impl Node<Color> for GrayscaleNode {
type Output = Color;
fn eval(&'n self, color: Color) -> Color {
fn eval(self, color: Color) -> Color {
let avg = (color.r() + color.g() + color.b()) / 3.0;
Color::from_rgbaf32(avg, avg, avg, color.a()).expect("Grayscale node created an invalid color")
Color::from_rgbaf32_unchecked(avg, avg, avg, color.a())
}
}
impl<'n> Node<Color> for &'n GrayscaleNode {
type Output = Color;
fn eval(self, color: Color) -> Color {
let avg = (color.r() + color.g() + color.b()) / 3.0;
Color::from_rgbaf32_unchecked(avg, avg, avg, color.a())
}
}
pub struct ForEachNode<'n, I: Iterator<Item = S>, MN: Node<'n, S>, S>(pub MN, PhantomData<&'n (I, S)>);
pub struct ForEachNode<MN>(pub MN);
impl<'n, I: Iterator<Item = S>, MN: Node<'n, S, Output = ()>, S> Node<'n, I> for ForEachNode<'n, I, MN, S> {
impl<'n, I: Iterator<Item = S>, MN: 'n, S> Node<I> for &'n ForEachNode<MN>
where
&'n MN: Node<S, Output = ()>,
{
type Output = ();
fn eval(&'n self, input: I) -> Self::Output {
input.for_each(|x| self.0.eval(x))
fn eval(self, input: I) -> Self::Output {
input.for_each(|x| (&self.0).eval(x))
}
}
pub struct MutWrapper<'n, N: Node<'n, T, Output = T>, T: Clone>(pub N, PhantomData<&'n T>);
pub struct MutWrapper<N>(pub N);
impl<'n, T: Clone, N: Node<'n, T, Output = T>> Node<'n, &'n mut T> for MutWrapper<'n, N, T> {
impl<'n, T: Clone, N> Node<&'n mut T> for &'n MutWrapper<N>
where
&'n N: Node<T, Output = T>,
{
type Output = ();
fn eval(&'n self, value: &'n mut T) {
*value = self.0.eval(value.clone());
fn eval(self, value: &'n mut T) {
*value = (&self.0).eval(value.clone());
}
}
@@ -41,8 +53,9 @@ mod test {
#[test]
fn map_node() {
let array = &mut [Color::from_rgbaf32(1.0, 0.0, 0.0, 1.0).unwrap()];
let map = ForEachNode(MutWrapper(GrayscaleNode, PhantomData), PhantomData);
map.eval(array.iter_mut());
(&GrayscaleNode).eval(Color::from_rgbf32_unchecked(1., 0., 0.));
let map = ForEachNode(MutWrapper(GrayscaleNode));
(&map).eval(array.iter_mut());
assert_eq!(array[0], Color::from_rgbaf32(0.33333334, 0.33333334, 0.33333334, 1.0).unwrap());
}
}

View File

@@ -14,11 +14,11 @@ pub struct Color {
}
impl Color {
pub const BLACK: Color = Color::from_unsafe(0., 0., 0.);
pub const WHITE: Color = Color::from_unsafe(1., 1., 1.);
pub const RED: Color = Color::from_unsafe(1., 0., 0.);
pub const GREEN: Color = Color::from_unsafe(0., 1., 0.);
pub const BLUE: Color = Color::from_unsafe(0., 0., 1.);
pub const BLACK: Color = Color::from_rgbf32_unchecked(0., 0., 0.);
pub const WHITE: Color = Color::from_rgbf32_unchecked(1., 1., 1.);
pub const RED: Color = Color::from_rgbf32_unchecked(1., 0., 0.);
pub const GREEN: Color = Color::from_rgbf32_unchecked(0., 1., 0.);
pub const BLUE: Color = Color::from_rgbf32_unchecked(0., 0., 1.);
/// Returns `Some(Color)` if `red`, `green`, `blue` and `alpha` have a valid value. Negative numbers (including `-0.0`), NaN, and infinity are not valid values and return `None`.
/// Alpha values greater than `1.0` are not valid.
@@ -40,7 +40,12 @@ impl Color {
}
/// Return an opaque `Color` from given `f32` RGB channels.
pub const fn from_unsafe(red: f32, green: f32, blue: f32) -> Color {
pub const fn from_rgbaf32_unchecked(red: f32, green: f32, blue: f32, alpha: f32) -> Color {
Color { red, green, blue, alpha }
}
/// Return an opaque `Color` from given `f32` RGB channels.
pub const fn from_rgbf32_unchecked(red: f32, green: f32, blue: f32) -> Color {
Color { red, green, blue, alpha: 1. }
}

View File

@@ -2,20 +2,20 @@ use core::marker::PhantomData;
use crate::Node;
pub struct ComposeNode<'n, Input, First: Node<'n, Input>, Second> {
pub struct ComposeNode<First, Second, Input> {
first: First,
second: Second,
_phantom: PhantomData<&'n Input>,
_phantom: PhantomData<Input>,
}
impl<'n, Input, Inter, First, Second> Node<'n, Input> for ComposeNode<'n, Input, First, Second>
impl<Input, Inter, First, Second> Node<Input> for ComposeNode<First, Second, Input>
where
First: Node<'n, Input, Output = Inter>,
Second: Node<'n, Inter>,
First: Node<Input, Output = Inter>,
Second: Node<Inter>,
{
type Output = <Second as Node<'n, Inter>>::Output;
type Output = <Second as Node<Inter>>::Output;
fn eval(&'n self, input: Input) -> Self::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
@@ -23,52 +23,105 @@ where
self.second.eval(arg)
}
}
impl<'n, Input, First, Second> ComposeNode<'n, Input, First, Second>
impl<'n, Input, Inter, First, Second> Node<Input> for &'n ComposeNode<First, Second, Input>
where
First: Node<'n, Input>,
Second: Node<'n, First::Output>,
First: Node<Input, Output = Inter> + Copy,
Second: Node<Inter> + Copy,
{
type Output = Second::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, First: 'n, Second: 'n> ComposeNode<First, Second, Input>
where
First: Node<Input>,
Second: Node<First::Output>,
{
pub const fn new(first: First, second: Second) -> Self {
ComposeNode::<'n, Input, First, Second> { first, second, _phantom: PhantomData }
ComposeNode::<First, Second, Input> { first, second, _phantom: PhantomData }
}
}
pub trait After<Inter>: Sized {
fn after<'n, First, Input>(self, first: First) -> ComposeNode<'n, Input, First, Self>
fn after<First, Input>(self, first: First) -> ComposeNode<First, Self, Input>
where
First: Node<'n, Input, Output = Inter>,
Self: Node<'n, Inter>,
First: Node<Input, Output = Inter>,
Self: Node<Inter>,
{
ComposeNode::new(first, self)
ComposeNode::<First, Self, Input> {
first,
second: self,
_phantom: PhantomData,
}
}
}
impl<'n, Second: Node<'n, I>, I> After<I> for Second {}
impl<Second: Node<I>, I> After<I> for Second {}
pub trait AfterRef<Inter>: Sized {
fn after<'n, First: 'n, Input>(&'n self, first: First) -> ComposeNode<First, &'n Self, Input>
where
First: Node<Input, Output = Inter> + Copy,
&'n Self: Node<Inter>,
Self: 'n,
{
ComposeNode::<First, &'n Self, Input> {
first,
second: self,
_phantom: PhantomData,
}
}
}
impl<'n, Second: 'n, I> AfterRef<I> for Second where &'n Second: Node<I> {}
pub struct ConsNode<Root>(pub Root);
impl<'n, Root, Input> Node<'n, Input> for ConsNode<Root>
impl<Root, Input> Node<Input> for ConsNode<Root>
where
Root: Node<'n, ()>,
Root: Node<()>,
{
type Output = (Input, <Root as Node<'n, ()>>::Output);
type Output = (Input, <Root as Node<()>>::Output);
fn eval(&'n self, input: Input) -> Self::Output {
fn eval(self, input: Input) -> Self::Output {
let arg = self.0.eval(());
(input, arg)
}
}
impl<'n, Root: Node<()> + Copy, Input> Node<Input> for &'n ConsNode<Root> {
type Output = (Input, Root::Output);
fn eval(self, input: Input) -> Self::Output {
let arg = (&self.0).eval(());
(input, arg)
}
}
pub struct ConsPassInputNode<Root>(pub Root);
impl<'n, Root, L, R> Node<'n, (L, R)> for ConsPassInputNode<Root>
impl<Root, L, R> Node<(L, R)> for ConsPassInputNode<Root>
where
Root: Node<'n, R>,
Root: Node<R>,
{
type Output = (L, <Root as Node<'n, R>>::Output);
type Output = (L, <Root as Node<R>>::Output);
fn eval(&'n self, input: (L, R)) -> Self::Output {
fn eval(self, input: (L, R)) -> Self::Output {
let arg = self.0.eval(input.1);
(input.0, arg)
}
}
impl<'n, Root, L, R> Node<(L, R)> for &'n ConsPassInputNode<Root>
where
&'n Root: Node<R>,
{
type Output = (L, <&'n Root as Node<R>>::Output);
fn eval(self, input: (L, R)) -> Self::Output {
let arg = (&self.0).eval(input.1);
(input.0, arg)
}
}

View File

@@ -2,23 +2,28 @@ use core::marker::PhantomData;
use core::mem::MaybeUninit;
use core::sync::atomic::AtomicBool;
use crate::ops::CloneNode;
use crate::structural::ComposeNode;
use crate::Node;
#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct IntNode<const N: u32>;
impl<'n, const N: u32> Node<'n, ()> for IntNode<N> {
impl<const N: u32> Node<()> for IntNode<N> {
type Output = u32;
fn eval(&self, _: ()) -> u32 {
fn eval(self, _: ()) -> u32 {
N
}
}
#[derive(Default)]
#[derive(Default, Debug)]
pub struct ValueNode<T>(pub T);
impl<'n, T: 'n> Node<'n, ()> for ValueNode<T> {
impl<'n, T: 'n> Node<()> for ValueNode<T> {
type Output = T;
fn eval(self, _: ()) -> Self::Output {
self.0
}
}
impl<'n, T: 'n> Node<()> for &'n ValueNode<T> {
type Output = &'n T;
fn eval(&'n self, _: ()) -> Self::Output {
fn eval(self, _: ()) -> Self::Output {
&self.0
}
}
@@ -29,39 +34,60 @@ impl<T> ValueNode<T> {
}
}
impl<'n, T: Clone + 'n> ValueNode<T> {
pub const fn clone(self) -> ComposeNode<'n, (), ValueNode<T>, CloneNode> {
ComposeNode::new(self, CloneNode)
}
}
impl<T> From<T> for ValueNode<T> {
fn from(value: T) -> Self {
ValueNode::new(value)
}
}
impl<T: Clone> Clone for ValueNode<T> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<T: Clone + Copy> Copy for ValueNode<T> {}
#[derive(Default)]
pub struct DefaultNode<T>(PhantomData<T>);
impl<'n, T: Default + 'n> Node<'n, ()> for DefaultNode<T> {
impl<T: Default> Node<()> for DefaultNode<T> {
type Output = T;
fn eval(&self, _: ()) -> T {
fn eval(self, _: ()) -> T {
T::default()
}
}
impl<'n, T: Default + 'n> Node<()> for &'n DefaultNode<T> {
type Output = T;
fn eval(self, _: ()) -> T {
T::default()
}
}
#[repr(C)]
/// Return the unit value
#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub struct UnitNode;
impl<'n> Node<'n, ()> for UnitNode {
impl Node<()> for UnitNode {
type Output = ();
fn eval(&'n self, _: ()) -> Self::Output {}
fn eval(self, _: ()) -> Self::Output {}
}
impl<'n> Node<()> for &'n UnitNode {
type Output = ();
fn eval(self, _: ()) -> Self::Output {}
}
pub struct InputNode<T>(MaybeUninit<T>, AtomicBool);
impl<'n, T: 'n> Node<'n, ()> for InputNode<T> {
impl<'n, T: 'n> Node<()> for InputNode<T> {
type Output = T;
fn eval(self, _: ()) -> Self::Output {
if self.1.load(core::sync::atomic::Ordering::SeqCst) {
unsafe { self.0.assume_init() }
} else {
panic!("tried to access an input before setting it")
}
}
}
impl<'n, T: 'n> Node<()> for &'n InputNode<T> {
type Output = &'n T;
fn eval(&'n self, _: ()) -> Self::Output {
fn eval(self, _: ()) -> Self::Output {
if self.1.load(core::sync::atomic::Ordering::SeqCst) {
unsafe { self.0.assume_init_ref() }
} else {