Skip to content

Commit c384e4f

Browse files
committed
more
1 parent 6b5ffdc commit c384e4f

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

src/sys/tree.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,20 @@ impl<'treeseq> LLTree<'treeseq> {
155155
pub fn flags(&self) -> TreeFlags {
156156
self.flags
157157
}
158+
159+
pub fn traverse_nodes(
160+
&self,
161+
order: NodeTraversalOrder,
162+
) -> Box<dyn Iterator<Item = NodeId> + '_> {
163+
match order {
164+
NodeTraversalOrder::Preorder => {
165+
Box::new(NodeIteratorAdapter(PreorderNodeIterator::new(self)))
166+
}
167+
NodeTraversalOrder::Postorder => {
168+
Box::new(NodeIteratorAdapter(PostorderNodeIterator::new(self)))
169+
}
170+
}
171+
}
158172
}
159173

160174
// Trait defining iteration over nodes.
@@ -227,6 +241,64 @@ impl NodeIterator for PreorderNodeIterator<'_> {
227241
}
228242
}
229243

244+
struct PostorderNodeIterator<'a> {
245+
nodes: Vec<NodeId>,
246+
current_node_index: usize,
247+
current_node: Option<NodeId>,
248+
num_nodes_current_tree: usize,
249+
tree: &'a LLTree<'a>,
250+
}
251+
252+
impl<'a> PostorderNodeIterator<'a> {
253+
fn new(tree: &'a LLTree<'a>) -> Self {
254+
let mut num_nodes_current_tree: tsk_size_t = 0;
255+
let ptr = std::ptr::addr_of_mut!(num_nodes_current_tree);
256+
let mut nodes = vec![
257+
NodeId::NULL;
258+
// NOTE: this fn does not return error codes
259+
usize::try_from(unsafe {
260+
bindings::tsk_tree_get_size_bound(tree.as_ptr())
261+
}).unwrap_or(usize::MAX)
262+
];
263+
264+
let rv = unsafe {
265+
bindings::tsk_tree_postorder(tree.as_ptr(), nodes.as_mut_ptr().cast::<tsk_id_t>(), ptr)
266+
};
267+
268+
// This is either out of memory
269+
// or node out of range.
270+
// The former is fatal, and the latter
271+
// not relevant (for now), as we start at roots.
272+
if rv < 0 {
273+
panic!("fatal error calculating postoder node list");
274+
}
275+
276+
Self {
277+
nodes,
278+
current_node_index: 0,
279+
current_node: None,
280+
num_nodes_current_tree: usize::try_from(num_nodes_current_tree).unwrap_or(0),
281+
tree,
282+
}
283+
}
284+
}
285+
286+
impl NodeIterator for PostorderNodeIterator<'_> {
287+
fn next_node(&mut self) {
288+
match self.current_node_index < self.num_nodes_current_tree {
289+
true => {
290+
self.current_node = Some(self.nodes[self.current_node_index]);
291+
self.current_node_index += 1;
292+
}
293+
false => self.current_node = None,
294+
}
295+
}
296+
297+
fn current_node(&mut self) -> Option<NodeId> {
298+
todo!()
299+
}
300+
}
301+
230302
struct SamplesIterator<'a> {
231303
current_node: Option<NodeId>,
232304
next_sample_index: NodeId,

src/trees/tree.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,20 @@ impl<'treeseq> Tree<'treeseq> {
146146
pub fn parent<N: Into<NodeId> + Copy + std::fmt::Debug>(&self, u: N) -> Option<NodeId> {
147147
self.inner.parent(u.into())
148148
}
149+
150+
/// Return an [`Iterator`] over all nodes in the tree.
151+
///
152+
/// # Parameters
153+
///
154+
/// * `order`: A value from [`NodeTraversalOrder`] specifying the
155+
/// iteration order.
156+
// Return value is dyn for later addition of other traversal orders
157+
pub fn traverse_nodes(
158+
&self,
159+
order: crate::NodeTraversalOrder,
160+
) -> Box<dyn Iterator<Item = NodeId> + '_> {
161+
self.inner.traverse_nodes(order)
162+
}
149163
}
150164

151165
impl<'ts> streaming_iterator::StreamingIterator for Tree<'ts> {

0 commit comments

Comments
 (0)