use core::cmp::Ordering;
use alloc::rc::Rc;
use crate::anchor::{AdoptAs, InsertAs};
use crate::membership::Membership;
use crate::node::{HierarchyError, HotNode, IntraTreeLink, IntraTreeLinkWeak, Node, NodeBuilder};
use crate::serial::{TreeBuildError, TreeBuilder};
use crate::traverse::DftEvent;
use crate::tree::TreeCore;
struct OrphanRoot<'a, T> {
link: &'a IntraTreeLink<T>,
is_newly_created: bool,
}
impl<'a, T> OrphanRoot<'a, T> {
fn create_and_process<F, E>(
data: T,
tree_core: Rc<TreeCore<T>>,
process: F,
) -> Result<Node<T>, E>
where
for<'b> F: FnOnce(OrphanRoot<'b, T>) -> Result<(), E>,
{
let membership = Membership::create_new_membership(tree_core);
let intra_link = NodeBuilder {
data,
parent: Default::default(),
first_child: Default::default(),
next_sibling: Default::default(),
prev_sibling_cyclic: Default::default(),
membership: membership.downgrade(),
num_children: 0,
}
.build_link();
let node = Node::with_link_and_membership(intra_link, membership);
process(OrphanRoot {
link: &node.intra_link,
is_newly_created: true,
})?;
Ok(node)
}
#[must_use]
fn new_by_unlink(node_to_unlink: &'a IntraTreeLink<T>) -> Self {
if node_to_unlink.is_root() {
return Self {
link: node_to_unlink,
is_newly_created: false,
};
}
let parent = node_to_unlink.parent_link();
let prev_sibling = node_to_unlink.prev_sibling_link();
let prev_sibling_cyclic = node_to_unlink.prev_sibling_cyclic_link();
let next_sibling = node_to_unlink.next_sibling_link();
if let Some(parent) = &parent {
if node_to_unlink.is_first_sibling() {
parent.replace_first_child(next_sibling.clone());
}
debug_assert!(
parent.num_children_cell().get() > 0,
"parent should have a child"
);
parent.num_children_sub(1);
}
if let Some(prev_sibling) = prev_sibling {
prev_sibling.replace_next_sibling(next_sibling.clone());
}
if let Some(next_sibling) = next_sibling {
next_sibling.replace_prev_sibling_cyclic(prev_sibling_cyclic.downgrade());
}
node_to_unlink.replace_parent(IntraTreeLinkWeak::default());
let link_weak = node_to_unlink.downgrade();
node_to_unlink.replace_prev_sibling_cyclic(link_weak);
node_to_unlink.replace_next_sibling(None);
Self {
link: node_to_unlink,
is_newly_created: true,
}
}
#[inline]
fn set_tree_core(&self, tree_core: &Rc<TreeCore<T>>) -> Result<(), ()> {
set_memberships_of_descendants_and_self(self.link, tree_core)
}
#[inline]
fn create_new_tree(self) {
let tree_core = TreeCore::new_rc(self.link.clone());
self.set_tree_core(&tree_core)
.expect("[validity] brand-new tree hierarchy can be locked by any types of lock");
}
#[must_use]
fn is_ancestor_of(&self, node: IntraTreeLink<T>) -> bool {
let mut current = Some(node);
while let Some(ancestor) = current {
if self.link.ptr_eq(&ancestor) {
return true;
}
current = ancestor.parent_link();
}
false
}
fn insert(self, dest: InsertAs<&IntraTreeLink<T>>) -> Result<(), HierarchyError> {
match dest {
InsertAs::FirstChildOf(parent) => self.insert_as_first_child_of(parent),
InsertAs::LastChildOf(parent) => self.insert_as_last_child_of(parent),
InsertAs::PreviousSiblingOf(anchor) => {
let parent = anchor
.parent_link()
.ok_or(HierarchyError::SiblingsWithoutParent)?;
match anchor.prev_sibling_link() {
Some(prev_sibling) => {
self.insert_between(&parent, &prev_sibling, anchor);
Ok(())
}
None => self.insert_as_first_child_of(&parent),
}
}
InsertAs::NextSiblingOf(anchor) => {
let parent = anchor
.parent_link()
.ok_or(HierarchyError::SiblingsWithoutParent)?;
match anchor.next_sibling_link() {
Some(next_sibling) => {
self.insert_between(&parent, anchor, &next_sibling);
Ok(())
}
None => self.insert_as_last_child_of(&parent),
}
}
}
}
fn insert_as_first_child_of(self, parent: &IntraTreeLink<T>) -> Result<(), HierarchyError> {
if !self.is_newly_created && self.is_ancestor_of(parent.clone()) {
return Err(HierarchyError::AncestorDescendantLoop);
}
if let Some((old_first_child, last_child)) = parent.first_last_child_link() {
self.link
.replace_prev_sibling_cyclic(last_child.downgrade());
IntraTreeLink::connect_adjacent_siblings(self.link, old_first_child);
} else {
self.link.replace_prev_sibling_cyclic(self.link.downgrade());
}
self.link.replace_parent(parent.downgrade());
parent.replace_first_child(Some(self.link.clone()));
parent.num_children_add(1);
Ok(())
}
fn insert_as_last_child_of(self, parent: &IntraTreeLink<T>) -> Result<(), HierarchyError> {
if !self.is_newly_created && self.is_ancestor_of(parent.clone()) {
return Err(HierarchyError::AncestorDescendantLoop);
}
if let Some((first_child, old_last_child)) = parent.first_last_child_link() {
first_child.replace_prev_sibling_cyclic(self.link.downgrade());
IntraTreeLink::connect_adjacent_siblings(&old_last_child, self.link.clone());
} else {
self.link.replace_prev_sibling_cyclic(self.link.downgrade());
parent.replace_first_child(Some(self.link.clone()));
}
self.link.replace_parent(parent.downgrade());
parent.num_children_add(1);
Ok(())
}
fn insert_between(
self,
parent: &IntraTreeLink<T>,
prev_sibling: &IntraTreeLink<T>,
next_sibling: &IntraTreeLink<T>,
) {
debug_assert!(
prev_sibling
.parent_link()
.map_or(false, |p| IntraTreeLink::ptr_eq(&p, parent)),
"`prev_sibling` must be a child of `parent`"
);
debug_assert!(
next_sibling
.parent_link()
.map_or(false, |p| IntraTreeLink::ptr_eq(&p, parent)),
"`next_sibling` must be a child of `parent`"
);
debug_assert!(
prev_sibling
.next_sibling_link()
.map_or(false, |p| IntraTreeLink::ptr_eq(&p, next_sibling)),
"`next_sibling` must be the next sibling of `prev_sibling`"
);
debug_assert!(
next_sibling
.prev_sibling_link()
.map_or(false, |p| IntraTreeLink::ptr_eq(&p, prev_sibling)),
"`prev_sibling` must be the previous sibling of `next_sibling`"
);
self.link.replace_parent(parent.downgrade());
let next_sibling_owned = prev_sibling.replace_next_sibling(Some(self.link.clone()));
self.link.replace_next_sibling(next_sibling_owned);
let prev_sibling_weak = next_sibling.replace_prev_sibling_cyclic(self.link.downgrade());
self.link.replace_prev_sibling_cyclic(prev_sibling_weak);
parent.num_children_add(1);
}
}
#[inline]
pub(super) fn detach_subtree<T>(this: &IntraTreeLink<T>) {
if this.is_root() {
return;
}
let orphan_this = OrphanRoot::new_by_unlink(this);
orphan_this.create_new_tree();
}
#[inline]
pub(super) fn detach_and_move_inside_same_tree<T>(
this: &IntraTreeLink<T>,
dest: InsertAs<&IntraTreeLink<T>>,
) -> Result<(), HierarchyError> {
if this.is_root() {
return Ok(());
}
let orphan_this = OrphanRoot::new_by_unlink(this);
orphan_this.insert(dest)
}
pub(super) fn detach_and_move_to_another_tree<T>(
this: &IntraTreeLink<T>,
dest: InsertAs<&IntraTreeLink<T>>,
dest_tree_core: &Rc<TreeCore<T>>,
) -> Result<(), HierarchyError> {
let orphan_this = OrphanRoot::new_by_unlink(this);
orphan_this
.set_tree_core(dest_tree_core)
.expect("[consistency] brand-new tree hierarchy can be locked by any types of lock");
orphan_this.insert(dest)
}
fn set_memberships_of_descendants_and_self<T>(
this: &IntraTreeLink<T>,
tree_core_rc: &Rc<TreeCore<T>>,
) -> Result<(), ()> {
for current in this.depth_first_traverse() {
if let DftEvent::Open(link) = current {
link.membership().set_tree_core(tree_core_rc)?;
}
}
Ok(())
}
pub(super) fn try_create_node_as<T>(
this: &IntraTreeLink<T>,
tree_core: Rc<TreeCore<T>>,
data: T,
dest: AdoptAs,
) -> Result<Node<T>, HierarchyError> {
match dest {
AdoptAs::FirstChild => Ok(create_as_first_child(this, tree_core, data)),
AdoptAs::LastChild => Ok(create_as_last_child(this, tree_core, data)),
AdoptAs::PreviousSibling => try_create_as_prev_sibling(this, tree_core, data),
AdoptAs::NextSibling => try_create_as_next_sibling(this, tree_core, data),
}
}
pub(super) fn create_as_first_child<T>(
this: &IntraTreeLink<T>,
tree_core: Rc<TreeCore<T>>,
data: T,
) -> Node<T> {
debug_assert!(
this.belongs_to_tree_core_rc(&tree_core),
"[validity] the given node link must belong to the tree with the given core"
);
OrphanRoot::create_and_process(data, tree_core, |orphan_link| {
orphan_link.insert_as_first_child_of(this)
})
.expect("[validity] the hierarchy of the tree the parent belongs to should be editable")
}
pub(super) fn create_as_last_child<T>(
this: &IntraTreeLink<T>,
tree_core: Rc<TreeCore<T>>,
data: T,
) -> Node<T> {
debug_assert!(
this.belongs_to_tree_core_rc(&tree_core),
"[validity] the given node link must belong to the tree with the given core"
);
OrphanRoot::create_and_process(data, tree_core, |orphan_link| {
orphan_link.insert_as_last_child_of(this)
})
.expect("[validity] the hierarchy of the tree the parent belongs to should be editable")
}
pub(super) fn try_create_as_prev_sibling<T>(
this: &IntraTreeLink<T>,
tree_core: Rc<TreeCore<T>>,
data: T,
) -> Result<Node<T>, HierarchyError> {
debug_assert!(
this.belongs_to_tree_core_rc(&tree_core),
"[validity] the given node link must belong to the tree with the given core"
);
OrphanRoot::create_and_process(data, tree_core, |orphan_link| {
orphan_link.insert(InsertAs::PreviousSiblingOf(this))
})
}
pub(super) fn try_create_as_next_sibling<T>(
this: &IntraTreeLink<T>,
tree_core: Rc<TreeCore<T>>,
data: T,
) -> Result<Node<T>, HierarchyError> {
debug_assert!(
this.belongs_to_tree_core_rc(&tree_core),
"[validity] the given node link must belong to the tree with the given core"
);
OrphanRoot::create_and_process(data, tree_core, |orphan_link| {
orphan_link.insert(InsertAs::NextSiblingOf(this))
})
}
pub(super) fn create_as_interrupting_parent<T>(
this: &IntraTreeLink<T>,
tree_core: Rc<TreeCore<T>>,
data: T,
) -> Node<T> {
OrphanRoot::create_and_process(data, tree_core.clone(), |new| {
if let Some(parent) = this.parent_link() {
let new_link = new.link;
if let Some(next_sib) = this.next_sibling_link() {
new.insert_between(&parent, this, &next_sib);
} else {
new.insert_as_last_child_of(&parent)
.expect("[validity] newly created node won't make no loop");
}
detach_and_move_inside_same_tree(this, InsertAs::LastChildOf(new_link))
.expect("[validity] the new node is neither ancestor nor descendant of `this`");
} else {
let new_downgraded = new.link.downgrade();
tree_core.replace_root(new.link.clone());
new.link.replace_prev_sibling_cyclic(new_downgraded.clone());
new.link.replace_first_child(Some(this.clone()));
this.replace_parent(new_downgraded);
new.link.num_children_add(1);
}
Ok::<_, core::convert::Infallible>(())
})
.expect("[validity] the operation is infallible")
}
pub(super) fn create_as_interrupting_child<T>(
this: &IntraTreeLink<T>,
tree_core: Rc<TreeCore<T>>,
data: T,
) -> Node<T> {
OrphanRoot::create_and_process(data, tree_core, |new| {
let first_child = this.replace_first_child(Some(new.link.clone()));
new.link.replace_parent(this.downgrade());
{
new.link.replace_first_child(first_child.clone());
let mut child_next = first_child;
while let Some(child) = &child_next {
child.replace_parent(new.link.downgrade());
child_next = child.next_sibling_link();
}
}
new.link
.num_children_cell()
.set(this.num_children_cell().get());
this.num_children_cell().set(1);
Ok::<_, core::convert::Infallible>(())
})
.expect("[validity] the operation is infallible")
}
pub(super) fn try_replace_with_children<T>(
this: &IntraTreeLink<T>,
tree_core: &Rc<TreeCore<T>>,
) -> Result<(), HierarchyError> {
let first_child_link = this.first_child_link();
if let Some(parent_link) = this.parent_link() {
{
let mut next = first_child_link.clone();
while let Some(current) = next {
next = current.next_sibling_link();
current.replace_parent(parent_link.downgrade());
}
}
let prev_sibling_link = this.prev_sibling_link();
let next_sibling_link = this.next_sibling_link();
if let Some(first_child_link) = first_child_link {
let last_child_link = first_child_link.prev_sibling_cyclic_link();
match (prev_sibling_link, next_sibling_link) {
(Some(prev_sibling_link), Some(next_sibling_link)) => {
IntraTreeLink::connect_adjacent_siblings(&prev_sibling_link, first_child_link);
IntraTreeLink::connect_adjacent_siblings(&last_child_link, next_sibling_link);
}
(Some(prev_sibling_link), None) => {
IntraTreeLink::connect_adjacent_siblings(&prev_sibling_link, first_child_link);
let first_sibling_link = parent_link
.first_child_link()
.expect("[validity] the parent has at least one child (prev of `self`)");
first_sibling_link.replace_prev_sibling_cyclic(last_child_link.downgrade());
}
(None, Some(next_sibling_link)) => {
IntraTreeLink::connect_adjacent_siblings(&last_child_link, next_sibling_link);
let last_sibling_link_weak = parent_link
.last_child_link_weak()
.expect("[validity] the parent has at least one child (next of `self`)");
first_child_link.replace_prev_sibling_cyclic(last_sibling_link_weak);
parent_link.replace_first_child(Some(first_child_link));
}
(None, None) => {
parent_link.replace_first_child(Some(first_child_link));
}
}
} else {
match (prev_sibling_link, next_sibling_link) {
(Some(prev_sibling_link), Some(next_sibling_link)) => {
IntraTreeLink::connect_adjacent_siblings(&prev_sibling_link, next_sibling_link);
}
(Some(prev_sibling_link), None) => {
prev_sibling_link.replace_next_sibling(None);
}
(None, Some(next_sibling_link)) => {
let last_sibling_link_weak = parent_link
.last_child_link_weak()
.expect("[validity] the parent has at least one child (next of `self`)");
next_sibling_link.replace_prev_sibling_cyclic(last_sibling_link_weak);
parent_link.replace_first_child(Some(next_sibling_link));
}
(None, None) => {
parent_link.replace_first_child(None);
}
}
}
debug_assert!(
parent_link.num_children_cell().get() > 0,
"[consistency] `parent` has a child `this`"
);
parent_link.num_children_sub(1);
parent_link.num_children_add(this.num_children_cell().get());
} else {
debug_assert!(
this.is_root(),
"[validity] the node without parent must be the root"
);
let child_link = match this.num_children_cell().get().cmp(&1) {
Ordering::Less => return Err(HierarchyError::EmptyTree),
Ordering::Equal => first_child_link.expect("[consistency] the parent node has a child"),
Ordering::Greater => return Err(HierarchyError::SiblingsWithoutParent),
};
child_link.replace_parent(IntraTreeLinkWeak::default());
tree_core.replace_root(child_link);
}
this.replace_parent(IntraTreeLinkWeak::default());
this.replace_first_child(None);
let this_weak = this.downgrade();
this.replace_prev_sibling_cyclic(this_weak);
this.replace_next_sibling(None);
this.num_children_cell().set(0);
let tree_core_rc = TreeCore::new_rc(this.clone());
set_memberships_of_descendants_and_self(this, &tree_core_rc)
.expect("[validity] brand-new tree hierarchy can be locked by any types of lock");
Ok(())
}
pub(super) fn try_clone_insert_subtree<T>(
source: &Node<T>,
dest: InsertAs<&HotNode<T>>,
) -> Result<HotNode<T>, HierarchyError>
where
T: Clone,
{
let subtree_root = dest.try_create_node(
source
.try_borrow_data()
.map_err(HierarchyError::BorrowNodeData)?
.clone(),
)?;
let mut events = source.to_events();
events.next();
events
.try_fold(
TreeBuilder::with_root(subtree_root),
|mut builder, ev_res| {
builder.push_event(ev_res?)?;
Ok(builder)
},
)
.and_then(|builder| builder.finish())
.map(|node| {
node.bundle_new_hierarchy_edit_grant()
.expect("[consistency] the hierarchy of the destination tree is already editable")
})
.map_err(|e| match e {
TreeBuildError::BorrowData(e) => HierarchyError::BorrowNodeData(e),
TreeBuildError::RootNotOpened | TreeBuildError::RootClosed => {
unreachable!("[validity] subtree should be consistently serializable")
}
})
}
#[cfg(test)]
mod tests {
use crate::HotNode;
#[test]
fn num_children_after_replace_with_children() {
let root = HotNode::new_tree("root");
let child0 = root.create_as_last_child("0");
let child1 = root.create_as_last_child("1");
let child1_0 = child1.create_as_last_child("1-0");
let child1_1 = child1.create_as_last_child("1-1");
let child1_2 = child1.create_as_last_child("1-2");
let child2 = root.create_as_last_child("2");
assert_eq!(root.num_children(), 3);
assert_eq!(child0.num_children(), 0);
assert_eq!(child1.num_children(), 3);
assert_eq!(child1_0.num_children(), 0);
assert_eq!(child1_1.num_children(), 0);
assert_eq!(child1_2.num_children(), 0);
assert_eq!(child2.num_children(), 0);
child1.replace_with_children();
assert_eq!(root.num_children(), 5);
assert_eq!(child0.num_children(), 0);
assert_eq!(child1_0.num_children(), 0);
assert_eq!(child1_1.num_children(), 0);
assert_eq!(child1_2.num_children(), 0);
assert_eq!(child2.num_children(), 0);
assert_eq!(child1.num_children(), 0);
}
#[test]
fn num_children_after_replace_root_with_children() {
let root = HotNode::new_tree("root");
let child0 = root.create_as_last_child("0");
let child0_0 = child0.create_as_last_child("0-0");
let child0_1 = child0.create_as_last_child("0-1");
let child0_2 = child0.create_as_last_child("0-2");
assert_eq!(root.num_children(), 1);
assert_eq!(child0.num_children(), 3);
assert_eq!(child0_0.num_children(), 0);
assert_eq!(child0_1.num_children(), 0);
assert_eq!(child0_2.num_children(), 0);
child0.replace_with_children();
assert_eq!(root.num_children(), 3);
assert_eq!(child0_0.num_children(), 0);
assert_eq!(child0_1.num_children(), 0);
assert_eq!(child0_2.num_children(), 0);
assert_eq!(child0.num_children(), 0);
}
}