diff options
author | Dmitry <[email protected]> | 2020-08-14 19:32:05 +0100 |
---|---|---|
committer | Dmitry <[email protected]> | 2020-08-14 19:32:05 +0100 |
commit | 178c3e135a2a249692f7784712492e7884ae0c00 (patch) | |
tree | ac6b769dbf7162150caa0c1624786a4dd79ff3be /crates/profile/src/tree.rs | |
parent | 06ff8e6c760ff05f10e868b5d1f9d79e42fbb49c (diff) | |
parent | c2594daf2974dbd4ce3d9b7ec72481764abaceb5 (diff) |
Merge remote-tracking branch 'origin/master'
Diffstat (limited to 'crates/profile/src/tree.rs')
-rw-r--r-- | crates/profile/src/tree.rs | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/crates/profile/src/tree.rs b/crates/profile/src/tree.rs new file mode 100644 index 000000000..096f58511 --- /dev/null +++ b/crates/profile/src/tree.rs | |||
@@ -0,0 +1,84 @@ | |||
1 | //! A simple tree implementation which tries to not allocate all over the place. | ||
2 | use std::ops; | ||
3 | |||
4 | use arena::Arena; | ||
5 | |||
6 | #[derive(Default)] | ||
7 | pub struct Tree<T> { | ||
8 | nodes: Arena<Node<T>>, | ||
9 | current_path: Vec<(Idx<T>, Option<Idx<T>>)>, | ||
10 | } | ||
11 | |||
12 | pub type Idx<T> = arena::Idx<Node<T>>; | ||
13 | |||
14 | impl<T> Tree<T> { | ||
15 | pub fn start(&mut self) | ||
16 | where | ||
17 | T: Default, | ||
18 | { | ||
19 | let me = self.nodes.alloc(Node::new(T::default())); | ||
20 | if let Some((parent, last_child)) = self.current_path.last_mut() { | ||
21 | let slot = match *last_child { | ||
22 | Some(last_child) => &mut self.nodes[last_child].next_sibling, | ||
23 | None => &mut self.nodes[*parent].first_child, | ||
24 | }; | ||
25 | let prev = slot.replace(me); | ||
26 | assert!(prev.is_none()); | ||
27 | *last_child = Some(me); | ||
28 | } | ||
29 | |||
30 | self.current_path.push((me, None)); | ||
31 | } | ||
32 | |||
33 | pub fn finish(&mut self, data: T) { | ||
34 | let (me, _last_child) = self.current_path.pop().unwrap(); | ||
35 | self.nodes[me].data = data; | ||
36 | } | ||
37 | |||
38 | pub fn root(&self) -> Option<Idx<T>> { | ||
39 | self.nodes.iter().next().map(|(idx, _)| idx) | ||
40 | } | ||
41 | |||
42 | pub fn children(&self, idx: Idx<T>) -> impl Iterator<Item = Idx<T>> + '_ { | ||
43 | NodeIter { nodes: &self.nodes, next: self.nodes[idx].first_child } | ||
44 | } | ||
45 | pub fn clear(&mut self) { | ||
46 | self.nodes.clear(); | ||
47 | self.current_path.clear(); | ||
48 | } | ||
49 | } | ||
50 | |||
51 | impl<T> ops::Index<Idx<T>> for Tree<T> { | ||
52 | type Output = T; | ||
53 | fn index(&self, index: Idx<T>) -> &T { | ||
54 | &self.nodes[index].data | ||
55 | } | ||
56 | } | ||
57 | |||
58 | pub struct Node<T> { | ||
59 | data: T, | ||
60 | first_child: Option<Idx<T>>, | ||
61 | next_sibling: Option<Idx<T>>, | ||
62 | } | ||
63 | |||
64 | impl<T> Node<T> { | ||
65 | fn new(data: T) -> Node<T> { | ||
66 | Node { data, first_child: None, next_sibling: None } | ||
67 | } | ||
68 | } | ||
69 | |||
70 | struct NodeIter<'a, T> { | ||
71 | nodes: &'a Arena<Node<T>>, | ||
72 | next: Option<Idx<T>>, | ||
73 | } | ||
74 | |||
75 | impl<'a, T> Iterator for NodeIter<'a, T> { | ||
76 | type Item = Idx<T>; | ||
77 | |||
78 | fn next(&mut self) -> Option<Idx<T>> { | ||
79 | self.next.map(|next| { | ||
80 | self.next = self.nodes[next].next_sibling; | ||
81 | next | ||
82 | }) | ||
83 | } | ||
84 | } | ||