sauron_core/dom/application/
skip_diff.rs1use crate::vdom::TreePath;
2
3#[derive(Debug, PartialEq, Clone)]
5pub enum SkipAttrs {
6 All,
8 Indices(Vec<usize>),
10}
11
12impl SkipAttrs {
13 pub fn none() -> Self {
15 Self::Indices(vec![])
16 }
17}
18
19#[derive(Debug, PartialEq, Clone)]
22pub struct SkipDiff {
23 pub skip_attrs: SkipAttrs,
25 pub children: Vec<SkipDiff>,
27}
28
29impl SkipDiff {
30 pub fn block() -> Self {
32 Self {
33 skip_attrs: SkipAttrs::none(),
34 children: vec![],
35 }
36 }
37
38 pub fn in_path(&self, path: &TreePath) -> Option<&Self> {
40 let mut path = path.clone();
41 if path.is_empty() {
42 Some(self)
43 } else {
44 let idx = path.remove_first();
45 if let Some(child) = self.children.get(idx) {
46 child.in_path(&path)
47 } else {
48 None
49 }
50 }
51 }
52
53 pub fn traverse(&self, idx: usize) -> Option<&Self> {
55 self.children.get(idx)
56 }
57
58 pub fn shall_skip_attributes(&self) -> bool {
61 self.skip_attrs == SkipAttrs::All
62 }
63
64 pub fn is_skippable_recursive(&self) -> bool {
66 self.shall_skip_attributes() && self.children.iter().all(Self::is_skippable_recursive)
67 }
68
69 pub fn shall_skip_node(&self) -> bool {
71 self.shall_skip_attributes() && self.children.is_empty()
72 }
73
74 pub fn collapse_children(self) -> Self {
76 let Self {
77 skip_attrs,
78 children,
79 } = self;
80 let can_skip_children = children.iter().all(Self::is_skippable_recursive);
81 Self {
82 skip_attrs,
83 children: if can_skip_children {
84 vec![]
85 } else {
86 children.into_iter().map(Self::collapse_children).collect()
87 },
88 }
89 }
90}
91
92pub fn skip_if(shall: bool, children: impl IntoIterator<Item = SkipDiff>) -> SkipDiff {
94 SkipDiff {
95 skip_attrs: if shall {
96 SkipAttrs::All
97 } else {
98 SkipAttrs::none()
99 },
100 children: children.into_iter().collect(),
101 }
102}
103
104#[derive(Debug)]
106pub struct SkipPath {
107 pub(crate) path: TreePath,
108 pub(crate) skip_diff: Option<SkipDiff>,
109}
110
111impl SkipPath {
112 pub(crate) fn new(path: TreePath, skip_diff: SkipDiff) -> Self {
113 Self {
114 path,
115 skip_diff: Some(skip_diff),
116 }
117 }
118
119 pub(crate) fn traverse(&self, idx: usize) -> Self {
120 Self {
121 path: self.path.traverse(idx),
122 skip_diff: if let Some(skip_diff) = self.skip_diff.as_ref() {
123 skip_diff.traverse(idx).cloned()
124 } else {
125 None
126 },
127 }
128 }
129
130 pub(crate) fn backtrack(&self) -> Self {
131 Self {
132 path: self.path.backtrack(),
133 skip_diff: None,
135 }
136 }
137}