use core::fmt;
use core::ops::Range;
use crate::links::Links;
use crate::node::{Children, Event, Node, Walk, WalkEvents};
#[cfg(feature = "std")]
use crate::Error;
use crate::{Flavor, Index, Pointer, Span, Storage, Width};
pub struct Tree<T, F>
where
T: Copy,
F: Flavor,
{
tree: F::Storage<Links<T, F::Index, F::Pointer>>,
span: Span<F::Index>,
indexes: F::Indexes,
first: Option<F::Pointer>,
last: Option<F::Pointer>,
}
impl<T, F> Tree<T, F>
where
T: Copy,
F: Flavor,
{
pub(crate) const fn new_with() -> Self {
Self {
tree: F::Storage::EMPTY,
span: Span::point(F::Index::EMPTY),
indexes: F::Indexes::EMPTY,
first: None,
last: None,
}
}
#[cfg(feature = "std")]
pub(crate) fn with_capacity(capacity: usize) -> Result<Self, Error<F::Error>> {
Ok(Self {
tree: F::Storage::with_capacity(capacity)?,
span: Span::point(F::Index::EMPTY),
indexes: F::Indexes::EMPTY,
first: None,
last: None,
})
}
pub const fn span(&self) -> &Span<F::Index> {
&self.span
}
pub(crate) fn span_mut(&mut self) -> &mut Span<F::Index> {
&mut self.span
}
pub fn len(&self) -> usize {
self.tree.len()
}
pub fn is_empty(&self) -> bool {
self.tree.is_empty()
}
pub fn capacity(&self) -> usize {
self.tree.capacity()
}
pub fn children(&self) -> Children<'_, T, F> {
Children::new(&self.tree, self.first, self.last)
}
pub fn walk(&self) -> Walk<'_, T, F> {
Walk::new(&self.tree, self.first, Event::Next)
}
pub fn walk_events(&self) -> WalkEvents<'_, T, F> {
WalkEvents::new(&self.tree, self.first, Event::Next)
}
#[inline]
pub fn first(&self) -> Option<Node<'_, T, F>> {
self.get(self.first?)
}
#[inline]
pub fn last(&self) -> Option<Node<'_, T, F>> {
self.get(self.last?)
}
pub(crate) fn links_mut(&mut self) -> (&mut Option<F::Pointer>, &mut Option<F::Pointer>) {
(&mut self.first, &mut self.last)
}
pub(crate) fn get_mut(
&mut self,
id: F::Pointer,
) -> Option<&mut Links<T, F::Index, F::Pointer>> {
self.tree.get_mut(id.get())
}
pub(crate) fn push(&mut self, links: Links<T, F::Index, F::Pointer>) -> Result<(), F::Error> {
self.tree.push(links)
}
pub(crate) fn indexes_mut(&mut self) -> &mut F::Indexes {
&mut self.indexes
}
pub(crate) fn links_at_mut(
&mut self,
index: F::Pointer,
) -> Option<&mut Links<T, F::Index, F::Pointer>> {
self.tree.get_mut(index.get())
}
pub fn get(&self, id: F::Pointer) -> Option<Node<'_, T, F>> {
let cur = self.tree.get(id.get())?;
Some(Node::new(cur, &self.tree))
}
#[must_use]
pub fn range(&self) -> Range<usize> {
self.span.range()
}
#[must_use]
pub fn node_with_range(&self, span: Range<usize>) -> Option<Node<'_, T, F>> {
let start = F::Index::from_usize(span.start)?;
let end = F::Index::from_usize(span.end)?;
self.node_with_span_internal(start, end)
}
#[must_use]
pub fn node_with_span(&self, span: Span<F::Index>) -> Option<Node<'_, T, F>> {
self.node_with_span_internal(span.start, span.end)
}
fn node_with_span_internal(&self, start: F::Index, end: F::Index) -> Option<Node<'_, T, F>> {
let result = self.indexes.binary_search_by(|f| f.index.cmp(&start));
let n = match result {
Ok(n) => n.saturating_add(1),
Err(n) => n,
};
let mut node = self.get(self.indexes.get(n)?.id)?;
while let Some(parent) = node.parent() {
node = parent;
if parent.span().end >= end {
break;
}
}
Some(node)
}
}
impl<T, F> Clone for Tree<T, F>
where
T: Copy,
F: Flavor<Indexes: Clone, Width: Width<Pointer: Clone>>,
F::Storage<Links<T, F::Index, F::Pointer>>: Clone,
{
#[inline]
fn clone(&self) -> Self {
Self {
tree: self.tree.clone(),
span: self.span,
indexes: self.indexes.clone(),
first: self.first,
last: self.last,
}
}
}
impl<T, F> Default for Tree<T, F>
where
T: Copy,
F: Flavor,
{
#[inline]
fn default() -> Self {
Self::new_with()
}
}
impl<T, A, B> PartialEq<Tree<T, A>> for Tree<T, B>
where
T: Copy + PartialEq,
A: Flavor,
B: Flavor<Index: PartialEq<A::Index>>,
{
fn eq(&self, other: &Tree<T, A>) -> bool {
struct Item<'a, T, F>((isize, Node<'a, T, F>))
where
T: Copy,
F: Flavor;
impl<'a, T, A, B> PartialEq<Item<'a, T, A>> for Item<'a, T, B>
where
T: Copy + PartialEq,
A: Flavor,
B: Flavor<Index: PartialEq<A::Index>>,
{
#[inline]
fn eq(&self, other: &Item<'a, T, A>) -> bool {
self.0 .0 == other.0 .0 && self.0 .1.eq(&other.0 .1)
}
}
self.walk()
.with_depths()
.map(Item)
.eq(other.walk().with_depths().map(Item))
}
}
impl<T, F> Eq for Tree<T, F>
where
T: Copy + Eq,
F: Flavor<Index: Eq>,
{
}
impl<T, F> fmt::Debug for Tree<T, F>
where
T: Copy + fmt::Debug,
F: Flavor<Index: fmt::Debug>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
struct List<'a, T, F>(&'a Tree<T, F>)
where
T: Copy,
F: Flavor;
impl<T, F> fmt::Debug for List<'_, T, F>
where
T: Copy + fmt::Debug,
F: Flavor<Index: fmt::Debug>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.0.walk().with_depths()).finish()
}
}
f.debug_tuple("Tree").field(&List(self)).finish()
}
}