use crate::*;
#[derive(PartialEq, Eq, Debug, Hash)]
pub enum LocResult {
Accept,
GoRight,
GoLeft,
}
use LocResult::*;
pub trait Locator<D: Data>: Clone {
fn locate(&self, left: D::Summary, node: &D::Value, right: D::Summary) -> LocResult;
}
impl<D: Data, F> Locator<D> for F
where
F: Fn(D::Summary, &D::Value, D::Summary) -> LocResult + Clone,
{
fn locate(&self, left: D::Summary, node: &D::Value, right: D::Summary) -> LocResult {
self(left, node, right)
}
}
pub fn query_locator<W, D: Data, L>(walker: &mut W, locator: &L) -> Option<LocResult>
where
W: crate::trees::SomeWalker<D> + ?Sized,
L: Locator<D>,
{
if let Some(value) = walker.value() {
let left = walker.left_summary();
let right = walker.right_summary();
Some(locator.locate(left, value, right))
} else {
None
}
}
pub fn clone_locate<D: Data, L>(
current_action: D::Action,
left: D::Summary,
value: &D::Value,
right: D::Summary,
locator: &L,
) -> LocResult
where
L: Locator<D>,
D::Value: Clone,
{
if !current_action.to_reverse() {
locator.locate(left, ¤t_action.act(value.clone()), right)
} else {
locator.locate(right, ¤t_action.act(value.clone()), left)
}
}
impl<D: Data> Locator<D> for usize
where
D::Summary: SizedSummary,
{
fn locate(&self, left: D::Summary, node: &D::Value, _right: D::Summary) -> LocResult {
let s = left.size();
if s > *self {
GoLeft
} else if s + node.to_summary().size() <= *self {
GoRight
} else {
Accept
}
}
}
impl<D: Data> Locator<D> for std::ops::RangeFull {
fn locate(&self, _left: D::Summary, _node: &D::Value, _right: D::Summary) -> LocResult {
Accept
}
}
impl<D: Data> Locator<D> for &std::ops::RangeFull {
fn locate(&self, _left: D::Summary, _node: &D::Value, _right: D::Summary) -> LocResult {
Accept
}
}
impl<D: Data> Locator<D> for std::ops::Range<usize>
where
D::Summary: SizedSummary,
{
fn locate(&self, left: D::Summary, node: &D::Value, _right: D::Summary) -> LocResult {
let s = left.size();
if s >= self.end {
GoLeft
} else if s + node.to_summary().size() <= self.start {
GoRight
} else {
Accept
}
}
}
impl<D: Data> Locator<D> for &std::ops::Range<usize>
where
D::Summary: SizedSummary,
{
fn locate(&self, left: D::Summary, node: &D::Value, _right: D::Summary) -> LocResult {
let s = left.size();
if s >= self.end {
GoLeft
} else if s + node.to_summary().size() <= self.start {
GoRight
} else {
Accept
}
}
}
impl<D: Data> Locator<D> for std::ops::RangeInclusive<usize>
where
D::Summary: SizedSummary,
{
fn locate(&self, left: D::Summary, node: &D::Value, _right: D::Summary) -> LocResult {
let s = left.size();
if s > *self.end() {
GoLeft
} else if s + node.to_summary().size() <= *self.start() {
GoRight
} else {
Accept
}
}
}
impl<D: Data> Locator<D> for &std::ops::RangeInclusive<usize>
where
D::Summary: SizedSummary,
{
fn locate(&self, left: D::Summary, node: &D::Value, _right: D::Summary) -> LocResult {
let s = left.size();
if s > *self.end() {
GoLeft
} else if s + node.to_summary().size() <= *self.start() {
GoRight
} else {
Accept
}
}
}
impl<D: Data> Locator<D> for std::ops::RangeFrom<usize>
where
D::Summary: SizedSummary,
{
fn locate(&self, left: D::Summary, node: &D::Value, _right: D::Summary) -> LocResult {
let s = left.size();
if s + node.to_summary().size() <= self.start {
GoRight
} else {
Accept
}
}
}
impl<D: Data> Locator<D> for &std::ops::RangeFrom<usize>
where
D::Summary: SizedSummary,
{
fn locate(&self, left: D::Summary, node: &D::Value, _right: D::Summary) -> LocResult {
let s = left.size();
if s + node.to_summary().size() <= self.start {
GoRight
} else {
Accept
}
}
}
impl<D: Data> Locator<D> for std::ops::RangeTo<usize>
where
D::Summary: SizedSummary,
{
fn locate(&self, left: D::Summary, _node: &D::Value, _right: D::Summary) -> LocResult {
let s = left.size();
if s >= self.end {
GoLeft
} else {
Accept
}
}
}
impl<D: Data> Locator<D> for &std::ops::RangeTo<usize>
where
D::Summary: SizedSummary,
{
fn locate(&self, left: D::Summary, _node: &D::Value, _right: D::Summary) -> LocResult {
let s = left.size();
if s >= self.end {
GoLeft
} else {
Accept
}
}
}
impl<D: Data> Locator<D> for std::ops::RangeToInclusive<usize>
where
D::Summary: SizedSummary,
{
fn locate(&self, left: D::Summary, _node: &D::Value, _right: D::Summary) -> LocResult {
let s = left.size();
if s > self.end {
GoLeft
} else {
Accept
}
}
}
impl<D: Data> Locator<D> for &std::ops::RangeToInclusive<usize>
where
D::Summary: SizedSummary,
{
fn locate(&self, left: D::Summary, _node: &D::Value, _right: D::Summary) -> LocResult {
let s = left.size();
if s > self.end {
GoLeft
} else {
Accept
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
pub struct ByKey<T>(pub T);
impl<'a, D: Data, Key: Ord> Locator<D> for ByKey<(&Key,)>
where
D::Value: Keyed<Key>,
{
fn locate(&self, _left: D::Summary, node: &D::Value, _right: D::Summary) -> LocResult {
match node.get_key().cmp(self.0 .0) {
std::cmp::Ordering::Less => GoRight,
std::cmp::Ordering::Equal => Accept,
std::cmp::Ordering::Greater => GoLeft,
}
}
}
impl<D: Data> Locator<D> for ByKey<std::ops::RangeFull> {
fn locate(&self, _left: D::Summary, _node: &D::Value, _right: D::Summary) -> LocResult {
Accept
}
}
impl<D: Data, Key: Ord> Locator<D> for ByKey<std::ops::Range<&Key>>
where
D::Value: Keyed<Key>,
{
fn locate(&self, _left: D::Summary, node: &D::Value, _right: D::Summary) -> LocResult {
let key = node.get_key();
if key < self.0.start {
GoRight
} else if self.0.end <= key {
GoLeft
} else {
Accept
}
}
}
impl<D: Data, Key: Ord> Locator<D> for ByKey<std::ops::RangeInclusive<&Key>>
where
D::Value: Keyed<Key>,
{
fn locate(&self, _left: D::Summary, node: &D::Value, _right: D::Summary) -> LocResult {
let key = &node.get_key();
if key < self.0.start() {
GoRight
} else if self.0.end() < key {
GoLeft
} else {
Accept
}
}
}
impl<D: Data, Key: Ord> Locator<D> for ByKey<std::ops::RangeFrom<&Key>>
where
D::Value: Keyed<Key>,
{
fn locate(&self, _left: D::Summary, node: &D::Value, _right: D::Summary) -> LocResult {
let key = node.get_key();
if key < self.0.start {
GoRight
} else {
Accept
}
}
}
impl<D: Data, Key: Ord> Locator<D> for ByKey<std::ops::RangeTo<&Key>>
where
D::Value: Keyed<Key>,
{
fn locate(&self, _left: D::Summary, node: &D::Value, _right: D::Summary) -> LocResult {
let key = node.get_key();
if self.0.end <= key {
GoLeft
} else {
Accept
}
}
}
impl<D: Data, Key: Ord> Locator<D> for ByKey<std::ops::RangeToInclusive<&Key>>
where
D::Value: Keyed<Key>,
{
fn locate(&self, _left: D::Summary, node: &D::Value, _right: D::Summary) -> LocResult {
let key = node.get_key();
if self.0.end < key {
GoLeft
} else {
Accept
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct LeftEdgeOf<L>(pub L);
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct RightEdgeOf<L>(pub L);
impl<D: Data, L: Locator<D>> Locator<D> for LeftEdgeOf<L> {
fn locate(&self, left: D::Summary, node: &D::Value, right: D::Summary) -> LocResult {
match self.0.locate(left, node, right) {
Accept => GoLeft,
res => res,
}
}
}
impl<D: Data, L: Locator<D>> Locator<D> for RightEdgeOf<L> {
fn locate(&self, left: D::Summary, node: &D::Value, right: D::Summary) -> LocResult {
match self.0.locate(left, node, right) {
Accept => GoRight,
res => res,
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct LeftOf<L>(pub L);
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct RightOf<L>(pub L);
impl<D: Data, L: Locator<D>> Locator<D> for LeftOf<L> {
fn locate(&self, left: D::Summary, node: &D::Value, right: D::Summary) -> LocResult {
match self.0.locate(left, node, right) {
GoRight => Accept,
_ => GoLeft,
}
}
}
impl<D: Data, L: Locator<D>> Locator<D> for RightOf<L> {
fn locate(&self, left: D::Summary, node: &D::Value, right: D::Summary) -> LocResult {
match self.0.locate(left, node, right) {
GoLeft => Accept,
_ => GoRight,
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct UnionLocator<L1, L2>(pub L1, pub L2);
impl<D: Data, L1: Locator<D>, L2: Locator<D>> Locator<D> for UnionLocator<L1, L2> {
fn locate(&self, left: D::Summary, node: &D::Value, right: D::Summary) -> LocResult {
let a = self.0.locate(left, node, right);
let b = self.1.locate(left, node, right);
if a == b {
a
} else {
Accept
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct BetweenLocator<L1, L2>(pub L1, pub L2);
impl<D: Data, L1: Locator<D>, L2: Locator<D>> Locator<D> for BetweenLocator<L1, L2> {
fn locate(&self, left: D::Summary, node: &D::Value, right: D::Summary) -> LocResult {
let a = self.0.locate(left, node, right);
let b = self.1.locate(left, node, right);
match (a, b) {
(GoLeft, GoRight) => Accept,
(GoRight, GoLeft) => Accept,
(Accept, x) => x,
(x, _) => x,
}
}
}