Skip to content

Commit 6141f0d

Browse files
committed
function to walk over all elements (recursive)
1 parent 4fc37c1 commit 6141f0d

5 files changed

Lines changed: 346 additions & 0 deletions

File tree

src/dom/element.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use super::node::Node;
22
#[cfg(feature = "source-span")]
33
use super::span::SourceSpan;
44
use crate::dom::vecmap::VecMap;
5+
use crate::dom::walk::Children;
56
use crate::{Attribute, VecSet};
67
use ownable::{IntoOwned, ToBorrowed, ToOwned};
78
use serde::Serialize;
@@ -68,3 +69,15 @@ impl Default for Element<'static> {
6869
}
6970
}
7071
}
72+
73+
impl<'a> Children<'a> for Element<'a> {
74+
#[inline]
75+
fn children(&self) -> &[Node<'a>] {
76+
self.children.as_slice()
77+
}
78+
79+
#[inline]
80+
fn children_mut(&mut self) -> &mut [Node<'a>] {
81+
self.children.as_mut_slice()
82+
}
83+
}

src/dom/mod.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@ pub mod node;
1717
pub mod span;
1818
pub mod vecmap;
1919
pub mod vecset;
20+
pub mod walk;
2021

2122
#[cfg(feature = "source-span")]
2223
use crate::dom::span::SourceSpan;
24+
use crate::dom::walk::Children;
2325
use element::{Element, ElementVariant};
2426
use node::Node;
2527

@@ -369,3 +371,15 @@ impl<'a> Dom<'a> {
369371
Ok(attribute)
370372
}
371373
}
374+
375+
impl<'a> Children<'a> for Dom<'a> {
376+
#[inline]
377+
fn children(&self) -> &[Node<'a>] {
378+
self.children.as_slice()
379+
}
380+
381+
#[inline]
382+
fn children_mut(&mut self) -> &mut [Node<'a>] {
383+
self.children.as_mut_slice()
384+
}
385+
}

src/dom/node.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use super::element::Element;
22
use crate::Text;
3+
use crate::dom::walk::Children;
34
use ownable::{IntoOwned, ToBorrowed, ToOwned};
45
use serde::Serialize;
6+
use std::array;
57

68
#[derive(Debug, Serialize, PartialEq, IntoOwned, ToBorrowed, ToOwned)]
79
#[serde(untagged)]
@@ -48,6 +50,18 @@ impl<'a> Node<'a> {
4850
}
4951
}
5052

53+
impl<'a> Children<'a> for Node<'a> {
54+
#[inline]
55+
fn children(&self) -> &[Node<'a>] {
56+
array::from_ref(self)
57+
}
58+
59+
#[inline]
60+
fn children_mut(&mut self) -> &mut [Node<'a>] {
61+
array::from_mut(self)
62+
}
63+
}
64+
5165
impl<'a> IntoIterator for &'a Node<'a> {
5266
type Item = &'a Node<'a>;
5367
type IntoIter = NodeIntoIterator<'a>;

src/dom/walk.rs

Lines changed: 304 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,304 @@
1+
use crate::{Element, Node, Text};
2+
use std::ops::ControlFlow;
3+
4+
pub enum WalkResult<T> {
5+
/// Continue walking.
6+
Continue,
7+
/// Skip the children of this element.
8+
Skip,
9+
/// Break walking.
10+
Break(T),
11+
}
12+
13+
#[allow(async_fn_in_trait)]
14+
pub trait Children<'a> {
15+
fn children(&self) -> &[Node<'a>];
16+
17+
#[inline]
18+
fn for_each_element<F>(&mut self, mut f: F)
19+
where
20+
F: FnMut(&Element<'a>) -> WalkResult<()>,
21+
{
22+
let _ = inner_for_each_element(self.children(), &mut f);
23+
}
24+
25+
#[inline]
26+
async fn for_each_element_async<F>(&mut self, mut f: F)
27+
where
28+
F: AsyncFnMut(&Element<'a>) -> WalkResult<()>,
29+
{
30+
let _ = inner_for_each_element_async(self.children(), &mut f).await;
31+
}
32+
33+
#[inline]
34+
fn for_each_element_brk<F, T>(&mut self, mut f: F) -> ControlFlow<T, ()>
35+
where
36+
F: FnMut(&Element<'a>) -> WalkResult<T>,
37+
{
38+
inner_for_each_element(self.children(), &mut f)
39+
}
40+
41+
#[inline]
42+
async fn for_each_element_async_brk<F, T>(&mut self, mut f: F) -> ControlFlow<T, ()>
43+
where
44+
F: AsyncFnMut(&Element<'a>) -> WalkResult<T>,
45+
{
46+
inner_for_each_element_async(self.children(), &mut f).await
47+
}
48+
49+
#[inline]
50+
fn for_each_text<F>(&mut self, mut f: F)
51+
where
52+
F: FnMut(&Text<'a>) -> WalkResult<()>,
53+
{
54+
let _ = inner_for_each_text(self.children(), &mut f);
55+
}
56+
57+
#[inline]
58+
async fn for_each_text_async<F>(&mut self, mut f: F)
59+
where
60+
F: AsyncFnMut(&Text<'a>) -> WalkResult<()>,
61+
{
62+
let _ = inner_for_each_text_async(self.children(), &mut f).await;
63+
}
64+
65+
#[inline]
66+
fn for_each_text_brk<F, T>(&mut self, mut f: F) -> ControlFlow<T, ()>
67+
where
68+
F: FnMut(&Text<'a>) -> WalkResult<T>,
69+
{
70+
inner_for_each_text(self.children(), &mut f)
71+
}
72+
73+
#[inline]
74+
async fn for_each_text_async_brk<F, T>(&mut self, mut f: F) -> ControlFlow<T, ()>
75+
where
76+
F: AsyncFnMut(&Text<'a>) -> WalkResult<T>,
77+
{
78+
inner_for_each_text_async(self.children(), &mut f).await
79+
}
80+
81+
fn children_mut(&mut self) -> &mut [Node<'a>];
82+
83+
#[inline]
84+
fn for_each_element_mut<F>(&mut self, mut f: F)
85+
where
86+
F: FnMut(&mut Element<'a>) -> WalkResult<()>,
87+
{
88+
let _ = inner_for_each_element_mut(self.children_mut(), &mut f);
89+
}
90+
91+
#[inline]
92+
async fn for_each_element_mut_async<F>(&mut self, mut f: F)
93+
where
94+
F: AsyncFnMut(&mut Element<'a>) -> WalkResult<()>,
95+
{
96+
let _ = inner_for_each_element_mut_async(self.children_mut(), &mut f).await;
97+
}
98+
99+
#[inline]
100+
fn for_each_element_mut_brk<F, T>(&mut self, mut f: F) -> ControlFlow<T, ()>
101+
where
102+
F: FnMut(&mut Element<'a>) -> WalkResult<T>,
103+
{
104+
inner_for_each_element_mut(self.children_mut(), &mut f)
105+
}
106+
107+
#[inline]
108+
async fn for_each_element_mut_async_brk<F, T>(&mut self, mut f: F) -> ControlFlow<T, ()>
109+
where
110+
F: AsyncFnMut(&mut Element<'a>) -> WalkResult<T>,
111+
{
112+
inner_for_each_element_mut_async(self.children_mut(), &mut f).await
113+
}
114+
115+
#[inline]
116+
fn for_each_text_mut<F>(&mut self, mut f: F)
117+
where
118+
F: FnMut(&mut Text<'a>) -> WalkResult<()>,
119+
{
120+
let _ = inner_for_each_text_mut(self.children_mut(), &mut f);
121+
}
122+
123+
#[inline]
124+
async fn for_each_text_mut_async<F>(&mut self, mut f: F)
125+
where
126+
F: AsyncFnMut(&mut Text<'a>) -> WalkResult<()>,
127+
{
128+
let _ = inner_for_each_text_mut_async(self.children_mut(), &mut f).await;
129+
}
130+
131+
#[inline]
132+
fn for_each_text_mut_brk<F, T>(&mut self, mut f: F) -> ControlFlow<T, ()>
133+
where
134+
F: FnMut(&mut Text<'a>) -> WalkResult<T>,
135+
{
136+
inner_for_each_text_mut(self.children_mut(), &mut f)
137+
}
138+
139+
#[inline]
140+
async fn for_each_text_mut_async_brk<F, T>(&mut self, mut f: F) -> ControlFlow<T, ()>
141+
where
142+
F: AsyncFnMut(&mut Text<'a>) -> WalkResult<T>,
143+
{
144+
inner_for_each_text_mut_async(self.children_mut(), &mut f).await
145+
}
146+
}
147+
148+
fn inner_for_each_element<'a, F, T>(tree: &[Node<'a>], f: &mut F) -> ControlFlow<T, ()>
149+
where
150+
F: FnMut(&Element<'a>) -> WalkResult<T>,
151+
{
152+
for n in tree {
153+
if let Node::Element(e) = n {
154+
match f(e) {
155+
WalkResult::Continue => {
156+
inner_for_each_element(e.children.as_slice(), f)?;
157+
}
158+
WalkResult::Skip => (),
159+
WalkResult::Break(t) => return ControlFlow::Break(t),
160+
}
161+
}
162+
}
163+
ControlFlow::Continue(())
164+
}
165+
166+
async fn inner_for_each_element_async<'a, F, T>(tree: &[Node<'a>], f: &mut F) -> ControlFlow<T, ()>
167+
where
168+
F: AsyncFnMut(&Element<'a>) -> WalkResult<T>,
169+
{
170+
for n in tree {
171+
if let Node::Element(e) = n {
172+
match f(e).await {
173+
WalkResult::Continue => {
174+
Box::pin(inner_for_each_element_async(e.children.as_slice(), f)).await?;
175+
}
176+
WalkResult::Skip => (),
177+
WalkResult::Break(t) => return ControlFlow::Break(t),
178+
}
179+
}
180+
}
181+
ControlFlow::Continue(())
182+
}
183+
184+
fn inner_for_each_text<'a, F, T>(tree: &[Node<'a>], f: &mut F) -> ControlFlow<T, ()>
185+
where
186+
F: FnMut(&Text<'a>) -> WalkResult<T>,
187+
{
188+
for n in tree {
189+
match n {
190+
Node::Text(t) => {
191+
if let WalkResult::Break(t) = f(t) {
192+
return ControlFlow::Break(t);
193+
}
194+
}
195+
Node::Element(e) => inner_for_each_text(e.children.as_slice(), f)?,
196+
Node::Comment(_) => {}
197+
}
198+
}
199+
ControlFlow::Continue(())
200+
}
201+
202+
async fn inner_for_each_text_async<'a, F, T>(tree: &[Node<'a>], f: &mut F) -> ControlFlow<T, ()>
203+
where
204+
F: AsyncFnMut(&Text<'a>) -> WalkResult<T>,
205+
{
206+
for n in tree {
207+
match n {
208+
Node::Text(t) => {
209+
if let WalkResult::Break(t) = f(t).await {
210+
return ControlFlow::Break(t);
211+
}
212+
}
213+
Node::Element(e) => {
214+
Box::pin(inner_for_each_text_async(e.children.as_slice(), f)).await?
215+
}
216+
Node::Comment(_) => {}
217+
}
218+
}
219+
ControlFlow::Continue(())
220+
}
221+
222+
fn inner_for_each_element_mut<'a, F, T>(tree: &mut [Node<'a>], f: &mut F) -> ControlFlow<T, ()>
223+
where
224+
F: FnMut(&mut Element<'a>) -> WalkResult<T>,
225+
{
226+
for n in tree {
227+
if let Node::Element(e) = n {
228+
match f(e) {
229+
WalkResult::Continue => {
230+
inner_for_each_element_mut(e.children.as_mut_slice(), f)?;
231+
}
232+
WalkResult::Skip => (),
233+
WalkResult::Break(t) => return ControlFlow::Break(t),
234+
}
235+
}
236+
}
237+
ControlFlow::Continue(())
238+
}
239+
240+
async fn inner_for_each_element_mut_async<'a, F, T>(
241+
tree: &mut [Node<'a>],
242+
f: &mut F,
243+
) -> ControlFlow<T, ()>
244+
where
245+
F: AsyncFnMut(&mut Element<'a>) -> WalkResult<T>,
246+
{
247+
for n in tree {
248+
if let Node::Element(e) = n {
249+
match f(e).await {
250+
WalkResult::Continue => {
251+
Box::pin(inner_for_each_element_mut_async(
252+
e.children.as_mut_slice(),
253+
f,
254+
))
255+
.await?;
256+
}
257+
WalkResult::Skip => (),
258+
WalkResult::Break(t) => return ControlFlow::Break(t),
259+
}
260+
}
261+
}
262+
ControlFlow::Continue(())
263+
}
264+
265+
fn inner_for_each_text_mut<'a, F, T>(tree: &mut [Node<'a>], f: &mut F) -> ControlFlow<T, ()>
266+
where
267+
F: FnMut(&mut Text<'a>) -> WalkResult<T>,
268+
{
269+
for n in tree {
270+
match n {
271+
Node::Text(t) => {
272+
if let WalkResult::Break(t) = f(t) {
273+
return ControlFlow::Break(t);
274+
}
275+
}
276+
Node::Element(e) => inner_for_each_text_mut(e.children.as_mut_slice(), f)?,
277+
Node::Comment(_) => {}
278+
}
279+
}
280+
ControlFlow::Continue(())
281+
}
282+
283+
async fn inner_for_each_text_mut_async<'a, F, T>(
284+
tree: &mut [Node<'a>],
285+
f: &mut F,
286+
) -> ControlFlow<T, ()>
287+
where
288+
F: AsyncFnMut(&mut Text<'a>) -> WalkResult<T>,
289+
{
290+
for n in tree {
291+
match n {
292+
Node::Text(t) => {
293+
if let WalkResult::Break(t) = f(t).await {
294+
return ControlFlow::Break(t);
295+
}
296+
}
297+
Node::Element(e) => {
298+
Box::pin(inner_for_each_text_mut_async(e.children.as_mut_slice(), f)).await?
299+
}
300+
Node::Comment(_) => {}
301+
}
302+
}
303+
ControlFlow::Continue(())
304+
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,5 +111,6 @@ pub use crate::dom::node::Node;
111111
pub use crate::dom::span::SourceSpan;
112112
pub use crate::dom::vecmap::VecMap;
113113
pub use crate::dom::vecset::VecSet;
114+
pub use crate::dom::walk::{Children, WalkResult};
114115
pub use crate::error::Error;
115116
pub use crate::error::Result;

0 commit comments

Comments
 (0)