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}