use std::sync::{Arc, Mutex, Weak};
pub type NodeRef<T, const N: usize> = Arc<Mutex<Node<T, N>>>;
pub type WeakNodeRef<T, const N: usize> = Weak<Mutex<Node<T, N>>>;
pub struct Node<T, const N: usize>{
parent: Option<WeakNodeRef<T, N>>,
children: [Option<NodeRef<T, N>>; N],
data: T
}
#[allow(dead_code)]
impl<T, const N: usize> Node<T, N>{
#[inline]
pub fn new(parent: Option<WeakNodeRef<T, N>>, data: T) -> Self{
Node { parent: parent, children: std::array::from_fn(|_| None), data: data }
}
#[inline]
pub fn new_root(data: T) -> NodeRef<T, N>{
Arc::new(Mutex::new(Node{ parent: None, children: std::array::from_fn(|_| None), data: data }))
}
#[inline]
pub fn is_root(&self) -> bool{
self.parent.is_none()
}
#[inline]
pub fn get_parent(&self) -> Option<NodeRef<T, N>>{
self.parent.as_ref().and_then(Weak::upgrade)
}
#[inline]
pub fn detach(&mut self){
self.parent = None;
}
#[inline]
pub fn get_child(&self, i: usize) -> Option<NodeRef<T, N>>{
if i >= N{
None
}
else{
self.children[i].as_ref().and_then(|x| Some(x.clone()))
}
}
#[inline]
pub fn add_child(node: &NodeRef<T, N>, i: usize, data: T) -> NodeRef<T, N>{
let ref_node = Arc::new(
Mutex::new(Node::<T, N>::new(Some(Arc::downgrade(node)), data))
);
node.lock().unwrap().children[i] = Some(Arc::clone(&ref_node));
ref_node
}
#[inline]
pub fn remove_child(node: &NodeRef<T, N>, i: usize){
node.lock().unwrap().children[i] = None;
}
#[inline]
pub fn get(&self) -> &T{
&self.data
}
#[inline]
pub fn get_mut(&mut self) -> &mut T{
&mut self.data
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_root_1() {
let root = Node::<u32, 4>::new_root(5);
let node = & *root.lock().unwrap();
assert_eq!(*node.get(), 5);
assert!(node.get_parent().is_none());
assert!(node.is_root());
assert!(node.get_child(0).is_none());
assert!(node.get_child(1).is_none());
assert!(node.get_child(2).is_none());
assert!(node.get_child(3).is_none());
}
#[test]
fn test_root_2() {
let root = Node::<u32, 3>::new_root(2);
let node = & *root.lock().unwrap();
assert_eq!(*node.get(), 2);
assert!(node.get_parent().is_none());
assert!(node.is_root());
assert!(node.get_child(0).is_none());
assert!(node.get_child(1).is_none());
assert!(node.get_child(2).is_none());
}
#[test]
fn test_add_node_1() {
let root = Node::<u32, 4>::new_root(6);
Node::add_child(&root, 0, 1);
Node::add_child(&root, 1, 2);
Node::add_child(&root, 3, 8);
let root_node = &*root.lock().unwrap();
assert_eq!(*root_node.get(), 6);
assert!(root_node.get_child(0).is_some());
assert!(root_node.get_child(1).is_some());
assert!(root_node.get_child(2).is_none());
assert!(root_node.get_child(3).is_some());
let ptr_node_0 = root_node.get_child(0).unwrap();
let ptr_node_1 = root_node.get_child(1).unwrap();
let ptr_node_3 = root_node.get_child(3).unwrap();
let node_0 = &*ptr_node_0.lock().unwrap();
let node_1 = &*ptr_node_1.lock().unwrap();
let node_3 = &*ptr_node_3.lock().unwrap();
assert_eq!(*node_0.get(), 1);
assert_eq!(*node_1.get(), 2);
assert_eq!(*node_3.get(), 8);
}
#[test]
fn test_remove_node_1() {
let root = Node::<u32, 4>::new_root(6);
Node::add_child(&root, 0, 1);
Node::add_child(&root, 1, 2);
Node::add_child(&root, 3, 8);
Node::remove_child(&root, 3);
let root_node = &*root.lock().unwrap();
assert_eq!(*root_node.get(), 6);
assert!(root_node.get_child(0).is_some());
assert!(root_node.get_child(1).is_some());
assert!(root_node.get_child(2).is_none());
assert!(root_node.get_child(3).is_none());
}
}