1 | // Copyright 2021 The AccessKit Authors. All rights reserved. |
2 | // Licensed under the Apache License, Version 2.0 (found in |
3 | // the LICENSE-APACHE file) or the MIT license (found in |
4 | // the LICENSE-MIT file), at your option. |
5 | |
6 | // Derived from Chromium's accessibility abstraction. |
7 | // Copyright 2018 The Chromium Authors. All rights reserved. |
8 | // Use of this source code is governed by a BSD-style license that can be |
9 | // found in the LICENSE.chromium file. |
10 | |
11 | use core::iter::FusedIterator; |
12 | |
13 | use accesskit::NodeId; |
14 | |
15 | use crate::{filters::FilterResult, node::Node, tree::State as TreeState}; |
16 | |
17 | /// An iterator that yields following siblings of a node. |
18 | /// |
19 | /// This struct is created by the [`following_siblings`](Node::following_siblings) method on [`Node`]. |
20 | pub struct FollowingSiblings<'a> { |
21 | back_position: usize, |
22 | done: bool, |
23 | front_position: usize, |
24 | parent: Option<Node<'a>>, |
25 | } |
26 | |
27 | impl<'a> FollowingSiblings<'a> { |
28 | pub(crate) fn new(node: Node<'a>) -> Self { |
29 | let parent_and_index: Option<(Node<'_>, usize)> = node.parent_and_index(); |
30 | let (back_position: usize, front_position: usize, done: bool) = |
31 | if let Some((ref parent: &Node<'a>, index: usize)) = parent_and_index { |
32 | let back_position: usize = parent.data().children().len() - 1; |
33 | let front_position: usize = index + 1; |
34 | ( |
35 | back_position, |
36 | front_position, |
37 | front_position > back_position, |
38 | ) |
39 | } else { |
40 | (0, 0, true) |
41 | }; |
42 | Self { |
43 | back_position, |
44 | done, |
45 | front_position, |
46 | parent: parent_and_index.map(|(parent: Node<'a>, _)| parent), |
47 | } |
48 | } |
49 | } |
50 | |
51 | impl<'a> Iterator for FollowingSiblings<'a> { |
52 | type Item = NodeId; |
53 | |
54 | fn next(&mut self) -> Option<Self::Item> { |
55 | if self.done { |
56 | None |
57 | } else { |
58 | self.done = self.front_position == self.back_position; |
59 | let child = self |
60 | .parent |
61 | .as_ref()? |
62 | .data() |
63 | .children() |
64 | .get(self.front_position)?; |
65 | self.front_position += 1; |
66 | Some(*child) |
67 | } |
68 | } |
69 | |
70 | fn size_hint(&self) -> (usize, Option<usize>) { |
71 | let len = match self.done { |
72 | true => 0, |
73 | _ => self.back_position + 1 - self.front_position, |
74 | }; |
75 | (len, Some(len)) |
76 | } |
77 | } |
78 | |
79 | impl<'a> DoubleEndedIterator for FollowingSiblings<'a> { |
80 | fn next_back(&mut self) -> Option<Self::Item> { |
81 | if self.done { |
82 | None |
83 | } else { |
84 | self.done = self.back_position == self.front_position; |
85 | let child: &NodeId = self |
86 | .parent |
87 | .as_ref()? |
88 | .data() |
89 | .children() |
90 | .get(self.back_position)?; |
91 | self.back_position -= 1; |
92 | Some(*child) |
93 | } |
94 | } |
95 | } |
96 | |
97 | impl<'a> ExactSizeIterator for FollowingSiblings<'a> {} |
98 | |
99 | impl<'a> FusedIterator for FollowingSiblings<'a> {} |
100 | |
101 | /// An iterator that yields preceding siblings of a node. |
102 | /// |
103 | /// This struct is created by the [`preceding_siblings`](Node::preceding_siblings) method on [`Node`]. |
104 | pub struct PrecedingSiblings<'a> { |
105 | back_position: usize, |
106 | done: bool, |
107 | front_position: usize, |
108 | parent: Option<Node<'a>>, |
109 | } |
110 | |
111 | impl<'a> PrecedingSiblings<'a> { |
112 | pub(crate) fn new(node: Node<'a>) -> Self { |
113 | let parent_and_index: Option<(Node<'_>, usize)> = node.parent_and_index(); |
114 | let (back_position: usize, front_position: usize, done: bool) = if let Some((_, index: usize)) = parent_and_index { |
115 | let front_position: usize = index.saturating_sub(1); |
116 | (0, front_position, index == 0) |
117 | } else { |
118 | (0, 0, true) |
119 | }; |
120 | Self { |
121 | back_position, |
122 | done, |
123 | front_position, |
124 | parent: parent_and_index.map(|(parent: Node<'a>, _)| parent), |
125 | } |
126 | } |
127 | } |
128 | |
129 | impl<'a> Iterator for PrecedingSiblings<'a> { |
130 | type Item = NodeId; |
131 | |
132 | fn next(&mut self) -> Option<Self::Item> { |
133 | if self.done { |
134 | None |
135 | } else { |
136 | self.done = self.front_position == self.back_position; |
137 | let child = self |
138 | .parent |
139 | .as_ref()? |
140 | .data() |
141 | .children() |
142 | .get(self.front_position)?; |
143 | if !self.done { |
144 | self.front_position -= 1; |
145 | } |
146 | Some(*child) |
147 | } |
148 | } |
149 | |
150 | fn size_hint(&self) -> (usize, Option<usize>) { |
151 | let len = match self.done { |
152 | true => 0, |
153 | _ => self.front_position + 1 - self.back_position, |
154 | }; |
155 | (len, Some(len)) |
156 | } |
157 | } |
158 | |
159 | impl<'a> DoubleEndedIterator for PrecedingSiblings<'a> { |
160 | fn next_back(&mut self) -> Option<Self::Item> { |
161 | if self.done { |
162 | None |
163 | } else { |
164 | self.done = self.back_position == self.front_position; |
165 | let child: &NodeId = self |
166 | .parent |
167 | .as_ref()? |
168 | .data() |
169 | .children() |
170 | .get(self.back_position)?; |
171 | self.back_position += 1; |
172 | Some(*child) |
173 | } |
174 | } |
175 | } |
176 | |
177 | impl<'a> ExactSizeIterator for PrecedingSiblings<'a> {} |
178 | |
179 | impl<'a> FusedIterator for PrecedingSiblings<'a> {} |
180 | |
181 | fn next_filtered_sibling<'a>( |
182 | node: Option<Node<'a>>, |
183 | filter: &impl Fn(&Node) -> FilterResult, |
184 | ) -> Option<Node<'a>> { |
185 | let mut next = node; |
186 | let mut consider_children = false; |
187 | while let Some(current) = next { |
188 | if let Some(Some(child)) = consider_children.then(|| current.children().next()) { |
189 | let result = filter(&child); |
190 | next = Some(child); |
191 | if result == FilterResult::Include { |
192 | return next; |
193 | } |
194 | consider_children = result == FilterResult::ExcludeNode; |
195 | } else if let Some(sibling) = current.following_siblings().next() { |
196 | let result = filter(&sibling); |
197 | next = Some(sibling); |
198 | if result == FilterResult::Include { |
199 | return next; |
200 | } |
201 | if result == FilterResult::ExcludeNode { |
202 | consider_children = true; |
203 | } |
204 | } else { |
205 | let parent = current.parent(); |
206 | next = parent; |
207 | if let Some(parent) = parent { |
208 | if filter(&parent) != FilterResult::ExcludeNode { |
209 | return None; |
210 | } |
211 | consider_children = false; |
212 | } else { |
213 | return None; |
214 | } |
215 | } |
216 | } |
217 | None |
218 | } |
219 | |
220 | fn previous_filtered_sibling<'a>( |
221 | node: Option<Node<'a>>, |
222 | filter: &impl Fn(&Node) -> FilterResult, |
223 | ) -> Option<Node<'a>> { |
224 | let mut previous = node; |
225 | let mut consider_children = false; |
226 | while let Some(current) = previous { |
227 | if let Some(Some(child)) = consider_children.then(|| current.children().next_back()) { |
228 | let result = filter(&child); |
229 | previous = Some(child); |
230 | if result == FilterResult::Include { |
231 | return previous; |
232 | } |
233 | consider_children = result == FilterResult::ExcludeNode; |
234 | } else if let Some(sibling) = current.preceding_siblings().next() { |
235 | let result = filter(&sibling); |
236 | previous = Some(sibling); |
237 | if result == FilterResult::Include { |
238 | return previous; |
239 | } |
240 | if result == FilterResult::ExcludeNode { |
241 | consider_children = true; |
242 | } |
243 | } else { |
244 | let parent = current.parent(); |
245 | previous = parent; |
246 | if let Some(parent) = parent { |
247 | if filter(&parent) != FilterResult::ExcludeNode { |
248 | return None; |
249 | } |
250 | consider_children = false; |
251 | } else { |
252 | return None; |
253 | } |
254 | } |
255 | } |
256 | None |
257 | } |
258 | |
259 | /// An iterator that yields following siblings of a node according to the |
260 | /// specified filter. |
261 | /// |
262 | /// This struct is created by the [`following_filtered_siblings`](Node::following_filtered_siblings) method on [`Node`]. |
263 | pub struct FollowingFilteredSiblings<'a, Filter: Fn(&Node) -> FilterResult> { |
264 | filter: Filter, |
265 | back: Option<Node<'a>>, |
266 | done: bool, |
267 | front: Option<Node<'a>>, |
268 | } |
269 | |
270 | impl<'a, Filter: Fn(&Node) -> FilterResult> FollowingFilteredSiblings<'a, Filter> { |
271 | pub(crate) fn new(node: Node<'a>, filter: Filter) -> Self { |
272 | let front: Option> = next_filtered_sibling(node:Some(node), &filter); |
273 | let back: Option> = nodeOption> |
274 | .filtered_parent(&filter) |
275 | .and_then(|parent: Node<'a>| parent.last_filtered_child(&filter)); |
276 | Self { |
277 | filter, |
278 | back, |
279 | done: back.is_none() || front.is_none(), |
280 | front, |
281 | } |
282 | } |
283 | } |
284 | |
285 | impl<'a, Filter: Fn(&Node) -> FilterResult> Iterator for FollowingFilteredSiblings<'a, Filter> { |
286 | type Item = Node<'a>; |
287 | |
288 | fn next(&mut self) -> Option<Self::Item> { |
289 | if self.done { |
290 | None |
291 | } else { |
292 | self.done = self.front.as_ref().unwrap().id() == self.back.as_ref().unwrap().id(); |
293 | let current: Option> = self.front; |
294 | self.front = next_filtered_sibling(self.front, &self.filter); |
295 | current |
296 | } |
297 | } |
298 | } |
299 | |
300 | impl<'a, Filter: Fn(&Node) -> FilterResult> DoubleEndedIterator |
301 | for FollowingFilteredSiblings<'a, Filter> |
302 | { |
303 | fn next_back(&mut self) -> Option<Self::Item> { |
304 | if self.done { |
305 | None |
306 | } else { |
307 | self.done = self.back.as_ref().unwrap().id() == self.front.as_ref().unwrap().id(); |
308 | let current: Option> = self.back; |
309 | self.back = previous_filtered_sibling(self.back, &self.filter); |
310 | current |
311 | } |
312 | } |
313 | } |
314 | |
315 | impl<'a, Filter: Fn(&Node) -> FilterResult> FusedIterator |
316 | for FollowingFilteredSiblings<'a, Filter> |
317 | { |
318 | } |
319 | |
320 | /// An iterator that yields preceding siblings of a node according to the |
321 | /// specified filter. |
322 | /// |
323 | /// This struct is created by the [`preceding_filtered_siblings`](Node::preceding_filtered_siblings) method on [`Node`]. |
324 | pub struct PrecedingFilteredSiblings<'a, Filter: Fn(&Node) -> FilterResult> { |
325 | filter: Filter, |
326 | back: Option<Node<'a>>, |
327 | done: bool, |
328 | front: Option<Node<'a>>, |
329 | } |
330 | |
331 | impl<'a, Filter: Fn(&Node) -> FilterResult> PrecedingFilteredSiblings<'a, Filter> { |
332 | pub(crate) fn new(node: Node<'a>, filter: Filter) -> Self { |
333 | let front: Option> = previous_filtered_sibling(node:Some(node), &filter); |
334 | let back: Option> = nodeOption> |
335 | .filtered_parent(&filter) |
336 | .and_then(|parent: Node<'a>| parent.first_filtered_child(&filter)); |
337 | Self { |
338 | filter, |
339 | back, |
340 | done: back.is_none() || front.is_none(), |
341 | front, |
342 | } |
343 | } |
344 | } |
345 | |
346 | impl<'a, Filter: Fn(&Node) -> FilterResult> Iterator for PrecedingFilteredSiblings<'a, Filter> { |
347 | type Item = Node<'a>; |
348 | |
349 | fn next(&mut self) -> Option<Self::Item> { |
350 | if self.done { |
351 | None |
352 | } else { |
353 | self.done = self.front.as_ref().unwrap().id() == self.back.as_ref().unwrap().id(); |
354 | let current: Option> = self.front; |
355 | self.front = previous_filtered_sibling(self.front, &self.filter); |
356 | current |
357 | } |
358 | } |
359 | } |
360 | |
361 | impl<'a, Filter: Fn(&Node) -> FilterResult> DoubleEndedIterator |
362 | for PrecedingFilteredSiblings<'a, Filter> |
363 | { |
364 | fn next_back(&mut self) -> Option<Self::Item> { |
365 | if self.done { |
366 | None |
367 | } else { |
368 | self.done = self.back.as_ref().unwrap().id() == self.front.as_ref().unwrap().id(); |
369 | let current: Option> = self.back; |
370 | self.back = next_filtered_sibling(self.back, &self.filter); |
371 | current |
372 | } |
373 | } |
374 | } |
375 | |
376 | impl<'a, Filter: Fn(&Node) -> FilterResult> FusedIterator |
377 | for PrecedingFilteredSiblings<'a, Filter> |
378 | { |
379 | } |
380 | |
381 | /// An iterator that yields children of a node according to the specified |
382 | /// filter. |
383 | /// |
384 | /// This struct is created by the [`filtered_children`](Node::filtered_children) method on [`Node`]. |
385 | pub struct FilteredChildren<'a, Filter: Fn(&Node) -> FilterResult> { |
386 | filter: Filter, |
387 | back: Option<Node<'a>>, |
388 | done: bool, |
389 | front: Option<Node<'a>>, |
390 | } |
391 | |
392 | impl<'a, Filter: Fn(&Node) -> FilterResult> FilteredChildren<'a, Filter> { |
393 | pub(crate) fn new(node: Node<'a>, filter: Filter) -> Self { |
394 | let front: Option> = node.first_filtered_child(&filter); |
395 | let back: Option> = node.last_filtered_child(&filter); |
396 | Self { |
397 | filter, |
398 | back, |
399 | done: back.is_none() || front.is_none(), |
400 | front, |
401 | } |
402 | } |
403 | } |
404 | |
405 | impl<'a, Filter: Fn(&Node) -> FilterResult> Iterator for FilteredChildren<'a, Filter> { |
406 | type Item = Node<'a>; |
407 | |
408 | fn next(&mut self) -> Option<Self::Item> { |
409 | if self.done { |
410 | None |
411 | } else { |
412 | self.done = self.front.as_ref().unwrap().id() == self.back.as_ref().unwrap().id(); |
413 | let current: Option> = self.front; |
414 | self.front = next_filtered_sibling(self.front, &self.filter); |
415 | current |
416 | } |
417 | } |
418 | } |
419 | |
420 | impl<'a, Filter: Fn(&Node) -> FilterResult> DoubleEndedIterator for FilteredChildren<'a, Filter> { |
421 | fn next_back(&mut self) -> Option<Self::Item> { |
422 | if self.done { |
423 | None |
424 | } else { |
425 | self.done = self.back.as_ref().unwrap().id() == self.front.as_ref().unwrap().id(); |
426 | let current: Option> = self.back; |
427 | self.back = previous_filtered_sibling(self.back, &self.filter); |
428 | current |
429 | } |
430 | } |
431 | } |
432 | |
433 | impl<'a, Filter: Fn(&Node) -> FilterResult> FusedIterator for FilteredChildren<'a, Filter> {} |
434 | |
435 | pub(crate) enum LabelledBy<'a, Filter: Fn(&Node) -> FilterResult> { |
436 | FromDescendants(FilteredChildren<'a, Filter>), |
437 | Explicit { |
438 | ids: core::slice::Iter<'a, NodeId>, |
439 | tree_state: &'a TreeState, |
440 | }, |
441 | } |
442 | |
443 | impl<'a, Filter: Fn(&Node) -> FilterResult> Iterator for LabelledBy<'a, Filter> { |
444 | type Item = Node<'a>; |
445 | |
446 | fn next(&mut self) -> Option<Self::Item> { |
447 | match self { |
448 | Self::FromDescendants(iter: &mut FilteredChildren<'a, Filter>) => iter.next(), |
449 | Self::Explicit { ids: &mut Iter<'a, NodeId>, tree_state: &mut &'a State } => { |
450 | ids.next().map(|id: &'a NodeId| tree_state.node_by_id(*id).unwrap()) |
451 | } |
452 | } |
453 | } |
454 | |
455 | fn size_hint(&self) -> (usize, Option<usize>) { |
456 | match self { |
457 | Self::FromDescendants(iter: &FilteredChildren<'a, Filter>) => iter.size_hint(), |
458 | Self::Explicit { ids: &Iter<'a, NodeId>, .. } => ids.size_hint(), |
459 | } |
460 | } |
461 | } |
462 | |
463 | impl<'a, Filter: Fn(&Node) -> FilterResult> DoubleEndedIterator for LabelledBy<'a, Filter> { |
464 | fn next_back(&mut self) -> Option<Self::Item> { |
465 | match self { |
466 | Self::FromDescendants(iter: &mut FilteredChildren<'a, Filter>) => iter.next_back(), |
467 | Self::Explicit { ids: &mut Iter<'a, NodeId>, tree_state: &mut &'a State } => idsOption<&'a NodeId> |
468 | .next_back() |
469 | .map(|id: &'a NodeId| tree_state.node_by_id(*id).unwrap()), |
470 | } |
471 | } |
472 | } |
473 | |
474 | impl<'a, Filter: Fn(&Node) -> FilterResult> FusedIterator for LabelledBy<'a, Filter> {} |
475 | |
476 | #[cfg (test)] |
477 | mod tests { |
478 | use crate::tests::*; |
479 | use accesskit::NodeId; |
480 | use alloc::vec::Vec; |
481 | |
482 | #[test ] |
483 | fn following_siblings() { |
484 | let tree = test_tree(); |
485 | assert!(tree.state().root().following_siblings().next().is_none()); |
486 | assert_eq!(0, tree.state().root().following_siblings().len()); |
487 | assert_eq!( |
488 | [ |
489 | PARAGRAPH_1_IGNORED_ID, |
490 | PARAGRAPH_2_ID, |
491 | PARAGRAPH_3_IGNORED_ID |
492 | ], |
493 | tree.state() |
494 | .node_by_id(PARAGRAPH_0_ID) |
495 | .unwrap() |
496 | .following_siblings() |
497 | .map(|node| node.id()) |
498 | .collect::<Vec<NodeId>>()[..] |
499 | ); |
500 | assert_eq!( |
501 | 3, |
502 | tree.state() |
503 | .node_by_id(PARAGRAPH_0_ID) |
504 | .unwrap() |
505 | .following_siblings() |
506 | .len() |
507 | ); |
508 | assert!(tree |
509 | .state() |
510 | .node_by_id(PARAGRAPH_3_IGNORED_ID) |
511 | .unwrap() |
512 | .following_siblings() |
513 | .next() |
514 | .is_none()); |
515 | assert_eq!( |
516 | 0, |
517 | tree.state() |
518 | .node_by_id(PARAGRAPH_3_IGNORED_ID) |
519 | .unwrap() |
520 | .following_siblings() |
521 | .len() |
522 | ); |
523 | } |
524 | |
525 | #[test ] |
526 | fn following_siblings_reversed() { |
527 | let tree = test_tree(); |
528 | assert!(tree |
529 | .state() |
530 | .root() |
531 | .following_siblings() |
532 | .next_back() |
533 | .is_none()); |
534 | assert_eq!( |
535 | [ |
536 | PARAGRAPH_3_IGNORED_ID, |
537 | PARAGRAPH_2_ID, |
538 | PARAGRAPH_1_IGNORED_ID |
539 | ], |
540 | tree.state() |
541 | .node_by_id(PARAGRAPH_0_ID) |
542 | .unwrap() |
543 | .following_siblings() |
544 | .rev() |
545 | .map(|node| node.id()) |
546 | .collect::<Vec<NodeId>>()[..] |
547 | ); |
548 | assert!(tree |
549 | .state() |
550 | .node_by_id(PARAGRAPH_3_IGNORED_ID) |
551 | .unwrap() |
552 | .following_siblings() |
553 | .next_back() |
554 | .is_none()); |
555 | } |
556 | |
557 | #[test ] |
558 | fn preceding_siblings() { |
559 | let tree = test_tree(); |
560 | assert!(tree.state().root().preceding_siblings().next().is_none()); |
561 | assert_eq!(0, tree.state().root().preceding_siblings().len()); |
562 | assert_eq!( |
563 | [PARAGRAPH_2_ID, PARAGRAPH_1_IGNORED_ID, PARAGRAPH_0_ID], |
564 | tree.state() |
565 | .node_by_id(PARAGRAPH_3_IGNORED_ID) |
566 | .unwrap() |
567 | .preceding_siblings() |
568 | .map(|node| node.id()) |
569 | .collect::<Vec<NodeId>>()[..] |
570 | ); |
571 | assert_eq!( |
572 | 3, |
573 | tree.state() |
574 | .node_by_id(PARAGRAPH_3_IGNORED_ID) |
575 | .unwrap() |
576 | .preceding_siblings() |
577 | .len() |
578 | ); |
579 | assert!(tree |
580 | .state() |
581 | .node_by_id(PARAGRAPH_0_ID) |
582 | .unwrap() |
583 | .preceding_siblings() |
584 | .next() |
585 | .is_none()); |
586 | assert_eq!( |
587 | 0, |
588 | tree.state() |
589 | .node_by_id(PARAGRAPH_0_ID) |
590 | .unwrap() |
591 | .preceding_siblings() |
592 | .len() |
593 | ); |
594 | } |
595 | |
596 | #[test ] |
597 | fn preceding_siblings_reversed() { |
598 | let tree = test_tree(); |
599 | assert!(tree |
600 | .state() |
601 | .root() |
602 | .preceding_siblings() |
603 | .next_back() |
604 | .is_none()); |
605 | assert_eq!( |
606 | [PARAGRAPH_0_ID, PARAGRAPH_1_IGNORED_ID, PARAGRAPH_2_ID], |
607 | tree.state() |
608 | .node_by_id(PARAGRAPH_3_IGNORED_ID) |
609 | .unwrap() |
610 | .preceding_siblings() |
611 | .rev() |
612 | .map(|node| node.id()) |
613 | .collect::<Vec<NodeId>>()[..] |
614 | ); |
615 | assert!(tree |
616 | .state() |
617 | .node_by_id(PARAGRAPH_0_ID) |
618 | .unwrap() |
619 | .preceding_siblings() |
620 | .next_back() |
621 | .is_none()); |
622 | } |
623 | |
624 | #[test ] |
625 | fn following_filtered_siblings() { |
626 | let tree = test_tree(); |
627 | assert!(tree |
628 | .state() |
629 | .root() |
630 | .following_filtered_siblings(test_tree_filter) |
631 | .next() |
632 | .is_none()); |
633 | assert_eq!( |
634 | [LABEL_1_1_ID, PARAGRAPH_2_ID, LABEL_3_1_0_ID, BUTTON_3_2_ID], |
635 | tree.state() |
636 | .node_by_id(PARAGRAPH_0_ID) |
637 | .unwrap() |
638 | .following_filtered_siblings(test_tree_filter) |
639 | .map(|node| node.id()) |
640 | .collect::<Vec<NodeId>>()[..] |
641 | ); |
642 | assert_eq!( |
643 | [BUTTON_3_2_ID], |
644 | tree.state() |
645 | .node_by_id(LABEL_3_1_0_ID) |
646 | .unwrap() |
647 | .following_filtered_siblings(test_tree_filter) |
648 | .map(|node| node.id()) |
649 | .collect::<Vec<NodeId>>()[..] |
650 | ); |
651 | assert!(tree |
652 | .state() |
653 | .node_by_id(PARAGRAPH_3_IGNORED_ID) |
654 | .unwrap() |
655 | .following_filtered_siblings(test_tree_filter) |
656 | .next() |
657 | .is_none()); |
658 | } |
659 | |
660 | #[test ] |
661 | fn following_filtered_siblings_reversed() { |
662 | let tree = test_tree(); |
663 | assert!(tree |
664 | .state() |
665 | .root() |
666 | .following_filtered_siblings(test_tree_filter) |
667 | .next_back() |
668 | .is_none()); |
669 | assert_eq!( |
670 | [BUTTON_3_2_ID, LABEL_3_1_0_ID, PARAGRAPH_2_ID, LABEL_1_1_ID], |
671 | tree.state() |
672 | .node_by_id(PARAGRAPH_0_ID) |
673 | .unwrap() |
674 | .following_filtered_siblings(test_tree_filter) |
675 | .rev() |
676 | .map(|node| node.id()) |
677 | .collect::<Vec<NodeId>>()[..] |
678 | ); |
679 | assert_eq!( |
680 | [BUTTON_3_2_ID,], |
681 | tree.state() |
682 | .node_by_id(LABEL_3_1_0_ID) |
683 | .unwrap() |
684 | .following_filtered_siblings(test_tree_filter) |
685 | .rev() |
686 | .map(|node| node.id()) |
687 | .collect::<Vec<NodeId>>()[..] |
688 | ); |
689 | assert!(tree |
690 | .state() |
691 | .node_by_id(PARAGRAPH_3_IGNORED_ID) |
692 | .unwrap() |
693 | .following_filtered_siblings(test_tree_filter) |
694 | .next_back() |
695 | .is_none()); |
696 | } |
697 | |
698 | #[test ] |
699 | fn preceding_filtered_siblings() { |
700 | let tree = test_tree(); |
701 | assert!(tree |
702 | .state() |
703 | .root() |
704 | .preceding_filtered_siblings(test_tree_filter) |
705 | .next() |
706 | .is_none()); |
707 | assert_eq!( |
708 | [PARAGRAPH_2_ID, LABEL_1_1_ID, PARAGRAPH_0_ID], |
709 | tree.state() |
710 | .node_by_id(PARAGRAPH_3_IGNORED_ID) |
711 | .unwrap() |
712 | .preceding_filtered_siblings(test_tree_filter) |
713 | .map(|node| node.id()) |
714 | .collect::<Vec<NodeId>>()[..] |
715 | ); |
716 | assert_eq!( |
717 | [PARAGRAPH_2_ID, LABEL_1_1_ID, PARAGRAPH_0_ID], |
718 | tree.state() |
719 | .node_by_id(LABEL_3_1_0_ID) |
720 | .unwrap() |
721 | .preceding_filtered_siblings(test_tree_filter) |
722 | .map(|node| node.id()) |
723 | .collect::<Vec<NodeId>>()[..] |
724 | ); |
725 | assert!(tree |
726 | .state() |
727 | .node_by_id(PARAGRAPH_0_ID) |
728 | .unwrap() |
729 | .preceding_filtered_siblings(test_tree_filter) |
730 | .next() |
731 | .is_none()); |
732 | } |
733 | |
734 | #[test ] |
735 | fn preceding_filtered_siblings_reversed() { |
736 | let tree = test_tree(); |
737 | assert!(tree |
738 | .state() |
739 | .root() |
740 | .preceding_filtered_siblings(test_tree_filter) |
741 | .next_back() |
742 | .is_none()); |
743 | assert_eq!( |
744 | [PARAGRAPH_0_ID, LABEL_1_1_ID, PARAGRAPH_2_ID], |
745 | tree.state() |
746 | .node_by_id(PARAGRAPH_3_IGNORED_ID) |
747 | .unwrap() |
748 | .preceding_filtered_siblings(test_tree_filter) |
749 | .rev() |
750 | .map(|node| node.id()) |
751 | .collect::<Vec<NodeId>>()[..] |
752 | ); |
753 | assert_eq!( |
754 | [PARAGRAPH_0_ID, LABEL_1_1_ID, PARAGRAPH_2_ID], |
755 | tree.state() |
756 | .node_by_id(LABEL_3_1_0_ID) |
757 | .unwrap() |
758 | .preceding_filtered_siblings(test_tree_filter) |
759 | .rev() |
760 | .map(|node| node.id()) |
761 | .collect::<Vec<NodeId>>()[..] |
762 | ); |
763 | assert!(tree |
764 | .state() |
765 | .node_by_id(PARAGRAPH_0_ID) |
766 | .unwrap() |
767 | .preceding_filtered_siblings(test_tree_filter) |
768 | .next_back() |
769 | .is_none()); |
770 | } |
771 | |
772 | #[test ] |
773 | fn filtered_children() { |
774 | let tree = test_tree(); |
775 | assert_eq!( |
776 | [ |
777 | PARAGRAPH_0_ID, |
778 | LABEL_1_1_ID, |
779 | PARAGRAPH_2_ID, |
780 | LABEL_3_1_0_ID, |
781 | BUTTON_3_2_ID |
782 | ], |
783 | tree.state() |
784 | .root() |
785 | .filtered_children(test_tree_filter) |
786 | .map(|node| node.id()) |
787 | .collect::<Vec<NodeId>>()[..] |
788 | ); |
789 | assert!(tree |
790 | .state() |
791 | .node_by_id(PARAGRAPH_0_ID) |
792 | .unwrap() |
793 | .filtered_children(test_tree_filter) |
794 | .next() |
795 | .is_none()); |
796 | assert!(tree |
797 | .state() |
798 | .node_by_id(LABEL_0_0_IGNORED_ID) |
799 | .unwrap() |
800 | .filtered_children(test_tree_filter) |
801 | .next() |
802 | .is_none()); |
803 | } |
804 | |
805 | #[test ] |
806 | fn filtered_children_reversed() { |
807 | let tree = test_tree(); |
808 | assert_eq!( |
809 | [ |
810 | BUTTON_3_2_ID, |
811 | LABEL_3_1_0_ID, |
812 | PARAGRAPH_2_ID, |
813 | LABEL_1_1_ID, |
814 | PARAGRAPH_0_ID |
815 | ], |
816 | tree.state() |
817 | .root() |
818 | .filtered_children(test_tree_filter) |
819 | .rev() |
820 | .map(|node| node.id()) |
821 | .collect::<Vec<NodeId>>()[..] |
822 | ); |
823 | assert!(tree |
824 | .state() |
825 | .node_by_id(PARAGRAPH_0_ID) |
826 | .unwrap() |
827 | .filtered_children(test_tree_filter) |
828 | .next_back() |
829 | .is_none()); |
830 | assert!(tree |
831 | .state() |
832 | .node_by_id(LABEL_0_0_IGNORED_ID) |
833 | .unwrap() |
834 | .filtered_children(test_tree_filter) |
835 | .next_back() |
836 | .is_none()); |
837 | } |
838 | } |
839 | |