util.rs 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. use crate::innerlude::*;
  2. /// An iterator that only yields "real" [`Element`]s. IE only Elements that are
  3. /// not [`VNode::VComponent`] or [`VNode::VFragment`], .
  4. pub struct ElementIdIterator<'a> {
  5. vdom: &'a VirtualDom,
  6. // Heuristically we should never bleed into 5 completely nested fragments/components
  7. // Smallvec lets us stack allocate our little stack machine so the vast majority of cases are sane
  8. stack: smallvec::SmallVec<[(u16, &'a VNode<'a>); 5]>,
  9. }
  10. impl<'a> ElementIdIterator<'a> {
  11. /// Create a new iterator from the given [`VirtualDom`] and [`VNode`]
  12. ///
  13. /// This will allow you to iterate through all the real childrne of the [`VNode`].
  14. pub fn new(vdom: &'a VirtualDom, node: &'a VNode<'a>) -> Self {
  15. Self {
  16. vdom,
  17. stack: smallvec::smallvec![(0, node)],
  18. }
  19. }
  20. }
  21. impl<'a> Iterator for ElementIdIterator<'a> {
  22. type Item = &'a VNode<'a>;
  23. fn next(&mut self) -> Option<&'a VNode<'a>> {
  24. let mut should_pop = false;
  25. let mut returned_node = None;
  26. let mut should_push = None;
  27. while returned_node.is_none() {
  28. if let Some((count, node)) = self.stack.last_mut() {
  29. match node {
  30. // We can only exit our looping when we get "real" nodes
  31. VNode::Element(_) | VNode::Text(_) | VNode::Placeholder(_) => {
  32. // We've recursed INTO an element/text
  33. // We need to recurse *out* of it and move forward to the next
  34. // println!("Found element! Returning it!");
  35. should_pop = true;
  36. returned_node = Some(&**node);
  37. }
  38. // If we get a fragment we push the next child
  39. VNode::Fragment(frag) => {
  40. let _count = *count as usize;
  41. if _count >= frag.children.len() {
  42. should_pop = true;
  43. } else {
  44. should_push = Some(&frag.children[_count]);
  45. }
  46. }
  47. // For components, we load their root and push them onto the stack
  48. VNode::Component(sc) => {
  49. let scope = self.vdom.get_scope(sc.scope.get().unwrap()).unwrap();
  50. // Simply swap the current node on the stack with the root of the component
  51. *node = scope.root_node();
  52. }
  53. }
  54. } else {
  55. // If there's no more items on the stack, we're done!
  56. return None;
  57. }
  58. if should_pop {
  59. self.stack.pop();
  60. if let Some((id, _)) = self.stack.last_mut() {
  61. *id += 1;
  62. }
  63. should_pop = false;
  64. }
  65. if let Some(push) = should_push {
  66. self.stack.push((0, push));
  67. should_push = None;
  68. }
  69. }
  70. returned_node
  71. }
  72. }