mod debug_print;
mod lock;
use core::cell::{BorrowError, RefCell};
use core::fmt;
use core::mem;
use alloc::rc::{Rc, Weak};
use crate::node::{Node, NodeCoreLink};
use crate::traverse::DftEvent;
pub use self::debug_print::{DebugPrettyPrint, DebugPrintTree, DebugPrintTreeLocal};
use self::lock::HierarchyLockManager;
pub(crate) use self::lock::LockAggregatorForNode;
pub use self::lock::{
HierarchyEditGrant, HierarchyEditGrantError, HierarchyEditProhibition,
HierarchyEditProhibitionError,
};
pub(crate) struct TreeCore<T> {
root: RefCell<NodeCoreLink<T>>,
lock_manager: HierarchyLockManager,
}
impl<T> TreeCore<T> {
#[must_use]
pub(crate) fn new_rc(root: NodeCoreLink<T>) -> Rc<Self> {
Rc::new(Self {
root: RefCell::new(root),
lock_manager: Default::default(),
})
}
#[must_use]
pub(crate) fn root_link(&self) -> NodeCoreLink<T> {
self.root
.try_borrow()
.expect("[consistency] `TreeCore::root` should not be borrowed nestedly")
.clone()
}
#[inline]
pub(crate) fn transfer_single_lock_to(
self: &Rc<TreeCore<T>>,
dest: &Rc<TreeCore<T>>,
) -> Result<(), ()> {
self.lock_manager
.transfer_single_lock_to(&dest.lock_manager)
}
pub fn replace_root(&self, new_root: NodeCoreLink<T>) -> NodeCoreLink<T> {
let mut root = self
.root
.try_borrow_mut()
.expect("[consistency] `TreeCore::root` should not be borrowed nestedly");
mem::replace(&mut *root, new_root)
}
}
impl<T> Drop for TreeCore<T> {
fn drop(&mut self) {
let root_link = self
.root
.try_borrow()
.expect("[validity] `TreeCore` is being accessed exclusively")
.clone();
let mut next = Some(DftEvent::Open(root_link));
while let Some(current) = next.take() {
next = current.next();
let close_link = match current {
DftEvent::Open(_) => continue,
DftEvent::Close(v) => v,
};
if let Some(parent_link) = close_link.parent_link() {
let next_sibling = close_link.replace_next_sibling(None);
parent_link.replace_first_child(next_sibling);
}
drop(close_link);
}
}
}
impl<T> TreeCore<T> {
#[inline]
#[must_use]
pub(crate) fn debug_print_local(&self) -> DebugPrintTreeLocal<'_, T> {
DebugPrintTreeLocal::new(self)
}
}
pub struct Tree<T> {
core: Rc<TreeCore<T>>,
}
impl<T> Clone for Tree<T> {
#[inline]
fn clone(&self) -> Self {
Self {
core: self.core.clone(),
}
}
}
impl<T> fmt::Debug for Tree<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.debug_print_local().fmt(f)
}
}
impl<T, U: PartialEq<U>> PartialEq<Tree<U>> for Tree<T>
where
T: PartialEq<U>,
{
#[inline]
fn eq(&self, other: &Tree<U>) -> bool {
self.try_eq(other).expect(
"[precondition] data associated to the nodes in both trees should be borrowable",
)
}
}
impl<T: Eq> Eq for Tree<T> {}
impl<T> Tree<T> {
#[inline]
#[must_use]
pub(crate) fn from_core_rc(core: Rc<TreeCore<T>>) -> Self {
Self { core }
}
#[inline]
#[must_use]
pub(crate) fn core(&self) -> &Rc<TreeCore<T>> {
&self.core
}
#[inline]
#[must_use]
pub fn root(&self) -> Node<T> {
let root_link = self.core.root_link();
Node::with_node_core(root_link)
}
#[inline]
pub fn prohibit_hierarchy_edit(
&self,
) -> Result<HierarchyEditProhibition<T>, HierarchyEditProhibitionError> {
HierarchyEditProhibition::new(&self.core)
}
#[inline]
pub fn grant_hierarchy_edit(&self) -> Result<HierarchyEditGrant<T>, HierarchyEditGrantError> {
HierarchyEditGrant::new(&self.core)
}
#[inline]
#[must_use]
pub fn ptr_eq(&self, other: &Self) -> bool {
Rc::ptr_eq(&self.core, &other.core)
}
#[inline]
pub fn try_eq<U>(&self, other: &Tree<U>) -> Result<bool, BorrowError>
where
T: PartialEq<U>,
{
self.root().try_eq(&other.root())
}
#[inline]
pub fn try_clone_tree(&self) -> Result<Self, BorrowError>
where
T: Clone,
{
self.root().try_clone_subtree().map(|root| root.tree())
}
#[inline]
#[must_use]
pub fn clone_tree(&self) -> Self
where
T: Clone,
{
self.try_clone_tree()
.expect("[precondition] data associated to nodes should be borrowable")
}
#[inline]
#[must_use]
pub fn downgrade(&self) -> TreeWeak<T> {
TreeWeak {
core: Rc::downgrade(&self.core),
}
}
}
impl<T> Tree<T> {
#[inline]
#[must_use]
pub fn debug_pretty_print(&self) -> DebugPrettyPrint<'_, T> {
DebugPrettyPrint::new(&self.core)
}
#[inline]
#[must_use]
pub fn debug_print_local(&self) -> DebugPrintTreeLocal<'_, T> {
self.core.debug_print_local()
}
#[inline]
#[must_use]
pub fn debug_print(&self) -> DebugPrintTree<'_, T>
where
T: fmt::Debug,
{
DebugPrintTree::new(self)
}
}
pub struct TreeWeak<T> {
core: Weak<TreeCore<T>>,
}
impl<T> Clone for TreeWeak<T> {
#[inline]
fn clone(&self) -> Self {
Self {
core: self.core.clone(),
}
}
}
impl<T> fmt::Debug for TreeWeak<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.upgrade() {
Some(tree) => tree.debug_print_local().fmt(f),
None => f.write_str("TreeWeak(<dropped>)"),
}
}
}
impl<T> TreeWeak<T> {
#[inline]
#[must_use]
pub fn upgrade(&self) -> Option<Tree<T>> {
Weak::upgrade(&self.core).map(|core| Tree { core })
}
}