cranelift_bforest/
pool.rs1#[cfg(test)]
4use super::Comparator;
5use super::{Forest, Node, NodeData};
6use crate::entity::PrimaryMap;
7#[cfg(test)]
8use core::fmt;
9use core::ops::{Index, IndexMut};
10
11pub(super) struct NodePool<F: Forest> {
13 nodes: PrimaryMap<Node, NodeData<F>>,
14 freelist: Option<Node>,
15}
16
17impl<F: Forest> NodePool<F> {
18 pub fn new() -> Self {
20 Self {
21 nodes: PrimaryMap::new(),
22 freelist: None,
23 }
24 }
25
26 pub fn clear(&mut self) {
28 self.nodes.clear();
29 self.freelist = None;
30 }
31
32 pub fn alloc_node(&mut self, data: NodeData<F>) -> Node {
34 debug_assert!(!data.is_free(), "can't allocate free node");
35 match self.freelist {
36 Some(node) => {
37 match self.nodes[node] {
39 NodeData::Free { next } => self.freelist = next,
40 _ => panic!("Invalid {} on free list", node),
41 }
42 self.nodes[node] = data;
43 node
44 }
45 None => {
46 self.nodes.push(data)
48 }
49 }
50 }
51
52 pub fn free_node(&mut self, node: Node) {
54 debug_assert!(!self.nodes[node].is_free(), "{} is already free", node);
56 self.nodes[node] = NodeData::Free {
57 next: self.freelist,
58 };
59 self.freelist = Some(node);
60 }
61
62 pub fn free_tree(&mut self, node: Node) {
64 if let NodeData::Inner { size, tree, .. } = self[node] {
65 #[cfg_attr(feature = "cargo-clippy", allow(clippy::needless_range_loop))]
67 for i in 0..usize::from(size + 1) {
68 self.free_tree(tree[i]);
72 }
73 }
74 self.free_node(node);
75 }
76}
77
78#[cfg(test)]
79impl<F: Forest> NodePool<F> {
80 pub fn verify_tree<C: Comparator<F::Key>>(&self, node: Node, comp: &C)
82 where
83 NodeData<F>: fmt::Display,
84 F::Key: fmt::Display,
85 {
86 use crate::entity::EntitySet;
87 use alloc::vec::Vec;
88 use core::borrow::Borrow;
89 use core::cmp::Ordering;
90
91 if let NodeData::Inner { size, .. } = self[node] {
94 assert!(size > 0, "Root must have more than one sub-tree");
95 }
96
97 let mut done = match self[node] {
98 NodeData::Inner { size, .. } | NodeData::Leaf { size, .. } => {
99 EntitySet::with_capacity(size.into())
100 }
101 _ => EntitySet::new(),
102 };
103
104 let mut todo = Vec::new();
105
106 todo.push((None, node, None));
111
112 while let Some((lkey, node, rkey)) = todo.pop() {
113 assert!(done.insert(node), "Node appears more than once in tree");
114 let mut lower = lkey;
115
116 match self[node] {
117 NodeData::Inner { size, keys, tree } => {
118 let size = size as usize;
119 let capacity = tree.len();
120 let keys = &keys[0..size];
121
122 assert!(
125 rkey.is_none() || (size + 1) * 2 >= capacity,
126 "Only {}/{} entries in {}:{}, upper={}",
127 size + 1,
128 capacity,
129 node,
130 self[node],
131 rkey.unwrap()
132 );
133
134 for i in 0..size + 1 {
136 let upper = keys.get(i).cloned().or(rkey);
138
139 if let (Some(a), Some(b)) = (lower, upper) {
141 assert_eq!(
142 comp.cmp(a, b),
143 Ordering::Less,
144 "Key order {} < {} failed in {}: {}",
145 a,
146 b,
147 node,
148 self[node]
149 );
150 }
151
152 todo.push((lower, tree[i], upper));
154
155 lower = upper;
157 }
158 }
159 NodeData::Leaf { size, keys, .. } => {
160 let size = size as usize;
161 let capacity = keys.borrow().len();
162 let keys = &keys.borrow()[0..size];
163
164 assert!(size > 0, "Leaf {} is empty", node);
167 assert!(
168 rkey.is_none() || size * 2 >= capacity,
169 "Only {}/{} entries in {}:{}, upper={}",
170 size,
171 capacity,
172 node,
173 self[node],
174 rkey.unwrap()
175 );
176
177 for i in 0..size + 1 {
178 let upper = keys.get(i).cloned().or(rkey);
179
180 if let (Some(a), Some(b)) = (lower, upper) {
182 let wanted = if i == 0 {
183 Ordering::Equal
184 } else {
185 Ordering::Less
186 };
187 assert_eq!(
188 comp.cmp(a, b),
189 wanted,
190 "Key order for {} - {} failed in {}: {}",
191 a,
192 b,
193 node,
194 self[node]
195 );
196 }
197
198 lower = upper;
200 }
201 }
202 NodeData::Free { .. } => panic!("Free {} reached", node),
203 }
204 }
205 }
206}
207
208impl<F: Forest> Index<Node> for NodePool<F> {
209 type Output = NodeData<F>;
210
211 fn index(&self, index: Node) -> &Self::Output {
212 self.nodes.index(index)
213 }
214}
215
216impl<F: Forest> IndexMut<Node> for NodePool<F> {
217 fn index_mut(&mut self, index: Node) -> &mut Self::Output {
218 self.nodes.index_mut(index)
219 }
220}