1use crate::document::{Node, NodeKind};
17
18fn is_attribute_or_namespace(kind: NodeKind) -> bool {
19 matches!(kind, NodeKind::Attribute | NodeKind::Namespace)
20}
21
22fn ancestor_vec<'a, N: Node<'a>>(n: N) -> Vec<N> {
25 let mut out = Vec::new();
26 let mut cur = n.parent();
27 while let Some(p) = cur {
28 out.push(p);
29 cur = p.parent();
30 }
31 out
32}
33
34fn descendant_vec<'a, N: Node<'a>>(n: N) -> Vec<N> {
36 let mut out = Vec::new();
37 for c in n.children() {
38 out.push(c);
39 out.extend(descendant_vec(c));
40 }
41 out
42}
43
44fn descendant_or_self_vec<'a, N: Node<'a>>(n: N) -> Vec<N> {
46 let mut out = vec![n];
47 out.extend(descendant_vec(n));
48 out
49}
50
51pub(crate) fn root_of<'a, N: Node<'a>>(n: N) -> N {
53 let mut cur = n;
54 while let Some(p) = cur.parent() {
55 cur = p;
56 }
57 cur
58}
59
60pub fn child<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
62 n.children()
63}
64
65pub fn descendant<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
68 descendant_vec(n).into_iter()
69}
70
71pub fn descendant_or_self<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
74 descendant_or_self_vec(n).into_iter()
75}
76
77pub fn parent<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
80 n.parent().into_iter()
81}
82
83pub fn ancestor<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
89 ancestor_vec(n).into_iter()
90}
91
92pub fn ancestor_or_self<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
96 let mut out = vec![n];
97 out.extend(ancestor_vec(n));
98 out.into_iter()
99}
100
101fn siblings_of<'a, N: Node<'a>>(n: N) -> Vec<N> {
105 if is_attribute_or_namespace(n.kind()) {
106 return Vec::new();
107 }
108 match n.parent() {
109 Some(parent) => parent.children().collect(),
110 None => Vec::new(),
111 }
112}
113
114pub fn following_sibling<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
118 let mut out = Vec::new();
119 let mut found = false;
120 for c in siblings_of(n) {
121 if found {
122 out.push(c);
123 } else if c == n {
124 found = true;
125 }
126 }
127 out.into_iter()
128}
129
130pub fn preceding_sibling<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
135 let mut out = Vec::new();
136 for c in siblings_of(n) {
137 if c == n {
138 break;
139 }
140 out.push(c);
141 }
142 out.reverse();
143 out.into_iter()
144}
145
146fn document_order_listing<'a, N: Node<'a>>(n: N) -> (Vec<N>, usize) {
149 let all = descendant_or_self_vec(root_of(n));
150 let idx = all
151 .iter()
152 .position(|x| *x == n)
153 .expect("n must be reachable from its own document root via children()");
154 (all, idx)
155}
156
157fn following_vec<'a, N: Node<'a>>(n: N) -> Vec<N> {
161 let (all, idx) = document_order_listing(n);
162 let subtree_len = 1 + descendant_vec(n).len();
163 all.into_iter().skip(idx + subtree_len).collect()
164}
165
166fn preceding_vec<'a, N: Node<'a>>(n: N) -> Vec<N> {
169 let (all, idx) = document_order_listing(n);
170 let ancestors = ancestor_vec(n);
171 let mut out: Vec<N> = all[..idx]
172 .iter()
173 .copied()
174 .filter(|c| !ancestors.contains(c))
175 .collect();
176 out.reverse();
177 out
178}
179
180fn owner_element<'a, N: Node<'a>>(n: N) -> N {
184 n.parent()
185 .expect("attribute/namespace node must have an owner element as parent")
186}
187
188pub fn following<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
200 let out: Vec<N> = if is_attribute_or_namespace(n.kind()) {
201 let owner = owner_element(n);
202 let mut v = descendant_vec(owner);
203 v.extend(following_vec(owner));
204 v
205 } else {
206 following_vec(n)
207 };
208 out.into_iter()
209}
210
211pub fn preceding<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
222 let out: Vec<N> = if is_attribute_or_namespace(n.kind()) {
223 let owner = owner_element(n);
224 preceding_vec(owner)
225 } else {
226 preceding_vec(n)
227 };
228 out.into_iter()
229}
230
231fn collect_if_element<'a, N: Node<'a>>(n: N, collect: impl FnOnce(N) -> Vec<N>) -> Vec<N> {
235 if n.kind() == NodeKind::Element {
236 collect(n)
237 } else {
238 Vec::new()
239 }
240}
241
242pub fn attribute<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
245 collect_if_element(n, |n| n.attributes().collect()).into_iter()
246}
247
248pub fn namespace<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
251 collect_if_element(n, |n| n.namespaces().collect()).into_iter()
252}
253
254pub fn self_axis<'a, N: Node<'a>>(n: N) -> impl Iterator<Item = N> + 'a {
256 std::iter::once(n)
257}
258
259#[cfg(test)]
260mod tests {
261 use super::*;
262 use crate::document::fixture::build;
263
264 #[test]
265 fn child_axis_on_nested_tree() {
266 let f = build();
267 let body = f.doc.node(f.body);
268 let got: Vec<_> = child(body).collect();
269 assert_eq!(
270 got,
271 vec![
272 f.doc.node(f.text0),
273 f.doc.node(f.span),
274 f.doc.node(f.comment),
275 f.doc.node(f.pi),
276 f.doc.node(f.text2),
277 ]
278 );
279 }
280
281 #[test]
282 fn descendant_axis_on_nested_tree() {
283 let f = build();
284 let html = f.doc.node(f.html);
285 let got: Vec<_> = descendant(html).collect();
286 assert_eq!(
287 got,
288 vec![
289 f.doc.node(f.body),
290 f.doc.node(f.text0),
291 f.doc.node(f.span),
292 f.doc.node(f.text1),
293 f.doc.node(f.comment),
294 f.doc.node(f.pi),
295 f.doc.node(f.text2),
296 ]
297 );
298 }
299
300 #[test]
301 fn descendant_or_self_axis_on_nested_tree() {
302 let f = build();
303 let span = f.doc.node(f.span);
304 let got: Vec<_> = descendant_or_self(span).collect();
305 assert_eq!(got, vec![span, f.doc.node(f.text1)]);
306 }
307
308 #[test]
309 fn parent_ancestor_ancestor_or_self_from_leaf_nearest_first() {
310 let f = build();
311 let text1 = f.doc.node(f.text1); let span = f.doc.node(f.span);
313 let body = f.doc.node(f.body);
314 let html = f.doc.node(f.html);
315 let root = f.doc.node(0);
316
317 assert_eq!(parent(text1).collect::<Vec<_>>(), vec![span]);
318 assert_eq!(
319 ancestor(text1).collect::<Vec<_>>(),
320 vec![span, body, html, root],
321 "ancestor must be nearest-parent-first, not root-first"
322 );
323 assert_eq!(
324 ancestor_or_self(text1).collect::<Vec<_>>(),
325 vec![text1, span, body, html, root]
326 );
327 }
328
329 #[test]
330 fn ancestor_of_root_is_empty() {
331 let f = build();
332 let root = f.doc.node(0);
333 assert_eq!(ancestor(root).collect::<Vec<_>>(), Vec::new());
334 }
335
336 #[test]
337 fn following_and_preceding_sibling_order_on_multiple_siblings() {
338 let f = build();
339 let comment = f.doc.node(f.comment);
340 assert_eq!(
342 following_sibling(comment).collect::<Vec<_>>(),
343 vec![f.doc.node(f.pi), f.doc.node(f.text2)]
344 );
345 assert_eq!(
346 preceding_sibling(comment).collect::<Vec<_>>(),
347 vec![f.doc.node(f.span), f.doc.node(f.text0)],
348 "preceding-sibling must be nearest-sibling-first"
349 );
350 }
351
352 #[test]
353 fn following_excludes_attribute_and_namespace_nodes() {
354 let f = build();
355 let span = f.doc.node(f.span);
356 let got: Vec<_> = following(span).collect();
362 assert_eq!(
363 got,
364 vec![f.doc.node(f.comment), f.doc.node(f.pi), f.doc.node(f.text2)]
365 );
366 assert!(!got.contains(&f.doc.node(f.span_attr)));
367 }
368
369 #[test]
370 fn preceding_excludes_attribute_and_namespace_nodes() {
371 let f = build();
372 let text0 = f.doc.node(f.text0);
373 let got: Vec<_> = preceding(text0).collect();
377 assert_eq!(got, Vec::new());
378 }
379
380 #[test]
381 fn preceding_excludes_a_preceding_siblings_own_attribute_node() {
382 let f = build();
383 let text1 = f.doc.node(f.text1);
384 let got: Vec<_> = preceding(text1).collect();
390 assert_eq!(got, vec![f.doc.node(f.text0)]);
391 assert!(!got.contains(&f.doc.node(f.span_attr)));
392 }
393
394 #[test]
395 fn preceding_reverse_document_order_excluding_ancestors() {
396 let f = build();
397 let text2 = f.doc.node(f.text2);
398 let got: Vec<_> = preceding(text2).collect();
399 assert_eq!(
400 got,
401 vec![
402 f.doc.node(f.pi),
403 f.doc.node(f.comment),
404 f.doc.node(f.text1),
405 f.doc.node(f.span),
406 f.doc.node(f.text0),
407 ],
408 "preceding must be reverse document order and exclude ancestors (body, html, root)"
409 );
410 assert!(!got.contains(&f.doc.node(f.body)));
411 assert!(!got.contains(&f.doc.node(f.html)));
412 }
413
414 #[test]
415 fn attribute_and_namespace_axes_on_element_with_both() {
416 let f = build();
417 let html = f.doc.node(f.html);
418 assert_eq!(
419 attribute(html).collect::<Vec<_>>(),
420 vec![f.doc.node(f.html_lang), f.doc.node(f.html_id)]
421 );
422 assert_eq!(
423 namespace(html).collect::<Vec<_>>(),
424 vec![f.doc.node(f.html_ns)]
425 );
426
427 let body = f.doc.node(f.body);
428 assert_eq!(
429 attribute(body).collect::<Vec<_>>(),
430 vec![f.doc.node(f.body_class)]
431 );
432 assert_eq!(
433 namespace(body).collect::<Vec<_>>(),
434 vec![f.doc.node(f.body_ns)]
435 );
436 }
437
438 #[test]
439 fn self_axis_is_trivial() {
440 let f = build();
441 let body = f.doc.node(f.body);
442 assert_eq!(self_axis(body).collect::<Vec<_>>(), vec![body]);
443 }
444
445 #[test]
446 fn attribute_node_has_no_attribute_namespace_or_sibling_axes() {
447 let f = build();
448 let lang = f.doc.node(f.html_lang);
449 assert_eq!(attribute(lang).collect::<Vec<_>>(), Vec::new());
450 assert_eq!(namespace(lang).collect::<Vec<_>>(), Vec::new());
451 assert_eq!(following_sibling(lang).collect::<Vec<_>>(), Vec::new());
452 assert_eq!(preceding_sibling(lang).collect::<Vec<_>>(), Vec::new());
453 }
454
455 #[test]
456 fn following_and_preceding_from_an_attribute_context_node() {
457 let f = build();
458 let lang = f.doc.node(f.html_lang);
459 assert_eq!(
462 following(lang).collect::<Vec<_>>(),
463 vec![
464 f.doc.node(f.body),
465 f.doc.node(f.text0),
466 f.doc.node(f.span),
467 f.doc.node(f.text1),
468 f.doc.node(f.comment),
469 f.doc.node(f.pi),
470 f.doc.node(f.text2),
471 ]
472 );
473 assert_eq!(preceding(lang).collect::<Vec<_>>(), Vec::new());
476 }
477}