1use alloc::vec::Vec;
21use core::{
22 ops::{Index, IndexMut},
23 slice::Iter,
24};
25
26pub use self::node_id::NodeId;
27use crate::styled_dom::NodeHierarchyItem;
28
29pub type NodeDepths = Vec<(usize, NodeId)>;
31
32pub mod node_id {
34
35 use alloc::vec::Vec;
36 use core::{
37 fmt,
38 ops::{Add, AddAssign},
39 };
40
41 #[repr(C)]
70 #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
71 pub struct NodeId {
72 inner: usize,
75 }
76
77 impl NodeId {
78 pub const ZERO: Self = Self { inner: 0 };
80
81 #[inline]
83 #[must_use] pub const fn new(value: usize) -> Self {
84 Self { inner: value }
85 }
86
87 #[inline]
100 #[must_use] pub const fn from_usize(value: usize) -> Option<Self> {
101 match value {
102 0 => None,
103 i => Some(Self { inner: i - 1 }),
104 }
105 }
106
107 #[inline]
116 #[must_use] pub const fn into_raw(val: &Option<Self>) -> usize {
117 match val {
118 None => 0,
119 Some(s) => s.inner + 1,
120 }
121 }
122
123 #[inline]
127 #[must_use] pub const fn index(&self) -> usize {
128 self.inner
129 }
130 }
131
132 impl From<usize> for NodeId {
133 fn from(val: usize) -> Self {
134 Self::new(val)
135 }
136 }
137
138 impl From<NodeId> for usize {
139 fn from(val: NodeId) -> Self {
140 val.inner
141 }
142 }
143
144 impl Add<usize> for NodeId {
145 type Output = Self;
146 #[inline]
152 fn add(self, other: usize) -> Self {
153 Self::new(self.inner.saturating_add(other))
154 }
155 }
156
157 impl AddAssign<usize> for NodeId {
158 #[inline]
160 fn add_assign(&mut self, other: usize) {
161 *self = *self + other;
162 }
163 }
164
165 impl fmt::Display for NodeId {
166 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
167 write!(f, "{}", self.inner)
168 }
169 }
170
171 impl fmt::Debug for NodeId {
172 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173 write!(f, "NodeId({})", self.inner)
174 }
175 }
176}
177
178#[derive(Debug, Default, Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
180pub struct Node {
181 pub parent: Option<NodeId>,
182 pub previous_sibling: Option<NodeId>,
183 pub next_sibling: Option<NodeId>,
184 pub last_child: Option<NodeId>,
185 }
194
195impl Node {
196 pub const ROOT: Self = Self {
197 parent: None,
198 previous_sibling: None,
199 next_sibling: None,
200 last_child: None,
201 };
202
203 #[inline]
204 #[must_use] pub const fn has_parent(&self) -> bool {
205 self.parent.is_some()
206 }
207 #[inline]
208 #[must_use] pub const fn has_previous_sibling(&self) -> bool {
209 self.previous_sibling.is_some()
210 }
211 #[inline]
212 #[must_use] pub const fn has_next_sibling(&self) -> bool {
213 self.next_sibling.is_some()
214 }
215 #[inline]
216 #[must_use] pub const fn has_first_child(&self) -> bool {
217 self.last_child.is_some() }
219 #[inline]
220 #[must_use] pub const fn has_last_child(&self) -> bool {
221 self.last_child.is_some()
222 }
223
224 #[inline]
225 #[must_use] pub fn get_first_child(&self, current_node_id: NodeId) -> Option<NodeId> {
226 self.last_child.map(|_| current_node_id + 1)
228 }
229}
230
231#[derive(Debug, Default, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
235pub struct NodeHierarchy {
236 pub internal: Vec<Node>,
237}
238
239impl NodeHierarchy {
240 #[inline]
241 #[must_use] pub const fn new(data: Vec<Node>) -> Self {
242 Self { internal: data }
243 }
244
245 #[inline]
246 #[must_use] pub fn as_ref(&self) -> NodeHierarchyRef<'_> {
247 NodeHierarchyRef {
248 internal: &self.internal[..],
249 }
250 }
251
252}
253
254#[derive(Debug, PartialEq, Hash, Eq)]
258pub struct NodeHierarchyRef<'a> {
259 pub internal: &'a [Node],
260}
261
262impl<'a> NodeHierarchyRef<'a> {
263 #[inline]
264 #[must_use] pub const fn from_slice(data: &'a [Node]) -> Self {
265 NodeHierarchyRef { internal: data }
266 }
267
268 #[inline]
269 #[must_use] pub const fn len(&self) -> usize {
270 self.internal.len()
271 }
272
273 #[inline]
274 #[must_use] pub const fn is_empty(&self) -> bool {
275 self.internal.is_empty()
276 }
277
278 #[inline]
279 #[must_use] pub fn get(&self, id: NodeId) -> Option<&Node> {
280 self.internal.get(id.index())
281 }
282
283 #[inline]
284 #[must_use] pub const fn linear_iter(&self) -> LinearIterator {
285 LinearIterator {
286 arena_len: self.len(),
287 position: 0,
288 }
289 }
290
291 #[allow(clippy::iter_with_drain)]
299 #[must_use] pub fn get_parents_sorted_by_depth(&self) -> NodeDepths {
300 if self.is_empty() {
303 return Vec::new();
304 }
305
306 let root = NodeId::new(0);
307 let mut non_leaf_nodes = Vec::new();
308
309 if !self[root].has_first_child() {
315 return non_leaf_nodes;
316 }
317
318 let mut current_children = vec![(0, root)];
319 let mut next_children = Vec::new();
320 let mut depth = 1_usize;
321
322 loop {
323 for id in ¤t_children {
324 for child_id in id.1.children(self).filter(|id| self[*id].has_first_child()) {
325 next_children.push((depth, child_id));
326 }
327 }
328
329 non_leaf_nodes.extend(&mut current_children.drain(..));
330
331 if next_children.is_empty() {
332 break;
333 }
334 current_children.extend(&mut next_children.drain(..));
335 depth += 1;
336 }
337
338 non_leaf_nodes
339 }
340
341}
342
343#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
344pub struct NodeDataContainer<T> {
345 pub internal: Vec<T>,
346}
347
348impl<T> From<Vec<T>> for NodeDataContainer<T> {
349 fn from(v: Vec<T>) -> Self {
350 Self { internal: v }
351 }
352}
353
354#[derive(Debug, PartialEq, Hash, Eq, PartialOrd, Ord)]
355pub struct NodeDataContainerRef<'a, T> {
356 pub internal: &'a [T],
357}
358
359#[derive(Debug, PartialEq, Hash, Eq, PartialOrd, Ord)]
360pub struct NodeDataContainerRefMut<'a, T> {
361 pub internal: &'a mut [T],
362}
363
364impl<T> Default for NodeDataContainer<T> {
365 fn default() -> Self {
366 Self {
367 internal: Vec::new(),
368 }
369 }
370}
371
372impl Index<NodeId> for NodeHierarchyRef<'_> {
373 type Output = Node;
374
375 #[inline]
376 fn index(&self, node_id: NodeId) -> &Node {
377 &self.internal[node_id.index()]
378 }
379}
380
381impl<T> NodeDataContainer<T> {
382 #[inline]
383 #[must_use] pub const fn new(data: Vec<T>) -> Self {
384 Self { internal: data }
385 }
386
387 #[inline]
388 #[must_use] pub const fn is_empty(&self) -> bool {
389 self.internal.is_empty()
390 }
391
392 #[inline]
393 #[must_use] pub fn as_ref(&self) -> NodeDataContainerRef<'_, T> {
394 NodeDataContainerRef {
395 internal: &self.internal[..],
396 }
397 }
398
399 #[inline]
400 pub fn as_ref_mut(&mut self) -> NodeDataContainerRefMut<'_, T> {
401 NodeDataContainerRefMut {
402 internal: &mut self.internal[..],
403 }
404 }
405
406 #[inline]
407 #[must_use] pub const fn len(&self) -> usize {
408 self.internal.len()
409 }
410}
411
412impl<'a, T: 'a> NodeDataContainerRefMut<'a, T> {
413 #[inline]
414 pub const fn from_slice(data: &'a mut [T]) -> Self {
415 NodeDataContainerRefMut { internal: data }
416 }
417}
418
419impl<'a, T: 'a> NodeDataContainerRefMut<'a, T> {
420 #[inline]
421 pub fn get_mut(&mut self, id: NodeId) -> Option<&mut T> {
422 self.internal.get_mut(id.index())
423 }
424}
425
426impl<'a, T: Send + 'a> NodeDataContainerRef<'a, T> {
427 pub fn transform_nodeid_optional<U: Send, F>(
428 &self,
429 closure: F,
430 ) -> NodeDataContainer<U>
431 where
432 F: Send + Sync + Fn(NodeId) -> Option<U>,
433 {
434 let len = self.len();
435 NodeDataContainer {
436 internal: (0..len)
437 .filter_map(|node_id| closure(NodeId::new(node_id)))
438 .collect::<Vec<U>>(),
439 }
440 }
441}
442
443impl<'a, T> IntoIterator for &NodeDataContainerRef<'a, T> {
444 type Item = &'a T;
445 type IntoIter = Iter<'a, T>;
446 #[inline]
447 fn into_iter(self) -> Self::IntoIter {
448 self.internal.iter()
449 }
450}
451
452impl<'a, T: 'a> NodeDataContainerRef<'a, T> {
453 #[inline]
454 pub const fn from_slice(data: &'a [T]) -> Self {
455 NodeDataContainerRef { internal: data }
456 }
457
458 #[inline]
459 #[must_use] pub const fn len(&self) -> usize {
460 self.internal.len()
461 }
462
463 #[inline]
464 #[must_use] pub const fn is_empty(&self) -> bool {
465 self.internal.is_empty()
466 }
467
468 #[inline]
469 #[must_use] pub fn get(&self, id: NodeId) -> Option<&T> {
470 self.internal.get(id.index())
471 }
472
473 #[inline]
474 pub fn iter(&self) -> Iter<'_, T> {
475 self.internal.iter()
476 }
477
478 #[inline]
479 #[must_use] pub const fn linear_iter(&self) -> LinearIterator {
480 LinearIterator {
481 arena_len: self.len(),
482 position: 0,
483 }
484 }
485}
486
487impl<T> Index<NodeId> for NodeDataContainerRef<'_, T> {
488 type Output = T;
489
490 #[inline]
491 fn index(&self, node_id: NodeId) -> &T {
492 &self.internal[node_id.index()]
493 }
494}
495
496impl<T> Index<NodeId> for NodeDataContainerRefMut<'_, T> {
497 type Output = T;
498
499 #[inline]
500 fn index(&self, node_id: NodeId) -> &T {
501 &self.internal[node_id.index()]
502 }
503}
504
505impl<T> IndexMut<NodeId> for NodeDataContainerRefMut<'_, T> {
506 #[inline]
507 fn index_mut(&mut self, node_id: NodeId) -> &mut T {
508 &mut self.internal[node_id.index()]
509 }
510}
511
512impl NodeId {
513 #[inline]
517 #[must_use] pub const fn preceding_siblings<'a>(
518 self,
519 node_hierarchy: &'a NodeHierarchyRef<'a>,
520 ) -> PrecedingSiblings<'a> {
521 PrecedingSiblings {
522 node_hierarchy,
523 node: Some(self),
524 }
525 }
526
527 #[inline]
529 #[must_use] pub fn children<'a>(self, node_hierarchy: &'a NodeHierarchyRef<'a>) -> Children<'a> {
530 Children {
531 node_hierarchy,
532 node: node_hierarchy[self].get_first_child(self),
533 }
534 }
535}
536
537macro_rules! impl_node_iterator {
538 ($name:ident, $next:expr) => {
539 impl Iterator for $name<'_> {
540 type Item = NodeId;
541
542 fn next(&mut self) -> Option<NodeId> {
543 match self.node.take() {
544 Some(node) => {
545 self.node = $next(&self.node_hierarchy[node]);
546 Some(node)
547 }
548 None => None,
549 }
550 }
551 }
552 };
553}
554
555#[derive(Debug, Clone)]
558pub struct LinearIterator {
559 arena_len: usize,
560 position: usize,
561}
562
563impl Iterator for LinearIterator {
564 type Item = NodeId;
565
566 fn next(&mut self) -> Option<NodeId> {
567 if self.arena_len < 1 || self.position > (self.arena_len - 1) {
568 None
569 } else {
570 let new_id = Some(NodeId::new(self.position));
571 self.position += 1;
572 new_id
573 }
574 }
575}
576
577#[derive(Debug)]
579pub struct PrecedingSiblings<'a> {
580 node_hierarchy: &'a NodeHierarchyRef<'a>,
581 node: Option<NodeId>,
582}
583
584impl_node_iterator!(PrecedingSiblings, |node: &Node| node.previous_sibling);
585
586#[derive(Debug)]
588pub struct AzChildren<'a> {
589 node_hierarchy: &'a NodeDataContainerRef<'a, NodeHierarchyItem>,
590 node: Option<NodeId>,
591}
592
593impl Iterator for AzChildren<'_> {
594 type Item = NodeId;
595
596 fn next(&mut self) -> Option<NodeId> {
597 match self.node.take() {
598 Some(node) => {
599 self.node = self.node_hierarchy[node].next_sibling_id();
600 Some(node)
601 }
602 None => None,
603 }
604 }
605}
606
607#[derive(Debug)]
609pub struct AzReverseChildren<'a> {
610 node_hierarchy: &'a NodeDataContainerRef<'a, NodeHierarchyItem>,
611 node: Option<NodeId>,
612}
613
614impl Iterator for AzReverseChildren<'_> {
615 type Item = NodeId;
616
617 fn next(&mut self) -> Option<NodeId> {
618 match self.node.take() {
619 Some(node) => {
620 self.node = self.node_hierarchy[node].previous_sibling_id();
621 Some(node)
622 }
623 None => None,
624 }
625 }
626}
627
628impl NodeId {
629 pub fn get_nearest_matching_parent<'a, F>(
634 self,
635 node_hierarchy: &'a NodeDataContainerRef<'a, NodeHierarchyItem>,
636 predicate: F,
637 ) -> Option<Self>
638 where
639 F: Fn(Self) -> bool,
640 {
641 let node_count = node_hierarchy.internal.len();
646 let mut current_node = node_hierarchy.internal.get(self.index())?.parent_id()?;
647 for _ in 0..node_count {
648 if predicate(current_node) {
649 return Some(current_node);
650 }
651 current_node = node_hierarchy.internal.get(current_node.index())?.parent_id()?;
652 }
653 None
654 }
655
656 #[inline]
658 #[must_use] pub fn az_children_collect<'a>(
659 self,
660 node_hierarchy: &'a NodeDataContainerRef<'a, NodeHierarchyItem>,
661 ) -> Vec<Self> {
662 self.az_children(node_hierarchy).collect()
663 }
664
665 #[inline]
667 #[must_use] pub fn az_children<'a>(
668 self,
669 node_hierarchy: &'a NodeDataContainerRef<'a, NodeHierarchyItem>,
670 ) -> AzChildren<'a> {
671 AzChildren {
672 node_hierarchy,
673 node: node_hierarchy[self].first_child_id(self),
674 }
675 }
676
677 #[inline]
679 #[must_use] pub fn az_reverse_children<'a>(
680 self,
681 node_hierarchy: &'a NodeDataContainerRef<'a, NodeHierarchyItem>,
682 ) -> AzReverseChildren<'a> {
683 AzReverseChildren {
684 node_hierarchy,
685 node: node_hierarchy[self].last_child_id(),
686 }
687 }
688}
689
690#[derive(Debug)]
692pub struct Children<'a> {
693 node_hierarchy: &'a NodeHierarchyRef<'a>,
694 node: Option<NodeId>,
695}
696
697impl_node_iterator!(Children, |node: &Node| node.next_sibling);
698
699#[cfg(test)]
700mod audit_tests {
701 use super::*;
702 use crate::styled_dom::NodeHierarchyItem;
703
704 #[test]
705 fn parents_by_depth_empty_hierarchy() {
706 let h = NodeHierarchy::new(Vec::new());
707 assert!(h.as_ref().get_parents_sorted_by_depth().is_empty());
708 }
709
710 #[test]
711 fn parents_by_depth_single_childless_root() {
712 let h = NodeHierarchy::new(vec![Node::ROOT]);
714 assert!(h.as_ref().get_parents_sorted_by_depth().is_empty());
715 }
716
717 #[test]
718 fn parents_by_depth_root_with_child() {
719 let root = Node {
720 parent: None,
721 previous_sibling: None,
722 next_sibling: None,
723 last_child: Some(NodeId::new(1)),
724 };
725 let child = Node {
726 parent: Some(NodeId::new(0)),
727 ..Node::ROOT
728 };
729 let h = NodeHierarchy::new(vec![root, child]);
730 let parents = h.as_ref().get_parents_sorted_by_depth();
731 assert_eq!(parents, vec![(0, NodeId::new(0))]);
732 }
733
734 fn item(parent: Option<usize>) -> NodeHierarchyItem {
735 NodeHierarchyItem {
736 parent: parent.map_or(0, |p| p + 1),
737 previous_sibling: 0,
738 next_sibling: 0,
739 last_child: 0,
740 }
741 }
742
743 #[test]
744 fn nearest_matching_parent_cycle_terminates() {
745 let items = vec![item(None), item(Some(2)), item(Some(1))];
747 let cont = NodeDataContainerRef { internal: &items };
748 let r = NodeId::new(1).get_nearest_matching_parent(&cont, |_| false);
749 assert_eq!(r, None);
750 }
751
752 #[test]
753 fn nearest_matching_parent_finds_match() {
754 let items = vec![item(None), item(Some(0)), item(Some(1))];
756 let cont = NodeDataContainerRef { internal: &items };
757 let r = NodeId::new(2).get_nearest_matching_parent(&cont, |n| n == NodeId::new(0));
758 assert_eq!(r, Some(NodeId::new(0)));
759 }
760
761 #[test]
762 fn node_id_add_saturates() {
763 assert_eq!(NodeId::new(5) + 3, NodeId::new(8));
764 assert_eq!(NodeId::new(usize::MAX) + 1, NodeId::new(usize::MAX));
765 let mut n = NodeId::new(usize::MAX);
766 n += 10;
767 assert_eq!(n, NodeId::new(usize::MAX));
768 }
769}
770
771#[cfg(test)]
772#[allow(clippy::pedantic, clippy::nursery)]
773mod autotest_generated {
774 use core::sync::atomic::{AtomicUsize, Ordering};
775
776 use super::*;
777 use crate::styled_dom::NodeHierarchyItem;
778
779 fn tree_5() -> Vec<Node> {
792 vec![
793 Node {
794 parent: None,
795 previous_sibling: None,
796 next_sibling: None,
797 last_child: Some(NodeId::new(4)),
798 },
799 Node {
800 parent: Some(NodeId::new(0)),
801 previous_sibling: None,
802 next_sibling: Some(NodeId::new(4)),
803 last_child: Some(NodeId::new(3)),
804 },
805 Node {
806 parent: Some(NodeId::new(1)),
807 previous_sibling: None,
808 next_sibling: Some(NodeId::new(3)),
809 last_child: None,
810 },
811 Node {
812 parent: Some(NodeId::new(1)),
813 previous_sibling: Some(NodeId::new(2)),
814 next_sibling: None,
815 last_child: None,
816 },
817 Node {
818 parent: Some(NodeId::new(0)),
819 previous_sibling: Some(NodeId::new(1)),
820 next_sibling: None,
821 last_child: None,
822 },
823 ]
824 }
825
826 fn items(nodes: &[Node]) -> Vec<NodeHierarchyItem> {
827 nodes.iter().copied().map(NodeHierarchyItem::from).collect()
828 }
829
830 #[test]
835 fn node_id_new_roundtrips_index_at_boundaries() {
836 for v in [0_usize, 1, 2, 42, usize::MAX - 1, usize::MAX] {
837 assert_eq!(NodeId::new(v).index(), v, "index() must echo new()");
838 }
839 }
840
841 #[test]
842 fn node_id_zero_matches_new_zero() {
843 assert_eq!(NodeId::ZERO, NodeId::new(0));
844 assert_eq!(NodeId::ZERO.index(), 0);
845 }
846
847 #[test]
848 fn node_id_usize_conversions_are_lossless() {
849 for v in [0_usize, 7, usize::MAX] {
850 let id: NodeId = v.into();
851 let back: usize = id.into();
852 assert_eq!(back, v);
853 }
854 }
855
856 #[test]
857 fn node_id_ordering_follows_index() {
858 assert!(NodeId::new(0) < NodeId::new(1));
859 assert!(NodeId::new(1) < NodeId::new(usize::MAX));
860 assert_eq!(NodeId::new(3), NodeId::new(3));
861 }
862
863 #[test]
868 fn from_usize_zero_is_none_and_shifts_by_one() {
869 assert_eq!(NodeId::from_usize(0), None);
870 assert_eq!(NodeId::from_usize(1), Some(NodeId::new(0)));
871 assert_eq!(NodeId::from_usize(2), Some(NodeId::new(1)));
872 assert_eq!(
874 NodeId::from_usize(usize::MAX),
875 Some(NodeId::new(usize::MAX - 1))
876 );
877 }
878
879 #[test]
880 fn into_raw_encodes_none_as_zero() {
881 assert_eq!(NodeId::into_raw(&None), 0);
882 assert_eq!(NodeId::into_raw(&Some(NodeId::new(0))), 1);
883 assert_eq!(NodeId::into_raw(&Some(NodeId::new(41))), 42);
884 assert_eq!(NodeId::into_raw(&Some(NodeId::new(usize::MAX - 1))), usize::MAX);
886 }
887
888 #[test]
889 fn encode_decode_roundtrip_is_identity() {
890 for x in [
892 None,
893 Some(NodeId::new(0)),
894 Some(NodeId::new(1)),
895 Some(NodeId::new(9_999)),
896 Some(NodeId::new(usize::MAX - 1)),
897 ] {
898 assert_eq!(NodeId::from_usize(NodeId::into_raw(&x)), x, "decode(encode({x:?}))");
899 }
900 for n in [0_usize, 1, 2, 12_345, usize::MAX] {
902 assert_eq!(NodeId::into_raw(&NodeId::from_usize(n)), n, "encode(decode({n}))");
903 }
904 }
905
906 #[cfg(feature = "std")]
913 #[test]
914 fn into_raw_at_usize_max_never_yields_a_bogus_node() {
915 let encoded = std::panic::catch_unwind(|| NodeId::into_raw(&Some(NodeId::new(usize::MAX))));
916 match encoded {
917 Err(_) => {}
919 Ok(raw) => {
921 assert_eq!(raw, 0, "wrapped encode must not alias a real node id");
922 assert_eq!(NodeId::from_usize(raw), None);
923 }
924 }
925 }
926
927 #[test]
932 fn node_id_display_and_debug_are_well_formed() {
933 assert_eq!(alloc::format!("{}", NodeId::new(0)), "0");
934 assert_eq!(alloc::format!("{}", NodeId::new(7)), "7");
935 assert_eq!(alloc::format!("{:?}", NodeId::new(7)), "NodeId(7)");
936 let max = alloc::format!("{}", NodeId::new(usize::MAX));
938 assert_eq!(max, alloc::format!("{}", usize::MAX));
939 assert!(!max.is_empty());
940 assert_eq!(
941 alloc::format!("{:?}", NodeId::new(usize::MAX)),
942 alloc::format!("NodeId({})", usize::MAX)
943 );
944 }
945
946 #[test]
951 fn node_root_and_default_have_no_relations() {
952 for n in [Node::ROOT, Node::default()] {
953 assert!(!n.has_parent());
954 assert!(!n.has_previous_sibling());
955 assert!(!n.has_next_sibling());
956 assert!(!n.has_first_child());
957 assert!(!n.has_last_child());
958 assert_eq!(n.get_first_child(NodeId::new(0)), None);
959 }
960 assert_eq!(Node::default(), Node::ROOT);
961 }
962
963 #[test]
964 fn node_predicates_report_each_populated_field() {
965 let full = Node {
966 parent: Some(NodeId::new(1)),
967 previous_sibling: Some(NodeId::new(2)),
968 next_sibling: Some(NodeId::new(3)),
969 last_child: Some(NodeId::new(4)),
970 };
971 assert!(full.has_parent());
972 assert!(full.has_previous_sibling());
973 assert!(full.has_next_sibling());
974 assert!(full.has_first_child());
975 assert!(full.has_last_child());
976 }
977
978 #[test]
981 fn has_first_child_always_agrees_with_has_last_child() {
982 for last_child in [None, Some(NodeId::new(0)), Some(NodeId::new(usize::MAX))] {
983 let n = Node {
984 last_child,
985 ..Node::ROOT
986 };
987 assert_eq!(n.has_first_child(), n.has_last_child());
988 assert_eq!(n.has_first_child(), last_child.is_some());
989 }
990 }
991
992 #[test]
993 fn get_first_child_is_self_plus_one_and_saturates() {
994 let parent = Node {
995 last_child: Some(NodeId::new(9)),
996 ..Node::ROOT
997 };
998 assert_eq!(parent.get_first_child(NodeId::new(0)), Some(NodeId::new(1)));
999 assert_eq!(parent.get_first_child(NodeId::new(5)), Some(NodeId::new(6)));
1000 assert_eq!(
1003 parent.get_first_child(NodeId::new(usize::MAX)),
1004 Some(NodeId::new(usize::MAX))
1005 );
1006 assert_eq!(Node::ROOT.get_first_child(NodeId::new(usize::MAX)), None);
1008 }
1009
1010 #[test]
1015 fn hierarchy_new_preserves_len_and_contents() {
1016 let h = NodeHierarchy::new(tree_5());
1017 assert_eq!(h.as_ref().len(), 5);
1018 assert!(!h.as_ref().is_empty());
1019 assert_eq!(h.as_ref().get(NodeId::new(0)), Some(&tree_5()[0]));
1020 assert_eq!(h.as_ref().internal, &tree_5()[..]);
1021 }
1022
1023 #[test]
1024 fn empty_hierarchy_is_empty_everywhere() {
1025 let h = NodeHierarchy::new(Vec::new());
1026 let r = h.as_ref();
1027 assert_eq!(r.len(), 0);
1028 assert!(r.is_empty());
1029 assert_eq!(r.get(NodeId::new(0)), None);
1030 assert_eq!(r.linear_iter().count(), 0);
1031 assert!(r.get_parents_sorted_by_depth().is_empty());
1032
1033 let default = NodeHierarchy::default();
1034 assert!(default.as_ref().is_empty());
1035 }
1036
1037 #[test]
1038 fn hierarchy_ref_from_slice_matches_len_and_emptiness() {
1039 let empty: [Node; 0] = [];
1040 assert_eq!(NodeHierarchyRef::from_slice(&empty).len(), 0);
1041 assert!(NodeHierarchyRef::from_slice(&empty).is_empty());
1042
1043 let nodes = tree_5();
1044 let r = NodeHierarchyRef::from_slice(&nodes);
1045 assert_eq!(r.len(), 5);
1046 assert!(!r.is_empty());
1047 }
1048
1049 #[test]
1052 fn hierarchy_ref_get_out_of_bounds_returns_none() {
1053 let nodes = tree_5();
1054 let r = NodeHierarchyRef::from_slice(&nodes);
1055 assert!(r.get(NodeId::new(4)).is_some());
1056 assert_eq!(r.get(NodeId::new(5)), None);
1057 assert_eq!(r.get(NodeId::new(usize::MAX)), None);
1058 }
1059
1060 #[test]
1063 #[should_panic]
1064 fn hierarchy_ref_index_out_of_bounds_panics() {
1065 let nodes = tree_5();
1066 let r = NodeHierarchyRef::from_slice(&nodes);
1067 let _ = &r[NodeId::new(5)];
1068 }
1069
1070 #[test]
1071 fn hierarchy_linear_iter_walks_every_index_in_order() {
1072 let nodes = tree_5();
1073 let r = NodeHierarchyRef::from_slice(&nodes);
1074 let ids: Vec<NodeId> = r.linear_iter().collect();
1075 assert_eq!(
1076 ids,
1077 (0..5).map(NodeId::new).collect::<Vec<_>>(),
1078 "linear_iter must yield 0..len exactly once, in order"
1079 );
1080 }
1081
1082 #[test]
1085 fn linear_iter_len_zero_and_one_boundaries() {
1086 let empty: [Node; 0] = [];
1087 assert_eq!(
1088 NodeHierarchyRef::from_slice(&empty).linear_iter().next(),
1089 None
1090 );
1091
1092 let one = [Node::ROOT];
1093 let mut it = NodeHierarchyRef::from_slice(&one).linear_iter();
1094 assert_eq!(it.next(), Some(NodeId::new(0)));
1095 assert_eq!(it.next(), None);
1096 assert_eq!(it.next(), None);
1098 }
1099
1100 #[test]
1101 fn get_parents_sorted_by_depth_is_depth_ordered_and_leaf_free() {
1102 let h = NodeHierarchy::new(tree_5());
1103 let parents = h.as_ref().get_parents_sorted_by_depth();
1104 assert_eq!(parents, vec![(0, NodeId::new(0)), (1, NodeId::new(1))]);
1106 assert!(parents.windows(2).all(|w| w[0].0 <= w[1].0));
1108 }
1109
1110 #[test]
1115 fn children_yields_direct_children_only() {
1116 let nodes = tree_5();
1117 let r = NodeHierarchyRef::from_slice(&nodes);
1118 assert_eq!(
1119 NodeId::new(0).children(&r).collect::<Vec<_>>(),
1120 vec![NodeId::new(1), NodeId::new(4)]
1121 );
1122 assert_eq!(
1123 NodeId::new(1).children(&r).collect::<Vec<_>>(),
1124 vec![NodeId::new(2), NodeId::new(3)]
1125 );
1126 assert_eq!(NodeId::new(2).children(&r).count(), 0);
1128 assert_eq!(NodeId::new(4).children(&r).count(), 0);
1129 }
1130
1131 #[test]
1132 #[should_panic]
1133 fn children_of_out_of_bounds_node_panics_loudly() {
1134 let nodes = tree_5();
1135 let r = NodeHierarchyRef::from_slice(&nodes);
1136 let _ = NodeId::new(99).children(&r);
1139 }
1140
1141 #[test]
1142 fn preceding_siblings_starts_with_self_then_walks_backwards() {
1143 let nodes = tree_5();
1144 let r = NodeHierarchyRef::from_slice(&nodes);
1145 assert_eq!(
1146 NodeId::new(3).preceding_siblings(&r).collect::<Vec<_>>(),
1147 vec![NodeId::new(3), NodeId::new(2)],
1148 "the iterator includes the node itself first"
1149 );
1150 assert_eq!(
1152 NodeId::new(2).preceding_siblings(&r).collect::<Vec<_>>(),
1153 vec![NodeId::new(2)]
1154 );
1155 }
1156
1157 #[test]
1162 fn preceding_siblings_on_self_cycle_repeats_without_panicking() {
1163 let nodes = vec![
1164 Node::ROOT,
1165 Node {
1166 parent: Some(NodeId::new(0)),
1167 previous_sibling: Some(NodeId::new(1)), next_sibling: None,
1169 last_child: None,
1170 },
1171 ];
1172 let r = NodeHierarchyRef::from_slice(&nodes);
1173 let first_4: Vec<NodeId> = NodeId::new(1).preceding_siblings(&r).take(4).collect();
1174 assert_eq!(first_4, vec![NodeId::new(1); 4]);
1175 }
1176
1177 #[test]
1182 fn data_container_new_and_len_track_the_vec() {
1183 let c = NodeDataContainer::new(vec![10_u32, 20, 30]);
1184 assert_eq!(c.len(), 3);
1185 assert!(!c.is_empty());
1186 assert_eq!(c.as_ref().len(), 3);
1187 assert_eq!(c.as_ref().get(NodeId::new(2)), Some(&30));
1188
1189 let empty: NodeDataContainer<u32> = NodeDataContainer::new(Vec::new());
1190 assert_eq!(empty.len(), 0);
1191 assert!(empty.is_empty());
1192 assert!(empty.as_ref().is_empty());
1193 assert_eq!(empty.as_ref().get(NodeId::new(0)), None);
1194
1195 assert!(NodeDataContainer::<u32>::default().is_empty());
1197 assert_eq!(NodeDataContainer::from(vec![1_u32, 2]).len(), 2);
1198 }
1199
1200 #[test]
1201 fn data_container_ref_get_out_of_bounds_returns_none() {
1202 let data = [1_u8, 2, 3];
1203 let r = NodeDataContainerRef::from_slice(&data);
1204 assert_eq!(r.get(NodeId::new(0)), Some(&1));
1205 assert_eq!(r.get(NodeId::new(3)), None);
1206 assert_eq!(r.get(NodeId::new(usize::MAX)), None);
1207 }
1208
1209 #[test]
1210 #[should_panic]
1211 fn data_container_ref_index_out_of_bounds_panics() {
1212 let data = [1_u8, 2, 3];
1213 let r = NodeDataContainerRef::from_slice(&data);
1214 let _ = &r[NodeId::new(3)];
1215 }
1216
1217 #[test]
1218 fn data_container_ref_iterators_cover_all_elements() {
1219 let data = [1_u8, 2, 3];
1220 let r = NodeDataContainerRef::from_slice(&data);
1221 assert_eq!(r.iter().copied().collect::<Vec<_>>(), vec![1, 2, 3]);
1222 assert_eq!((&r).into_iter().copied().collect::<Vec<_>>(), vec![1, 2, 3]);
1223 assert_eq!(r.linear_iter().count(), 3);
1224
1225 let empty: [u8; 0] = [];
1226 let e = NodeDataContainerRef::from_slice(&empty);
1227 assert_eq!(e.len(), 0);
1228 assert!(e.is_empty());
1229 assert_eq!(e.iter().count(), 0);
1230 assert_eq!(e.linear_iter().next(), None);
1231 }
1232
1233 #[test]
1234 fn data_container_ref_mut_get_mut_is_bounds_checked() {
1235 let mut c = NodeDataContainer::new(vec![1_u32, 2, 3]);
1236 let mut m = c.as_ref_mut();
1237 assert_eq!(m.get_mut(NodeId::new(3)), None);
1238 assert_eq!(m.get_mut(NodeId::new(usize::MAX)), None);
1239 *m.get_mut(NodeId::new(1)).unwrap() = 99;
1240 m[NodeId::new(2)] = 7;
1241 assert_eq!(m[NodeId::new(2)], 7);
1242 assert_eq!(c.internal, vec![1, 99, 7]);
1243 }
1244
1245 #[test]
1246 fn data_container_ref_mut_from_slice_on_empty_slice() {
1247 let mut empty: [u32; 0] = [];
1248 let mut m = NodeDataContainerRefMut::from_slice(&mut empty);
1249 assert_eq!(m.get_mut(NodeId::new(0)), None);
1250 assert!(m.internal.is_empty());
1251 }
1252
1253 #[test]
1254 #[should_panic]
1255 fn data_container_ref_mut_index_out_of_bounds_panics() {
1256 let mut data = [1_u8, 2];
1257 let m = NodeDataContainerRefMut::from_slice(&mut data);
1258 let _ = &m[NodeId::new(2)];
1259 }
1260
1261 #[test]
1266 fn transform_nodeid_optional_maps_every_index() {
1267 let data = [0_u32; 4];
1268 let r = NodeDataContainerRef::from_slice(&data);
1269 let out = r.transform_nodeid_optional(|id| Some(id.index() as u32 * 10));
1270 assert_eq!(out.internal, vec![0, 10, 20, 30]);
1271 assert_eq!(out.len(), r.len());
1272 }
1273
1274 #[test]
1275 fn transform_nodeid_optional_empty_input_never_calls_the_closure() {
1276 let empty: [u32; 0] = [];
1277 let r = NodeDataContainerRef::from_slice(&empty);
1278 let calls = AtomicUsize::new(0);
1279 let out = r.transform_nodeid_optional(|_| {
1280 calls.fetch_add(1, Ordering::SeqCst);
1281 Some(1_u32)
1282 });
1283 assert_eq!(calls.load(Ordering::SeqCst), 0);
1284 assert!(out.is_empty());
1285 }
1286
1287 #[test]
1293 fn transform_nodeid_optional_compacts_and_breaks_nodeid_alignment() {
1294 let data = [0_u32; 5];
1295 let r = NodeDataContainerRef::from_slice(&data);
1296 let out = r.transform_nodeid_optional(|id| {
1298 if id.index() % 2 == 0 {
1299 Some(id.index() as u32)
1300 } else {
1301 None
1302 }
1303 });
1304 assert_eq!(out.len(), 3, "output is compacted, NOT padded to the input len");
1305 assert_eq!(out.internal, vec![0, 2, 4]);
1306 assert_eq!(out.as_ref().get(NodeId::new(1)), Some(&2));
1308 assert_eq!(out.as_ref().get(NodeId::new(4)), None);
1309
1310 let none_out = r.transform_nodeid_optional(|_| -> Option<u32> { None });
1312 assert!(none_out.is_empty());
1313 }
1314
1315 #[test]
1320 fn az_children_walks_forwards_and_reverse_walks_backwards() {
1321 let nodes = tree_5();
1322 let it = items(&nodes);
1323 let h = NodeDataContainerRef::from_slice(&it);
1324
1325 assert_eq!(
1326 NodeId::new(0).az_children_collect(&h),
1327 vec![NodeId::new(1), NodeId::new(4)]
1328 );
1329 assert_eq!(
1330 NodeId::new(1).az_children(&h).collect::<Vec<_>>(),
1331 vec![NodeId::new(2), NodeId::new(3)]
1332 );
1333 assert_eq!(
1334 NodeId::new(1).az_reverse_children(&h).collect::<Vec<_>>(),
1335 vec![NodeId::new(3), NodeId::new(2)],
1336 "reverse iteration starts at last_child and walks previous_sibling"
1337 );
1338 assert_eq!(NodeId::new(2).az_children(&h).count(), 0);
1340 assert_eq!(NodeId::new(2).az_reverse_children(&h).count(), 0);
1341 assert!(NodeId::new(3).az_children_collect(&h).is_empty());
1342 }
1343
1344 #[test]
1345 #[should_panic]
1346 fn az_children_of_out_of_bounds_node_panics_loudly() {
1347 let nodes = tree_5();
1348 let it = items(&nodes);
1349 let h = NodeDataContainerRef::from_slice(&it);
1350 let _ = NodeId::new(5).az_children(&h);
1351 }
1352
1353 #[test]
1358 fn az_children_on_sibling_cycle_repeats_without_panicking() {
1359 let nodes = vec![
1360 Node {
1361 last_child: Some(NodeId::new(1)),
1362 ..Node::ROOT
1363 },
1364 Node {
1365 parent: Some(NodeId::new(0)),
1366 previous_sibling: None,
1367 next_sibling: Some(NodeId::new(1)), last_child: None,
1369 },
1370 ];
1371 let it = items(&nodes);
1372 let h = NodeDataContainerRef::from_slice(&it);
1373 let prefix: Vec<NodeId> = NodeId::new(0).az_children(&h).take(5).collect();
1374 assert_eq!(prefix, vec![NodeId::new(1); 5]);
1375 }
1376
1377 #[test]
1382 fn nearest_matching_parent_skips_non_matching_ancestors() {
1383 let nodes = tree_5();
1384 let it = items(&nodes);
1385 let h = NodeDataContainerRef::from_slice(&it);
1386 assert_eq!(
1388 NodeId::new(2).get_nearest_matching_parent(&h, |_| true),
1389 Some(NodeId::new(1))
1390 );
1391 assert_eq!(
1392 NodeId::new(2).get_nearest_matching_parent(&h, |n| n == NodeId::new(0)),
1393 Some(NodeId::new(0))
1394 );
1395 assert_eq!(
1397 NodeId::new(0).get_nearest_matching_parent(&h, |_| true),
1398 None
1399 );
1400 assert_eq!(
1402 NodeId::new(3).get_nearest_matching_parent(&h, |_| false),
1403 None
1404 );
1405 }
1406
1407 #[test]
1408 fn nearest_matching_parent_out_of_bounds_self_returns_none() {
1409 let nodes = tree_5();
1410 let it = items(&nodes);
1411 let h = NodeDataContainerRef::from_slice(&it);
1412 assert_eq!(
1413 NodeId::new(5).get_nearest_matching_parent(&h, |_| true),
1414 None
1415 );
1416 assert_eq!(
1417 NodeId::new(usize::MAX).get_nearest_matching_parent(&h, |_| true),
1418 None
1419 );
1420 }
1421
1422 #[test]
1423 fn nearest_matching_parent_self_parent_cycle_terminates() {
1424 let nodes = vec![
1426 Node::ROOT,
1427 Node {
1428 parent: Some(NodeId::new(1)),
1429 ..Node::ROOT
1430 },
1431 ];
1432 let it = items(&nodes);
1433 let h = NodeDataContainerRef::from_slice(&it);
1434 assert_eq!(
1435 NodeId::new(1).get_nearest_matching_parent(&h, |_| false),
1436 None
1437 );
1438 }
1439
1440 #[test]
1446 fn nearest_matching_parent_out_of_bounds_ancestor_does_not_panic() {
1447 let nodes = vec![
1448 Node::ROOT,
1449 Node {
1450 parent: Some(NodeId::new(99)), ..Node::ROOT
1452 },
1453 ];
1454 let it = items(&nodes);
1455 let h = NodeDataContainerRef::from_slice(&it);
1456
1457 assert_eq!(
1459 NodeId::new(1).get_nearest_matching_parent(&h, |_| false),
1460 None
1461 );
1462 assert_eq!(
1464 NodeId::new(1).get_nearest_matching_parent(&h, |_| true),
1465 Some(NodeId::new(99))
1466 );
1467 assert!(h.get(NodeId::new(99)).is_none(), "and it is NOT a valid index");
1468 }
1469}