2021-10-30 01:43:21 +00:00
|
|
|
use std::marker::PhantomData;
|
|
|
|
|
|
|
|
/*
|
|
|
|
Remember: calls to rsx! are lazy - they are not evaluated immediately.
|
|
|
|
|
|
|
|
They also using dynamic dispatch, so we can return multiple rsx!'s from match statements and such.
|
|
|
|
|
|
|
|
If we allocated every rsx! call on the heap, it would be quite wasteful. Rsx! calls are FnOnce, so they can be stored in a stack.
|
|
|
|
|
|
|
|
Solutions like stackdst are useful, but they only support 'static closures.
|
|
|
|
|
|
|
|
All our closures are bound by the bump lifetime, so stack-dst will not work for us
|
|
|
|
|
|
|
|
Our solution is to try and manually allocate the closure onto the stack.
|
|
|
|
If it fails, then we default to Box.
|
|
|
|
|
|
|
|
*/
|
|
|
|
use crate::innerlude::{IntoVNode, NodeFactory, VNode};
|
|
|
|
|
|
|
|
/// A concrete type provider for closures that build VNode structures.
|
|
|
|
///
|
|
|
|
/// This struct wraps lazy structs that build VNode trees Normally, we cannot perform a blanket implementation over
|
|
|
|
/// closures, but if we wrap the closure in a concrete type, we can maintain separate implementations of IntoVNode.
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// ```rust
|
|
|
|
/// LazyNodes::new(|f| f.element("div", [], [], [] None))
|
|
|
|
/// ```
|
2021-11-01 06:41:23 +00:00
|
|
|
pub struct LazyNodes<'a, 'b> {
|
|
|
|
inner: StackNodeStorage<'a, 'b>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'b> LazyNodes<'a, 'b> {
|
|
|
|
pub fn new<F>(f: F) -> Self
|
|
|
|
where
|
|
|
|
F: FnOnce(NodeFactory<'a>) -> VNode<'a> + 'b,
|
|
|
|
{
|
|
|
|
Self {
|
|
|
|
inner: StackNodeStorage::Heap(Box::new(f)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn call(self, f: NodeFactory<'a>) -> VNode<'a> {
|
|
|
|
match self.inner {
|
|
|
|
StackNodeStorage::Heap(lazy) => lazy(f),
|
|
|
|
_ => todo!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-10-30 01:43:21 +00:00
|
|
|
|
|
|
|
type StackHeapSize = [usize; 12];
|
|
|
|
|
2021-11-01 06:41:23 +00:00
|
|
|
enum StackNodeStorage<'a, 'b> {
|
2021-10-30 01:43:21 +00:00
|
|
|
Stack {
|
|
|
|
next_ofs: usize,
|
|
|
|
buf: StackHeapSize,
|
|
|
|
width: usize,
|
|
|
|
},
|
2021-11-01 06:41:23 +00:00
|
|
|
Heap(Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a> + 'b>),
|
2021-10-30 01:43:21 +00:00
|
|
|
}
|
|
|
|
|
2021-10-30 21:11:15 +00:00
|
|
|
// impl<'a, F: FnOnce(NodeFactory<'a>) -> VNode<'a>> LazyNodes<'a, F> {
|
|
|
|
// pub fn new(f: F) -> Self {
|
|
|
|
// // let width = std::mem?::size_of::<F>();
|
|
|
|
// // let b: Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a>> = Box::new(f);
|
|
|
|
|
|
|
|
// todo!()
|
|
|
|
// // Self { inner: b }
|
|
|
|
// // todo!()
|
|
|
|
|
|
|
|
// // if width > std::mem::size_of::<StackHeapSize>() {
|
|
|
|
// // let g: Box<dyn for<'b> FnOnce(NodeFactory<'b>) -> VNode<'b> + 'g> = Box::new(f);
|
|
|
|
// // LazyNodes {
|
|
|
|
// // inner: StackNodeStorage::Heap(g),
|
|
|
|
// // }
|
|
|
|
// // } else {
|
|
|
|
// // let mut buf = [0; 12];
|
|
|
|
// // let mut next_ofs = 0;
|
|
|
|
// // next_ofs += 1;
|
|
|
|
// // LazyNodes {
|
|
|
|
// // inner: StackNodeStorage::Stack {
|
|
|
|
// // next_ofs,
|
|
|
|
// // buf,
|
|
|
|
// // width,
|
|
|
|
// // },
|
|
|
|
// // }
|
|
|
|
// // }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // Our blanket impl
|
|
|
|
// impl<'a> IntoIterator for LazyNodes<'a>
|
|
|
|
// // where
|
|
|
|
// // F: FnOnce(NodeFactory<'a>) -> VNode<'a>,
|
|
|
|
// // impl<'a, F> IntoIterator for LazyNodes<'a, F>
|
|
|
|
// // where
|
|
|
|
// // F: FnOnce(NodeFactory<'a>) -> VNode<'a>,
|
|
|
|
// {
|
|
|
|
// type Item = Self;
|
|
|
|
// type IntoIter = std::iter::Once<Self::Item>;
|
|
|
|
// fn into_iter(self) -> Self::IntoIter {
|
|
|
|
// std::iter::once(self)
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // Our blanket impl
|
|
|
|
// impl IntoVNode for LazyNodes<'_> {
|
|
|
|
// // impl<'a, F: FnOnce(NodeFactory<'a>) -> VNode<'a>> IntoVNode<'a> for LazyNodes<'a, F> {
|
|
|
|
// fn into_vnode<'a>(self, cx: NodeFactory<'a>) -> VNode<'a> {
|
|
|
|
// todo!()
|
|
|
|
// // match self.inner {
|
|
|
|
// // StackNodeStorage::Stack {
|
|
|
|
// // buf,
|
|
|
|
// // next_ofs,
|
|
|
|
// // width,
|
|
|
|
// // } => {
|
|
|
|
// // // get the start of the allocation
|
|
|
|
// // let r = &buf[0];
|
|
|
|
|
|
|
|
// // // recast the allocation as dyn FnOnce
|
|
|
|
|
|
|
|
// // // pretend the FnOnce is box
|
|
|
|
// // let g: Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a>> = todo!();
|
|
|
|
// // // Box::from_raw(r as *const usize as *mut dyn FnOnce(NodeFactory<'a>));
|
|
|
|
|
|
|
|
// // // use Box's ability to act as FnOnce
|
|
|
|
// // g(cx)
|
|
|
|
// // }
|
|
|
|
// // StackNodeStorage::Heap(b) => b(cx),
|
|
|
|
// // }
|
|
|
|
// }
|
|
|
|
// }
|