use crate::*;
use locators::*;
use trees::basic_tree::{ImmDownBasicWalker, *};
pub fn segment_summary<TR, L, D: Data>(tree: TR, locator: L) -> D::Summary
where
TR: SomeTreeRef<D>,
L: Locator<D>,
{
use LocResult::*;
let mut walker = tree.walker();
while let Some(res) = query_locator(&mut walker, &locator) {
match res {
GoRight => walker.go_right().unwrap(),
GoLeft => walker.go_left().unwrap(),
Accept => {
let node_value = walker.node_summary();
let depth = walker.depth();
walker.go_left().unwrap();
let first_half = segment_summary_on_suffix_unclonable(&mut walker, locator.clone());
for _ in 0..walker.depth() - depth {
walker.go_up().unwrap();
}
walker.go_right().unwrap();
let second_half = segment_summary_on_prefix_unclonable(&mut walker, locator);
return first_half + node_value + second_half;
}
}
}
Default::default()
}
fn segment_summary_on_suffix_unclonable<W, L, D: Data>(walker: &mut W, locator: L) -> D::Summary
where
W: SomeWalker<D>,
L: Locator<D>,
{
let mut res = Default::default();
use LocResult::*;
while let Some(dir) = query_locator(walker, &locator) {
match dir {
Accept => {
res = walker.node_summary() + walker.right_subtree_summary().unwrap() + res;
walker.go_left().unwrap();
}
GoRight => walker.go_right().unwrap(),
GoLeft => panic!("inconsistent locator"),
}
}
res
}
fn segment_summary_on_prefix_unclonable<W, L, D: Data>(walker: &mut W, locator: L) -> D::Summary
where
W: SomeWalker<D>,
L: Locator<D>,
{
let mut res = Default::default();
use LocResult::*;
while let Some(dir) = query_locator(walker, &locator) {
match dir {
Accept => {
res = res + walker.left_subtree_summary().unwrap() + walker.node_summary();
walker.go_right().unwrap();
}
GoRight => panic!("inconsistent locator"),
GoLeft => walker.go_left().unwrap(),
}
}
res
}
pub fn act_segment<TR, L, D: Data>(tree: TR, action: D::Action, locator: L)
where
TR: SomeTreeRef<D>,
L: Locator<D>,
{
assert!(
!action.to_reverse(),
"This tree type might not support reversals"
);
use LocResult::*;
let mut walker = tree.walker();
while let Some(res) = query_locator(&mut walker, &locator) {
match res {
GoRight => walker.go_right().unwrap(),
GoLeft => walker.go_left().unwrap(),
Accept => {
walker.act_node(action);
let depth = walker.depth();
walker.go_left().unwrap();
act_on_suffix(&mut walker, action, locator.clone());
for _ in 0..walker.depth() - depth {
walker.go_up().unwrap();
}
walker.go_right().unwrap();
act_on_prefix(&mut walker, action, locator);
return;
}
}
}
}
fn act_on_suffix<W, L, D: Data>(walker: &mut W, action: D::Action, locator: L)
where
W: SomeWalker<D>,
L: Locator<D>,
{
use LocResult::*;
while let Some(dir) = query_locator(walker, &locator) {
match dir {
Accept => {
walker.act_node(action);
walker.act_right_subtree(action).unwrap();
walker.go_left().unwrap();
}
GoRight => walker.go_right().unwrap(),
GoLeft => panic!("inconsistent locator"),
}
}
}
fn act_on_prefix<W, L, D: Data>(walker: &mut W, action: D::Action, locator: L)
where
W: SomeWalker<D>,
L: Locator<D>,
{
use LocResult::*;
while let Some(dir) = query_locator(walker, &locator) {
match dir {
Accept => {
walker.act_node(action);
walker.act_left_subtree(action).unwrap();
walker.go_right().unwrap();
}
GoRight => panic!("inconsistent locator"),
GoLeft => walker.go_left().unwrap(),
}
}
}
const SUDDENLY_EMPTY_ERROR: &str = "The locator unexpectedly became empty";
const INCONSISTENT_LOCATOR_ERROR: &str = "inconsistent locator";
pub fn segment_summary_imm<D: Data, T, L>(tree: &BasicTree<D, T>, locator: L) -> D::Summary
where
L: Locator<D>,
D::Value: Clone,
{
use locators::LocResult::*;
use trees::*;
let mut walker = ImmDownBasicWalker::new(tree);
while let Some(direction) = walker.query_locator(&locator) {
match direction {
GoLeft => {
walker.go_left();
}
GoRight => {
walker.go_right();
}
Accept => {
let current_node_summary = walker.node_summary().expect(SUDDENLY_EMPTY_ERROR);
let mut left_walker = walker.clone();
let mut right_walker = walker;
left_walker.go_left().expect(SUDDENLY_EMPTY_ERROR);
right_walker.go_right().expect(SUDDENLY_EMPTY_ERROR);
let left_half = segment_summary_on_suffix_imm(left_walker, locator.clone());
let right_half = segment_summary_on_prefix_imm(right_walker, locator);
return left_half + current_node_summary + right_half;
}
}
}
Default::default()
}
fn segment_summary_on_suffix_imm<D: Data, T, L>(
mut walker: ImmDownBasicWalker<D, T>,
locator: L,
) -> D::Summary
where
L: Locator<D>,
D::Value: Clone,
{
use locators::LocResult::*;
use trees::*;
let mut result: D::Summary = Default::default();
while let Some(direction) = walker.query_locator(&locator) {
match direction {
GoLeft => panic!("{}", INCONSISTENT_LOCATOR_ERROR),
GoRight => walker.go_right().expect(SUDDENLY_EMPTY_ERROR),
Accept => {
let extra = walker.go_left_extra().expect(SUDDENLY_EMPTY_ERROR);
result = extra + result;
}
}
}
result
}
fn segment_summary_on_prefix_imm<D: Data, T, L>(
mut walker: ImmDownBasicWalker<D, T>,
locator: L,
) -> D::Summary
where
L: Locator<D>,
D::Value: Clone,
{
use locators::LocResult::*;
use trees::*;
let mut result: D::Summary = Default::default();
while let Some(direction) = walker.query_locator(&locator) {
match direction {
GoLeft => walker.go_left().expect(SUDDENLY_EMPTY_ERROR),
GoRight => panic!("{}", INCONSISTENT_LOCATOR_ERROR),
Accept => {
let extra = walker.go_right_extra().expect(SUDDENLY_EMPTY_ERROR);
result = result + extra;
}
}
}
result
}