diff --git a/node-graph/gcore/src/generic.rs b/node-graph/gcore/src/generic.rs index 34bc8718..82b5a53e 100644 --- a/node-graph/gcore/src/generic.rs +++ b/node-graph/gcore/src/generic.rs @@ -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 O, I, O>(T, PhantomData<(I, O)>); +impl O, O, I> Node for FnNode { 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 for &'n FnNode { + 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 O, I, O> FnNode { 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 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 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) } diff --git a/node-graph/gcore/src/lib.rs b/node-graph/gcore/src/lib.rs index 97889af8..50c0f531 100644 --- a/node-graph/gcore/src/lib.rs +++ b/node-graph/gcore/src/lib.rs @@ -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 { + 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 { @@ -34,21 +26,21 @@ trait Input { #[cfg(feature = "async")] #[async_trait] -pub trait AsyncNode<'n, T> { - type Output; // TODO: replace with generic associated type +pub trait AsyncNode { + 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 + Send + Sync + 'n, T: Send + 'n> AsyncNode 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); diff --git a/node-graph/gcore/src/ops.rs b/node-graph/gcore/src/ops.rs index 17800ffe..9d2bd7e0 100644 --- a/node-graph/gcore/src/ops.rs +++ b/node-graph/gcore/src/ops.rs @@ -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 + 'n, R, O: 'n> Node<'n, (L, R)> for AddNode { +impl<'n, L: Add + 'n, R, O: 'n> Node<(L, R)> for AddNode { type Output = >::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 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 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(pub MN, pub PhantomData<(I, E)>); -impl<'n, MN: Node<'n, I>, I, E> Node<'n, Result> for MapResultNode<'n, MN, I, E> { +impl, I, E> Node> for MapResultNode { type Output = Result; - fn eval(&'n self, input: Result) -> Self::Output { + fn eval(self, input: Result) -> Self::Output { input.map(|x| self.0.eval(x)) } } +impl<'n, MN: Node + Copy, I, E> Node> for &'n MapResultNode { + type Output = Result; + fn eval(self, input: Result) -> Self::Output { + input.map(|x| (&self.0).eval(x)) + } +} -impl<'n, MN: Node<'n, I>, I, E> MapResultNode<'n, MN, I, E> { +impl MapResultNode { 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, I, E>(pub MN, pub PhantomData<(I, E)>); -impl<'n, MN: Node<'n, I, Output = Result>, I, O: 'n, E: 'n> Node<'n, Result> for FlatMapResultNode<'n, MN, I, E> { +impl<'n, MN: Node>, I, O: 'n, E: 'n> Node> for FlatMapResultNode { type Output = Result; - fn eval(&'n self, input: Result) -> Self::Output { + fn eval(self, input: Result) -> 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>, I, O: 'n, E: 'n> Node<'n, Resul } } -impl<'n, MN: Node<'n, I>, I, E> FlatMapResultNode<'n, MN, I, E> { +impl, I, E> FlatMapResultNode { 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); } } diff --git a/node-graph/gcore/src/raster.rs b/node-graph/gcore/src/raster.rs index 0ca3e3be..5139255e 100644 --- a/node-graph/gcore/src/raster.rs +++ b/node-graph/gcore/src/raster.rs @@ -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 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 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, MN: Node<'n, S>, S>(pub MN, PhantomData<&'n (I, S)>); +pub struct ForEachNode(pub MN); -impl<'n, I: Iterator, MN: Node<'n, S, Output = ()>, S> Node<'n, I> for ForEachNode<'n, I, MN, S> { +impl<'n, I: Iterator, MN: 'n, S> Node for &'n ForEachNode +where + &'n MN: Node, +{ 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(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 +where + &'n N: Node, +{ 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()); } } diff --git a/node-graph/gcore/src/raster/color.rs b/node-graph/gcore/src/raster/color.rs index 69f8a2fb..ef735ec5 100644 --- a/node-graph/gcore/src/raster/color.rs +++ b/node-graph/gcore/src/raster/color.rs @@ -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. } } diff --git a/node-graph/gcore/src/structural.rs b/node-graph/gcore/src/structural.rs index 2b562512..4db0131c 100644 --- a/node-graph/gcore/src/structural.rs +++ b/node-graph/gcore/src/structural.rs @@ -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: First, second: Second, - _phantom: PhantomData<&'n Input>, + _phantom: PhantomData, } -impl<'n, Input, Inter, First, Second> Node<'n, Input> for ComposeNode<'n, Input, First, Second> +impl Node for ComposeNode where - First: Node<'n, Input, Output = Inter>, - Second: Node<'n, Inter>, + First: Node, + Second: Node, { - type Output = >::Output; + type Output = >::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 for &'n ComposeNode where - First: Node<'n, Input>, - Second: Node<'n, First::Output>, + First: Node + Copy, + Second: Node + 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 +where + First: Node, + Second: Node, { pub const fn new(first: First, second: Second) -> Self { - ComposeNode::<'n, Input, First, Second> { first, second, _phantom: PhantomData } + ComposeNode:: { first, second, _phantom: PhantomData } } } - pub trait After: Sized { - fn after<'n, First, Input>(self, first: First) -> ComposeNode<'n, Input, First, Self> + fn after(self, first: First) -> ComposeNode where - First: Node<'n, Input, Output = Inter>, - Self: Node<'n, Inter>, + First: Node, + Self: Node, { - ComposeNode::new(first, self) + ComposeNode:: { + first, + second: self, + _phantom: PhantomData, + } } } -impl<'n, Second: Node<'n, I>, I> After for Second {} +impl, I> After for Second {} + +pub trait AfterRef: Sized { + fn after<'n, First: 'n, Input>(&'n self, first: First) -> ComposeNode + where + First: Node + Copy, + &'n Self: Node, + Self: 'n, + { + ComposeNode:: { + first, + second: self, + _phantom: PhantomData, + } + } +} +impl<'n, Second: 'n, I> AfterRef for Second where &'n Second: Node {} pub struct ConsNode(pub Root); -impl<'n, Root, Input> Node<'n, Input> for ConsNode +impl Node for ConsNode where - Root: Node<'n, ()>, + Root: Node<()>, { - type Output = (Input, >::Output); + type Output = (Input, >::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 for &'n ConsNode { + type Output = (Input, Root::Output); + + fn eval(self, input: Input) -> Self::Output { + let arg = (&self.0).eval(()); + (input, arg) + } +} pub struct ConsPassInputNode(pub Root); -impl<'n, Root, L, R> Node<'n, (L, R)> for ConsPassInputNode +impl Node<(L, R)> for ConsPassInputNode where - Root: Node<'n, R>, + Root: Node, { - type Output = (L, >::Output); + type Output = (L, >::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 +where + &'n Root: Node, +{ + type Output = (L, <&'n Root as Node>::Output); + + fn eval(self, input: (L, R)) -> Self::Output { + let arg = (&self.0).eval(input.1); + (input.0, arg) + } +} diff --git a/node-graph/gcore/src/value.rs b/node-graph/gcore/src/value.rs index d2855e0b..5d35bec9 100644 --- a/node-graph/gcore/src/value.rs +++ b/node-graph/gcore/src/value.rs @@ -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; -impl<'n, const N: u32> Node<'n, ()> for IntNode { +impl Node<()> for IntNode { type Output = u32; - fn eval(&self, _: ()) -> u32 { + fn eval(self, _: ()) -> u32 { N } } -#[derive(Default)] +#[derive(Default, Debug)] pub struct ValueNode(pub T); -impl<'n, T: 'n> Node<'n, ()> for ValueNode { +impl<'n, T: 'n> Node<()> for ValueNode { + type Output = T; + fn eval(self, _: ()) -> Self::Output { + self.0 + } +} +impl<'n, T: 'n> Node<()> for &'n ValueNode { type Output = &'n T; - fn eval(&'n self, _: ()) -> Self::Output { + fn eval(self, _: ()) -> Self::Output { &self.0 } } @@ -29,39 +34,60 @@ impl ValueNode { } } -impl<'n, T: Clone + 'n> ValueNode { - pub const fn clone(self) -> ComposeNode<'n, (), ValueNode, CloneNode> { - ComposeNode::new(self, CloneNode) - } -} - impl From for ValueNode { fn from(value: T) -> Self { ValueNode::new(value) } } +impl Clone for ValueNode { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} +impl Copy for ValueNode {} #[derive(Default)] pub struct DefaultNode(PhantomData); -impl<'n, T: Default + 'n> Node<'n, ()> for DefaultNode { +impl Node<()> for DefaultNode { type Output = T; - fn eval(&self, _: ()) -> T { + fn eval(self, _: ()) -> T { + T::default() + } +} +impl<'n, T: Default + 'n> Node<()> for &'n DefaultNode { + 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(MaybeUninit, AtomicBool); -impl<'n, T: 'n> Node<'n, ()> for InputNode { +impl<'n, T: 'n> Node<()> for InputNode { + 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 { 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 { diff --git a/node-graph/gstd/src/lib.rs b/node-graph/gstd/src/lib.rs index 09824b48..76ca35a9 100644 --- a/node-graph/gstd/src/lib.rs +++ b/node-graph/gstd/src/lib.rs @@ -1,4 +1,3 @@ -#![feature(type_alias_impl_trait)] //pub mod value; pub use graphene_core::{generic, ops /*, structural*/}; diff --git a/node-graph/gstd/src/memo.rs b/node-graph/gstd/src/memo.rs index 5be80d4e..83121fcd 100644 --- a/node-graph/gstd/src/memo.rs +++ b/node-graph/gstd/src/memo.rs @@ -3,34 +3,26 @@ use once_cell::sync::OnceCell; use std::marker::PhantomData; /// Caches the output of a given Node and acts as a proxy -pub struct CacheNode<'n, CachedNode: Node<'n, I>, I> { +pub struct CacheNode, I> { node: CachedNode, cache: OnceCell, - _phantom: PhantomData<&'n ()>, } -impl<'n, CashedNode: Node<'n, I>, I> Node<'n, I> for CacheNode<'n, CashedNode, I> -where - CashedNode::Output: 'n, -{ +impl<'n, CashedNode: Node + Copy, I> Node for &'n CacheNode { type Output = &'n CashedNode::Output; - fn eval(&'n self, input: I) -> Self::Output { + fn eval(self, input: I) -> Self::Output { self.cache.get_or_init(|| self.node.eval(input)) } } -impl<'n, CachedNode: Node<'n, I>, I> CacheNode<'n, CachedNode, I> { +impl<'n, CachedNode: Node, I> CacheNode { pub fn clear(&'n mut self) { self.cache = OnceCell::new(); } - pub fn new(node: CachedNode) -> CacheNode<'n, CachedNode, I> { - CacheNode { - node, - cache: OnceCell::new(), - _phantom: PhantomData, - } + pub fn new(node: CachedNode) -> CacheNode { + CacheNode { node, cache: OnceCell::new() } } } -impl<'n, CachedNode: Node<'n, I>, I> Cache for CacheNode<'n, CachedNode, I> { +impl, I> Cache for CacheNode { fn clear(&mut self) { self.cache = OnceCell::new(); } diff --git a/node-graph/gstd/src/raster.rs b/node-graph/gstd/src/raster.rs index e17794d2..c2a1c9ca 100644 --- a/node-graph/gstd/src/raster.rs +++ b/node-graph/gstd/src/raster.rs @@ -2,30 +2,36 @@ use core::marker::PhantomData; use graphene_core::ops::FlatMapResultNode; use graphene_core::raster::color::Color; use graphene_core::structural::{ComposeNode, ConsNode}; -use graphene_core::{generic::FnNode, ops::MapResultNode, structural::After, value::ValueNode, Node}; +use graphene_core::{ + generic::FnNode, + ops::MapResultNode, + structural::{After, AfterRef}, + value::ValueNode, + Node, +}; use image::Pixel; use std::path::Path; -pub struct MapNode<'n, MN: Node<'n, S>, I: IntoIterator, S>(pub MN, PhantomData<&'n (S, I)>); +pub struct MapNode, I: IntoIterator, S>(pub MN, PhantomData<(S, I)>); -impl<'n, I: IntoIterator, MN: Node<'n, S>, S> Node<'n, I> for MapNode<'n, MN, I, S> { +impl, MN: Node + Copy, S> Node for MapNode { type Output = Vec; - fn eval(&'n self, input: I) -> Self::Output { + fn eval(self, input: I) -> Self::Output { input.into_iter().map(|x| self.0.eval(x)).collect() } } -impl<'n, I: IntoIterator, MN: Node<'n, S>, S> MapNode<'n, MN, I, S> { +impl, MN: Node, S> MapNode { pub const fn new(mn: MN) -> Self { MapNode(mn, PhantomData) } } -pub struct MapImageNode<'n, MN: Node<'n, Color, Output = Color>>(pub MN, PhantomData<&'n ()>); +pub struct MapImageNode + Copy>(pub MN); -impl<'n, MN: Node<'n, Color, Output = Color>> Node<'n, Image> for MapImageNode<'n, MN> { +impl<'n, MN: Node + Copy> Node for &'n MapImageNode { type Output = Image; - fn eval(&'n self, input: Image) -> Self::Output { + fn eval(self, input: Image) -> Self::Output { Image { width: input.width, height: input.height, @@ -34,9 +40,9 @@ impl<'n, MN: Node<'n, Color, Output = Color>> Node<'n, Image> for MapImageNode<' } } -impl<'n, MN: Node<'n, Color, Output = Color>> MapImageNode<'n, MN> { +impl + Copy> MapImageNode { pub const fn new(mn: MN) -> Self { - MapImageNode(mn, PhantomData) + MapImageNode(mn) } } @@ -66,20 +72,20 @@ impl FileSystem for StdFs { type Reader = Box; pub struct FileNode, FS: FileSystem>(PhantomData<(P, FS)>); -impl<'n, P: AsRef, FS: FileSystem> Node<'n, (P, FS)> for FileNode { +impl, FS: FileSystem> Node<(P, FS)> for FileNode { type Output = Result; - fn eval(&'n self, input: (P, FS)) -> Self::Output { + fn eval(self, input: (P, FS)) -> Self::Output { let (path, fs) = input; fs.open(path) } } pub struct BufferNode; -impl<'n, Reader: std::io::Read> Node<'n, Reader> for BufferNode { +impl Node for BufferNode { type Output = Result, Error>; - fn eval(&'n self, mut reader: Reader) -> Self::Output { + fn eval(self, mut reader: Reader) -> Self::Output { let mut buffer = Vec::new(); reader.read_to_end(&mut buffer)?; Ok(buffer) @@ -109,23 +115,18 @@ impl<'a> IntoIterator for &'a Image { } } -pub fn file_node<'n, P: AsRef + 'n>() -> impl Node<'n, P, Output = Result, Error>> { +pub fn file_node<'n, P: AsRef + 'n>() -> impl Node, Error>> { let fs = ValueNode(StdFs).clone(); let fs = ConsNode(fs); - let file: ComposeNode> = FileNode(PhantomData).after(fs); - let buffer = FlatMapResultNode::new(BufferNode).after(file); - buffer -} -type Ret<'n> = impl Node<'n, (), Output = u32>; + let file: ComposeNode<_, _, P> = FileNode(PhantomData).after(fs); -pub fn test_node<'n>() -> Ret<'n> { - ValueNode(432).clone() + FlatMapResultNode::new(BufferNode).after(file) } -pub fn image_node<'n, P: AsRef + 'n>() -> impl Node<'n, P, Output = Result> { +pub fn image_node<'n, P: AsRef + 'n>() -> impl Node> { let file = file_node(); let image_loader = FnNode::new(|data: Vec| image::load_from_memory(&data).map_err(Error::Image).map(|image| image.into_rgba32f())); - let image: ComposeNode<'_, P, _, _> = FlatMapResultNode::new(image_loader).after(file); + let image: ComposeNode<_, _, P> = FlatMapResultNode::new(image_loader).after(file); let convert_image = FnNode::new(|image: image::ImageBuffer<_, _>| { let data = image .enumerate_pixels() @@ -140,11 +141,11 @@ pub fn image_node<'n, P: AsRef + 'n>() -> impl Node<'n, P, Output = Result data, } }); - let image = MapResultNode::new(convert_image).after(image); - image + + MapResultNode::new(convert_image).after(image) } -pub fn export_image_node<'n>() -> impl Node<'n, (Image, &'n str), Output = Result<(), Error>> { +pub fn export_image_node<'n>() -> impl Node<(Image, &'n str), Output = Result<(), Error>> { FnNode::new(|input: (Image, &str)| { let (image, path) = input; let mut new_image = image::ImageBuffer::new(image.width, image.height); @@ -152,7 +153,7 @@ pub fn export_image_node<'n>() -> impl Node<'n, (Image, &'n str), Output = Resul let color: Color = *color; assert!(x < image.width); assert!(y < image.height); - *pixel = image::Rgba([color.r(), color.g(), color.b(), color.a()]) + *pixel = image::Rgba(color.to_rgba8()) } new_image.save(path).map_err(Error::Image) }) @@ -174,24 +175,13 @@ mod test { #[test] fn load_image() { - /*let image = image_node(); - let gray = MapImageNode::new(GrayscaleNode); + let image = image_node::<&str>(); + let gray = MapImageNode::new(GrayscaleNode); - let gray_scale_picture = MapResultNode::new(gray).after(image); - let gray_scale_picture = gray_scale_picture.eval("image"); - */ - let test_node = test_node(); - { - let foo = test_node.eval(()); - std::mem::drop(foo); - } + let grayscale_picture = MapResultNode::new(&gray).after(image); let export = export_image_node(); - /*let export = FnNode::new(|input: (&str, &str)| { - let (input, output) = input;*/ - //let picture = gray_scale_picture.eval("/home/dennis/screenshot.png").unwrap().clone(); - //export.eval((picture, "screenshot.png")); - /*}); - export.eval(("screenshot.png", "/home/dennis/screenshot.png"));*/ + let picture = grayscale_picture.eval("/home/dennis/screenshot.png").expect("failed to load image"); + export.eval((picture, "/tmp/screenshot.png")).unwrap(); } }