lazynodes.rs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. use std::marker::PhantomData;
  2. /*
  3. Remember: calls to rsx! are lazy - they are not evaluated immediately.
  4. They also using dynamic dispatch, so we can return multiple rsx!'s from match statements and such.
  5. 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.
  6. Solutions like stackdst are useful, but they only support 'static closures.
  7. All our closures are bound by the bump lifetime, so stack-dst will not work for us
  8. Our solution is to try and manually allocate the closure onto the stack.
  9. If it fails, then we default to Box.
  10. */
  11. use crate::innerlude::{IntoVNode, NodeFactory, VNode};
  12. /// A concrete type provider for closures that build VNode structures.
  13. ///
  14. /// This struct wraps lazy structs that build VNode trees Normally, we cannot perform a blanket implementation over
  15. /// closures, but if we wrap the closure in a concrete type, we can maintain separate implementations of IntoVNode.
  16. ///
  17. ///
  18. /// ```rust
  19. /// LazyNodes::new(|f| f.element("div", [], [], [] None))
  20. /// ```
  21. // pub struct LazyNodes<'a, F: FnOnce(NodeFactory<'a>) -> VNode<'a>> {
  22. // inner: Box<F>,
  23. // _p: PhantomData<&'a ()>,
  24. // // inner: StackNodeStorage<'a>,
  25. // // inner: StackNodeStorage<'a>,
  26. // }
  27. pub type LazyNodes<'b> = Box<dyn for<'a> FnOnce(NodeFactory<'a>) -> VNode<'a> + 'b>;
  28. type StackHeapSize = [usize; 12];
  29. enum StackNodeStorage<'a> {
  30. Stack {
  31. next_ofs: usize,
  32. buf: StackHeapSize,
  33. width: usize,
  34. },
  35. Heap(Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a>>),
  36. }
  37. // impl<'a, F: FnOnce(NodeFactory<'a>) -> VNode<'a>> LazyNodes<'a, F> {
  38. // pub fn new(f: F) -> Self {
  39. // // let width = std::mem?::size_of::<F>();
  40. // // let b: Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a>> = Box::new(f);
  41. // todo!()
  42. // // Self { inner: b }
  43. // // todo!()
  44. // // if width > std::mem::size_of::<StackHeapSize>() {
  45. // // let g: Box<dyn for<'b> FnOnce(NodeFactory<'b>) -> VNode<'b> + 'g> = Box::new(f);
  46. // // LazyNodes {
  47. // // inner: StackNodeStorage::Heap(g),
  48. // // }
  49. // // } else {
  50. // // let mut buf = [0; 12];
  51. // // let mut next_ofs = 0;
  52. // // next_ofs += 1;
  53. // // LazyNodes {
  54. // // inner: StackNodeStorage::Stack {
  55. // // next_ofs,
  56. // // buf,
  57. // // width,
  58. // // },
  59. // // }
  60. // // }
  61. // }
  62. // }
  63. // // Our blanket impl
  64. // impl<'a> IntoIterator for LazyNodes<'a>
  65. // // where
  66. // // F: FnOnce(NodeFactory<'a>) -> VNode<'a>,
  67. // // impl<'a, F> IntoIterator for LazyNodes<'a, F>
  68. // // where
  69. // // F: FnOnce(NodeFactory<'a>) -> VNode<'a>,
  70. // {
  71. // type Item = Self;
  72. // type IntoIter = std::iter::Once<Self::Item>;
  73. // fn into_iter(self) -> Self::IntoIter {
  74. // std::iter::once(self)
  75. // }
  76. // }
  77. // // Our blanket impl
  78. // impl IntoVNode for LazyNodes<'_> {
  79. // // impl<'a, F: FnOnce(NodeFactory<'a>) -> VNode<'a>> IntoVNode<'a> for LazyNodes<'a, F> {
  80. // fn into_vnode<'a>(self, cx: NodeFactory<'a>) -> VNode<'a> {
  81. // todo!()
  82. // // match self.inner {
  83. // // StackNodeStorage::Stack {
  84. // // buf,
  85. // // next_ofs,
  86. // // width,
  87. // // } => {
  88. // // // get the start of the allocation
  89. // // let r = &buf[0];
  90. // // // recast the allocation as dyn FnOnce
  91. // // // pretend the FnOnce is box
  92. // // let g: Box<dyn FnOnce(NodeFactory<'a>) -> VNode<'a>> = todo!();
  93. // // // Box::from_raw(r as *const usize as *mut dyn FnOnce(NodeFactory<'a>));
  94. // // // use Box's ability to act as FnOnce
  95. // // g(cx)
  96. // // }
  97. // // StackNodeStorage::Heap(b) => b(cx),
  98. // // }
  99. // }
  100. // }