diff --git a/Cargo.lock b/Cargo.lock index a5eb3749..31197f1e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -234,9 +234,9 @@ dependencies = [ [[package]] name = "either" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "env_logger" @@ -253,16 +253,15 @@ dependencies = [ [[package]] name = "exr" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14cc0e06fb5f67e5d6beadf3a382fec9baca1aa751c6d5368fdeee7e5932c215" +checksum = "78c26a90d9dd411a3d119d6f55752fb4c134ca243250c32fb9cab7b2561638d2" dependencies = [ "bit_field", - "deflate", "flume", "half", - "inflate", "lebe", + "miniz_oxide", "smallvec", "threadpool", ] @@ -298,15 +297,15 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "futures-core" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +checksum = "d2acedae88d38235936c3922476b10fced7b2b68136f5e3c03c2d5be348a1115" [[package]] name = "futures-sink" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +checksum = "ca0bae1fe9752cf7fd9b0064c674ae63f97b37bc714d745cbde0afb7ec4e6765" [[package]] name = "getrandom" @@ -479,15 +478,6 @@ dependencies = [ "tiff", ] -[[package]] -name = "inflate" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff" -dependencies = [ - "adler32", -] - [[package]] name = "itoa" version = "1.0.1" @@ -529,9 +519,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lebe" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7efd1d698db0759e6ef11a7cd44407407399a910c774dd804c64c032da7826ff" +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" @@ -646,18 +636,18 @@ checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" [[package]] name = "pin-project" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78203e83c48cffbe01e4a2d35d566ca4de445d79a85372fc64e378bfc812a260" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "710faf75e1b33345361201d36d04e98ac1ed8909151a017ed384700836104c74" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", "quote", diff --git a/libraries/dyn-any/src/lib.rs b/libraries/dyn-any/src/lib.rs index e0e10c50..985e1906 100644 --- a/libraries/dyn-any/src/lib.rs +++ b/libraries/dyn-any/src/lib.rs @@ -25,6 +25,15 @@ pub fn downcast_ref<'a, V: StaticType>(i: &'a dyn DynAny<'a>) -> Option<&'a V> { None } } +pub fn downcast<'a, V: StaticType>(i: Box + 'a>) -> Option> { + if i.type_id() == std::any::TypeId::of::<::Static>() { + // SAFETY: caller guarantees that T is the correct type + let ptr = Box::into_raw(i) as *mut dyn DynAny<'a> as *mut V; + Some(unsafe { Box::from_raw(ptr) }) + } else { + None + } +} pub trait StaticType { type Static: 'static + ?Sized; @@ -39,8 +48,11 @@ pub trait StaticTypeSized { std::any::TypeId::of::() } } -impl<'a, T: StaticTypeSized> StaticType for T { - type Static = ::Static; +impl StaticTypeSized for T +where + T::Static: Sized, +{ + type Static = ::Static; } pub trait StaticTypeClone { type Static: 'static + Clone; @@ -48,41 +60,44 @@ pub trait StaticTypeClone { std::any::TypeId::of::() } } -impl<'a, T: StaticTypeClone> StaticTypeSized for T { - type Static = ::Static; +impl StaticTypeClone for T +where + T::Static: Clone, +{ + type Static = ::Static; } macro_rules! impl_type { ($($id:ident$(<$($(($l:lifetime, $s:lifetime)),*|)?$($T:ident),*>)?),*) => { $( - impl<'a, $($($T: 'a + $crate::StaticTypeSized + Sized,)*)?> $crate::StaticTypeSized for $id $(<$($($l,)*)?$($T, )*>)?{ + impl< $($($T: $crate::StaticTypeSized ,)*)?> $crate::StaticType for $id $(<$($($l,)*)?$($T, )*>)?{ type Static = $id$(<$($($s,)*)?$(<$T as $crate::StaticTypeSized>::Static,)*>)?; } )* }; } -impl<'a, T: Clone + StaticTypeClone> StaticTypeClone for std::borrow::Cow<'a, T> { - type Static = std::borrow::Cow<'static, ::Static>; +impl<'a, T: StaticTypeClone + Clone> StaticType for std::borrow::Cow<'a, T> { + type Static = std::borrow::Cow<'static, T::Static>; } -impl<'a, T: StaticTypeSized> StaticTypeSized for *const [T] { +impl StaticType for *const [T] { type Static = *const [::Static]; } -impl<'a, T: StaticTypeSized> StaticTypeSized for *mut [T] { +impl StaticType for *mut [T] { type Static = *mut [::Static]; } -impl<'a, T: StaticTypeSized> StaticTypeSized for &'a [T] { +impl<'a, T: StaticTypeSized> StaticType for &'a [T] { type Static = &'static [::Static]; } -impl<'a> StaticTypeSized for &'a str { +impl<'a> StaticType for &'a str { type Static = &'static str; } -impl<'a> StaticTypeSized for () { +impl StaticType for () { type Static = (); } -impl<'a, T: 'a + StaticTypeClone> StaticTypeClone for &'a T { - type Static = &'static ::Static; +impl<'a, T: 'a + StaticType> StaticType for &'a T { + type Static = &'static ::Static; } -impl<'a, T: StaticTypeSized, const N: usize> StaticTypeSized for [T; N] { +impl StaticType for [T; N] { type Static = [::Static; N]; } @@ -102,7 +117,7 @@ use std::{ impl_type!(Option,Result,Cell,UnsafeCell,RefCell,MaybeUninit, Vec, String, BTreeMap,BTreeSet, LinkedList, VecDeque, - BinaryHeap, ManuallyDrop, PhantomData, PhantomPinned,Empty, + BinaryHeap, Box, ManuallyDrop, PhantomData, PhantomPinned,Empty, Wrapping, Duration, Once, Mutex, RwLock, bool, f32, f64, char, u8, AtomicU8, u16,AtomicU16, u32,AtomicU32, u64,AtomicU64, usize,AtomicUsize, i8,AtomicI8, i16,AtomicI16, i32,AtomicI32, i64,AtomicI64, isize,AtomicIsize, @@ -115,7 +130,7 @@ macro_rules! impl_tuple { impl_tuple! { @rec $($t)* } }; (@impl $($t:ident)*) => { - impl<'dyn_any, $($t: StaticTypeSized,)*> StaticTypeSized for ($($t,)*) { + impl< $($t: StaticTypeSized,)*> StaticType for ($($t,)*) { type Static = ($(<$t as $crate::StaticTypeSized>::Static,)*); } }; diff --git a/node-graph/borrow_stack/src/lib.rs b/node-graph/borrow_stack/src/lib.rs index 5026607a..90fcaf4f 100644 --- a/node-graph/borrow_stack/src/lib.rs +++ b/node-graph/borrow_stack/src/lib.rs @@ -7,8 +7,11 @@ use std::{ pub trait BorrowStack<'n> { type Item; + /// # Safety unsafe fn push(&'n self, value: Self::Item); + /// # Safety unsafe fn pop(&'n self); + /// # Safety unsafe fn get(&'n self) -> &'n [Self::Item]; } @@ -37,6 +40,10 @@ impl<'n, T: Unpin> FixedSizeStack<'n, T> { pub fn len(&self) -> usize { self.len.load(Ordering::SeqCst) } + + pub fn is_empty(&self) -> bool { + self.len.load(Ordering::SeqCst) == 0 + } } impl<'n, T> BorrowStack<'n> for FixedSizeStack<'n, T> { diff --git a/node-graph/gcore/Cargo.toml b/node-graph/gcore/Cargo.toml index 56e43bbc..79415975 100644 --- a/node-graph/gcore/Cargo.toml +++ b/node-graph/gcore/Cargo.toml @@ -10,7 +10,7 @@ license = "MIT OR Apache-2.0" [features] std = ["dyn-any"] -default = ["gpu", "async"] +default = ["async"] gpu = ["spirv-std"] async = ["async-trait"] nightly = [] diff --git a/node-graph/gcore/src/lib.rs b/node-graph/gcore/src/lib.rs index 50c0f531..6f34c850 100644 --- a/node-graph/gcore/src/lib.rs +++ b/node-graph/gcore/src/lib.rs @@ -3,6 +3,7 @@ #[cfg(feature = "async")] extern crate alloc; + #[cfg(feature = "async")] use alloc::boxed::Box; #[cfg(feature = "async")] @@ -18,12 +19,35 @@ pub trait Node { type Output; fn eval(self, input: T) -> Self::Output; + fn input(&self) -> &str { + core::any::type_name::() + } + fn output(&self) -> &str { + core::any::type_name::() + } } trait Input { unsafe fn input(&self, input: I); } +pub trait RefNode { + type Output; + + fn eval_ref(&self, input: T) -> Self::Output; +} + +impl<'n, N: 'n, I> RefNode for &'n N +where + &'n N: Node, + Self: 'n, +{ + type Output = <&'n N as Node>::Output; + fn eval_ref(&self, input: I) -> Self::Output { + self.eval(input) + } +} + #[cfg(feature = "async")] #[async_trait] pub trait AsyncNode { @@ -46,13 +70,23 @@ pub trait Cache { fn clear(&mut self); } -#[cfg(not(feature = "gpu"))] -extern crate alloc; -#[cfg(not(feature = "gpu"))] -impl<'n, I, O: 'n> Node<'n, I> for alloc::boxed::Box> { - type Output = O; - - fn eval(&'n self, input: &'n I) -> Self::Output { +#[cfg(feature = "async")] +impl Node for Box +where + N: Node, +{ + type Output = >::Output; + fn eval(self, input: I) -> Self::Output { + (*self).eval(input) + } +} +#[cfg(feature = "async")] +impl<'n, N, I> Node for &'n Box +where + &'n N: Node, +{ + type Output = <&'n N as Node>::Output; + fn eval(self, input: I) -> Self::Output { self.as_ref().eval(input) } } diff --git a/node-graph/gcore/src/ops.rs b/node-graph/gcore/src/ops.rs index 9d2bd7e0..3aca9eba 100644 --- a/node-graph/gcore/src/ops.rs +++ b/node-graph/gcore/src/ops.rs @@ -11,6 +11,24 @@ impl<'n, L: Add + 'n, R, O: 'n> Node<(L, R)> for AddNode { input.0 + input.1 } } +impl<'n, L: Add + 'n, R, O: 'n> Node<(L, R)> for &'n AddNode { + type Output = >::Output; + fn eval(self, input: (L, R)) -> Self::Output { + input.0 + input.1 + } +} +impl<'n, L: Add + 'n + Copy, R: Copy, O: 'n> Node<&'n (L, R)> for AddNode { + type Output = >::Output; + fn eval(self, input: &'n (L, R)) -> Self::Output { + input.0 + input.1 + } +} +impl<'n, L: Add + 'n + Copy, R: Copy, O: 'n> Node<&'n (L, R)> for &'n AddNode { + type Output = >::Output; + fn eval(self, input: &'n (L, R)) -> Self::Output { + input.0 + input.1 + } +} #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct CloneNode; @@ -82,7 +100,7 @@ pub struct DupNode; impl<'n, T: Clone + 'n> Node for DupNode { type Output = (T, T); fn eval(self, input: T) -> Self::Output { - (input.clone(), input) //TODO: use Copy/Clone implementation + (input.clone(), input) } } @@ -95,6 +113,12 @@ impl<'n, T: 'n> Node for IdNode { input } } +impl<'n, T: 'n> Node for &'n IdNode { + type Output = T; + fn eval(self, input: T) -> Self::Output { + input + } +} pub struct MapResultNode(pub MN, pub PhantomData<(I, E)>); diff --git a/node-graph/gcore/src/raster.rs b/node-graph/gcore/src/raster.rs index 5139255e..7772ddb0 100644 --- a/node-graph/gcore/src/raster.rs +++ b/node-graph/gcore/src/raster.rs @@ -34,7 +34,7 @@ where } } -pub struct MutWrapper(pub N); +/*pub struct MutWrapper(pub N); impl<'n, T: Clone, N> Node<&'n mut T> for &'n MutWrapper where @@ -44,7 +44,7 @@ where fn eval(self, value: &'n mut T) { *value = (&self.0).eval(value.clone()); } -} +}*/ #[cfg(test)] mod test { @@ -54,8 +54,8 @@ mod test { fn map_node() { let array = &mut [Color::from_rgbaf32(1.0, 0.0, 0.0, 1.0).unwrap()]; (&GrayscaleNode).eval(Color::from_rgbf32_unchecked(1., 0., 0.)); - let map = ForEachNode(MutWrapper(GrayscaleNode)); + /*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()); + assert_eq!(array[0], Color::from_rgbaf32(0.33333334, 0.33333334, 0.33333334, 1.0).unwrap());*/ } } diff --git a/node-graph/gcore/src/structural.rs b/node-graph/gcore/src/structural.rs index 4db0131c..4dcd7f65 100644 --- a/node-graph/gcore/src/structural.rs +++ b/node-graph/gcore/src/structural.rs @@ -1,7 +1,8 @@ use core::marker::PhantomData; -use crate::Node; +use crate::{Node, RefNode}; +#[derive(Debug)] pub struct ComposeNode { first: First, second: Second, @@ -25,25 +26,40 @@ where } impl<'n, Input, Inter, First, Second> Node for &'n ComposeNode where - First: Node + Copy, - Second: Node + Copy, + First: RefNode + Copy, + Second: RefNode + Copy, { - type Output = Second::Output; + 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) + let arg: Inter = (self.first).eval_ref(input); + (self.second).eval_ref(arg) } } - -impl<'n, Input, First: 'n, Second: 'n> ComposeNode +impl RefNode for ComposeNode where - First: Node, - Second: Node, + 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 } } @@ -79,6 +95,24 @@ pub trait AfterRef: Sized { } impl<'n, Second: 'n, I> AfterRef for Second where &'n Second: Node {} +#[cfg(feature = "async")] +pub trait AfterBox { + fn after<'n, First: 'n, Input>(self, first: First) -> ComposeNode + where + First: Node + Copy, + alloc::boxed::Box: Node, + Self: Sized, + { + ComposeNode:: { + first, + second: self, + _phantom: PhantomData, + } + } +} +#[cfg(feature = "async")] +impl<'n, Second: 'n, I> AfterBox for alloc::boxed::Box where &'n alloc::boxed::Box: Node {} + pub struct ConsNode(pub Root); impl Node for ConsNode diff --git a/node-graph/gstd/Cargo.toml b/node-graph/gstd/Cargo.toml index f37ada4e..82db125e 100644 --- a/node-graph/gstd/Cargo.toml +++ b/node-graph/gstd/Cargo.toml @@ -15,7 +15,7 @@ default = ["derive", "memoization"] [dependencies] -graphene-core = {path = "../gcore"} +graphene-core = {path = "../gcore", features = ["async", "std"]} borrow_stack = {path = "../borrow_stack"} dyn-any = {path = "../../libraries/dyn-any", features = ["derive"]} graph-proc-macros = {path = "../proc-macro", optional = true} diff --git a/node-graph/gstd/src/any.rs b/node-graph/gstd/src/any.rs new file mode 100644 index 00000000..17f80741 --- /dev/null +++ b/node-graph/gstd/src/any.rs @@ -0,0 +1,161 @@ +use dyn_any::{DynAny, StaticType}; +pub use graphene_core::{generic, ops /*, structural*/, Node, RefNode}; +use std::marker::PhantomData; + +fn fmt_error() -> String { + format!("DynAnyNode: input is not of correct type, expected {}", std::any::type_name::()) +} + +pub struct DynAnyNode<'n, N: RefNode, I>(pub N, pub PhantomData<&'n I>); +/*impl<'n, I: StaticType, N: RefNode<'n, &'n I, Output = O> + 'n, O: 'n + StaticType> Node<&'n dyn DynAny<'n>> for DynAnyNode<'n, N, I> { + type Output = Box + 'n>; + fn eval(self, input: &'n dyn DynAny<'n>) -> Self::Output { + let output = self.0.eval_ref(dyn_any::downcast_ref(input).expect(fmt_error::().as_str())); + Box::new(output) + } +}*/ +/* +impl<'n, I: StaticType, N: RefNode<&'n I, Output = O> + Copy + 'n, O: 'n + StaticType> Node<&'n dyn DynAny<'n>> for &'n DynAnyNode<'n, N, I> { + type Output = Box + 'n>; + fn eval(self, input: &'n dyn DynAny<'n>) -> Self::Output { + let output = self.0.eval_ref(dyn_any::downcast_ref(input).unwrap_or_else(|| panic!("{}", fmt_error::()))); + Box::new(output) + } +} +impl<'n, I: StaticType, N: RefNode<'n, I, Output = O> + 'n, O: 'n + StaticType> Node>> for DynAnyNode<'n, N, I> { + type Output = Box + 'n>; + fn eval(self, input: Box>) -> Self::Output { + let input: Box = dyn_any::downcast(input).unwrap_or_else(|| panic!("{}", fmt_error::())); + Box::new(self.0.eval_ref(*input)) + } +}*/ +impl<'n, I: StaticType, N: RefNode + Copy + 'n, O: 'n + StaticType> Node> for &'n DynAnyNode<'n, N, I> { + type Output = Any<'n>; + fn eval(self, input: Any<'n>) -> Self::Output { + let input: Box = dyn_any::downcast(input).unwrap_or_else(|| panic!("{}", fmt_error::())); + Box::new(self.0.eval_ref(*input)) + } +} + +impl<'n, I: StaticType, N: RefNode + 'n + Copy, O: 'n + StaticType> DynAnyNode<'n, N, I> +where + N::Output: StaticType, +{ + pub fn new(n: N) -> Self { + DynAnyNode(n, PhantomData) + } + pub fn into_erased(&'n self) -> impl RefNode, Output = Any<'n>> { + self + } + /*pub fn as_ref(&'n self) -> &'n AnyNode<'n> { + self + } + pub fn into_ref_box(self) -> Box + 'n)>, Output = Box<(dyn DynAny<'n> + 'n)>> + 'n> { + Box::new(self) + }*/ + pub fn into_ref(self: &'n &'n Self) -> &'n (dyn RefNode, Output = Any<'n>> + 'n) { + self + } +} + +/*impl<'n: 'static, I: StaticType, N, O: 'n + StaticType> DynAnyNode<'n, N, I> +where + N: RefNode + 'n + Copy, +{ + /*pub fn into_owned_erased(self) -> impl RefNode, Output = Any<'n>> + 'n { + self + }*/ + pub fn as_owned(&'n self) -> &'n (dyn RefNode, Output = Any<'n>> + 'n) { + self + } + /*pub fn into_owned_box(&self) -> Box> { + Box::new(self) + }*/ +}*/ +pub type Any<'n> = Box + 'n>; +pub type AnyNode<'n> = dyn RefNode, Output = Any<'n>>; + +pub trait DynNodeRef<'n>: RefNode<&'n dyn DynAny<'n>, Output = Box + 'n>> + 'n {} +impl<'n, N: RefNode<&'n dyn DynAny<'n>, Output = Box + 'n>> + 'n> DynNodeRef<'n> for N {} + +pub trait DynNodeOwned<'n>: RefNode, Output = Any<'n>> + 'n {} +impl<'n, N: RefNode, Output = Any<'n>> + 'n> DynNodeOwned<'n> for N {} + +/*impl<'n> Node>> for &'n Box> { + type Output = Box + 'n>; + fn eval(self, input: Box>) -> Self::Output { + (&*self as &dyn Node + 'n>, Output = Box + 'n>>).eval(input) + } +}*/ + +#[cfg(test)] +mod test { + use super::*; + use graphene_core::ops::{AddNode, IdNode}; + use graphene_core::value::ValueNode; + /*#[test] + pub fn dyn_input_compositon() { + use graphene_core::structural::After; + use graphene_core::structural::ComposeNode; + let id: DynAnyNode<_, u32> = DynAnyNode::new(IdNode); + let add: DynAnyNode<_, (u32, u32)> = DynAnyNode::new(AddNode); + let value: DynAnyNode<_, ()> = DynAnyNode::new(ValueNode((3u32, 4u32))); + let id = &id.as_owned(); + let add = add.as_owned(); + let value = value.as_owned(); + + /*let computation = ComposeNode::new(value, add); + let computation = id.after(add.after(value)); + let result: u32 = *dyn_any::downcast(computation.eval(&())).unwrap();*/ + }*/ + #[test] + #[should_panic] + pub fn dyn_input_invalid_eval_panic() { + static ADD: &DynAnyNode<&AddNode, (u32, u32)> = &DynAnyNode(&AddNode, PhantomData); + + let add = ADD.into_ref(); + add.eval_ref(Box::new(&("32", 32u32))); + } + /*#[test] + pub fn dyn_input_storage() { + let mut vec: Vec> = vec![]; + let id: DynAnyNode<_, u32> = DynAnyNode::new(IdNode); + let add: DynAnyNode<_, (u32, u32)> = DynAnyNode::new(AddNode); + let value: DynAnyNode<_, ()> = DynAnyNode::new(ValueNode((3u32, 4u32))); + + vec.push(add.into_ref_box()); + vec.push(id.into_ref_box()); + vec.push(value.into_ref_box()); + }*/ + #[test] + pub fn dyn_input_storage_composition() { + let mut vec: Vec<&(dyn RefNode)> = vec![]; + //let id: DynAnyNode<_, u32> = DynAnyNode::new(IdNode); + let value: &DynAnyNode<&ValueNode<(u32, u32)>, ()> = &DynAnyNode(&ValueNode((3u32, 4u32)), PhantomData); + let add: &DynAnyNode<&AddNode, &(u32, u32)> = &DynAnyNode(&AddNode, PhantomData); + + let value_ref = (&value).into_ref(); + let add_ref = (&add).into_ref(); + vec.push(value_ref); + vec.push(add_ref); + //vec.push(add.as_owned()); + //vec.push(id.as_owned()); + //let vec = vec.leak(); + + let n_value = vec[0]; + let n_add = vec[1]; + //let id = vec[2]; + + assert_eq!(*(dyn_any::downcast::<&(u32, u32)>(n_value.eval_ref(Box::new(()))).unwrap()), &(3u32, 4u32)); + fn compose<'n>( + first: &'n (dyn RefNode + 'n)>, Output = Box<(dyn DynAny<'n> + 'n)>> + 'n), + second: &'n (dyn RefNode + 'n)>, Output = Box<(dyn DynAny<'n> + 'n)>> + 'n), + input: Any<'n>, + ) -> Any<'n> { + second.eval_ref(first.eval_ref(input)) + } + let result = compose(n_value, n_add, Box::new(())); + assert_eq!(*dyn_any::downcast::(result).unwrap(), 7u32); + //let result: u32 = *dyn_any::downcast(computation.eval(Box::new(()))).unwrap(); + } +} diff --git a/node-graph/gstd/src/document.rs b/node-graph/gstd/src/document.rs new file mode 100644 index 00000000..309d2158 --- /dev/null +++ b/node-graph/gstd/src/document.rs @@ -0,0 +1,94 @@ +/* +use core::marker::PhantomData; + +use graphene_core::{structural::After, structural::ComposeNode, value::ValueNode, Node, RefNode}; + +use crate::any::Any; +use crate::any::DynAnyNode; + +pub trait DocumentNode: RefNode { + fn input_hints(&self) -> &'static [&'static str]; + fn input_types(&self) -> &'static [&'static str]; + fn inputs(&self) -> Vec { + self.input_hints().iter().zip(self.input_types()).map(|(a, b)| format!("{}{}", a, b)).collect() + } +} + +struct InjectNode + Copy, I>(N, PhantomData); + +impl<'n, N: Node + Copy, I> Node<&'n [&'n AnyNode<'n>]> for &'n InjectNode { + type Output = Box, Output = Any<'n>> + 'n>; + fn eval(self, input: &'n [&'n AnyNode<'n>]) -> Self::Output { + assert_eq!(input.len(), 1); + Box::new(ComposeNode::new(&DynAnyNode(input[0]), &DynAnyNode(self.0))) + } +} + +impl + Copy, I> InjectNode { + const TYPES: &'static [&'static str] = &[core::any::type_name::()]; + const HINTS: &'static [&'static str] = &["input: "]; +} +impl<'n, N: Node + Copy, I> DocumentNode<&'n [&'n AnyNode<'n>]> for &'n InjectNode { + fn input_hints(&self) -> &'static [&'static str] { + InjectNode::::HINTS + } + fn input_types(&self) -> &'static [&'static str] { + InjectNode::::TYPES + } +} + +pub type NodeId = u32; + +type AnyNode<'n> = dyn RefNode, Output = Any<'n>>; + +pub struct DocumentGraphNode<'n> { + pub id: NodeId, + pub inputs: Vec, + pub node: NodeWrapper<'n>, +} + +impl<'n> DocumentGraphNode<'n> { + pub fn new(id: NodeId, inputs: Vec, node: NodeWrapper<'n>) -> Self { + Self { id, inputs, node } + } +} + +pub struct NodeWrapper<'n> { + pub node: &'n (dyn Node, Output = Any<'n>> + 'n), + + pub path: &'static str, +} + +impl<'n> NodeWrapper<'n> { + pub fn new(node: &'n (dyn Node, Output = Any<'n>> + 'n), path: &'static str) -> Self { + Self { node, path } + } +} + +pub enum NodeInput { + Node(NodeId), + Default(ValueNode>), +} + +#[cfg(test)] +mod test { + use crate::any::DynAnyNode; + + use super::*; + use graphene_core::value::ValueNode; + + #[test] + fn inject_node() { + let inject_node = InjectNode(&ValueNode(4u32), PhantomData); + use super::DocumentNode; + /*assert_eq!( + (&inject_node as &dyn DocumentNode<&[&AnyNode], Output = ComposeNode<&AnyNode, ValueNode, ()>>).inputs(), + vec!["input: ()"] + );*/ + let any_inject = DynAnyNode(&inject_node, PhantomData); + let any_inject = Box::leak(Box::new(any_inject)); + let wrapped = NodeWrapper::new((&any_inject) as &(dyn Node<&[&AnyNode], Output = Any>), "grahpene_core::document::InjectNode"); + let document_node = DocumentGraphNode::new(0, vec![], wrapped); + } +} +*/ diff --git a/node-graph/gstd/src/lib.rs b/node-graph/gstd/src/lib.rs index 76ca35a9..ae9447b1 100644 --- a/node-graph/gstd/src/lib.rs +++ b/node-graph/gstd/src/lib.rs @@ -1,22 +1,17 @@ //pub mod value; -pub use graphene_core::{generic, ops /*, structural*/}; +//#![feature(const_type_name)] #[cfg(feature = "memoization")] pub mod memo; pub mod raster; +pub mod any; + +pub mod document; + pub use graphene_core::*; -/*use dyn_any::DynAny; -pub type DynNode<'n, T> = &'n (dyn Node<'n, Output = T> + 'n); -pub type DynAnyNode<'n> = &'n (dyn Node<'n, Output = &'n dyn DynAny<'n>> + 'n); -pub trait DynamicInput<'n> { - fn set_kwarg_by_name(&mut self, name: &str, value: DynAnyNode<'n>); - fn set_arg_by_index(&mut self, index: usize, value: DynAnyNode<'n>); -} - -*/ use quote::quote; use syn::{Expr, ExprPath, Type}; @@ -31,6 +26,7 @@ pub struct NodeGraph { pub output: Type, pub input: Type, } + pub enum NodeKind { Value(Expr), Input, diff --git a/node-graph/gstd/src/main.rs b/node-graph/gstd/src/main.rs index 1fdca03b..5eb05960 100644 --- a/node-graph/gstd/src/main.rs +++ b/node-graph/gstd/src/main.rs @@ -99,6 +99,7 @@ fn main() { ]; //println!("{}", node_graph(1)); + // let _nodegraph = NodeGraph { nodes, diff --git a/node-graph/gstd/src/memo.rs b/node-graph/gstd/src/memo.rs index 83121fcd..3c1a1e55 100644 --- a/node-graph/gstd/src/memo.rs +++ b/node-graph/gstd/src/memo.rs @@ -1,6 +1,5 @@ use graphene_core::{Cache, Node}; use once_cell::sync::OnceCell; -use std::marker::PhantomData; /// Caches the output of a given Node and acts as a proxy pub struct CacheNode, I> { diff --git a/node-graph/gstd/src/raster.rs b/node-graph/gstd/src/raster.rs index 0e0676a0..ed4d6b31 100644 --- a/node-graph/gstd/src/raster.rs +++ b/node-graph/gstd/src/raster.rs @@ -2,13 +2,7 @@ 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, AfterRef}, - value::ValueNode, - Node, -}; +use graphene_core::{generic::FnNode, ops::MapResultNode, structural::After, value::ValueNode, Node}; use image::Pixel; use std::path::Path; diff --git a/node-graph/gstd/test-image-1-result.png b/node-graph/gstd/test-image-1-result.png new file mode 100644 index 00000000..67da108e Binary files /dev/null and b/node-graph/gstd/test-image-1-result.png differ