use hashbrown::HashMap;
use crate::NodeId;
#[derive(Debug)]
struct TreeNode<T> {
id: NodeId,
item: T,
children: HashMap<NodeId, TreeNode<T>>,
}
#[derive(Debug, Default)]
pub struct TreeArena<T> {
roots: HashMap<NodeId, TreeNode<T>>,
parents_map: HashMap<NodeId, Option<NodeId>>,
}
#[derive(Debug)]
pub struct ArenaRef<'arena, T> {
pub parent_id: Option<NodeId>,
pub item: &'arena T,
pub children: ArenaRefList<'arena, T>,
}
#[derive(Debug)]
pub struct ArenaMut<'arena, T> {
pub parent_id: Option<NodeId>,
pub item: &'arena mut T,
pub children: ArenaMutList<'arena, T>,
}
#[derive(Debug)]
pub struct ArenaRefList<'arena, T> {
parent_id: Option<NodeId>,
children: &'arena HashMap<NodeId, TreeNode<T>>,
parents_map: ArenaMapRef<'arena>,
}
#[derive(Debug)]
pub struct ArenaMutList<'arena, T> {
parent_id: Option<NodeId>,
children: &'arena mut HashMap<NodeId, TreeNode<T>>,
parents_map: ArenaMapMut<'arena>,
}
#[derive(Clone, Copy, Debug)]
pub struct ArenaMapRef<'arena> {
parents_map: &'arena HashMap<NodeId, Option<NodeId>>,
}
#[derive(Debug)]
pub struct ArenaMapMut<'arena> {
parents_map: &'arena mut HashMap<NodeId, Option<NodeId>>,
}
impl<T> Clone for ArenaRef<'_, T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for ArenaRef<'_, T> {}
impl<T> Clone for ArenaRefList<'_, T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for ArenaRefList<'_, T> {}
impl<T> TreeArena<T> {
pub fn new() -> Self {
Self {
roots: HashMap::new(),
parents_map: HashMap::new(),
}
}
pub fn roots(&self) -> ArenaRefList<'_, T> {
ArenaRefList {
parent_id: None,
children: &self.roots,
parents_map: ArenaMapRef {
parents_map: &self.parents_map,
},
}
}
pub fn root_ids(&self) -> impl Iterator<Item = NodeId> {
self.roots.keys().copied()
}
pub fn roots_mut(&mut self) -> ArenaMutList<'_, T> {
ArenaMutList {
parent_id: None,
children: &mut self.roots,
parents_map: ArenaMapMut {
parents_map: &mut self.parents_map,
},
}
}
pub fn find(&self, id: impl Into<NodeId>) -> Option<ArenaRef<'_, T>> {
self.roots().find_inner(id.into())
}
pub fn find_mut(&mut self, id: impl Into<NodeId>) -> Option<ArenaMut<'_, T>> {
self.roots_mut().find_mut_inner(id.into())
}
pub fn get_id_path(&self, id: impl Into<NodeId>) -> Vec<NodeId> {
let parents_map = ArenaMapRef {
parents_map: &self.parents_map,
};
parents_map.get_id_path(id.into(), None)
}
pub fn reparent(&mut self, child: impl Into<NodeId>, new_parent: impl Into<NodeId>) {
let child_id = child.into();
let new_parent_id = new_parent.into();
assert_ne!(
child_id, new_parent_id,
"expected child to be different from new_parent but both have id #{child_id}"
);
assert!(
!self.get_id_path(new_parent_id).contains(&child_id),
"cannot reparent because new_parent #{new_parent_id} is a child of the to-be-reparented node #{child_id}"
);
assert!(
!self.roots.contains_key(&child_id),
"reparenting of root nodes is currently not supported"
);
let old_parent_id = self
.parents_map
.get(&child_id)
.unwrap_or_else(|| panic!("no node found for child id #{child_id}"))
.unwrap();
let child_node = self
.find_mut(old_parent_id)
.unwrap()
.children
.children
.remove(&child_id)
.unwrap();
self.parents_map.insert(child_id, Some(new_parent_id));
self.find_mut(new_parent_id)
.unwrap_or_else(|| panic!("no node found for new_parent id #{new_parent_id}"))
.children
.children
.insert(child_id, child_node);
}
}
impl<T> TreeNode<T> {
fn arena_ref<'arena>(
&'arena self,
parent_id: Option<NodeId>,
parents_map: &'arena HashMap<NodeId, Option<NodeId>>,
) -> ArenaRef<'arena, T> {
ArenaRef {
parent_id,
item: &self.item,
children: ArenaRefList {
parent_id: Some(self.id),
children: &self.children,
parents_map: ArenaMapRef { parents_map },
},
}
}
fn arena_mut<'arena>(
&'arena mut self,
parent_id: Option<NodeId>,
parents_map: &'arena mut HashMap<NodeId, Option<NodeId>>,
) -> ArenaMut<'arena, T> {
ArenaMut {
parent_id,
item: &mut self.item,
children: ArenaMutList {
parent_id: Some(self.id),
children: &mut self.children,
parents_map: ArenaMapMut { parents_map },
},
}
}
}
impl<T> ArenaRef<'_, T> {
pub fn id(&self) -> NodeId {
self.children
.parent_id
.expect("ArenaRefList always has a parent_id when it's a member of ArenaRef")
}
pub fn child_ids(&self) -> impl IntoIterator<Item = NodeId> {
self.children.children.keys().copied()
}
}
impl<T> ArenaMut<'_, T> {
pub fn id(&self) -> NodeId {
self.children
.parent_id
.expect("ArenaRefList always has a parent_id when it's a member of ArenaRef")
}
pub fn reborrow(&mut self) -> ArenaRef<'_, T> {
ArenaRef {
parent_id: self.parent_id,
item: self.item,
children: self.children.reborrow(),
}
}
pub fn reborrow_mut(&mut self) -> ArenaMut<'_, T> {
ArenaMut {
parent_id: self.parent_id,
item: self.item,
children: self.children.reborrow_mut(),
}
}
}
impl<'arena, T> ArenaRefList<'arena, T> {
pub fn has(self, id: impl Into<NodeId>) -> bool {
let id = id.into();
self.children.contains_key(&id)
}
pub fn item(&self, id: impl Into<NodeId>) -> Option<ArenaRef<'_, T>> {
let id = id.into();
self.children
.get(&id)
.map(|child| child.arena_ref(self.parent_id, self.parents_map.parents_map))
}
pub fn into_item(self, id: impl Into<NodeId>) -> Option<ArenaRef<'arena, T>> {
let id = id.into();
self.children
.get(&id)
.map(|child| child.arena_ref(self.parent_id, self.parents_map.parents_map))
}
pub fn find(self, id: impl Into<NodeId>) -> Option<ArenaRef<'arena, T>> {
self.find_inner(id.into())
}
fn find_inner(self, id: NodeId) -> Option<ArenaRef<'arena, T>> {
let parent_id = self.parents_map.parents_map.get(&id)?;
let id_path = if let Some(parent_id) = parent_id {
self.parents_map.get_id_path(*parent_id, self.parent_id)
} else {
Vec::new()
};
let mut id_path = id_path.as_slice();
let mut node_children = self.children;
while let Some((ancestor_id, new_id_path)) = id_path.split_last() {
id_path = new_id_path;
node_children = &node_children.get(ancestor_id)?.children;
}
let node = node_children.get(&id)?;
Some(node.arena_ref(*parent_id, self.parents_map.parents_map))
}
}
impl<'arena, T> ArenaMutList<'arena, T> {
pub fn has(&self, id: impl Into<NodeId>) -> bool {
let id = id.into();
self.children.contains_key(&id)
}
pub fn item(&self, id: impl Into<NodeId>) -> Option<ArenaRef<'_, T>> {
let id = id.into();
self.children
.get(&id)
.map(|child| child.arena_ref(self.parent_id, self.parents_map.parents_map))
}
pub fn item_mut(&mut self, id: impl Into<NodeId>) -> Option<ArenaMut<'_, T>> {
let id = id.into();
self.children
.get_mut(&id)
.map(|child| child.arena_mut(self.parent_id, self.parents_map.parents_map))
}
pub fn into_item(self, id: impl Into<NodeId>) -> Option<ArenaRef<'arena, T>> {
let id = id.into();
self.children
.get(&id)
.map(|child| child.arena_ref(self.parent_id, self.parents_map.parents_map))
}
pub fn into_item_mut(self, id: impl Into<NodeId>) -> Option<ArenaMut<'arena, T>> {
let id = id.into();
self.children
.get_mut(&id)
.map(|child| child.arena_mut(self.parent_id, self.parents_map.parents_map))
}
pub fn insert(&mut self, child_id: impl Into<NodeId>, value: T) -> ArenaMut<'_, T> {
let child_id = child_id.into();
assert!(
!self.parents_map.parents_map.contains_key(&child_id),
"Key already present"
);
self.parents_map
.parents_map
.insert(child_id, self.parent_id);
self.children.insert(
child_id,
TreeNode {
id: child_id,
item: value,
children: HashMap::new(),
},
);
self.children
.get_mut(&child_id)
.unwrap()
.arena_mut(self.parent_id, self.parents_map.parents_map)
}
#[must_use]
pub fn remove(&mut self, child_id: impl Into<NodeId>) -> Option<T> {
let child_id = child_id.into();
let child = self.children.remove(&child_id)?;
fn remove_children_from_map<I>(
node: &TreeNode<I>,
parents_map: &mut HashMap<NodeId, Option<NodeId>>,
) {
for child in &node.children {
remove_children_from_map(child.1, parents_map);
}
parents_map.remove(&node.id);
}
remove_children_from_map(&child, self.parents_map.parents_map);
Some(child.item)
}
pub fn reborrow(&self) -> ArenaRefList<'_, T> {
ArenaRefList {
parent_id: self.parent_id,
children: &*self.children,
parents_map: self.parents_map.reborrow(),
}
}
pub fn reborrow_mut(&mut self) -> ArenaMutList<'_, T> {
ArenaMutList {
parent_id: self.parent_id,
children: &mut *self.children,
parents_map: self.parents_map.reborrow_mut(),
}
}
pub fn find(&self, id: impl Into<NodeId>) -> Option<ArenaRef<'_, T>> {
self.reborrow().find(id)
}
pub fn find_mut(self, id: impl Into<NodeId>) -> Option<ArenaMut<'arena, T>> {
self.find_mut_inner(id.into())
}
fn find_mut_inner(self, id: NodeId) -> Option<ArenaMut<'arena, T>> {
let parent_id = self.parents_map.parents_map.get(&id)?;
let id_path = if let Some(parent_id) = parent_id {
self.parents_map.get_id_path(*parent_id, self.parent_id)
} else {
Vec::new()
};
let mut id_path = id_path.as_slice();
let mut node_children: &'arena mut _ = &mut *self.children;
while let Some((ancestor_id, new_id_path)) = id_path.split_last() {
id_path = new_id_path;
node_children = &mut node_children.get_mut(ancestor_id)?.children;
}
let node = node_children.get_mut(&id)?;
Some(node.arena_mut(*parent_id, &mut *self.parents_map.parents_map))
}
#[doc(hidden)]
pub fn realloc_inner_storage(&mut self) {
std::hint::black_box(());
}
}
impl ArenaMapRef<'_> {
pub fn get_id_path(self, id: NodeId, start_id: Option<NodeId>) -> Vec<NodeId> {
let mut path = Vec::new();
if !self.parents_map.contains_key(&id) {
return path;
}
let mut current_id = Some(id);
while let Some(current) = current_id {
path.push(current);
current_id = *self
.parents_map
.get(¤t)
.expect("All ids in the tree should have a parent in the parent map");
if current_id == start_id {
break;
}
}
if current_id != start_id {
path.clear();
}
path
}
}
impl ArenaMapMut<'_> {
pub fn reborrow(&self) -> ArenaMapRef<'_> {
ArenaMapRef {
parents_map: self.parents_map,
}
}
pub fn reborrow_mut(&mut self) -> ArenaMapMut<'_> {
ArenaMapMut {
parents_map: self.parents_map,
}
}
pub fn get_id_path(&self, id: NodeId, start_id: Option<NodeId>) -> Vec<NodeId> {
self.reborrow().get_id_path(id, start_id)
}
}