1use itertools::Itertools;
2
3use crate::{
4 prelude::{Path, Tree},
5 tree::NodeIDX,
6};
7use std::{any::Any, hash::Hash, iter::FusedIterator, marker::PhantomData, mem};
8
9use super::depth::{Traversal, TreeIterTarget};
10
11pub struct IterSortable<'a, N, B, T, S>
12where
13 T: TreeIterTarget<'a, N, B>,
14 S: FnMut(&mut Vec<(&'a B, usize)>),
15{
16 tree: &'a Tree<N, B>,
17 root: Option<NodeIDX>,
18 stages: Vec<Vec<(&'a B, usize)>>,
19 up: usize,
20 sort: S,
21 _phantom: PhantomData<T>,
22}
23
24impl<'a, N, B, T, S> IterSortable<'a, N, B, T, S>
25where
26 T: TreeIterTarget<'a, N, B>,
27 S: FnMut(&mut Vec<(&'a B, usize)>),
28{
29 pub fn new(tree: &'a Tree<N, B>, sort: S) -> Self {
30 Self {
31 tree,
32 root: tree.get_root_idx(),
33 stages: vec![],
34 up: 0,
35 sort,
36 _phantom: PhantomData,
37 }
38 }
39}
40
41impl<'a, N, B, T> IterSortable<'a, N, B, T, fn(&mut Vec<(&'a B, usize)>)>
42where
43 T: TreeIterTarget<'a, N, B>,
44{
45 pub fn new_unsorted(tree: &'a Tree<N, B>) -> Self {
46 Self {
47 tree,
48 root: tree.get_root_idx(),
49 stages: vec![],
50 up: 0,
51 sort: |_| {},
52 _phantom: PhantomData,
53 }
54 }
55
56 pub fn up(&self) -> usize {
57 self.up
58 }
59}
60
61impl<'a, N, B, T, S> IterSortable<'a, N, B, T, S>
62where
63 B: Clone + Eq + Hash,
64 T: TreeIterTarget<'a, N, B>,
65 S: FnMut(&mut Vec<(&'a B, usize)>),
66{
67 pub fn new_sub_state(
68 tree: &'a Tree<N, B>,
69 path: Path<B>,
70 sort: S,
71 ) -> Result<Self, Option<Path<B>>> {
72 Ok(Self {
73 tree,
74 root: Some(
75 tree.get_idx(&path, None)
76 .map_err(|r| r.map(|(_, idx_p)| path.path_to(idx_p)))?,
77 ),
78 stages: vec![],
79 up: 0,
80 sort,
81 _phantom: PhantomData,
82 })
83 }
84}
85
86impl<'a, N, B, T> IterSortable<'a, N, B, T, fn(&mut Vec<(&'a B, usize)>)>
87where
88 B: Clone + Eq + Hash,
89 T: TreeIterTarget<'a, N, B>,
90{
91 pub fn new_sub_state_unsorted(
92 tree: &'a Tree<N, B>,
93 path: Path<B>,
94 ) -> Result<Self, Option<Path<B>>> {
95 Ok(Self {
96 tree,
97 root: Some(
98 tree.get_idx(&path, None)
99 .map_err(|r| r.map(|(_, idx_p)| path.path_to(idx_p)))?,
100 ),
101 stages: vec![],
102 up: 0,
103 sort: |_| {},
104 _phantom: PhantomData,
105 })
106 }
107
108 pub fn is_last_child(&mut self) -> bool {
109 if let Some(last) = self.stages.last_mut() {
110 last.is_empty()
111 } else {
112 true
113 }
114 }
115
116 pub fn try_follow(&mut self, branch: B) -> bool {
118 if let Some(children) = self.stages.last_mut() {
119 if let Some((idx, _)) = children.iter().find_position(|&&x| *x.0 == branch) {
120 let last = children.len() - 1;
121 children.swap(idx, last);
122 true
123 } else {
124 false
125 }
126 } else {
127 false
128 }
129 }
130}
131
132impl<'a, N, B, T, S> Iterator for IterSortable<'a, N, B, T, S>
133where
134 T: TreeIterTarget<'a, N, B>,
135 S: FnMut(&mut Vec<(&'a B, usize)>),
136{
137 type Item = Traversal<T::Target, &'a B>;
138
139 fn next(&mut self) -> Option<Self::Item> {
140 if let Some(last) = self.stages.last_mut() {
141 if let Some((branch, node_idx)) = last.pop() {
143 let node = &self.tree.nodes[node_idx];
145 self.stages
146 .push(node.children.iter().map(|(b, i)| (b, *i)).collect());
147 Some(Traversal::Step {
149 up: std::mem::replace(&mut self.up, 0),
150 branch,
151 data: T::target(self.tree, node_idx),
152 })
153 } else {
155 self.stages.pop();
157 self.up += 1;
159 self.next()
160 }
161 } else if let Some(root) = self.root.take() {
162 let node = &self.tree.nodes[root];
163 self.stages
164 .push(node.children.iter().map(|(b, i)| (b, *i)).collect());
165 Some(Traversal::Start(T::target(self.tree, root)))
166 } else {
167 None
168 }
169 }
170}
171
172impl<'a, N, B, T, S> FusedIterator for IterSortable<'a, N, B, T, S>
173where
174 T: TreeIterTarget<'a, N, B>,
175 S: FnMut(&mut Vec<(&'a B, usize)>),
176{
177}