use std::num::NonZeroUsize;
use std::ops::{Add, Sub};
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum TreePointer {
Nil,
Valid(TreeIndex),
}
impl TreePointer {
pub fn unwrap(self) -> TreeIndex {
match self {
TreePointer::Nil => panic!("Called unwrap on a Nil value"),
TreePointer::Valid(ix) => ix,
}
}
}
#[derive(Debug, Eq, PartialEq, Copy, Clone, PartialOrd)]
pub struct TreeIndex(NonZeroUsize);
impl TreeIndex {
fn new(i: usize) -> Self {
TreeIndex(NonZeroUsize::new(i).unwrap())
}
pub fn get(self) -> usize {
self.0.get()
}
}
impl Add<usize> for TreeIndex {
type Output = TreeIndex;
fn add(self, rhs: usize) -> Self {
let inner = self.0.get() + rhs;
TreeIndex::new(inner)
}
}
impl Sub<usize> for TreeIndex {
type Output = TreeIndex;
fn sub(self, rhs: usize) -> Self {
let inner = self.0.get().checked_sub(rhs).unwrap();
TreeIndex::new(inner)
}
}
#[derive(Debug)]
pub struct Node<T> {
pub child: TreePointer,
pub next: TreePointer,
pub item: T,
}
pub struct Tree<T> {
nodes: Vec<Node<T>>,
spine: Vec<TreeIndex>, cur: TreePointer,
}
impl<T: Default> Tree<T> {
pub fn new() -> Tree<T> {
Tree {
nodes: vec![Node {
child: TreePointer::Nil,
next: TreePointer::Nil,
item: <T as Default>::default(),
}],
spine: Vec::new(),
cur: TreePointer::Nil,
}
}
pub fn cur(&self) -> TreePointer {
self.cur
}
pub fn append(&mut self, item: T) -> TreeIndex {
let ix = self.create_node(item);
let this = TreePointer::Valid(ix);
if let TreePointer::Valid(ix) = self.cur {
self[ix].next = this;
} else if let Some(&parent) = self.spine.last() {
self[parent].child = this;
}
self.cur = this;
ix
}
pub fn create_node(&mut self, item: T) -> TreeIndex {
let this = self.nodes.len();
self.nodes.push(Node {
child: TreePointer::Nil,
next: TreePointer::Nil,
item,
});
TreeIndex::new(this)
}
pub fn push(&mut self) {
let cur_ix = self.cur.unwrap();
self.spine.push(cur_ix);
self.cur = self[cur_ix].child;
}
pub fn pop(&mut self) -> Option<TreeIndex> {
let ix = self.spine.pop()?;
self.cur = TreePointer::Valid(ix);
Some(ix)
}
pub fn peek_up(&self) -> Option<TreeIndex> {
self.spine.last().cloned()
}
pub fn peek_grandparent(&self) -> Option<TreeIndex> {
if self.spine.len() >= 2 {
Some(self.spine[self.spine.len() - 2])
} else {
None
}
}
pub fn is_empty(&self) -> bool {
self.nodes.len() <= 1
}
pub fn spine_len(&self) -> usize {
self.spine.len()
}
pub fn reset(&mut self) {
self.cur = if self.is_empty() {
TreePointer::Nil
} else {
TreePointer::Valid(TreeIndex::new(1))
};
self.spine.truncate(0);
}
pub fn walk_spine(&self) -> impl Iterator<Item = &TreeIndex> {
self.spine.iter()
}
pub fn next_sibling(&mut self) -> TreePointer {
let next = self[self.cur.unwrap()].next;
self.cur = next;
next
}
}
impl<T> std::ops::Index<TreeIndex> for Tree<T> {
type Output = Node<T>;
fn index(&self, ix: TreeIndex) -> &Self::Output {
self.nodes.index(ix.get())
}
}
impl<T> std::ops::IndexMut<TreeIndex> for Tree<T> {
fn index_mut(&mut self, ix: TreeIndex) -> &mut Node<T> {
self.nodes.index_mut(ix.get())
}
}