tasty_ntree/ntree_node.rs
1#[cfg(feature = "debug")]
2use std::fmt::Debug;
3#[cfg(feature = "display")]
4use std::fmt::Display;
5
6use super::macros::none_array;
7
8type NodeChildren<const N: usize, T> = [Option<Box<NtreeNode<N, T>>>; N];
9
10/// Safe interface to a specific node in an n-tree.
11///
12/// Usage example:
13/// ```
14/// use tasty_ntree::Ntree;
15///
16/// // Making a quadtree where each node holds a String.
17/// let mut i32_octree = Ntree::<4, String>::new("Root node".to_string());
18///
19/// // As it was passed as the default value, the root node
20/// // will hold a 5 as its data.
21/// let root_data = i32_octree.interface().get_data();
22/// println!("Found data: {:}", root_data);
23/// assert_eq!(root_data, &"Root node".to_string());
24///
25/// let oct_interface = i32_octree.interface_mut();
26/// //oct_interface.peek_or_push_mut(0, "This is node 0".to_string());
27/// //oct_interface.peek_or_push_mut(3, "And this is node 3".to_string());
28/// let node_2 = oct_interface.bounded_push_mut(2, "Hello from node 2".to_string()).expect("Array bounding error");
29///
30/// node_2
31/// .bounded_push_mut(1, "And 2.1".to_string())
32/// .expect("Array bounding error")
33/// .bounded_push_mut(3, "And 2.1.3".to_string());
34///
35/// node_2.bounded_push_mut(2, "And 2.2!".to_string());
36///
37/// #[cfg(feature = "debug")]
38/// println!("Tree:\n{:?}", i32_octree);
39///
40/// // With the debug feature enabled, this would print:
41/// // [NTree]
42/// // 0 NtreeNode ( "Root node" )
43/// // | 0 NTreeNode ( "This is node 0" )
44/// // | 2 NTreeNode ( "Hello from node 2" )
45/// // | | 1 NtreeNode ( "And 2.1" )
46/// // | | | 3 NtreeNode ( "And 2.1.3" )
47/// // | | 2 NtreeNode ( "And 2.2!" )
48/// // | 3 NtreeNode ( "And this is node 3" )
49/// ```
50pub trait NtreeNodeInterface<const N: usize, T: Sized> {
51 /// Returns a reference to the data in this node.
52 fn get_data(&self) -> &T;
53 /// Returns a mutable reference to the data in this node.
54 fn get_data_mut(&mut self) -> &mut T;
55 /// Sets data inside this node to new value and returns old value.
56 fn set_data(&mut self, data: T) -> T;
57 /// Returns a mutable reference to an interface to child node `i` if it exists.
58 ///
59 /// Panics if i is bigger than the ammount of children the node has.
60 unsafe fn peek_mut(&mut self, i: usize) -> Option<&mut dyn NtreeNodeInterface<N, T>>;
61 /// Returns a mutable reference to an interface to child node `i` if it exists.
62 ///
63 /// Does bounds checking at runtime.
64 fn bounded_peek_mut(&mut self, i: usize) -> Option<&mut dyn NtreeNodeInterface<N, T>> {
65 if i > N {
66 return None;
67 }
68 unsafe { self.peek_mut(i) }
69 }
70 /// Returns a reference to an interface to child node `i` if it exists.
71 ///
72 /// Panics if i is bigger than the ammount of children the node has.
73 unsafe fn peek(&self, i: usize) -> Option<&dyn NtreeNodeInterface<N, T>>;
74 /// Returns a reference to an interface to child node `i` if it exists.
75 ///
76 /// Does bounds checking at runtime.
77 fn bounded_peek(&mut self, i: usize) -> Option<&dyn NtreeNodeInterface<N, T>> {
78 if i > N {
79 return None;
80 }
81 unsafe { self.peek(i) }
82 }
83 /// If child node 'i' exists, overwrites it.
84 ///
85 /// If it doesn't, creates it and returns a mutable reference to it.
86 ///
87 /// If you only want to create a child if one doesn't already exist,
88 /// use [peek_or_push] or [peek_or_push_mut].
89 ///
90 /// Panics if i is bigger than the ammount of children the node has.
91 unsafe fn push_mut(&mut self, i: usize, data: T) -> &mut dyn NtreeNodeInterface<N, T>;
92 /// If child node 'i' exists, overwrites it.
93 ///
94 /// If it doesn't, creates it and returns a mutable reference to it (as long as `i` is within bounds).
95 ///
96 /// Does bounds checking at runtime. If `i` is out of bounds, returns `None`.
97 fn bounded_push_mut(&mut self, i: usize, data: T) -> Option<&mut dyn NtreeNodeInterface<N, T>> {
98 if i > N {
99 return None;
100 }
101 unsafe { Some(self.push_mut(i, data)) }
102 }
103 /// If child node 'i' exists, overwrites it.
104 ///
105 /// If it doesn't, creates it and returns a reference to it.
106 ///
107 /// If you only want to create a child if one doesn't already exist,
108 /// use [peek_or_push] or [peek_or_push_mut].
109 ///
110 /// Panics if i is bigger than the ammount of children the node has.
111 unsafe fn push(&mut self, i: usize, data: T) -> &dyn NtreeNodeInterface<N, T> {
112 self.push_mut(i, data)
113 }
114 /// If child node 'i' exists, overwrites it.
115 ///
116 /// If it doesn't, creates it and returns a reference to it (as long as `i` is within bounds).
117 ///
118 /// Does bounds checking at runtime. If `i` is out of bounds, returns `None`.
119 fn bounded_push(&mut self, i: usize, data: T) -> Option<&dyn NtreeNodeInterface<N, T>> {
120 if i > N {
121 return None;
122 }
123 unsafe { Some(self.push(i, data)) }
124 }
125 /// Returns a reference to an interface to child node `i` if it exists,
126 /// if not, creates it and returns it.
127 ///
128 /// Panics if i is bigger than the ammount of children the node has.
129 unsafe fn peek_or_push(&mut self, i: usize, default_data: T) -> &dyn NtreeNodeInterface<N, T> {
130 self.peek_or_push_mut(i, default_data)
131 }
132 /// Returns a reference to an interface to child node `i` if it exists,
133 /// if not, creates it and returns it (as long as `i` is within bounds).
134 ///
135 /// Does bounds checking at runtime. If `i` is out of bounds, returns `None`.
136 fn bounded_peek_or_push(
137 &mut self,
138 i: usize,
139 default_data: T,
140 ) -> Option<&dyn NtreeNodeInterface<N, T>> {
141 if i > N {
142 return None;
143 }
144 unsafe { Some(self.peek_or_push(i, default_data)) }
145 }
146 /// Returns a mutable reference to an interface to child node `i` if it exists,
147 /// if not, creates it and returns it.
148 ///
149 /// Panics if i is bigger than the ammount of children the node has.
150 unsafe fn peek_or_push_mut(
151 &mut self,
152 i: usize,
153 default_data: T,
154 ) -> &mut dyn NtreeNodeInterface<N, T> {
155 if self.peek(i).is_none() {
156 self.push_mut(i, default_data);
157 }
158 self.peek_mut(i).unwrap()
159 }
160 /// Returns a mutable reference to an interface to child node `i` if it exists,
161 /// if not, creates it and returns it (as long as `i` is within bounds).
162 ///
163 /// Does bounds checking at runtime.
164 fn bounded_peek_or_push_mut(
165 &mut self,
166 i: usize,
167 default_data: T,
168 ) -> Option<&mut dyn NtreeNodeInterface<N, T>> {
169 if i > N {
170 return None;
171 }
172 unsafe { Some(self.peek_or_push_mut(i, default_data)) }
173 }
174 /// Pops child node 'i' and returns an optional value representing inner data.
175 ///
176 /// Returns `Some(data)` if it existed, `None` if it didn't.
177 ///
178 /// Panics if i is bigger than the ammount of children the node has.
179 unsafe fn pop(&mut self, i: usize) -> Option<T>;
180 /// Pops child node 'i' and returns an optional value representing inner data.
181 ///
182 /// Returns `Some(data)` if it existed, `None` if it didn't.
183 ///
184 /// Does bounds checking at runtime.
185 fn bounded_pop(&mut self, i: usize) -> Option<T> {
186 if i > N {
187 return None;
188 }
189 unsafe { self.pop(i) }
190 }
191}
192
193#[derive(PartialEq, Eq)]
194pub struct NtreeNode<const N: usize, T: Sized> {
195 pub data: T,
196 pub children: NodeChildren<N, T>,
197}
198
199impl<const N: usize, T: Sized> NtreeNode<N, T> {
200 pub fn new(data: T) -> Self {
201 let children = none_array!(N, Box<NtreeNode<N, T>>);
202
203 Self { data, children }
204 }
205
206 fn new_node(&mut self, i: usize, data: T) {
207 self.children[i] = Some(Box::new(NtreeNode::new(data)));
208 }
209
210 fn take_data(self) -> T {
211 self.data
212 }
213}
214
215////////////////////////// Trait impl //////////////////////////
216
217impl<const N: usize, T: Sized> NtreeNodeInterface<N, T> for NtreeNode<N, T> {
218 fn get_data(&self) -> &T {
219 &self.data
220 }
221
222 fn get_data_mut(&mut self) -> &mut T {
223 &mut self.data
224 }
225
226 fn set_data(&mut self, data: T) -> T {
227 std::mem::replace(&mut self.data, data)
228 }
229
230 unsafe fn peek_mut(&mut self, i: usize) -> Option<&mut dyn NtreeNodeInterface<N, T>> {
231 let node_opt = &mut self.children[i];
232 match node_opt {
233 Some(node) => Some(node.as_mut()),
234 None => None,
235 }
236 }
237
238 unsafe fn peek(&self, i: usize) -> Option<&dyn NtreeNodeInterface<N, T>> {
239 let node_opt = &self.children[i];
240 match node_opt {
241 Some(node) => Some(node.as_ref()),
242 None => None,
243 }
244 }
245
246 unsafe fn pop(&mut self, i: usize) -> Option<T> {
247 match self.children[i].take() {
248 Some(node) => Some(node.take_data()),
249 None => None,
250 }
251 }
252
253 unsafe fn push_mut(&mut self, i: usize, data: T) -> &mut dyn NtreeNodeInterface<N, T> {
254 self.children[i] = Some(Box::from(Self::new(data)));
255 self.peek_mut(i).unwrap()
256 }
257}
258
259//////////////////////////// Debug /////////////////////////////
260
261#[cfg(feature = "debug")]
262impl<const N: usize, T: Sized + Debug> NtreeNode<N, T> {
263 pub fn dbg_indent(
264 &self,
265 index: usize,
266 indentation: u32,
267 f: &mut std::fmt::Formatter<'_>,
268 ) -> std::fmt::Result {
269 f.write_str("\n")?;
270 for _ in 0..indentation {
271 f.write_str(" |")?;
272 }
273 f.write_fmt(format_args!(" {} NtreeNode ( {:?} )", index, self.data))?;
274 for i in 0..N {
275 match &self.children[i] {
276 Some(child) => child.dbg_indent(i, indentation + 1, f)?,
277 None => (),
278 }
279 }
280 Ok(())
281 }
282}
283
284#[cfg(feature = "debug")]
285impl<const N: usize, T: Sized + Debug> Debug for NtreeNode<N, T> {
286 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
287 self.dbg_indent(0, 0, f)
288 }
289}
290
291/////////////////////////// Display ////////////////////////////
292
293#[cfg(feature = "display")]
294impl<const N: usize, T: Sized> NtreeNode<N, T> {
295 pub fn fmt_indent(
296 &self,
297 index: usize,
298 indentation: u32,
299 f: &mut std::fmt::Formatter<'_>,
300 ) -> std::fmt::Result {
301 f.write_str("\n")?;
302 for _ in 0..indentation {
303 f.write_str(" |")?;
304 }
305 f.write_fmt(format_args!(" {} NtreeNode", index))?;
306 for i in 0..N {
307 match &self.children[i] {
308 Some(child) => child.fmt_indent(i, indentation + 1, f)?,
309 None => (),
310 }
311 }
312 Ok(())
313 }
314}
315
316#[cfg(feature = "display")]
317impl<const N: usize, T: Sized> Display for NtreeNode<N, T> {
318 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
319 self.fmt_indent(0, 0, f)
320 }
321}