use super::*;
use recursive_reference::*;
use crate::trees::SomeWalker;
pub(super) struct Frame<D: ?Sized + Data> {
pub left: D::Summary,
pub right: D::Summary,
}
impl<D: ?Sized + Data> Clone for Frame<D>
where
D::Summary: Clone,
{
fn clone(&self) -> Self {
Frame {
left: self.left.clone(),
right: self.right.clone(),
}
}
}
impl<D: Data> Frame<D> {
pub fn empty() -> Frame<D> {
Frame {
left: Default::default(),
right: Default::default(),
}
}
}
#[derive(destructure)]
pub struct BasicWalker<'a, D: Data, T = ()> {
pub(super) rec_ref: RecRef<'a, BasicTree<D, T>>,
pub(super) vals: Vec<Frame<D>>,
pub(super) is_left: Vec<Side>,
}
impl<'a, D: Data, T> BasicWalker<'a, D, T> {
pub fn new(tree: &'a mut BasicTree<D, T>) -> BasicWalker<'a, D, T> {
tree.access();
BasicWalker {
rec_ref: RecRef::new(tree),
vals: vec![Frame::empty()],
is_left: vec![],
}
}
pub fn new_with_context(
tree: &'a mut BasicTree<D, T>,
left_summary: D::Summary,
right_summary: D::Summary,
) -> BasicWalker<'a, D, T> {
tree.access();
BasicWalker {
rec_ref: RecRef::new(tree),
vals: vec![Frame {
left: left_summary,
right: right_summary,
}],
is_left: vec![],
}
}
pub fn is_empty(&self) -> bool {
self.rec_ref.is_empty()
}
pub fn is_root(&self) -> bool {
self.is_left.is_empty()
}
pub fn is_left_son(&self) -> Option<Side> {
self.is_left.last().cloned()
}
pub(in super::super) fn rebuild(&mut self) {
self.rec_ref.rebuild();
}
pub fn inner(&self) -> &BasicTree<D, T> {
&*self.rec_ref
}
pub(in super::super) fn inner_mut(&mut self) -> &mut BasicTree<D, T> {
&mut *self.rec_ref
}
pub fn node(&self) -> Option<&BasicNode<D, T>> {
self.rec_ref.node()
}
pub(in super::super) fn node_mut(&mut self) -> Option<&mut BasicNode<D, T>> {
self.rec_ref.node_mut()
}
pub fn rot_left(&mut self) -> Option<()> {
self.rot_left_with_custom_rebuilder(|_| {})
}
pub fn rot_left_with_custom_rebuilder<F: FnMut(&mut BasicNode<D, T>)>(
&mut self,
mut rebuilder: F,
) -> Option<()> {
let owned_tree = std::mem::replace(&mut *self.rec_ref, BasicTree::Empty);
let mut bn1: Box<BasicNode<D, T>> = owned_tree.into_node_boxed()?;
assert!(bn1.action.is_identity());
let mut bn2: Box<BasicNode<D, T>> = bn1.right.into_node_boxed()?;
bn2.access();
bn1.right = bn2.left;
bn2.subtree_summary = bn1.subtree_summary; bn1.rebuild();
rebuilder(&mut *bn1);
bn2.left = BasicTree::from_boxed_node(bn1);
rebuilder(&mut *bn2);
*self.rec_ref = BasicTree::from_boxed_node(bn2); Some(())
}
pub fn rot_right(&mut self) -> Option<()> {
self.rot_right_with_custom_rebuilder(|_| {})
}
pub fn rot_right_with_custom_rebuilder<F: FnMut(&mut BasicNode<D, T>)>(
&mut self,
mut rebuilder: F,
) -> Option<()> {
let owned_tree = std::mem::replace(&mut *self.rec_ref, BasicTree::Empty);
let mut bn1: Box<BasicNode<D, T>> = owned_tree.into_node_boxed()?;
assert!(bn1.action.is_identity());
let mut bn2: Box<BasicNode<D, T>> = bn1.left.into_node_boxed()?;
bn2.access();
bn1.left = bn2.right;
bn2.subtree_summary = bn1.subtree_summary; bn1.rebuild();
rebuilder(&mut *bn1);
bn2.right = BasicTree::from_boxed_node(bn1);
rebuilder(&mut *bn2);
*self.rec_ref = BasicTree::from_boxed_node(bn2); Some(())
}
pub fn rot_side(&mut self, side: Side) -> Option<()> {
match side {
Side::Left => self.rot_left(),
Side::Right => self.rot_right(),
}
}
pub fn rot_side_with_custom_rebuilder<F: FnMut(&mut BasicNode<D, T>)>(
&mut self,
side: Side,
rebuilder: F,
) -> Option<()> {
match side {
Side::Left => self.rot_left_with_custom_rebuilder(rebuilder),
Side::Right => self.rot_right_with_custom_rebuilder(rebuilder),
}
}
pub fn rot_up(&mut self) -> Result<Side, ()> {
let b = self.go_up()?;
self.rot_side(b.flip())
.expect("original node went missing?");
Ok(b)
}
pub fn rot_up_with_custom_rebuilder<F: FnMut(&mut BasicNode<D, T>)>(
&mut self,
rebuilder: F,
) -> Result<Side, ()> {
let b = self.go_up()?;
self.rot_side_with_custom_rebuilder::<F>(b.flip(), rebuilder)
.expect("original node went missing?");
Ok(b)
}
pub fn go_to_root(&mut self) {
while self.go_up().is_ok() {}
}
pub fn root_into_ref(mut self) -> &'a mut BasicTree<D, T> {
self.go_to_root();
let (tel, _, _) = self.destructure();
RecRef::into_ref(tel)
}
pub fn detached_walker(&mut self) -> BasicWalker<D, T> {
let left = self.far_left_summary();
let right = self.far_right_summary();
BasicWalker::new_with_context(self.inner_mut(), left, right)
}
pub fn insert_with_alg_data(&mut self, value: D::Value, alg_data: T) -> Option<()> {
match *self.rec_ref {
Empty => {
*self.rec_ref = BasicTree::from_node(BasicNode::new_alg(value, alg_data));
Some(())
}
_ => None,
}
}
pub(in super::super) fn take_subtree(&mut self) -> BasicTree<D, T> {
std::mem::replace(&mut *self.rec_ref, BasicTree::Empty)
}
pub(in super::super) fn put_subtree(&mut self, new: BasicTree<D, T>) -> Option<()> {
if self.rec_ref.is_empty() {
*self.rec_ref = new;
Some(())
} else {
None
}
}
pub fn delete_with_alg_data(&mut self) -> Option<(D::Value, T)> {
let mut node = self.take_subtree().into_node()?;
if node.right.is_empty() {
self.put_subtree(node.left).unwrap();
} else {
let mut walker = node.right.walker();
while walker.go_left().is_ok() {}
let res = walker.go_up();
assert_eq!(res, Ok(Side::Left));
let mut boxed_replacement_node = walker.take_subtree().into_node_boxed().unwrap();
assert!(boxed_replacement_node.left.is_empty());
walker.put_subtree(boxed_replacement_node.right).unwrap();
drop(walker);
boxed_replacement_node.left = node.left;
boxed_replacement_node.right = node.right;
boxed_replacement_node.rebuild();
self.put_subtree(BasicTree::from_boxed_node(boxed_replacement_node))
.unwrap();
}
Some((node.node_value, node.alg_data))
}
pub fn steps_until_sided_ancestor(&self, side: Side) -> Option<usize> {
let mut res = 0;
for s in self.is_left.iter().rev() {
res += 1;
if *s == side {
return Some(res);
}
}
None
}
}
impl<'a, D: Data, T> Drop for BasicWalker<'a, D, T> {
fn drop(&mut self) {
self.go_to_root();
}
}