util.rs 2.7 KB

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