Allow seeking SumTree cursor by multiple seek types per dimension
Also, remove the cursor's sum_dimension. Replace it with a blanket implementation of Dimension for two-element tuples of dimensions. Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
co-authored by
Nathan Sobo
parent
39fbf7d4d1
commit
ab31ddfc31
+31
-34
@@ -128,7 +128,7 @@ impl Element for List {
|
||||
});
|
||||
|
||||
// Render items after the scroll top, including those in the trailing overdraw.
|
||||
let mut cursor = old_items.cursor::<Count, ()>();
|
||||
let mut cursor = old_items.cursor::<Count>();
|
||||
cursor.seek(&Count(scroll_top.item_ix), Bias::Right, &());
|
||||
for (ix, item) in cursor.by_ref().enumerate() {
|
||||
if rendered_height - scroll_top.offset_in_item >= size.y() + state.overdraw {
|
||||
@@ -149,8 +149,7 @@ impl Element for List {
|
||||
while rendered_height < size.y() {
|
||||
cursor.prev(&());
|
||||
if let Some(item) = cursor.item() {
|
||||
let element =
|
||||
state.render_item(cursor.seek_start().0, item, item_constraint, cx);
|
||||
let element = state.render_item(cursor.start().0, item, item_constraint, cx);
|
||||
rendered_height += element.size().y();
|
||||
rendered_items.push_front(ListItem::Rendered(element));
|
||||
} else {
|
||||
@@ -159,7 +158,7 @@ impl Element for List {
|
||||
}
|
||||
|
||||
scroll_top = ListOffset {
|
||||
item_ix: cursor.seek_start().0,
|
||||
item_ix: cursor.start().0,
|
||||
offset_in_item: rendered_height - size.y(),
|
||||
};
|
||||
|
||||
@@ -170,7 +169,7 @@ impl Element for List {
|
||||
}
|
||||
Orientation::Bottom => {
|
||||
scroll_top = ListOffset {
|
||||
item_ix: cursor.seek_start().0,
|
||||
item_ix: cursor.start().0,
|
||||
offset_in_item: rendered_height - size.y(),
|
||||
};
|
||||
state.logical_scroll_top = None;
|
||||
@@ -183,7 +182,7 @@ impl Element for List {
|
||||
while leading_overdraw < state.overdraw {
|
||||
cursor.prev(&());
|
||||
if let Some(item) = cursor.item() {
|
||||
let element = state.render_item(cursor.seek_start().0, item, item_constraint, cx);
|
||||
let element = state.render_item(cursor.start().0, item, item_constraint, cx);
|
||||
leading_overdraw += element.size().y();
|
||||
rendered_items.push_front(ListItem::Rendered(element));
|
||||
} else {
|
||||
@@ -191,10 +190,9 @@ impl Element for List {
|
||||
}
|
||||
}
|
||||
|
||||
let new_rendered_range =
|
||||
cursor.seek_start().0..(cursor.seek_start().0 + rendered_items.len());
|
||||
let new_rendered_range = cursor.start().0..(cursor.start().0 + rendered_items.len());
|
||||
|
||||
let mut cursor = old_items.cursor::<Count, ()>();
|
||||
let mut cursor = old_items.cursor::<Count>();
|
||||
|
||||
if state.rendered_range.start < new_rendered_range.start {
|
||||
new_items.push_tree(
|
||||
@@ -202,7 +200,7 @@ impl Element for List {
|
||||
&(),
|
||||
);
|
||||
let remove_to = state.rendered_range.end.min(new_rendered_range.start);
|
||||
while cursor.seek_start().0 < remove_to {
|
||||
while cursor.start().0 < remove_to {
|
||||
new_items.push(cursor.item().unwrap().remove(), &());
|
||||
cursor.next(&());
|
||||
}
|
||||
@@ -221,7 +219,7 @@ impl Element for List {
|
||||
&(),
|
||||
);
|
||||
}
|
||||
while cursor.seek_start().0 < state.rendered_range.end {
|
||||
while cursor.start().0 < state.rendered_range.end {
|
||||
new_items.push(cursor.item().unwrap().remove(), &());
|
||||
cursor.next(&());
|
||||
}
|
||||
@@ -263,7 +261,7 @@ impl Element for List {
|
||||
|
||||
let mut state = self.state.0.borrow_mut();
|
||||
let mut item_origin = bounds.origin() - vec2f(0., scroll_top.offset_in_item);
|
||||
let mut cursor = state.items.cursor::<Count, ()>();
|
||||
let mut cursor = state.items.cursor::<Count>();
|
||||
let mut new_items = cursor.slice(&Count(scroll_top.item_ix), Bias::Right, &());
|
||||
while let Some(item) = cursor.item() {
|
||||
if item_origin.y() > bounds.max_y() {
|
||||
@@ -390,7 +388,7 @@ impl ListState {
|
||||
new_end + state.rendered_range.end.saturating_sub(old_range.end);
|
||||
}
|
||||
|
||||
let mut old_heights = state.items.cursor::<Count, ()>();
|
||||
let mut old_heights = state.items.cursor::<Count>();
|
||||
let mut new_heights = old_heights.slice(&Count(old_range.start), Bias::Right, &());
|
||||
old_heights.seek_forward(&Count(old_range.end), Bias::Right, &());
|
||||
|
||||
@@ -426,12 +424,11 @@ impl StateInner {
|
||||
}
|
||||
|
||||
fn visible_range(&self, height: f32, scroll_top: &ListOffset) -> Range<usize> {
|
||||
let mut cursor = self.items.cursor::<Count, Height>();
|
||||
let mut cursor = self.items.cursor::<ListItemSummary>();
|
||||
cursor.seek(&Count(scroll_top.item_ix), Bias::Right, &());
|
||||
let start_y = cursor.sum_start().0 + scroll_top.offset_in_item;
|
||||
let mut cursor = cursor.swap_dimensions();
|
||||
let start_y = cursor.start().height + scroll_top.offset_in_item;
|
||||
cursor.seek_forward(&Height(start_y + height), Bias::Left, &());
|
||||
scroll_top.item_ix..cursor.sum_start().0 + 1
|
||||
scroll_top.item_ix..cursor.start().count + 1
|
||||
}
|
||||
|
||||
fn visible_elements<'a>(
|
||||
@@ -440,7 +437,7 @@ impl StateInner {
|
||||
scroll_top: &ListOffset,
|
||||
) -> impl Iterator<Item = (ElementRc, Vector2F)> + 'a {
|
||||
let mut item_origin = bounds.origin() - vec2f(0., scroll_top.offset_in_item);
|
||||
let mut cursor = self.items.cursor::<Count, ()>();
|
||||
let mut cursor = self.items.cursor::<Count>();
|
||||
cursor.seek(&Count(scroll_top.item_ix), Bias::Right, &());
|
||||
std::iter::from_fn(move || {
|
||||
while let Some(item) = cursor.item() {
|
||||
@@ -482,10 +479,10 @@ impl StateInner {
|
||||
if self.orientation == Orientation::Bottom && new_scroll_top == scroll_max {
|
||||
self.logical_scroll_top = None;
|
||||
} else {
|
||||
let mut cursor = self.items.cursor::<Height, Count>();
|
||||
let mut cursor = self.items.cursor::<ListItemSummary>();
|
||||
cursor.seek(&Height(new_scroll_top), Bias::Right, &());
|
||||
let item_ix = cursor.sum_start().0;
|
||||
let offset_in_item = new_scroll_top - cursor.seek_start().0;
|
||||
let item_ix = cursor.start().count;
|
||||
let offset_in_item = new_scroll_top - cursor.start().height;
|
||||
self.logical_scroll_top = Some(ListOffset {
|
||||
item_ix,
|
||||
offset_in_item,
|
||||
@@ -502,9 +499,9 @@ impl StateInner {
|
||||
}
|
||||
|
||||
fn scroll_top(&self, logical_scroll_top: &ListOffset) -> f32 {
|
||||
let mut cursor = self.items.cursor::<Count, Height>();
|
||||
let mut cursor = self.items.cursor::<ListItemSummary>();
|
||||
cursor.seek(&Count(logical_scroll_top.item_ix), Bias::Right, &());
|
||||
cursor.sum_start().0 + logical_scroll_top.offset_in_item
|
||||
cursor.start().height + logical_scroll_top.offset_in_item
|
||||
}
|
||||
}
|
||||
|
||||
@@ -556,12 +553,6 @@ impl sum_tree::Summary for ListItemSummary {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> sum_tree::Dimension<'a, ListItemSummary> for ListItemSummary {
|
||||
fn add_summary(&mut self, summary: &'a ListItemSummary, _: &()) {
|
||||
sum_tree::Summary::add_summary(self, summary, &());
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> sum_tree::Dimension<'a, ListItemSummary> for Count {
|
||||
fn add_summary(&mut self, summary: &'a ListItemSummary, _: &()) {
|
||||
self.0 += summary.count;
|
||||
@@ -586,9 +577,15 @@ impl<'a> sum_tree::Dimension<'a, ListItemSummary> for Height {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> sum_tree::SeekDimension<'a, ListItemSummary> for Height {
|
||||
fn cmp(&self, other: &Self, _: &()) -> std::cmp::Ordering {
|
||||
self.0.partial_cmp(&other.0).unwrap()
|
||||
impl<'a> sum_tree::SeekTarget<'a, ListItemSummary, ListItemSummary> for Count {
|
||||
fn cmp(&self, other: &ListItemSummary, _: &()) -> std::cmp::Ordering {
|
||||
self.0.partial_cmp(&other.count).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> sum_tree::SeekTarget<'a, ListItemSummary, ListItemSummary> for Height {
|
||||
fn cmp(&self, other: &ListItemSummary, _: &()) -> std::cmp::Ordering {
|
||||
self.0.partial_cmp(&other.height).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -760,7 +757,7 @@ mod tests {
|
||||
log::info!("splice({:?}, {:?})", start_ix..end_ix, new_elements);
|
||||
state.splice(start_ix..end_ix, new_elements.len());
|
||||
elements.splice(start_ix..end_ix, new_elements);
|
||||
for (ix, item) in state.0.borrow().items.cursor::<(), ()>().enumerate() {
|
||||
for (ix, item) in state.0.borrow().items.cursor::<()>().enumerate() {
|
||||
if let ListItem::Rendered(element) = item {
|
||||
let (expected_id, _) = elements[ix];
|
||||
element.with_metadata(|metadata: Option<&usize>| {
|
||||
@@ -797,7 +794,7 @@ mod tests {
|
||||
let mut first_rendered_element_top = None;
|
||||
let mut last_rendered_element_bottom = None;
|
||||
assert_eq!(state.items.summary().count, elements.borrow().len());
|
||||
for (ix, item) in state.items.cursor::<(), ()>().enumerate() {
|
||||
for (ix, item) in state.items.cursor::<()>().enumerate() {
|
||||
match item {
|
||||
ListItem::Unrendered => {
|
||||
let item_bottom = item_top;
|
||||
|
||||
+101
-64
@@ -3,6 +3,7 @@ mod cursor;
|
||||
use arrayvec::ArrayVec;
|
||||
pub use cursor::Cursor;
|
||||
pub use cursor::FilterCursor;
|
||||
use std::marker::PhantomData;
|
||||
use std::{cmp::Ordering, fmt, iter::FromIterator, sync::Arc};
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -32,17 +33,58 @@ pub trait Dimension<'a, S: Summary>: Clone + fmt::Debug + Default {
|
||||
fn add_summary(&mut self, _summary: &'a S, _: &S::Context);
|
||||
}
|
||||
|
||||
impl<'a, T: Summary> Dimension<'a, T> for T {
|
||||
fn add_summary(&mut self, summary: &'a T, cx: &T::Context) {
|
||||
Summary::add_summary(self, summary, cx);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SeekTarget<'a, S: Summary, D: Dimension<'a, S>>: fmt::Debug {
|
||||
fn cmp(&self, cursor_location: &D, cx: &S::Context) -> Ordering;
|
||||
}
|
||||
|
||||
impl<'a, S: Summary, D: Dimension<'a, S> + Ord> SeekTarget<'a, S, D> for D {
|
||||
fn cmp(&self, cursor_location: &Self, _: &S::Context) -> Ordering {
|
||||
Ord::cmp(self, cursor_location)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Summary> Dimension<'a, T> for () {
|
||||
fn add_summary(&mut self, _: &'a T, _: &T::Context) {}
|
||||
}
|
||||
|
||||
pub trait SeekDimension<'a, T: Summary>: Dimension<'a, T> {
|
||||
fn cmp(&self, other: &Self, cx: &T::Context) -> Ordering;
|
||||
impl<'a, T: Summary, D1: Dimension<'a, T>, D2: Dimension<'a, T>> Dimension<'a, T> for (D1, D2) {
|
||||
fn add_summary(&mut self, summary: &'a T, cx: &T::Context) {
|
||||
self.0.add_summary(summary, cx);
|
||||
self.1.add_summary(summary, cx);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, S: Summary, T: Dimension<'a, S> + Ord> SeekDimension<'a, S> for T {
|
||||
fn cmp(&self, other: &Self, _ctx: &S::Context) -> Ordering {
|
||||
Ord::cmp(self, other)
|
||||
impl<'a, S: Summary, D1: SeekTarget<'a, S, D1> + Dimension<'a, S>, D2: Dimension<'a, S>>
|
||||
SeekTarget<'a, S, (D1, D2)> for D1
|
||||
{
|
||||
fn cmp(&self, cursor_location: &(D1, D2), cx: &S::Context) -> Ordering {
|
||||
self.cmp(&cursor_location.0, cx)
|
||||
}
|
||||
}
|
||||
|
||||
struct End<D>(PhantomData<D>);
|
||||
|
||||
impl<D> End<D> {
|
||||
fn new() -> Self {
|
||||
Self(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, S: Summary, D: Dimension<'a, S>> SeekTarget<'a, S, D> for End<D> {
|
||||
fn cmp(&self, _: &D, _: &S::Context) -> Ordering {
|
||||
Ordering::Greater
|
||||
}
|
||||
}
|
||||
|
||||
impl<D> fmt::Debug for End<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("End").finish()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,7 +141,7 @@ impl<T: Item> SumTree<T> {
|
||||
#[allow(unused)]
|
||||
pub fn items(&self, cx: &<T::Summary as Summary>::Context) -> Vec<T> {
|
||||
let mut items = Vec::new();
|
||||
let mut cursor = self.cursor::<(), ()>();
|
||||
let mut cursor = self.cursor::<()>();
|
||||
cursor.next(cx);
|
||||
while let Some(item) = cursor.item() {
|
||||
items.push(item.clone());
|
||||
@@ -108,10 +150,9 @@ impl<T: Item> SumTree<T> {
|
||||
items
|
||||
}
|
||||
|
||||
pub fn cursor<'a, S, U>(&'a self) -> Cursor<T, S, U>
|
||||
pub fn cursor<'a, S>(&'a self) -> Cursor<T, S>
|
||||
where
|
||||
S: Dimension<'a, T::Summary>,
|
||||
U: Dimension<'a, T::Summary>,
|
||||
{
|
||||
Cursor::new(self)
|
||||
}
|
||||
@@ -230,7 +271,7 @@ impl<T: Item> SumTree<T> {
|
||||
}) = leaf.as_mut()
|
||||
{
|
||||
let item_summary = item.summary();
|
||||
summary.add_summary(&item_summary, cx);
|
||||
<T::Summary as Summary>::add_summary(summary, &item_summary, cx);
|
||||
items.push(item);
|
||||
item_summaries.push(item_summary);
|
||||
} else {
|
||||
@@ -281,7 +322,7 @@ impl<T: Item> SumTree<T> {
|
||||
..
|
||||
} => {
|
||||
let other_node = other.0.clone();
|
||||
summary.add_summary(other_node.summary(), cx);
|
||||
<T::Summary as Summary>::add_summary(summary, other_node.summary(), cx);
|
||||
|
||||
let height_delta = *height - other_node.height();
|
||||
let mut summaries_to_append = ArrayVec::<T::Summary, { 2 * TREE_BASE }>::new();
|
||||
@@ -378,7 +419,7 @@ impl<T: Item> SumTree<T> {
|
||||
item_summaries: right_summaries,
|
||||
})))
|
||||
} else {
|
||||
summary.add_summary(other_node.summary(), cx);
|
||||
<T::Summary as Summary>::add_summary(summary, other_node.summary(), cx);
|
||||
items.extend(other_node.items().iter().cloned());
|
||||
item_summaries.extend(other_node.child_summaries().iter().cloned());
|
||||
None
|
||||
@@ -430,7 +471,7 @@ impl<T: KeyedItem> SumTree<T> {
|
||||
pub fn insert_or_replace(&mut self, item: T, cx: &<T::Summary as Summary>::Context) -> bool {
|
||||
let mut replaced = false;
|
||||
*self = {
|
||||
let mut cursor = self.cursor::<T::Key, ()>();
|
||||
let mut cursor = self.cursor::<T::Key>();
|
||||
let mut new_tree = cursor.slice(&item.key(), Bias::Left, cx);
|
||||
if cursor
|
||||
.item()
|
||||
@@ -459,7 +500,7 @@ impl<T: KeyedItem> SumTree<T> {
|
||||
edits.sort_unstable_by_key(|item| item.key());
|
||||
|
||||
*self = {
|
||||
let mut cursor = self.cursor::<T::Key, ()>();
|
||||
let mut cursor = self.cursor::<T::Key>();
|
||||
let mut new_tree = SumTree::new();
|
||||
let mut buffered_items = Vec::new();
|
||||
|
||||
@@ -502,7 +543,7 @@ impl<T: KeyedItem> SumTree<T> {
|
||||
}
|
||||
|
||||
pub fn get(&self, key: &T::Key, cx: &<T::Summary as Summary>::Context) -> Option<&T> {
|
||||
let mut cursor = self.cursor::<T::Key, ()>();
|
||||
let mut cursor = self.cursor::<T::Key>();
|
||||
if cursor.seek(key, Bias::Left, cx) {
|
||||
cursor.item()
|
||||
} else {
|
||||
@@ -617,7 +658,6 @@ mod tests {
|
||||
use super::*;
|
||||
use rand::{distributions, prelude::*};
|
||||
use std::cmp;
|
||||
use std::ops::Add;
|
||||
|
||||
#[test]
|
||||
fn test_extend_and_push_tree() {
|
||||
@@ -655,7 +695,7 @@ mod tests {
|
||||
reference_items.splice(splice_start..splice_end, new_items.clone());
|
||||
|
||||
tree = {
|
||||
let mut cursor = tree.cursor::<Count, ()>();
|
||||
let mut cursor = tree.cursor::<Count>();
|
||||
let mut new_tree = cursor.slice(&Count(splice_start), Bias::Right, &());
|
||||
new_tree.extend(new_items, &());
|
||||
cursor.seek(&Count(splice_end), Bias::Right, &());
|
||||
@@ -681,11 +721,11 @@ mod tests {
|
||||
|
||||
let mut pos = rng.gen_range(0..tree.extent::<Count>(&()).0 + 1);
|
||||
let mut before_start = false;
|
||||
let mut cursor = tree.cursor::<Count, Count>();
|
||||
let mut cursor = tree.cursor::<Count>();
|
||||
cursor.seek(&Count(pos), Bias::Right, &());
|
||||
|
||||
for i in 0..10 {
|
||||
assert_eq!(cursor.sum_start().0, pos);
|
||||
assert_eq!(cursor.start().0, pos);
|
||||
|
||||
if pos > 0 {
|
||||
assert_eq!(cursor.prev_item().unwrap(), &reference_items[pos - 1]);
|
||||
@@ -721,14 +761,14 @@ mod tests {
|
||||
let start_bias = if rng.gen() { Bias::Left } else { Bias::Right };
|
||||
let end_bias = if rng.gen() { Bias::Left } else { Bias::Right };
|
||||
|
||||
let mut cursor = tree.cursor::<Count, ()>();
|
||||
let mut cursor = tree.cursor::<Count>();
|
||||
cursor.seek(&Count(start), start_bias, &());
|
||||
let slice = cursor.slice(&Count(end), end_bias, &());
|
||||
|
||||
cursor.seek(&Count(start), start_bias, &());
|
||||
let summary = cursor.summary::<Sum>(&Count(end), end_bias, &());
|
||||
let summary = cursor.summary::<_, Sum>(&Count(end), end_bias, &());
|
||||
|
||||
assert_eq!(summary, slice.summary().sum);
|
||||
assert_eq!(summary.0, slice.summary().sum);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -736,42 +776,42 @@ mod tests {
|
||||
fn test_cursor() {
|
||||
// Empty tree
|
||||
let tree = SumTree::<u8>::new();
|
||||
let mut cursor = tree.cursor::<Count, Sum>();
|
||||
let mut cursor = tree.cursor::<IntegersSummary>();
|
||||
assert_eq!(
|
||||
cursor.slice(&Count(0), Bias::Right, &()).items(&()),
|
||||
Vec::<u8>::new()
|
||||
);
|
||||
assert_eq!(cursor.item(), None);
|
||||
assert_eq!(cursor.prev_item(), None);
|
||||
assert_eq!(cursor.sum_start(), &Sum(0));
|
||||
assert_eq!(cursor.start().sum, 0);
|
||||
|
||||
// Single-element tree
|
||||
let mut tree = SumTree::<u8>::new();
|
||||
tree.extend(vec![1], &());
|
||||
let mut cursor = tree.cursor::<Count, Sum>();
|
||||
let mut cursor = tree.cursor::<IntegersSummary>();
|
||||
assert_eq!(
|
||||
cursor.slice(&Count(0), Bias::Right, &()).items(&()),
|
||||
Vec::<u8>::new()
|
||||
);
|
||||
assert_eq!(cursor.item(), Some(&1));
|
||||
assert_eq!(cursor.prev_item(), None);
|
||||
assert_eq!(cursor.sum_start(), &Sum(0));
|
||||
assert_eq!(cursor.start().sum, 0);
|
||||
|
||||
cursor.next(&());
|
||||
assert_eq!(cursor.item(), None);
|
||||
assert_eq!(cursor.prev_item(), Some(&1));
|
||||
assert_eq!(cursor.sum_start(), &Sum(1));
|
||||
assert_eq!(cursor.start().sum, 1);
|
||||
|
||||
cursor.prev(&());
|
||||
assert_eq!(cursor.item(), Some(&1));
|
||||
assert_eq!(cursor.prev_item(), None);
|
||||
assert_eq!(cursor.sum_start(), &Sum(0));
|
||||
assert_eq!(cursor.start().sum, 0);
|
||||
|
||||
let mut cursor = tree.cursor::<Count, Sum>();
|
||||
let mut cursor = tree.cursor::<IntegersSummary>();
|
||||
assert_eq!(cursor.slice(&Count(1), Bias::Right, &()).items(&()), [1]);
|
||||
assert_eq!(cursor.item(), None);
|
||||
assert_eq!(cursor.prev_item(), Some(&1));
|
||||
assert_eq!(cursor.sum_start(), &Sum(1));
|
||||
assert_eq!(cursor.start().sum, 1);
|
||||
|
||||
cursor.seek(&Count(0), Bias::Right, &());
|
||||
assert_eq!(
|
||||
@@ -782,80 +822,80 @@ mod tests {
|
||||
);
|
||||
assert_eq!(cursor.item(), None);
|
||||
assert_eq!(cursor.prev_item(), Some(&1));
|
||||
assert_eq!(cursor.sum_start(), &Sum(1));
|
||||
assert_eq!(cursor.start().sum, 1);
|
||||
|
||||
// Multiple-element tree
|
||||
let mut tree = SumTree::new();
|
||||
tree.extend(vec![1, 2, 3, 4, 5, 6], &());
|
||||
let mut cursor = tree.cursor::<Count, Sum>();
|
||||
let mut cursor = tree.cursor::<IntegersSummary>();
|
||||
|
||||
assert_eq!(cursor.slice(&Count(2), Bias::Right, &()).items(&()), [1, 2]);
|
||||
assert_eq!(cursor.item(), Some(&3));
|
||||
assert_eq!(cursor.prev_item(), Some(&2));
|
||||
assert_eq!(cursor.sum_start(), &Sum(3));
|
||||
assert_eq!(cursor.start().sum, 3);
|
||||
|
||||
cursor.next(&());
|
||||
assert_eq!(cursor.item(), Some(&4));
|
||||
assert_eq!(cursor.prev_item(), Some(&3));
|
||||
assert_eq!(cursor.sum_start(), &Sum(6));
|
||||
assert_eq!(cursor.start().sum, 6);
|
||||
|
||||
cursor.next(&());
|
||||
assert_eq!(cursor.item(), Some(&5));
|
||||
assert_eq!(cursor.prev_item(), Some(&4));
|
||||
assert_eq!(cursor.sum_start(), &Sum(10));
|
||||
assert_eq!(cursor.start().sum, 10);
|
||||
|
||||
cursor.next(&());
|
||||
assert_eq!(cursor.item(), Some(&6));
|
||||
assert_eq!(cursor.prev_item(), Some(&5));
|
||||
assert_eq!(cursor.sum_start(), &Sum(15));
|
||||
assert_eq!(cursor.start().sum, 15);
|
||||
|
||||
cursor.next(&());
|
||||
cursor.next(&());
|
||||
assert_eq!(cursor.item(), None);
|
||||
assert_eq!(cursor.prev_item(), Some(&6));
|
||||
assert_eq!(cursor.sum_start(), &Sum(21));
|
||||
assert_eq!(cursor.start().sum, 21);
|
||||
|
||||
cursor.prev(&());
|
||||
assert_eq!(cursor.item(), Some(&6));
|
||||
assert_eq!(cursor.prev_item(), Some(&5));
|
||||
assert_eq!(cursor.sum_start(), &Sum(15));
|
||||
assert_eq!(cursor.start().sum, 15);
|
||||
|
||||
cursor.prev(&());
|
||||
assert_eq!(cursor.item(), Some(&5));
|
||||
assert_eq!(cursor.prev_item(), Some(&4));
|
||||
assert_eq!(cursor.sum_start(), &Sum(10));
|
||||
assert_eq!(cursor.start().sum, 10);
|
||||
|
||||
cursor.prev(&());
|
||||
assert_eq!(cursor.item(), Some(&4));
|
||||
assert_eq!(cursor.prev_item(), Some(&3));
|
||||
assert_eq!(cursor.sum_start(), &Sum(6));
|
||||
assert_eq!(cursor.start().sum, 6);
|
||||
|
||||
cursor.prev(&());
|
||||
assert_eq!(cursor.item(), Some(&3));
|
||||
assert_eq!(cursor.prev_item(), Some(&2));
|
||||
assert_eq!(cursor.sum_start(), &Sum(3));
|
||||
assert_eq!(cursor.start().sum, 3);
|
||||
|
||||
cursor.prev(&());
|
||||
assert_eq!(cursor.item(), Some(&2));
|
||||
assert_eq!(cursor.prev_item(), Some(&1));
|
||||
assert_eq!(cursor.sum_start(), &Sum(1));
|
||||
assert_eq!(cursor.start().sum, 1);
|
||||
|
||||
cursor.prev(&());
|
||||
assert_eq!(cursor.item(), Some(&1));
|
||||
assert_eq!(cursor.prev_item(), None);
|
||||
assert_eq!(cursor.sum_start(), &Sum(0));
|
||||
assert_eq!(cursor.start().sum, 0);
|
||||
|
||||
cursor.prev(&());
|
||||
assert_eq!(cursor.item(), None);
|
||||
assert_eq!(cursor.prev_item(), None);
|
||||
assert_eq!(cursor.sum_start(), &Sum(0));
|
||||
assert_eq!(cursor.start().sum, 0);
|
||||
|
||||
cursor.next(&());
|
||||
assert_eq!(cursor.item(), Some(&1));
|
||||
assert_eq!(cursor.prev_item(), None);
|
||||
assert_eq!(cursor.sum_start(), &Sum(0));
|
||||
assert_eq!(cursor.start().sum, 0);
|
||||
|
||||
let mut cursor = tree.cursor::<Count, Sum>();
|
||||
let mut cursor = tree.cursor::<IntegersSummary>();
|
||||
assert_eq!(
|
||||
cursor
|
||||
.slice(&tree.extent::<Count>(&()), Bias::Right, &())
|
||||
@@ -864,7 +904,7 @@ mod tests {
|
||||
);
|
||||
assert_eq!(cursor.item(), None);
|
||||
assert_eq!(cursor.prev_item(), Some(&6));
|
||||
assert_eq!(cursor.sum_start(), &Sum(21));
|
||||
assert_eq!(cursor.start().sum, 21);
|
||||
|
||||
cursor.seek(&Count(3), Bias::Right, &());
|
||||
assert_eq!(
|
||||
@@ -875,7 +915,7 @@ mod tests {
|
||||
);
|
||||
assert_eq!(cursor.item(), None);
|
||||
assert_eq!(cursor.prev_item(), Some(&6));
|
||||
assert_eq!(cursor.sum_start(), &Sum(21));
|
||||
assert_eq!(cursor.start().sum, 21);
|
||||
|
||||
// Seeking can bias left or right
|
||||
cursor.seek(&Count(1), Bias::Left, &());
|
||||
@@ -922,8 +962,8 @@ mod tests {
|
||||
|
||||
#[derive(Clone, Default, Debug)]
|
||||
pub struct IntegersSummary {
|
||||
count: Count,
|
||||
sum: Sum,
|
||||
count: usize,
|
||||
sum: usize,
|
||||
contains_even: bool,
|
||||
max: u8,
|
||||
}
|
||||
@@ -939,8 +979,8 @@ mod tests {
|
||||
|
||||
fn summary(&self) -> Self::Summary {
|
||||
IntegersSummary {
|
||||
count: Count(1),
|
||||
sum: Sum(*self as usize),
|
||||
count: 1,
|
||||
sum: *self as usize,
|
||||
contains_even: (*self & 1) == 0,
|
||||
max: *self,
|
||||
}
|
||||
@@ -959,8 +999,8 @@ mod tests {
|
||||
type Context = ();
|
||||
|
||||
fn add_summary(&mut self, other: &Self, _: &()) {
|
||||
self.count.0 += &other.count.0;
|
||||
self.sum.0 += &other.sum.0;
|
||||
self.count += other.count;
|
||||
self.sum += other.sum;
|
||||
self.contains_even |= other.contains_even;
|
||||
self.max = cmp::max(self.max, other.max);
|
||||
}
|
||||
@@ -974,22 +1014,19 @@ mod tests {
|
||||
|
||||
impl<'a> Dimension<'a, IntegersSummary> for Count {
|
||||
fn add_summary(&mut self, summary: &IntegersSummary, _: &()) {
|
||||
self.0 += summary.count.0;
|
||||
self.0 += summary.count;
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> SeekTarget<'a, IntegersSummary, IntegersSummary> for Count {
|
||||
fn cmp(&self, cursor_location: &IntegersSummary, _: &()) -> Ordering {
|
||||
self.0.cmp(&cursor_location.count)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Dimension<'a, IntegersSummary> for Sum {
|
||||
fn add_summary(&mut self, summary: &IntegersSummary, _: &()) {
|
||||
self.0 += summary.sum.0;
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Add<&'a Self> for Sum {
|
||||
type Output = Self;
|
||||
|
||||
fn add(mut self, other: &Self) -> Self {
|
||||
self.0 += other.0;
|
||||
self
|
||||
self.0 += summary.sum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+107
-177
@@ -3,51 +3,31 @@ use arrayvec::ArrayVec;
|
||||
use std::{cmp::Ordering, sync::Arc};
|
||||
|
||||
#[derive(Clone)]
|
||||
struct StackEntry<'a, T: Item, S, U> {
|
||||
struct StackEntry<'a, T: Item, D> {
|
||||
tree: &'a SumTree<T>,
|
||||
index: usize,
|
||||
seek_dimension: S,
|
||||
sum_dimension: U,
|
||||
}
|
||||
|
||||
impl<'a, T, S, U> StackEntry<'a, T, S, U>
|
||||
where
|
||||
T: Item,
|
||||
S: SeekDimension<'a, T::Summary>,
|
||||
U: SeekDimension<'a, T::Summary>,
|
||||
{
|
||||
fn swap_dimensions(self) -> StackEntry<'a, T, U, S> {
|
||||
StackEntry {
|
||||
tree: self.tree,
|
||||
index: self.index,
|
||||
seek_dimension: self.sum_dimension,
|
||||
sum_dimension: self.seek_dimension,
|
||||
}
|
||||
}
|
||||
position: D,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Cursor<'a, T: Item, S, U> {
|
||||
pub struct Cursor<'a, T: Item, D> {
|
||||
tree: &'a SumTree<T>,
|
||||
stack: ArrayVec<StackEntry<'a, T, S, U>, 16>,
|
||||
seek_dimension: S,
|
||||
sum_dimension: U,
|
||||
stack: ArrayVec<StackEntry<'a, T, D>, 16>,
|
||||
position: D,
|
||||
did_seek: bool,
|
||||
at_end: bool,
|
||||
}
|
||||
|
||||
impl<'a, T, S, U> Cursor<'a, T, S, U>
|
||||
impl<'a, T, D> Cursor<'a, T, D>
|
||||
where
|
||||
T: Item,
|
||||
S: Dimension<'a, T::Summary>,
|
||||
U: Dimension<'a, T::Summary>,
|
||||
D: Dimension<'a, T::Summary>,
|
||||
{
|
||||
pub fn new(tree: &'a SumTree<T>) -> Self {
|
||||
Self {
|
||||
tree,
|
||||
stack: ArrayVec::new(),
|
||||
seek_dimension: S::default(),
|
||||
sum_dimension: U::default(),
|
||||
position: D::default(),
|
||||
did_seek: false,
|
||||
at_end: false,
|
||||
}
|
||||
@@ -57,35 +37,20 @@ where
|
||||
self.did_seek = false;
|
||||
self.at_end = false;
|
||||
self.stack.truncate(0);
|
||||
self.seek_dimension = S::default();
|
||||
self.sum_dimension = U::default();
|
||||
self.position = D::default();
|
||||
}
|
||||
|
||||
pub fn seek_start(&self) -> &S {
|
||||
&self.seek_dimension
|
||||
pub fn start(&self) -> &D {
|
||||
&self.position
|
||||
}
|
||||
|
||||
pub fn seek_end(&self, cx: &<T::Summary as Summary>::Context) -> S {
|
||||
pub fn end(&self, cx: &<T::Summary as Summary>::Context) -> D {
|
||||
if let Some(item_summary) = self.item_summary() {
|
||||
let mut end = self.seek_start().clone();
|
||||
let mut end = self.start().clone();
|
||||
end.add_summary(item_summary, cx);
|
||||
end
|
||||
} else {
|
||||
self.seek_start().clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sum_start(&self) -> &U {
|
||||
&self.sum_dimension
|
||||
}
|
||||
|
||||
pub fn sum_end(&self, cx: &<T::Summary as Summary>::Context) -> U {
|
||||
if let Some(item_summary) = self.item_summary() {
|
||||
let mut end = self.sum_start().clone();
|
||||
end.add_summary(item_summary, cx);
|
||||
end
|
||||
} else {
|
||||
self.sum_start().clone()
|
||||
self.start().clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,8 +132,7 @@ where
|
||||
assert!(self.did_seek, "Must seek before calling this method");
|
||||
|
||||
if self.at_end {
|
||||
self.seek_dimension = S::default();
|
||||
self.sum_dimension = U::default();
|
||||
self.position = D::default();
|
||||
self.descend_to_last_item(self.tree, cx);
|
||||
self.at_end = false;
|
||||
} else {
|
||||
@@ -176,17 +140,10 @@ where
|
||||
if entry.index > 0 {
|
||||
let new_index = entry.index - 1;
|
||||
|
||||
if let Some(StackEntry {
|
||||
seek_dimension,
|
||||
sum_dimension,
|
||||
..
|
||||
}) = self.stack.last()
|
||||
{
|
||||
self.seek_dimension = seek_dimension.clone();
|
||||
self.sum_dimension = sum_dimension.clone();
|
||||
if let Some(StackEntry { position, .. }) = self.stack.last() {
|
||||
self.position = position.clone();
|
||||
} else {
|
||||
self.seek_dimension = S::default();
|
||||
self.sum_dimension = U::default();
|
||||
self.position = D::default();
|
||||
}
|
||||
|
||||
match entry.tree.0.as_ref() {
|
||||
@@ -196,27 +153,23 @@ where
|
||||
..
|
||||
} => {
|
||||
for summary in &child_summaries[0..new_index] {
|
||||
self.seek_dimension.add_summary(summary, cx);
|
||||
self.sum_dimension.add_summary(summary, cx);
|
||||
self.position.add_summary(summary, cx);
|
||||
}
|
||||
self.stack.push(StackEntry {
|
||||
tree: entry.tree,
|
||||
index: new_index,
|
||||
seek_dimension: self.seek_dimension.clone(),
|
||||
sum_dimension: self.sum_dimension.clone(),
|
||||
position: self.position.clone(),
|
||||
});
|
||||
self.descend_to_last_item(&child_trees[new_index], cx);
|
||||
}
|
||||
Node::Leaf { item_summaries, .. } => {
|
||||
for item_summary in &item_summaries[0..new_index] {
|
||||
self.seek_dimension.add_summary(item_summary, cx);
|
||||
self.sum_dimension.add_summary(item_summary, cx);
|
||||
self.position.add_summary(item_summary, cx);
|
||||
}
|
||||
self.stack.push(StackEntry {
|
||||
tree: entry.tree,
|
||||
index: new_index,
|
||||
seek_dimension: self.seek_dimension.clone(),
|
||||
sum_dimension: self.sum_dimension.clone(),
|
||||
position: self.position.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -241,8 +194,7 @@ where
|
||||
self.stack.push(StackEntry {
|
||||
tree: self.tree,
|
||||
index: 0,
|
||||
seek_dimension: S::default(),
|
||||
sum_dimension: U::default(),
|
||||
position: D::default(),
|
||||
});
|
||||
descend = true;
|
||||
self.did_seek = true;
|
||||
@@ -258,8 +210,7 @@ where
|
||||
..
|
||||
} => {
|
||||
if !descend {
|
||||
entry.seek_dimension = self.seek_dimension.clone();
|
||||
entry.sum_dimension = self.sum_dimension.clone();
|
||||
entry.position = self.position.clone();
|
||||
entry.index += 1;
|
||||
}
|
||||
|
||||
@@ -268,8 +219,7 @@ where
|
||||
if filter_node(next_summary) {
|
||||
break;
|
||||
} else {
|
||||
self.seek_dimension.add_summary(next_summary, cx);
|
||||
self.sum_dimension.add_summary(next_summary, cx);
|
||||
self.position.add_summary(next_summary, cx);
|
||||
}
|
||||
entry.index += 1;
|
||||
}
|
||||
@@ -279,10 +229,8 @@ where
|
||||
Node::Leaf { item_summaries, .. } => {
|
||||
if !descend {
|
||||
let item_summary = &item_summaries[entry.index];
|
||||
self.seek_dimension.add_summary(item_summary, cx);
|
||||
entry.seek_dimension.add_summary(item_summary, cx);
|
||||
self.sum_dimension.add_summary(item_summary, cx);
|
||||
entry.sum_dimension.add_summary(item_summary, cx);
|
||||
self.position.add_summary(item_summary, cx);
|
||||
entry.position.add_summary(item_summary, cx);
|
||||
entry.index += 1;
|
||||
}
|
||||
|
||||
@@ -291,10 +239,8 @@ where
|
||||
if filter_node(next_item_summary) {
|
||||
return;
|
||||
} else {
|
||||
self.seek_dimension.add_summary(next_item_summary, cx);
|
||||
entry.seek_dimension.add_summary(next_item_summary, cx);
|
||||
self.sum_dimension.add_summary(next_item_summary, cx);
|
||||
entry.sum_dimension.add_summary(next_item_summary, cx);
|
||||
self.position.add_summary(next_item_summary, cx);
|
||||
entry.position.add_summary(next_item_summary, cx);
|
||||
entry.index += 1;
|
||||
}
|
||||
} else {
|
||||
@@ -310,8 +256,7 @@ where
|
||||
self.stack.push(StackEntry {
|
||||
tree: subtree,
|
||||
index: 0,
|
||||
seek_dimension: self.seek_dimension.clone(),
|
||||
sum_dimension: self.sum_dimension.clone(),
|
||||
position: self.position.clone(),
|
||||
});
|
||||
} else {
|
||||
descend = false;
|
||||
@@ -337,29 +282,25 @@ where
|
||||
..
|
||||
} => {
|
||||
for summary in &child_summaries[0..child_summaries.len() - 1] {
|
||||
self.seek_dimension.add_summary(summary, cx);
|
||||
self.sum_dimension.add_summary(summary, cx);
|
||||
self.position.add_summary(summary, cx);
|
||||
}
|
||||
|
||||
self.stack.push(StackEntry {
|
||||
tree: subtree,
|
||||
index: child_trees.len() - 1,
|
||||
seek_dimension: self.seek_dimension.clone(),
|
||||
sum_dimension: self.sum_dimension.clone(),
|
||||
position: self.position.clone(),
|
||||
});
|
||||
subtree = child_trees.last().unwrap();
|
||||
}
|
||||
Node::Leaf { item_summaries, .. } => {
|
||||
let last_index = item_summaries.len().saturating_sub(1);
|
||||
for item_summary in &item_summaries[0..last_index] {
|
||||
self.seek_dimension.add_summary(item_summary, cx);
|
||||
self.sum_dimension.add_summary(item_summary, cx);
|
||||
self.position.add_summary(item_summary, cx);
|
||||
}
|
||||
self.stack.push(StackEntry {
|
||||
tree: subtree,
|
||||
index: last_index,
|
||||
seek_dimension: self.seek_dimension.clone(),
|
||||
sum_dimension: self.sum_dimension.clone(),
|
||||
position: self.position.clone(),
|
||||
});
|
||||
break;
|
||||
}
|
||||
@@ -368,34 +309,47 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, S, U> Cursor<'a, T, S, U>
|
||||
impl<'a, T, D> Cursor<'a, T, D>
|
||||
where
|
||||
T: Item,
|
||||
S: SeekDimension<'a, T::Summary>,
|
||||
U: Dimension<'a, T::Summary>,
|
||||
D: Dimension<'a, T::Summary>,
|
||||
{
|
||||
pub fn seek(&mut self, pos: &S, bias: Bias, cx: &<T::Summary as Summary>::Context) -> bool {
|
||||
pub fn seek<Target>(
|
||||
&mut self,
|
||||
pos: &Target,
|
||||
bias: Bias,
|
||||
cx: &<T::Summary as Summary>::Context,
|
||||
) -> bool
|
||||
where
|
||||
Target: SeekTarget<'a, T::Summary, D>,
|
||||
{
|
||||
self.reset();
|
||||
self.seek_internal::<()>(Some(pos), bias, &mut SeekAggregate::None, cx)
|
||||
self.seek_internal::<_, ()>(pos, bias, &mut SeekAggregate::None, cx)
|
||||
}
|
||||
|
||||
pub fn seek_forward(
|
||||
pub fn seek_forward<Target>(
|
||||
&mut self,
|
||||
pos: &S,
|
||||
pos: &Target,
|
||||
bias: Bias,
|
||||
cx: &<T::Summary as Summary>::Context,
|
||||
) -> bool {
|
||||
self.seek_internal::<()>(Some(pos), bias, &mut SeekAggregate::None, cx)
|
||||
) -> bool
|
||||
where
|
||||
Target: SeekTarget<'a, T::Summary, D>,
|
||||
{
|
||||
self.seek_internal::<_, ()>(pos, bias, &mut SeekAggregate::None, cx)
|
||||
}
|
||||
|
||||
pub fn slice(
|
||||
pub fn slice<Target>(
|
||||
&mut self,
|
||||
end: &S,
|
||||
end: &Target,
|
||||
bias: Bias,
|
||||
cx: &<T::Summary as Summary>::Context,
|
||||
) -> SumTree<T> {
|
||||
) -> SumTree<T>
|
||||
where
|
||||
Target: SeekTarget<'a, T::Summary, D>,
|
||||
{
|
||||
let mut slice = SeekAggregate::Slice(SumTree::new());
|
||||
self.seek_internal::<()>(Some(end), bias, &mut slice, cx);
|
||||
self.seek_internal::<_, ()>(end, bias, &mut slice, cx);
|
||||
if let SeekAggregate::Slice(slice) = slice {
|
||||
slice
|
||||
} else {
|
||||
@@ -405,7 +359,7 @@ where
|
||||
|
||||
pub fn suffix(&mut self, cx: &<T::Summary as Summary>::Context) -> SumTree<T> {
|
||||
let mut slice = SeekAggregate::Slice(SumTree::new());
|
||||
self.seek_internal::<()>(None, Bias::Right, &mut slice, cx);
|
||||
self.seek_internal::<_, ()>(&End::new(), Bias::Right, &mut slice, cx);
|
||||
if let SeekAggregate::Slice(slice) = slice {
|
||||
slice
|
||||
} else {
|
||||
@@ -413,12 +367,18 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn summary<D>(&mut self, end: &S, bias: Bias, cx: &<T::Summary as Summary>::Context) -> D
|
||||
pub fn summary<Target, Output>(
|
||||
&mut self,
|
||||
end: &Target,
|
||||
bias: Bias,
|
||||
cx: &<T::Summary as Summary>::Context,
|
||||
) -> Output
|
||||
where
|
||||
D: Dimension<'a, T::Summary>,
|
||||
Target: SeekTarget<'a, T::Summary, D>,
|
||||
Output: Dimension<'a, T::Summary>,
|
||||
{
|
||||
let mut summary = SeekAggregate::Summary(D::default());
|
||||
self.seek_internal(Some(end), bias, &mut summary, cx);
|
||||
let mut summary = SeekAggregate::Summary(Output::default());
|
||||
self.seek_internal(end, bias, &mut summary, cx);
|
||||
if let SeekAggregate::Summary(summary) = summary {
|
||||
summary
|
||||
} else {
|
||||
@@ -426,32 +386,30 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn seek_internal<D>(
|
||||
fn seek_internal<Target, Output>(
|
||||
&mut self,
|
||||
target: Option<&S>,
|
||||
target: &Target,
|
||||
bias: Bias,
|
||||
aggregate: &mut SeekAggregate<T, D>,
|
||||
aggregate: &mut SeekAggregate<T, Output>,
|
||||
cx: &<T::Summary as Summary>::Context,
|
||||
) -> bool
|
||||
where
|
||||
D: Dimension<'a, T::Summary>,
|
||||
Target: SeekTarget<'a, T::Summary, D>,
|
||||
Output: Dimension<'a, T::Summary>,
|
||||
{
|
||||
if let Some(target) = target {
|
||||
debug_assert!(
|
||||
target.cmp(&self.seek_dimension, cx) >= Ordering::Equal,
|
||||
"cannot seek backward from {:?} to {:?}",
|
||||
self.seek_dimension,
|
||||
target
|
||||
);
|
||||
}
|
||||
debug_assert!(
|
||||
target.cmp(&self.position, cx) >= Ordering::Equal,
|
||||
"cannot seek backward from {:?} to {:?}",
|
||||
self.position,
|
||||
target
|
||||
);
|
||||
|
||||
if !self.did_seek {
|
||||
self.did_seek = true;
|
||||
self.stack.push(StackEntry {
|
||||
tree: self.tree,
|
||||
index: 0,
|
||||
seek_dimension: Default::default(),
|
||||
sum_dimension: Default::default(),
|
||||
position: Default::default(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -471,16 +429,14 @@ where
|
||||
.iter()
|
||||
.zip(&child_summaries[entry.index..])
|
||||
{
|
||||
let mut child_end = self.seek_dimension.clone();
|
||||
let mut child_end = self.position.clone();
|
||||
child_end.add_summary(&child_summary, cx);
|
||||
|
||||
let comparison =
|
||||
target.map_or(Ordering::Greater, |t| t.cmp(&child_end, cx));
|
||||
let comparison = target.cmp(&child_end, cx);
|
||||
if comparison == Ordering::Greater
|
||||
|| (comparison == Ordering::Equal && bias == Bias::Right)
|
||||
{
|
||||
self.seek_dimension = child_end;
|
||||
self.sum_dimension.add_summary(child_summary, cx);
|
||||
self.position = child_end;
|
||||
match aggregate {
|
||||
SeekAggregate::None => {}
|
||||
SeekAggregate::Slice(slice) => {
|
||||
@@ -491,14 +447,12 @@ where
|
||||
}
|
||||
}
|
||||
entry.index += 1;
|
||||
entry.seek_dimension = self.seek_dimension.clone();
|
||||
entry.sum_dimension = self.sum_dimension.clone();
|
||||
entry.position = self.position.clone();
|
||||
} else {
|
||||
self.stack.push(StackEntry {
|
||||
tree: child_tree,
|
||||
index: 0,
|
||||
seek_dimension: self.seek_dimension.clone(),
|
||||
sum_dimension: self.sum_dimension.clone(),
|
||||
position: self.position.clone(),
|
||||
});
|
||||
ascending = false;
|
||||
continue 'outer;
|
||||
@@ -521,25 +475,24 @@ where
|
||||
.iter()
|
||||
.zip(&item_summaries[entry.index..])
|
||||
{
|
||||
let mut child_end = self.seek_dimension.clone();
|
||||
let mut child_end = self.position.clone();
|
||||
child_end.add_summary(item_summary, cx);
|
||||
|
||||
let comparison =
|
||||
target.map_or(Ordering::Greater, |t| t.cmp(&child_end, cx));
|
||||
let comparison = target.cmp(&child_end, cx);
|
||||
if comparison == Ordering::Greater
|
||||
|| (comparison == Ordering::Equal && bias == Bias::Right)
|
||||
{
|
||||
self.seek_dimension = child_end;
|
||||
self.sum_dimension.add_summary(item_summary, cx);
|
||||
self.position = child_end;
|
||||
match aggregate {
|
||||
SeekAggregate::None => {}
|
||||
SeekAggregate::Slice(_) => {
|
||||
slice_items.push(item.clone());
|
||||
slice_item_summaries.push(item_summary.clone());
|
||||
slice_items_summary
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.add_summary(item_summary, cx);
|
||||
<T::Summary as Summary>::add_summary(
|
||||
slice_items_summary.as_mut().unwrap(),
|
||||
item_summary,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
SeekAggregate::Summary(summary) => {
|
||||
summary.add_summary(item_summary, cx);
|
||||
@@ -583,23 +536,22 @@ where
|
||||
self.at_end = self.stack.is_empty();
|
||||
debug_assert!(self.stack.is_empty() || self.stack.last().unwrap().tree.0.is_leaf());
|
||||
|
||||
let mut end = self.seek_dimension.clone();
|
||||
let mut end = self.position.clone();
|
||||
if bias == Bias::Left {
|
||||
if let Some(summary) = self.item_summary() {
|
||||
end.add_summary(summary, cx);
|
||||
}
|
||||
}
|
||||
|
||||
target.map_or(false, |t| t.cmp(&end, cx) == Ordering::Equal)
|
||||
target.cmp(&end, cx) == Ordering::Equal
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, S, Seek, Sum> Iterator for Cursor<'a, T, Seek, Sum>
|
||||
impl<'a, T, S, D> Iterator for Cursor<'a, T, D>
|
||||
where
|
||||
T: Item<Summary = S>,
|
||||
S: Summary<Context = ()>,
|
||||
Seek: Dimension<'a, T::Summary>,
|
||||
Sum: Dimension<'a, T::Summary>,
|
||||
D: Dimension<'a, T::Summary>,
|
||||
{
|
||||
type Item = &'a T;
|
||||
|
||||
@@ -617,45 +569,23 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T, S, U> Cursor<'a, T, S, U>
|
||||
where
|
||||
T: Item,
|
||||
S: SeekDimension<'a, T::Summary>,
|
||||
U: SeekDimension<'a, T::Summary>,
|
||||
{
|
||||
pub fn swap_dimensions(self) -> Cursor<'a, T, U, S> {
|
||||
Cursor {
|
||||
tree: self.tree,
|
||||
stack: self
|
||||
.stack
|
||||
.into_iter()
|
||||
.map(StackEntry::swap_dimensions)
|
||||
.collect(),
|
||||
seek_dimension: self.sum_dimension,
|
||||
sum_dimension: self.seek_dimension,
|
||||
did_seek: self.did_seek,
|
||||
at_end: self.at_end,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FilterCursor<'a, F: Fn(&T::Summary) -> bool, T: Item, U> {
|
||||
cursor: Cursor<'a, T, (), U>,
|
||||
pub struct FilterCursor<'a, F: Fn(&T::Summary) -> bool, T: Item, D> {
|
||||
cursor: Cursor<'a, T, D>,
|
||||
filter_node: F,
|
||||
}
|
||||
|
||||
impl<'a, F, T, U> FilterCursor<'a, F, T, U>
|
||||
impl<'a, F, T, D> FilterCursor<'a, F, T, D>
|
||||
where
|
||||
F: Fn(&T::Summary) -> bool,
|
||||
T: Item,
|
||||
U: Dimension<'a, T::Summary>,
|
||||
D: Dimension<'a, T::Summary>,
|
||||
{
|
||||
pub fn new(
|
||||
tree: &'a SumTree<T>,
|
||||
filter_node: F,
|
||||
cx: &<T::Summary as Summary>::Context,
|
||||
) -> Self {
|
||||
let mut cursor = tree.cursor::<(), U>();
|
||||
let mut cursor = tree.cursor::<D>();
|
||||
cursor.next_internal(&filter_node, cx);
|
||||
Self {
|
||||
cursor,
|
||||
@@ -663,8 +593,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(&self) -> &U {
|
||||
self.cursor.sum_start()
|
||||
pub fn start(&self) -> &D {
|
||||
self.cursor.start()
|
||||
}
|
||||
|
||||
pub fn item(&self) -> Option<&'a T> {
|
||||
|
||||
Reference in New Issue
Block a user