Remove type parameters from Cursor::seek_internal

Instead, use trait objects for the target dimension and aggregation
This commit is contained in:
Max Brunsfeld 2021-09-30 17:17:33 -07:00
parent 3719a9ee23
commit 24918b5cbc

View file

@ -1,6 +1,6 @@
use super::*; use super::*;
use arrayvec::ArrayVec; use arrayvec::ArrayVec;
use std::{cmp::Ordering, sync::Arc}; use std::{cmp::Ordering, mem, sync::Arc};
#[derive(Clone)] #[derive(Clone)]
struct StackEntry<'a, T: Item, D> { struct StackEntry<'a, T: Item, D> {
@ -324,7 +324,7 @@ where
Target: SeekTarget<'a, T::Summary, D>, Target: SeekTarget<'a, T::Summary, D>,
{ {
self.reset(); self.reset();
self.seek_internal::<_, ()>(pos, bias, &mut SeekAggregate::None, cx) self.seek_internal(pos, bias, &mut (), cx)
} }
pub fn seek_forward<Target>( pub fn seek_forward<Target>(
@ -336,7 +336,7 @@ where
where where
Target: SeekTarget<'a, T::Summary, D>, Target: SeekTarget<'a, T::Summary, D>,
{ {
self.seek_internal::<_, ()>(pos, bias, &mut SeekAggregate::None, cx) self.seek_internal(pos, bias, &mut (), cx)
} }
pub fn slice<Target>( pub fn slice<Target>(
@ -348,23 +348,18 @@ where
where where
Target: SeekTarget<'a, T::Summary, D>, Target: SeekTarget<'a, T::Summary, D>,
{ {
let mut slice = SeekAggregate::Slice(SumTree::new()); let mut slice = SliceSeekAggregate {
self.seek_internal::<_, ()>(end, bias, &mut slice, cx); tree: SumTree::new(),
if let SeekAggregate::Slice(slice) = slice { leaf_items: ArrayVec::new(),
slice leaf_item_summaries: ArrayVec::new(),
} else { leaf_summary: T::Summary::default(),
unreachable!() };
} self.seek_internal(end, bias, &mut slice, cx);
slice.tree
} }
pub fn suffix(&mut self, cx: &<T::Summary as Summary>::Context) -> SumTree<T> { pub fn suffix(&mut self, cx: &<T::Summary as Summary>::Context) -> SumTree<T> {
let mut slice = SeekAggregate::Slice(SumTree::new()); self.slice(&End::new(), Bias::Right, cx)
self.seek_internal::<_, ()>(&End::new(), Bias::Right, &mut slice, cx);
if let SeekAggregate::Slice(slice) = slice {
slice
} else {
unreachable!()
}
} }
pub fn summary<Target, Output>( pub fn summary<Target, Output>(
@ -377,26 +372,18 @@ where
Target: SeekTarget<'a, T::Summary, D>, Target: SeekTarget<'a, T::Summary, D>,
Output: Dimension<'a, T::Summary>, Output: Dimension<'a, T::Summary>,
{ {
let mut summary = SeekAggregate::Summary(Output::default()); let mut summary = SummarySeekAggregate(Output::default());
self.seek_internal(end, bias, &mut summary, cx); self.seek_internal(end, bias, &mut summary, cx);
if let SeekAggregate::Summary(summary) = summary { summary.0
summary
} else {
unreachable!()
}
} }
fn seek_internal<Target, Output>( fn seek_internal(
&mut self, &mut self,
target: &Target, target: &dyn SeekTarget<'a, T::Summary, D>,
bias: Bias, bias: Bias,
aggregate: &mut SeekAggregate<T, Output>, aggregate: &mut dyn SeekAggregate<'a, T>,
cx: &<T::Summary as Summary>::Context, cx: &<T::Summary as Summary>::Context,
) -> bool ) -> bool {
where
Target: SeekTarget<'a, T::Summary, D>,
Output: Dimension<'a, T::Summary>,
{
debug_assert!( debug_assert!(
target.cmp(&self.position, cx) >= Ordering::Equal, target.cmp(&self.position, cx) >= Ordering::Equal,
"cannot seek backward from {:?} to {:?}", "cannot seek backward from {:?} to {:?}",
@ -437,15 +424,7 @@ where
|| (comparison == Ordering::Equal && bias == Bias::Right) || (comparison == Ordering::Equal && bias == Bias::Right)
{ {
self.position = child_end; self.position = child_end;
match aggregate { aggregate.push_tree(child_tree, child_summary, cx);
SeekAggregate::None => {}
SeekAggregate::Slice(slice) => {
slice.push_tree(child_tree.clone(), cx);
}
SeekAggregate::Summary(summary) => {
summary.add_summary(child_summary, cx);
}
}
entry.index += 1; entry.index += 1;
entry.position = self.position.clone(); entry.position = self.position.clone();
} else { } else {
@ -464,12 +443,7 @@ where
ref item_summaries, ref item_summaries,
.. ..
} => { } => {
let mut slice_items = ArrayVec::<T, { 2 * TREE_BASE }>::new(); aggregate.begin_leaf();
let mut slice_item_summaries = ArrayVec::<T::Summary, { 2 * TREE_BASE }>::new();
let mut slice_items_summary = match aggregate {
SeekAggregate::Slice(_) => Some(T::Summary::default()),
_ => None,
};
for (item, item_summary) in items[entry.index..] for (item, item_summary) in items[entry.index..]
.iter() .iter()
@ -483,49 +457,15 @@ where
|| (comparison == Ordering::Equal && bias == Bias::Right) || (comparison == Ordering::Equal && bias == Bias::Right)
{ {
self.position = child_end; self.position = child_end;
match aggregate { aggregate.push_item(item, item_summary, cx);
SeekAggregate::None => {}
SeekAggregate::Slice(_) => {
slice_items.push(item.clone());
slice_item_summaries.push(item_summary.clone());
<T::Summary as Summary>::add_summary(
slice_items_summary.as_mut().unwrap(),
item_summary,
cx,
);
}
SeekAggregate::Summary(summary) => {
summary.add_summary(item_summary, cx);
}
}
entry.index += 1; entry.index += 1;
} else { } else {
if let SeekAggregate::Slice(slice) = aggregate { aggregate.end_leaf(cx);
slice.push_tree(
SumTree(Arc::new(Node::Leaf {
summary: slice_items_summary.unwrap(),
items: slice_items,
item_summaries: slice_item_summaries,
})),
cx,
);
}
break 'outer; break 'outer;
} }
} }
if let SeekAggregate::Slice(slice) = aggregate { aggregate.end_leaf(cx);
if !slice_items.is_empty() {
slice.push_tree(
SumTree(Arc::new(Node::Leaf {
summary: slice_items_summary.unwrap(),
items: slice_items,
item_summaries: slice_item_summaries,
})),
cx,
);
}
}
} }
} }
@ -625,8 +565,81 @@ where
} }
} }
enum SeekAggregate<T: Item, D> { trait SeekAggregate<'a, T: Item> {
None, fn begin_leaf(&mut self);
Slice(SumTree<T>), fn end_leaf(&mut self, cx: &<T::Summary as Summary>::Context);
Summary(D), fn push_item(
&mut self,
item: &'a T,
summary: &'a T::Summary,
cx: &<T::Summary as Summary>::Context,
);
fn push_tree(
&mut self,
tree: &'a SumTree<T>,
summary: &'a T::Summary,
cx: &<T::Summary as Summary>::Context,
);
}
struct SliceSeekAggregate<T: Item> {
tree: SumTree<T>,
leaf_items: ArrayVec<T, { 2 * TREE_BASE }>,
leaf_item_summaries: ArrayVec<T::Summary, { 2 * TREE_BASE }>,
leaf_summary: T::Summary,
}
struct SummarySeekAggregate<D>(D);
impl<'a, T: Item> SeekAggregate<'a, T> for () {
fn begin_leaf(&mut self) {}
fn end_leaf(&mut self, _: &<T::Summary as Summary>::Context) {}
fn push_item(&mut self, _: &T, _: &T::Summary, _: &<T::Summary as Summary>::Context) {}
fn push_tree(&mut self, _: &SumTree<T>, _: &T::Summary, _: &<T::Summary as Summary>::Context) {}
}
impl<'a, T: Item> SeekAggregate<'a, T> for SliceSeekAggregate<T> {
fn begin_leaf(&mut self) {}
fn end_leaf(&mut self, cx: &<T::Summary as Summary>::Context) {
self.tree.push_tree(
SumTree(Arc::new(Node::Leaf {
summary: mem::take(&mut self.leaf_summary),
items: mem::take(&mut self.leaf_items),
item_summaries: mem::take(&mut self.leaf_item_summaries),
})),
cx,
);
}
fn push_item(&mut self, item: &T, summary: &T::Summary, cx: &<T::Summary as Summary>::Context) {
self.leaf_items.push(item.clone());
self.leaf_item_summaries.push(summary.clone());
Summary::add_summary(&mut self.leaf_summary, summary, cx);
}
fn push_tree(
&mut self,
tree: &SumTree<T>,
_: &T::Summary,
cx: &<T::Summary as Summary>::Context,
) {
self.tree.push_tree(tree.clone(), cx);
}
}
impl<'a, T: Item, D> SeekAggregate<'a, T> for SummarySeekAggregate<D>
where
D: Dimension<'a, T::Summary>,
{
fn begin_leaf(&mut self) {}
fn end_leaf(&mut self, _: &<T::Summary as Summary>::Context) {}
fn push_item(&mut self, _: &T, summary: &'a T::Summary, cx: &<T::Summary as Summary>::Context) {
self.0.add_summary(summary, cx);
}
fn push_tree(
&mut self,
_: &SumTree<T>,
summary: &'a T::Summary,
cx: &<T::Summary as Summary>::Context,
) {
self.0.add_summary(summary, cx);
}
} }