Skip to content

Commit be06c43

Browse files
committed
okay
1 parent 804859b commit be06c43

File tree

2 files changed

+114
-0
lines changed

2 files changed

+114
-0
lines changed

src/sys/traits.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use super::bindings::tsk_id_t;
2+
13
/// For a type `tsk_foo_t`, this trait abstracts
24
/// out the functionality of `tsk_foo_free`
35
///

src/sys/tree.rs

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use crate::bindings;
2+
13
use super::bindings::tsk_id_t;
24
use super::bindings::tsk_size_t;
35
use super::bindings::tsk_tree_t;
@@ -74,4 +76,114 @@ impl<'treeseq> LLTree<'treeseq> {
7476
pub fn as_ref(&self) -> &tsk_tree_t {
7577
self.inner.as_ref()
7678
}
79+
80+
pub fn left_sib<N: Into<tsk_id_t> + Copy>(&self, u: N) -> Option<tsk_id_t> {
81+
todo!("doc SAFETY");
82+
super::tsk_column_access::<tsk_id_t, _, _, _>(
83+
u.into(),
84+
self.as_ref().left_sib,
85+
unsafe {
86+
self.as_ref()
87+
.tree_sequence
88+
.as_ref()
89+
.unwrap()
90+
.tables
91+
.as_ref()
92+
}
93+
.unwrap()
94+
.nodes
95+
.num_rows,
96+
)
97+
}
98+
99+
pub fn right_child<N: Into<tsk_id_t> + Copy>(&self, u: N) -> Option<tsk_id_t> {
100+
todo!("doc SAFETY");
101+
super::tsk_column_access::<tsk_id_t, _, _, _>(
102+
u.into(),
103+
self.as_ref().right_child,
104+
unsafe {
105+
self.as_ref()
106+
.tree_sequence
107+
.as_ref()
108+
.unwrap()
109+
.tables
110+
.as_ref()
111+
}
112+
.unwrap()
113+
.nodes
114+
.num_rows,
115+
)
116+
}
117+
}
118+
119+
// Trait defining iteration over nodes.
120+
pub trait NodeIterator {
121+
fn next_node(&mut self);
122+
fn current_node(&mut self) -> Option<tsk_id_t>;
123+
}
124+
125+
struct NodeIteratorAdapter<T>
126+
where
127+
T: NodeIterator,
128+
{
129+
ni: T,
130+
}
131+
132+
impl<T> Iterator for NodeIteratorAdapter<T>
133+
where
134+
T: NodeIterator,
135+
{
136+
type Item = tsk_id_t;
137+
fn next(&mut self) -> Option<Self::Item> {
138+
self.ni.next_node();
139+
self.ni.current_node()
140+
}
141+
}
142+
143+
struct PreorderNodeIterator<'a> {
144+
current_root: tsk_id_t,
145+
node_stack: Vec<tsk_id_t>,
146+
tree: &'a LLTree<'a>,
147+
current_node_: Option<tsk_id_t>,
148+
}
149+
150+
impl<'a> PreorderNodeIterator<'a> {
151+
fn new(tree: &'a LLTree) -> Self {
152+
debug_assert!(tree.right_child(tree.virtual_root()).is_some());
153+
let mut rv = PreorderNodeIterator {
154+
current_root: tree.right_child(tree.virtual_root()).unwrap_or(-1),
155+
node_stack: vec![],
156+
tree,
157+
current_node_: None,
158+
};
159+
let mut c = rv.current_root;
160+
while c != -1 {
161+
rv.node_stack.push(c);
162+
debug_assert!(rv.tree.left_sib(c).is_some());
163+
c = rv.tree.left_sib(c).unwrap_or(-1);
164+
}
165+
rv
166+
}
167+
}
168+
169+
impl NodeIterator for PreorderNodeIterator<'_> {
170+
fn next_node(&mut self) {
171+
self.current_node_ = self.node_stack.pop();
172+
if let Some(u) = self.current_node_ {
173+
// NOTE: process children right-to-left
174+
// because we later pop them from a steck
175+
// to generate the expected left-to-right ordering.
176+
debug_assert!(self.tree.right_child(u).is_some());
177+
let mut c = self.tree.right_child(u).unwrap_or(-1);
178+
while c != NodeId::NULL {
179+
self.node_stack.push(c);
180+
debug_assert!(self.tree.right_child(c).is_some());
181+
c = self.tree.left_sib(c).unwrap_or(-1);
182+
}
183+
};
184+
}
185+
186+
fn current_node(&mut self) -> Option<tsk_id_t> {
187+
self.current_node_
188+
}
77189
}

0 commit comments

Comments
 (0)