#![cfg_attr(not(windows), doc = include_str!("../README.md"))]
#![cfg_attr(windows, doc = include_str!("..\\README.md"))]
#![no_std]
pub trait DeepSafeDrop<Link>
{
#[inline]
fn take_next_child_at_any_index(&mut self) -> Option<Link>
{
self.take_child_at_index_0().or_else(|| self.take_next_child_at_pos_index())
}
fn set_parent_at_index_0(
&mut self,
parent: Link,
) -> SetParent<Link>;
fn take_child_at_index_0(&mut self) -> Option<Link>;
fn take_next_child_at_pos_index(&mut self) -> Option<Link>;
}
#[derive(Debug)]
#[allow(clippy::exhaustive_enums)]
pub enum SetParent<Link>
{
YesReplacedChild
{
child0: Link,
},
Yes,
No
{
returned_parent: Link,
},
}
pub trait Link<Node: ?Sized>
{
fn get_mut(&mut self) -> &mut Node;
}
fn drop_leaf<L, N>(mut link: L)
where
L: Link<N>,
N: DeepSafeDrop<L> + ?Sized,
{
let node = link.get_mut();
debug_assert!(node.take_next_child_at_any_index().is_none(), "must be leaf");
debug_assert!(node.take_child_at_index_0().is_none(), "must be leaf");
debug_assert!(node.take_next_child_at_pos_index().is_none(), "must be leaf");
drop(link);
}
fn take_parent<L, N>(node: &mut N) -> Option<L>
where N: DeepSafeDrop<L> + ?Sized
{
let child0 = node.take_child_at_index_0();
debug_assert!(node.take_child_at_index_0().is_none(), "must be gone after take");
child0
}
fn take_ancestor_next_child<L, N>(parent: L) -> (L, Option<L>)
where
L: Link<N>,
N: DeepSafeDrop<L> + ?Sized,
{
let mut ancestor = parent;
loop {
if let Some(next_child) = ancestor.get_mut().take_next_child_at_pos_index() {
break (ancestor, Some(next_child));
}
else if let Some(grandancestor) = take_parent(ancestor.get_mut()) {
drop_leaf(ancestor); ancestor = grandancestor;
}
else {
break (ancestor, None);
}
}
}
fn main_deep_safe_drop<L, N>(top: L)
where
L: Link<N>,
N: DeepSafeDrop<L> + ?Sized,
{
let mut parent = top;
if let Some(mut cur) = parent.get_mut().take_next_child_at_any_index() {
loop {
match cur.get_mut().set_parent_at_index_0(parent) {
SetParent::YesReplacedChild { child0 } => {
parent = cur;
cur = child0;
continue;
},
SetParent::Yes => {
let next = cur.get_mut().take_next_child_at_pos_index();
parent = cur;
if let Some(child) = next {
cur = child;
continue;
}
},
SetParent::No { returned_parent } => {
parent = returned_parent;
drop_leaf(cur); },
}
let (ancestor, ancestor_child) = take_ancestor_next_child(parent);
parent = ancestor;
if let Some(ancestor_child) = ancestor_child {
cur = ancestor_child;
}
else {
drop_leaf(parent);
break;
}
}
}
}
#[inline]
pub fn deep_safe_drop<RootNode, Link, Node>(root: &mut RootNode)
where
RootNode: DeepSafeDrop<Link> + ?Sized,
Link: crate::Link<Node>,
Node: DeepSafeDrop<Link> + ?Sized,
{
while let Some(next_child) = root.take_next_child_at_any_index() {
main_deep_safe_drop(next_child);
}
}