Rework DynAnyNode design to work with the borrow stack (#796)
This commit is contained in:
parent
cef58b16c2
commit
562217015d
|
|
@ -25,12 +25,20 @@ pub fn downcast_ref<'a, V: StaticType>(i: &'a dyn DynAny<'a>) -> Option<&'a V> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn downcast<'a, V: StaticType>(i: Box<dyn DynAny<'a> + 'a>) -> Option<Box<V>> {
|
pub fn downcast<'a, V: StaticType>(i: Box<dyn DynAny<'a> + 'a>) -> Option<Box<V>> {
|
||||||
if i.type_id() == std::any::TypeId::of::<<V as StaticType>::Static>() {
|
let type_id = DynAny::type_id(i.as_ref());
|
||||||
|
if type_id == std::any::TypeId::of::<<V as StaticType>::Static>() {
|
||||||
// SAFETY: caller guarantees that T is the correct type
|
// SAFETY: caller guarantees that T is the correct type
|
||||||
let ptr = Box::into_raw(i) as *mut dyn DynAny<'a> as *mut V;
|
let ptr = Box::into_raw(i) as *mut dyn DynAny<'a> as *mut V;
|
||||||
Some(unsafe { Box::from_raw(ptr) })
|
Some(unsafe { Box::from_raw(ptr) })
|
||||||
} else {
|
} else {
|
||||||
|
// TODO: add log error
|
||||||
|
if type_id == std::any::TypeId::of::<&dyn DynAny<'static>>() {
|
||||||
|
panic!("downcast error: type_id == std::any::TypeId::of::<dyn DynAny<'a>>()");
|
||||||
|
}
|
||||||
|
println!("expected: {:?}", std::any::TypeId::of::<<V as StaticType>::Static>());
|
||||||
|
println!("actual one: {:?}", type_id);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -94,13 +102,29 @@ impl<'a> StaticType for &'a str {
|
||||||
impl StaticType for () {
|
impl StaticType for () {
|
||||||
type Static = ();
|
type Static = ();
|
||||||
}
|
}
|
||||||
impl<'a, T: 'a + StaticType> StaticType for &'a T {
|
impl<'a, T: 'a + StaticType + ?Sized> StaticType for &'a T {
|
||||||
type Static = &'static <T as StaticType>::Static;
|
type Static = &'static <T as StaticType>::Static;
|
||||||
}
|
}
|
||||||
impl<T: StaticTypeSized, const N: usize> StaticType for [T; N] {
|
impl<T: StaticTypeSized, const N: usize> StaticType for [T; N] {
|
||||||
type Static = [<T as StaticTypeSized>::Static; N];
|
type Static = [<T as StaticTypeSized>::Static; N];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> StaticType for dyn DynAny<'a> + '_ {
|
||||||
|
type Static = dyn DynAny<'static>;
|
||||||
|
}
|
||||||
|
pub trait IntoDynAny<'n>: Sized + StaticType + 'n {
|
||||||
|
fn into_dyn(self) -> Box<dyn DynAny<'n> + 'n> {
|
||||||
|
Box::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'n, T: StaticType + 'n> IntoDynAny<'n> for T {}
|
||||||
|
|
||||||
|
impl From<()> for Box<dyn DynAny<'static>> {
|
||||||
|
fn from(_: ()) -> Box<dyn DynAny<'static>> {
|
||||||
|
Box::new(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
use core::{
|
use core::{
|
||||||
cell::{Cell, RefCell, UnsafeCell},
|
cell::{Cell, RefCell, UnsafeCell},
|
||||||
iter::Empty,
|
iter::Empty,
|
||||||
|
|
@ -117,12 +141,21 @@ use std::{
|
||||||
|
|
||||||
impl_type!(Option<T>,Result<T, E>,Cell<T>,UnsafeCell<T>,RefCell<T>,MaybeUninit<T>,
|
impl_type!(Option<T>,Result<T, E>,Cell<T>,UnsafeCell<T>,RefCell<T>,MaybeUninit<T>,
|
||||||
Vec<T>, String, BTreeMap<K,V>,BTreeSet<V>, LinkedList<T>, VecDeque<T>,
|
Vec<T>, String, BTreeMap<K,V>,BTreeSet<V>, LinkedList<T>, VecDeque<T>,
|
||||||
BinaryHeap<T>, Box<T>, ManuallyDrop<T>, PhantomData<T>, PhantomPinned,Empty<T>,
|
BinaryHeap<T>, ManuallyDrop<T>, PhantomData<T>, PhantomPinned,Empty<T>,
|
||||||
Wrapping<T>, Duration, Once, Mutex<T>, RwLock<T>, bool, f32, f64, char,
|
Wrapping<T>, Duration, Once, Mutex<T>, RwLock<T>, bool, f32, f64, char,
|
||||||
u8, AtomicU8, u16,AtomicU16, u32,AtomicU32, u64,AtomicU64, usize,AtomicUsize,
|
u8, AtomicU8, u16,AtomicU16, u32,AtomicU32, u64,AtomicU64, usize,AtomicUsize,
|
||||||
i8,AtomicI8, i16,AtomicI16, i32,AtomicI32, i64,AtomicI64, isize,AtomicIsize,
|
i8,AtomicI8, i16,AtomicI16, i32,AtomicI32, i64,AtomicI64, isize,AtomicIsize,
|
||||||
i128, u128, AtomicBool, AtomicPtr<T>
|
i128, u128, AtomicBool, AtomicPtr<T>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
impl<T: crate::StaticType + ?Sized> crate::StaticType for Box<T> {
|
||||||
|
type Static = Box<<T as crate::StaticType>::Static>;
|
||||||
|
}
|
||||||
|
fn test() {
|
||||||
|
let foo = (Box::new(&1 as &dyn DynAny<'static>), Box::new(&2 as &dyn DynAny<'static>));
|
||||||
|
//let bar = &foo as &dyn DynAny<'static>;
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! impl_tuple {
|
macro_rules! impl_tuple {
|
||||||
(@rec $t:ident) => { };
|
(@rec $t:ident) => { };
|
||||||
(@rec $_:ident $($t:ident)+) => {
|
(@rec $_:ident $($t:ident)+) => {
|
||||||
|
|
@ -148,3 +181,9 @@ fn simple_downcast() {
|
||||||
let x = Box::new(3_u32) as Box<dyn DynAny>;
|
let x = Box::new(3_u32) as Box<dyn DynAny>;
|
||||||
assert_eq!(*downcast::<u32>(x).unwrap(), 3_u32);
|
assert_eq!(*downcast::<u32>(x).unwrap(), 3_u32);
|
||||||
}
|
}
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn simple_downcast_panic() {
|
||||||
|
let x = Box::new(3_i32) as Box<dyn DynAny>;
|
||||||
|
assert_eq!(*downcast::<u32>(x).expect("attempted to perform invalid downcast"), 3_u32);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,11 @@ use std::{
|
||||||
pub trait BorrowStack<'n> {
|
pub trait BorrowStack<'n> {
|
||||||
type Item;
|
type Item;
|
||||||
/// # Safety
|
/// # Safety
|
||||||
unsafe fn push(&'n self, value: Self::Item);
|
unsafe fn push(&self, value: Self::Item);
|
||||||
/// # Safety
|
/// # Safety
|
||||||
unsafe fn pop(&'n self);
|
unsafe fn pop(&self);
|
||||||
/// # Safety
|
/// # Safety
|
||||||
unsafe fn get(&'n self) -> &'n [Self::Item];
|
unsafe fn get(&self) -> &'n [Self::Item];
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -23,7 +23,7 @@ pub struct FixedSizeStack<'n, T> {
|
||||||
_phantom: PhantomData<&'n ()>,
|
_phantom: PhantomData<&'n ()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'n, T: Unpin> FixedSizeStack<'n, T> {
|
impl<'n, T: Unpin + 'n> FixedSizeStack<'n, T> {
|
||||||
pub fn new(capacity: usize) -> Self {
|
pub fn new(capacity: usize) -> Self {
|
||||||
let layout = std::alloc::Layout::array::<MaybeUninit<T>>(capacity).unwrap();
|
let layout = std::alloc::Layout::array::<MaybeUninit<T>>(capacity).unwrap();
|
||||||
let array = unsafe { std::alloc::alloc(layout) };
|
let array = unsafe { std::alloc::alloc(layout) };
|
||||||
|
|
@ -44,12 +44,15 @@ impl<'n, T: Unpin> FixedSizeStack<'n, T> {
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.len.load(Ordering::SeqCst) == 0
|
self.len.load(Ordering::SeqCst) == 0
|
||||||
}
|
}
|
||||||
|
pub fn push_fn(&self, f: impl FnOnce(&'n [T]) -> T) {
|
||||||
|
unsafe { self.push(f(self.get())) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'n, T> BorrowStack<'n> for FixedSizeStack<'n, T> {
|
impl<'n, T> BorrowStack<'n> for FixedSizeStack<'n, T> {
|
||||||
type Item = T;
|
type Item = T;
|
||||||
|
|
||||||
unsafe fn push(&'n self, value: Self::Item) {
|
unsafe fn push(&self, value: Self::Item) {
|
||||||
let len = self.len.load(Ordering::SeqCst);
|
let len = self.len.load(Ordering::SeqCst);
|
||||||
assert!(len < self.capacity);
|
assert!(len < self.capacity);
|
||||||
let ptr = self.data[len].as_ptr();
|
let ptr = self.data[len].as_ptr();
|
||||||
|
|
@ -57,13 +60,13 @@ impl<'n, T> BorrowStack<'n> for FixedSizeStack<'n, T> {
|
||||||
self.len.fetch_add(1, Ordering::SeqCst);
|
self.len.fetch_add(1, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn pop(&'n self) {
|
unsafe fn pop(&self) {
|
||||||
let ptr = self.data[self.len.load(Ordering::SeqCst)].as_ptr();
|
let ptr = self.data[self.len.load(Ordering::SeqCst)].as_ptr();
|
||||||
Box::from_raw(ptr as *mut T);
|
let _ = Box::from_raw(ptr as *mut T);
|
||||||
self.len.fetch_sub(1, Ordering::SeqCst);
|
self.len.fetch_sub(1, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn get(&'n self) -> &'n [Self::Item] {
|
unsafe fn get(&self) -> &'n [Self::Item] {
|
||||||
std::slice::from_raw_parts(self.data.as_ptr() as *const T, self.len.load(Ordering::SeqCst))
|
std::slice::from_raw_parts(self.data.as_ptr() as *const T, self.len.load(Ordering::SeqCst))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,34 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait AsBoxNode<'n, T>
|
||||||
|
where
|
||||||
|
&'n Self: Node<T>,
|
||||||
|
Self: 'n,
|
||||||
|
{
|
||||||
|
type Output;
|
||||||
|
fn eval_box(&'n self, input: T) -> <Self>::Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'n, N: 'n, I> AsBoxNode<'n, I> for N
|
||||||
|
where
|
||||||
|
&'n N: Node<I, Output = N::Output>,
|
||||||
|
N: Node<I>,
|
||||||
|
Self: 'n,
|
||||||
|
{
|
||||||
|
type Output = <&'n N as Node<I>>::Output;
|
||||||
|
fn eval_box(&'n self, input: I) -> <Self>::Output {
|
||||||
|
self.eval(input)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'n, T> Node<T> for &'n (dyn AsBoxNode<'n, T, Output = T> + 'n) {
|
||||||
|
type Output = T;
|
||||||
|
fn eval(self, input: T) -> Self::Output {
|
||||||
|
self.eval_box(input)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "async")]
|
#[cfg(feature = "async")]
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait AsyncNode<T> {
|
pub trait AsyncNode<T> {
|
||||||
|
|
|
||||||
|
|
@ -240,7 +240,7 @@ mod test {
|
||||||
pub fn add_node() {
|
pub fn add_node() {
|
||||||
let a = ValueNode(42u32);
|
let a = ValueNode(42u32);
|
||||||
let b = ValueNode(6u32);
|
let b = ValueNode(6u32);
|
||||||
let cons_a = ConsNode(a);
|
let cons_a = ConsNode(a, PhantomData);
|
||||||
|
|
||||||
let sum = b.then(cons_a).then(AddNode);
|
let sum = b.then(cons_a).then(AddNode);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -115,49 +115,24 @@ pub trait ThenBox<Inter, Input> {
|
||||||
#[cfg(feature = "async")]
|
#[cfg(feature = "async")]
|
||||||
impl<'n, First: 'n, Inter, Input> ThenBox<Inter, Input> for alloc::boxed::Box<First> where &'n alloc::boxed::Box<First>: Node<Input, Output = Inter> {}
|
impl<'n, First: 'n, Inter, Input> ThenBox<Inter, Input> for alloc::boxed::Box<First> where &'n alloc::boxed::Box<First>: Node<Input, Output = Inter> {}
|
||||||
|
|
||||||
pub struct ConsNode<Root>(pub Root);
|
pub struct ConsNode<Root, T: From<()>>(pub Root, pub PhantomData<T>);
|
||||||
|
|
||||||
impl<Root, Input> Node<Input> for ConsNode<Root>
|
impl<Root, Input, T: From<()>> Node<Input> for ConsNode<Root, T>
|
||||||
where
|
where
|
||||||
Root: Node<()>,
|
Root: Node<T>,
|
||||||
{
|
{
|
||||||
type Output = (Input, <Root as Node<()>>::Output);
|
type Output = (Input, <Root as Node<T>>::Output);
|
||||||
|
|
||||||
fn eval(self, input: Input) -> Self::Output {
|
fn eval(self, input: Input) -> Self::Output {
|
||||||
let arg = self.0.eval(());
|
let arg = self.0.eval(().into());
|
||||||
(input, arg)
|
(input, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'n, Root: Node<()> + Copy, Input> Node<Input> for &'n ConsNode<Root> {
|
impl<'n, Root: Node<T> + Copy, T: From<()>, Input> Node<Input> for &'n ConsNode<Root, T> {
|
||||||
type Output = (Input, Root::Output);
|
type Output = (Input, Root::Output);
|
||||||
|
|
||||||
fn eval(self, input: Input) -> Self::Output {
|
fn eval(self, input: Input) -> Self::Output {
|
||||||
let arg = (&self.0).eval(());
|
let arg = self.0.eval(().into());
|
||||||
(input, arg)
|
(input, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ConsPassInputNode<Root>(pub Root);
|
|
||||||
|
|
||||||
impl<Root, L, R> Node<(L, R)> for ConsPassInputNode<Root>
|
|
||||||
where
|
|
||||||
Root: Node<R>,
|
|
||||||
{
|
|
||||||
type Output = (L, <Root as Node<R>>::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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,53 @@
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
use graphene_core::structural::*;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use graphene_core::value::ValueNode;
|
use graphene_core::value::ValueNode;
|
||||||
|
use graphene_core::{structural::*, RefNode};
|
||||||
|
|
||||||
use borrow_stack::BorrowStack;
|
use borrow_stack::BorrowStack;
|
||||||
use graphene_std::any::{Any, DynAnyNode, DynAnyNodeTrait};
|
use dyn_any::{downcast, DynAny, IntoDynAny};
|
||||||
|
use graphene_std::any::{Any, DowncastNode, DynAnyNode, TypeErasedNode};
|
||||||
use graphene_std::ops::AddNode;
|
use graphene_std::ops::AddNode;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn borrow_stack() {
|
fn borrow_stack() {
|
||||||
let stack = borrow_stack::FixedSizeStack::new(256);
|
let stack = borrow_stack::FixedSizeStack::new(256);
|
||||||
unsafe {
|
unsafe {
|
||||||
let dynanynode: DynAnyNode<'_, _, ()> = DynAnyNode::new(&ValueNode(2_u32));
|
let dynanynode: DynAnyNode<_, (), _, _> = DynAnyNode::new(ValueNode(2_u32));
|
||||||
let refn = Box::new(dynanynode) as Box<dyn DynAnyNodeTrait>;
|
stack.push(dynanynode.into_box());
|
||||||
stack.push(refn);
|
|
||||||
}
|
|
||||||
unsafe {
|
|
||||||
let dynanynode: DynAnyNode<'_, _, &u32> = DynAnyNode::new(&ConsNode(ValueNode(2_u32)));
|
|
||||||
let refn = Box::new(dynanynode) as Box<dyn DynAnyNodeTrait>;
|
|
||||||
stack.push(refn);
|
|
||||||
}
|
|
||||||
unsafe {
|
|
||||||
let dynanynode: DynAnyNode<'_, _, (&u32, u32)> = DynAnyNode::new(&AddNode);
|
|
||||||
let refn = Box::new(dynanynode) as Box<dyn DynAnyNodeTrait>;
|
|
||||||
stack.push(refn);
|
|
||||||
}
|
}
|
||||||
|
stack.push_fn(|nodes| {
|
||||||
|
let downcast: DowncastNode<_, &u32> = DowncastNode::new(&nodes[0]);
|
||||||
|
let dynanynode: DynAnyNode<ConsNode<_, Any<'_>>, u32, _, _> = DynAnyNode::new(ConsNode(downcast, PhantomData));
|
||||||
|
dynanynode.into_box()
|
||||||
|
});
|
||||||
|
stack.push_fn(|_| {
|
||||||
|
let dynanynode: DynAnyNode<_, (u32, &u32), _, _> = DynAnyNode::new(AddNode);
|
||||||
|
dynanynode.into_box()
|
||||||
|
});
|
||||||
|
stack.push_fn(|nodes| {
|
||||||
|
let compose_node = nodes[1].after(&nodes[2]);
|
||||||
|
TypeErasedNode(Box::new(compose_node))
|
||||||
|
});
|
||||||
|
|
||||||
let mut input = Box::new(()) as Any;
|
let result = unsafe { &stack.get()[1] }.eval_ref(4_u32.into_dyn());
|
||||||
|
assert_eq!(*downcast::<(u32, &u32)>(result).unwrap(), (4_u32, &2_u32));
|
||||||
|
let result = unsafe { &stack.get()[1] }.eval_ref(4_u32.into_dyn());
|
||||||
|
let add = unsafe { &stack.get()[2] }.eval_ref(result);
|
||||||
|
assert_eq!(*downcast::<u32>(add).unwrap(), 6_u32);
|
||||||
|
let add = unsafe { &stack.get()[3] }.eval_ref(4_u32.into_dyn());
|
||||||
|
assert_eq!(*downcast::<u32>(add).unwrap(), 6_u32);
|
||||||
|
|
||||||
|
/*
|
||||||
for i in 0..3 {
|
for i in 0..3 {
|
||||||
|
println!("node_id: {}", i);
|
||||||
let value = unsafe { &stack.get()[i] };
|
let value = unsafe { &stack.get()[i] };
|
||||||
input = value.eval_ref_dispatch(input);
|
input = value.eval_ref(input);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
assert_eq!(*dyn_any::downcast::<u32>(input).unwrap(), 4)
|
//assert_eq!(*dyn_any::downcast::<u32>(result).unwrap(), 4)
|
||||||
|
|
||||||
//assert_eq!(4, *dyn_any::downcast::<u32>(DynamicAddNode.eval((Box::new(2_u32) as Dynamic, Box::new(2_u32) as Dynamic))).unwrap());
|
//assert_eq!(4, *dyn_any::downcast::<u32>(DynamicAddNode.eval((Box::new(2_u32) as Dynamic, Box::new(2_u32) as Dynamic))).unwrap());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ fn fmt_error<I>() -> String {
|
||||||
format!("DynAnyNode: input is not of correct type, expected {}", std::any::type_name::<I>())
|
format!("DynAnyNode: input is not of correct type, expected {}", std::any::type_name::<I>())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DynAnyNode<'n, N: RefNode<I>, I>(pub N, pub PhantomData<&'n I>);
|
pub struct DynAnyNode<N, I: StaticType, O: StaticType, ORef: StaticType>(pub N, PhantomData<(I, O, ORef)>);
|
||||||
/*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> {
|
/*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<dyn dyn_any::DynAny<'n> + 'n>;
|
type Output = Box<dyn dyn_any::DynAny<'n> + 'n>;
|
||||||
fn eval(self, input: &'n dyn DynAny<'n>) -> Self::Output {
|
fn eval(self, input: &'n dyn DynAny<'n>) -> Self::Output {
|
||||||
|
|
@ -29,22 +29,42 @@ impl<'n, I: StaticType, N: RefNode<'n, I, Output = O> + 'n, O: 'n + StaticType>
|
||||||
Box::new(self.0.eval_ref(*input))
|
Box::new(self.0.eval_ref(*input))
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
impl<'n, I: StaticType, N: RefNode<I, Output = O> + Copy + 'n, O: 'n + StaticType> Node<Any<'n>> for &'n DynAnyNode<'n, N, I> {
|
impl<'n, I: StaticType, N: 'n, O: 'n + StaticType, ORef: 'n + StaticType> Node<Any<'n>> for DynAnyNode<N, I, O, ORef>
|
||||||
|
where
|
||||||
|
N: Node<I, Output = O>,
|
||||||
|
{
|
||||||
type Output = Any<'n>;
|
type Output = Any<'n>;
|
||||||
fn eval(self, input: Any<'n>) -> Self::Output {
|
fn eval(self, input: Any<'n>) -> Self::Output {
|
||||||
let input: Box<I> = dyn_any::downcast(input).unwrap_or_else(|| panic!("{}", fmt_error::<I>()));
|
let input: Box<I> = dyn_any::downcast(input).unwrap_or_else(|| panic!("{}", fmt_error::<I>()));
|
||||||
Box::new(self.0.eval_ref(*input))
|
Box::new(self.0.eval(*input))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'n, I: StaticType, N: 'n, O: 'n + StaticType, ORef: 'n + StaticType> Node<Any<'n>> for &'n DynAnyNode<N, I, O, ORef>
|
||||||
|
where
|
||||||
|
&'n N: Node<I, Output = ORef>,
|
||||||
|
{
|
||||||
|
type Output = Any<'n>;
|
||||||
|
fn eval(self, input: Any<'n>) -> Self::Output {
|
||||||
|
let input: Box<I> = dyn_any::downcast(input).unwrap_or_else(|| panic!("{}", fmt_error::<I>()));
|
||||||
|
Box::new((&self.0).eval_ref(*input))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub struct TypeErasedNode<'n>(pub Box<dyn AsBoxNode<'n, Any<'n>, Output = Any<'n>>>);
|
||||||
|
impl<'n> Node<Any<'n>> for &'n TypeErasedNode<'n> {
|
||||||
|
type Output = Any<'n>;
|
||||||
|
fn eval(self, input: Any<'n>) -> Self::Output {
|
||||||
|
self.0.eval_box(input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'n, I: StaticType, N: RefNode<I, Output = O> + 'n + Copy, O: 'n + StaticType> DynAnyNode<'n, N, I>
|
impl<'n, I: StaticType + 'n, N: 'n, O: 'n + StaticType, ORef: 'n + StaticType> DynAnyNode<N, I, O, ORef>
|
||||||
where
|
where
|
||||||
N::Output: StaticType,
|
&'n N: Node<I, Output = ORef>,
|
||||||
{
|
{
|
||||||
pub fn new(n: N) -> Self {
|
pub fn new(n: N) -> Self {
|
||||||
DynAnyNode(n, PhantomData)
|
DynAnyNode(n, PhantomData)
|
||||||
}
|
}
|
||||||
pub fn into_erased(&'n self) -> impl RefNode<Any<'n>, Output = Any<'n>> {
|
pub fn into_impl(&'n self) -> impl RefNode<Any<'n>, Output = Any<'n>> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
/*pub fn as_ref(&'n self) -> &'n AnyNode<'n> {
|
/*pub fn as_ref(&'n self) -> &'n AnyNode<'n> {
|
||||||
|
|
@ -53,22 +73,61 @@ where
|
||||||
pub fn into_ref_box(self) -> Box<dyn RefNode<Box<(dyn DynAny<'n> + 'n)>, Output = Box<(dyn DynAny<'n> + 'n)>> + 'n> {
|
pub fn into_ref_box(self) -> Box<dyn RefNode<Box<(dyn DynAny<'n> + 'n)>, Output = Box<(dyn DynAny<'n> + 'n)>> + 'n> {
|
||||||
Box::new(self)
|
Box::new(self)
|
||||||
}*/
|
}*/
|
||||||
pub fn into_ref(self: &'n &'n Self) -> &'n (dyn RefNode<Any<'n>, Output = Any<'n>> + 'n) {
|
pub fn as_ref(self: &'n &'n Self) -> &'n (dyn RefNode<Any<'n>, Output = Any<'n>> + 'n) {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
pub fn into_box<'a: 'n>(self) -> TypeErasedNode<'n>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
N: Node<I, Output = O>,
|
||||||
|
{
|
||||||
|
TypeErasedNode(Box::new(self))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct DowncastNode<N, I: StaticType>(pub N, PhantomData<I>);
|
||||||
|
impl<N: Copy + Clone, I: StaticType> Clone for DowncastNode<N, I> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self(self.0, self.1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<N: Copy + Clone, I: StaticType> Copy for DowncastNode<N, I> {}
|
||||||
|
|
||||||
|
impl<'n, N, O: 'n + StaticType> Node<Any<'n>> for DowncastNode<N, O>
|
||||||
|
where
|
||||||
|
N: Node<Any<'n>, Output = Any<'n>>,
|
||||||
|
{
|
||||||
|
type Output = O;
|
||||||
|
fn eval(self, input: Any<'n>) -> Self::Output {
|
||||||
|
let output = self.0.eval(input);
|
||||||
|
*dyn_any::downcast(output).unwrap_or_else(|| panic!("DowncastNode: {}", fmt_error::<O>()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'n, N, I: StaticType> DowncastNode<N, I>
|
||||||
|
where
|
||||||
|
N: Node<Any<'n>>,
|
||||||
|
{
|
||||||
|
pub fn new(n: N) -> Self {
|
||||||
|
DowncastNode(n, PhantomData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
/// If we store a `Box<dyn RefNode>` in the stack then the origional DynAnyNode is dropped (because it is not stored by reference)
|
/// If we store a `Box<dyn RefNode>` in the stack then the origional DynAnyNode is dropped (because it is not stored by reference)
|
||||||
/// This trait is implemented directly by `DynAnyNode` so this means the borrow stack will hold by value
|
/// This trait is implemented directly by `DynAnyNode` so this means the borrow stack will hold by value
|
||||||
pub trait DynAnyNodeTrait<'n> {
|
pub trait DynAnyNodeTrait<'n> {
|
||||||
fn eval_ref_dispatch(&'n self, input: Any<'n>) -> Any<'n>;
|
fn eval_ref_dispatch(&'n self, input: Any<'n>) -> Any<'n>;
|
||||||
}
|
}
|
||||||
impl<'n, I: StaticType, O: 'n + StaticType, Node: RefNode<I, Output = O> + Copy + 'n> DynAnyNodeTrait<'n> for DynAnyNode<'n, Node, I> {
|
impl<'n, I: StaticType, O: 'n + StaticType, Node: 'n> DynAnyNodeTrait<'n> for DynAnyNode<Node, I, O>
|
||||||
|
where
|
||||||
|
&'n Node: RefNode<I>,
|
||||||
|
{
|
||||||
fn eval_ref_dispatch(&'n self, input: Any<'n>) -> Any<'n> {
|
fn eval_ref_dispatch(&'n self, input: Any<'n>) -> Any<'n> {
|
||||||
self.eval_ref(input)
|
self.eval_ref(input)
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
use graphene_core::ops::Dynamic;
|
use graphene_core::{ops::Dynamic, AsBoxNode};
|
||||||
pub struct BoxedComposition<'a, Second> {
|
pub struct BoxedComposition<'a, Second> {
|
||||||
pub first: Box<dyn Node<(), Output = Dynamic<'a>>>,
|
pub first: Box<dyn Node<(), Output = Dynamic<'a>>>,
|
||||||
pub second: Second,
|
pub second: Second,
|
||||||
|
|
@ -138,9 +197,9 @@ mod test {
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic]
|
#[should_panic]
|
||||||
pub fn dyn_input_invalid_eval_panic() {
|
pub fn dyn_input_invalid_eval_panic() {
|
||||||
static ADD: &DynAnyNode<&AddNode, (u32, u32)> = &DynAnyNode(&AddNode, PhantomData);
|
static ADD: &DynAnyNode<AddNode, (u32, u32), u32, u32> = &DynAnyNode(AddNode, PhantomData);
|
||||||
|
|
||||||
let add = ADD.into_ref();
|
let add = ADD.as_ref();
|
||||||
add.eval_ref(Box::new(&("32", 32u32)));
|
add.eval_ref(Box::new(&("32", 32u32)));
|
||||||
}
|
}
|
||||||
/*#[test]
|
/*#[test]
|
||||||
|
|
@ -161,11 +220,11 @@ mod test {
|
||||||
|
|
||||||
// If we put this until the push in a new scope then it failes to compile due to lifetime errors which I'm struggling to fix.
|
// If we put this until the push in a new scope then it failes to compile due to lifetime errors which I'm struggling to fix.
|
||||||
|
|
||||||
let value: &DynAnyNode<&ValueNode<(u32, u32)>, ()> = &DynAnyNode(&ValueNode((3u32, 4u32)), PhantomData);
|
let value: &DynAnyNode<ValueNode<(u32, u32)>, (), &(u32, u32), _> = &DynAnyNode(ValueNode((3u32, 4u32)), PhantomData);
|
||||||
let add: &DynAnyNode<&AddNode, &(u32, u32)> = &DynAnyNode(&AddNode, PhantomData);
|
let add: &DynAnyNode<AddNode, &(u32, u32), u32, _> = &DynAnyNode(AddNode, PhantomData);
|
||||||
|
|
||||||
let value_ref = (&value).into_ref();
|
let value_ref = value.as_ref();
|
||||||
let add_ref = (&add).into_ref();
|
let add_ref = add.as_ref();
|
||||||
vec.push(value_ref);
|
vec.push(value_ref);
|
||||||
vec.push(add_ref);
|
vec.push(add_ref);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ impl<'a> IntoIterator for &'a Image {
|
||||||
|
|
||||||
pub fn file_node<'n, P: AsRef<Path> + 'n>() -> impl Node<P, Output = Result<Vec<u8>, Error>> {
|
pub fn file_node<'n, P: AsRef<Path> + 'n>() -> impl Node<P, Output = Result<Vec<u8>, Error>> {
|
||||||
let fs = ValueNode(StdFs).clone();
|
let fs = ValueNode(StdFs).clone();
|
||||||
let fs = ConsNode(fs);
|
let fs = ConsNode(fs, PhantomData);
|
||||||
let file: ComposeNode<_, _, P> = fs.then(FileNode(PhantomData));
|
let file: ComposeNode<_, _, P> = fs.then(FileNode(PhantomData));
|
||||||
|
|
||||||
file.then(FlatMapResultNode::new(BufferNode))
|
file.then(FlatMapResultNode::new(BufferNode))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue