use core::cell::BorrowError;
use core::fmt;
use crate::node::{FrozenNode, HotNode, Node};
use crate::traverse::{self, DftEvent};
use crate::tree::Tree;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Event<T> {
Open(T),
Close(usize),
}
impl<T> Event<T> {
#[inline]
pub fn map<F, U>(self, f: F) -> Event<U>
where
F: FnOnce(T) -> U,
{
match self {
Self::Open(v) => Event::Open(f(v)),
Self::Close(v) => Event::Close(v),
}
}
}
impl<T: Clone> TryFrom<DftEvent<Node<T>>> for Event<T> {
type Error = BorrowError;
fn try_from(ev: DftEvent<Node<T>>) -> Result<Self, Self::Error> {
match ev {
DftEvent::Open(node) => node.try_borrow_data().map(|data| Event::Open(data.clone())),
DftEvent::Close(_) => Ok(Event::Close(1)),
}
}
}
impl<T: Clone> TryFrom<DftEvent<FrozenNode<T>>> for Event<T> {
type Error = BorrowError;
fn try_from(ev: DftEvent<FrozenNode<T>>) -> Result<Self, Self::Error> {
match ev {
DftEvent::Open(node) => node.try_borrow_data().map(|data| Event::Open(data.clone())),
DftEvent::Close(_) => Ok(Event::Close(1)),
}
}
}
impl<T: Clone> TryFrom<DftEvent<HotNode<T>>> for Event<T> {
type Error = BorrowError;
fn try_from(ev: DftEvent<HotNode<T>>) -> Result<Self, Self::Error> {
match ev {
DftEvent::Open(node) => node.try_borrow_data().map(|data| Event::Open(data.clone())),
DftEvent::Close(_) => Ok(Event::Close(1)),
}
}
}
impl<T> FromIterator<Event<T>> for Result<Node<T>, TreeBuildError> {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = Event<T>>,
{
let mut builder = TreeBuilder::new();
builder.push_events(iter)?;
builder.finish()
}
}
impl<T: Clone> FromIterator<DftEvent<Node<T>>> for Result<Node<T>, TreeBuildError> {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = DftEvent<Node<T>>>,
{
let mut builder = TreeBuilder::new();
builder.push_dft_events(iter)?;
builder.finish()
}
}
impl<T> FromIterator<Event<T>> for Result<FrozenNode<T>, TreeBuildError> {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = Event<T>>,
{
let root = iter.into_iter().collect::<Result<Node<T>, _>>()?;
let frozen = root
.bundle_new_hierarchy_edit_prohibition()
.expect("[validity] brand-new tree must be lockable");
Ok(frozen)
}
}
impl<T> FromIterator<Event<T>> for Result<HotNode<T>, TreeBuildError> {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = Event<T>>,
{
let root = iter.into_iter().collect::<Result<Node<T>, _>>()?;
let hot = root
.bundle_new_hierarchy_edit_grant()
.expect("[validity] brand-new tree must be lockable");
Ok(hot)
}
}
impl<T> FromIterator<Event<T>> for Result<Tree<T>, TreeBuildError> {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = Event<T>>,
{
iter.into_iter()
.collect::<Result<Node<T>, _>>()
.map(|root| root.tree())
}
}
#[derive(Debug)]
pub enum TreeBuildError {
RootNotOpened,
RootClosed,
BorrowData(BorrowError),
}
impl fmt::Display for TreeBuildError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let msg = match self {
Self::RootNotOpened => "attempt to close a node while root node is not yet opened",
Self::RootClosed => {
"cannot receive events anymore since the root node is already closed"
}
Self::BorrowData(_) => "cannot borrow node data because it was exclusively borrowed",
};
f.write_str(msg)
}
}
#[cfg(feature = "std")]
impl std::error::Error for TreeBuildError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::BorrowData(e) => Some(e),
_ => None,
}
}
}
impl From<BorrowError> for TreeBuildError {
#[inline]
fn from(e: BorrowError) -> Self {
Self::BorrowData(e)
}
}
pub struct TreeBuilder<T> {
root: Option<Node<T>>,
current: Option<HotNode<T>>,
}
impl<T> Default for TreeBuilder<T> {
#[inline]
fn default() -> Self {
Self {
root: None,
current: None,
}
}
}
impl<T> TreeBuilder<T> {
#[inline]
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[inline]
#[must_use]
pub fn with_root(root: HotNode<T>) -> Self {
Self {
root: Some(root.plain()),
current: Some(root),
}
}
#[inline]
#[must_use]
pub fn is_root_closed(&self) -> bool {
self.root.is_some() && self.current.is_none()
}
#[inline]
#[must_use]
pub fn is_root_available(&self) -> bool {
self.root.is_some()
}
#[inline]
pub fn finish(self) -> Result<Node<T>, TreeBuildError> {
self.root.ok_or(TreeBuildError::RootNotOpened)
}
#[inline]
#[must_use]
pub fn finish_opt(self) -> Option<Node<T>> {
self.root
}
}
impl<T> TreeBuilder<T> {
pub fn open(&mut self, data: T) -> Result<(), TreeBuildError> {
if self.root.is_none() {
let root = HotNode::new_tree(data);
self.root = Some(root.plain());
self.current = Some(root);
return Ok(());
}
let current = self.current.as_mut().ok_or(TreeBuildError::RootClosed)?;
*current = current.create_as_last_child(data);
Ok(())
}
pub fn close(&mut self, level: usize) -> Result<(), TreeBuildError> {
if level == 0 {
return Ok(());
}
if let Some(current) = &mut self.current {
let parent_level = level - 1;
for _ in 0..parent_level {
let root = self
.root
.as_ref()
.expect("[validity] `root` should be set when some node is tracked");
if current.ptr_eq_plain(root) {
return Err(TreeBuildError::RootClosed);
}
*current = current.parent().ok_or(TreeBuildError::RootClosed)?;
}
self.current = current.parent();
Ok(())
} else if self.root.is_some() {
Err(TreeBuildError::RootClosed)
} else {
Err(TreeBuildError::RootNotOpened)
}
}
pub fn push_event(&mut self, ev: Event<T>) -> Result<(), TreeBuildError> {
match ev {
Event::Open(data) => self.open(data),
Event::Close(level) => self.close(level),
}
}
#[inline]
pub fn push_events<I>(&mut self, events: I) -> Result<(), TreeBuildError>
where
I: IntoIterator<Item = Event<T>>,
{
self.push_events_impl(events.into_iter())
}
fn push_events_impl<I>(&mut self, events: I) -> Result<(), TreeBuildError>
where
I: Iterator<Item = Event<T>>,
{
for ev in events {
match ev {
Event::Open(data) => self.open(data)?,
Event::Close(level) => self.close(level)?,
}
}
Ok(())
}
#[inline]
pub fn push_dft_event(&mut self, ev: DftEvent<Node<T>>) -> Result<(), TreeBuildError>
where
T: Clone,
{
let ev: Event<T> = ev.try_into()?;
self.push_event(ev)
}
pub fn push_dft_events<I>(&mut self, events: I) -> Result<(), TreeBuildError>
where
I: IntoIterator<Item = DftEvent<Node<T>>>,
T: Clone,
{
self.push_dft_events_impl(events.into_iter())
}
fn push_dft_events_impl<I>(&mut self, events: I) -> Result<(), TreeBuildError>
where
I: Iterator<Item = DftEvent<Node<T>>>,
T: Clone,
{
for ev in events.map(TryInto::try_into) {
match ev? {
Event::Open(node) => self.open(node)?,
Event::Close(level) => self.close(level)?,
}
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct TreeSerializeIter<T> {
inner: traverse::DepthFirstTraverser<T>,
}
impl<T: Clone> TreeSerializeIter<T> {
#[inline]
#[must_use]
pub(crate) fn new(node: &Node<T>) -> Self {
Self {
inner: node.depth_first_traverse(),
}
}
}
impl<T: Clone> Iterator for TreeSerializeIter<T> {
type Item = Result<Event<T>, BorrowError>;
fn next(&mut self) -> Option<Self::Item> {
match self.inner.next()? {
DftEvent::Open(node) => {
Some(node.try_borrow_data().map(|data| Event::Open(data.clone())))
}
DftEvent::Close(_) => {
let mut count: usize = 1;
while let Some(DftEvent::Close(_)) = self.inner.peek() {
match count.checked_add(1) {
Some(v) => {
self.inner.next();
count = v;
}
None => break,
};
}
Some(Ok(Event::Close(count)))
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use alloc::vec;
use alloc::vec::Vec;
use crate::traverse::DftEvent;
mod builder {
use super::*;
#[test]
fn root_not_opened() {
let builder = TreeBuilder::<i32>::new();
assert!(matches!(
builder.finish(),
Err(TreeBuildError::RootNotOpened)
));
}
#[test]
fn excessive_close() {
let mut builder = TreeBuilder::<&str>::new();
builder.open("root").expect("root is not yet closed");
assert!(matches!(builder.close(2), Err(TreeBuildError::RootClosed)));
}
}
mod event_streaming {
use super::*;
fn sample_events() -> Vec<Event<&'static str>> {
vec![
Event::Open("root"),
Event::Open("0"),
Event::Close(1),
Event::Open("1"),
Event::Open("1-0"),
Event::Close(1),
Event::Open("1-1"),
Event::Close(1),
Event::Open("1-2"),
Event::Open("1-2-0"),
Event::Close(3),
Event::Open("2"),
Event::Close(2),
]
}
const DFT_EVENTS: &[DftEvent<&str>] = &[
DftEvent::Open("root"),
DftEvent::Open("0"),
DftEvent::Close("0"),
DftEvent::Open("1"),
DftEvent::Open("1-0"),
DftEvent::Close("1-0"),
DftEvent::Open("1-1"),
DftEvent::Close("1-1"),
DftEvent::Open("1-2"),
DftEvent::Open("1-2-0"),
DftEvent::Close("1-2-0"),
DftEvent::Close("1-2"),
DftEvent::Close("1"),
DftEvent::Open("2"),
DftEvent::Close("2"),
DftEvent::Close("root"),
];
fn sample_tree() -> Node<&'static str> {
sample_events()
.into_iter()
.collect::<Result<_, _>>()
.expect("valid events that can construct tree")
}
#[test]
fn check_events() {
let root = sample_tree();
let dft_events = root
.depth_first_traverse()
.map(|ev| ev.map(|node| *node.borrow_data()))
.collect::<Vec<_>>();
assert_eq!(dft_events, DFT_EVENTS);
}
#[test]
fn roundtrip_from_events() {
let expected_events = sample_events();
let root: Node<&'static str> = expected_events
.iter()
.cloned()
.collect::<Result<_, _>>()
.expect("valid events that can construct tree");
let expected_events = expected_events.into_iter().collect::<Vec<_>>();
let events = root
.to_events()
.collect::<Result<Vec<_>, _>>()
.expect("data associated to any nodes are not borrowed");
assert_eq!(events, expected_events);
}
#[test]
fn collect_dft_events() {
let root = sample_tree();
let expected_events = sample_events();
let cloned_root: Node<_> = root
.depth_first_traverse()
.collect::<Result<_, _>>()
.expect("tree should be traversable and events should be consistent");
let events = cloned_root
.to_events()
.collect::<Result<Vec<_>, _>>()
.expect("data associated to any nodes are not borrowed");
assert_eq!(events, expected_events);
}
}
}