Compare commits
6 commits
main
...
sumtree-v1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3870eeff32 | ||
![]() |
74a6c78fff | ||
![]() |
2be18a200f | ||
![]() |
4e2907e296 | ||
![]() |
b43153a99f | ||
![]() |
57ea58c83e |
4 changed files with 174 additions and 143 deletions
|
@ -154,7 +154,7 @@ impl BufferDiffSnapshot {
|
||||||
BufferDiffSnapshot {
|
BufferDiffSnapshot {
|
||||||
inner: BufferDiffInner {
|
inner: BufferDiffInner {
|
||||||
base_text: language::Buffer::build_empty_snapshot(cx),
|
base_text: language::Buffer::build_empty_snapshot(cx),
|
||||||
hunks: SumTree::new(buffer),
|
hunks: SumTree::new(),
|
||||||
pending_hunks: SumTree::new(buffer),
|
pending_hunks: SumTree::new(buffer),
|
||||||
base_text_exists: false,
|
base_text_exists: false,
|
||||||
},
|
},
|
||||||
|
|
|
@ -205,13 +205,13 @@ where
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn prev(&mut self) {
|
pub fn prev(&mut self) {
|
||||||
self.search_backward(|_| true)
|
self.search_backward(|_| Ordering::Equal)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn search_backward<F>(&mut self, mut filter_node: F)
|
pub fn search_backward<F>(&mut self, mut filter_node: F)
|
||||||
where
|
where
|
||||||
F: FnMut(&T::Summary) -> bool,
|
F: FnMut(&T::Summary) -> Ordering,
|
||||||
{
|
{
|
||||||
if !self.did_seek {
|
if !self.did_seek {
|
||||||
self.did_seek = true;
|
self.did_seek = true;
|
||||||
|
@ -222,10 +222,15 @@ where
|
||||||
self.position = D::zero(self.cx);
|
self.position = D::zero(self.cx);
|
||||||
self.at_end = self.tree.is_empty();
|
self.at_end = self.tree.is_empty();
|
||||||
if !self.tree.is_empty() {
|
if !self.tree.is_empty() {
|
||||||
|
let position = if let Some(summary) = self.tree.0.summary() {
|
||||||
|
D::from_summary(summary, self.cx)
|
||||||
|
} else {
|
||||||
|
D::zero(self.cx)
|
||||||
|
};
|
||||||
self.stack.push(StackEntry {
|
self.stack.push(StackEntry {
|
||||||
tree: self.tree,
|
tree: self.tree,
|
||||||
index: self.tree.0.child_summaries().len(),
|
index: self.tree.0.child_summaries().len(),
|
||||||
position: D::from_summary(self.tree.summary(), self.cx),
|
position,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,12 +253,14 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for summary in &entry.tree.0.child_summaries()[..entry.index] {
|
if entry.index != 0 {
|
||||||
self.position.add_summary(summary, self.cx);
|
self.position
|
||||||
|
.add_summary(&entry.tree.0.child_summaries()[entry.index - 1], self.cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
entry.position = self.position.clone();
|
entry.position = self.position.clone();
|
||||||
|
|
||||||
descending = filter_node(&entry.tree.0.child_summaries()[entry.index]);
|
descending = filter_node(&entry.tree.0.child_summaries()[entry.index]).is_ge();
|
||||||
match entry.tree.0.as_ref() {
|
match entry.tree.0.as_ref() {
|
||||||
Node::Internal { child_trees, .. } => {
|
Node::Internal { child_trees, .. } => {
|
||||||
if descending {
|
if descending {
|
||||||
|
@ -276,13 +283,13 @@ where
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn next(&mut self) {
|
pub fn next(&mut self) {
|
||||||
self.search_forward(|_| true)
|
self.search_forward(|_| Ordering::Equal)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn search_forward<F>(&mut self, mut filter_node: F)
|
pub fn search_forward<F>(&mut self, mut filter_node: F)
|
||||||
where
|
where
|
||||||
F: FnMut(&T::Summary) -> bool,
|
F: FnMut(&T::Summary) -> Ordering,
|
||||||
{
|
{
|
||||||
let mut descend = false;
|
let mut descend = false;
|
||||||
|
|
||||||
|
@ -312,14 +319,15 @@ where
|
||||||
entry.position = self.position.clone();
|
entry.position = self.position.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
while entry.index < child_summaries.len() {
|
if entry.index < child_summaries.len() {
|
||||||
let next_summary = &child_summaries[entry.index];
|
let index = child_summaries[entry.index..]
|
||||||
if filter_node(next_summary) {
|
.partition_point(|item| filter_node(item).is_lt());
|
||||||
break;
|
|
||||||
} else {
|
entry.index += index;
|
||||||
entry.index += 1;
|
|
||||||
entry.position.add_summary(next_summary, self.cx);
|
if let Some(summary) = child_summaries.get(entry.index) {
|
||||||
self.position.add_summary(next_summary, self.cx);
|
entry.position.add_summary(summary, self.cx);
|
||||||
|
self.position.add_summary(summary, self.cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,18 +341,19 @@ where
|
||||||
self.position.add_summary(item_summary, self.cx);
|
self.position.add_summary(item_summary, self.cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
if entry.index < item_summaries.len() {
|
||||||
if let Some(next_item_summary) = item_summaries.get(entry.index) {
|
let index = item_summaries[entry.index..]
|
||||||
if filter_node(next_item_summary) {
|
.partition_point(|item| filter_node(item).is_lt());
|
||||||
return;
|
|
||||||
} else {
|
entry.index += index;
|
||||||
entry.index += 1;
|
|
||||||
entry.position.add_summary(next_item_summary, self.cx);
|
if let Some(summary) = item_summaries.get(entry.index) {
|
||||||
self.position.add_summary(next_item_summary, self.cx);
|
entry.position.add_summary(summary, self.cx);
|
||||||
}
|
self.position.add_summary(summary, self.cx);
|
||||||
} else {
|
|
||||||
break None;
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -405,7 +414,7 @@ where
|
||||||
Target: SeekTarget<'a, T::Summary, D>,
|
Target: SeekTarget<'a, T::Summary, D>,
|
||||||
{
|
{
|
||||||
let mut slice = SliceSeekAggregate {
|
let mut slice = SliceSeekAggregate {
|
||||||
tree: SumTree::new(self.cx),
|
tree: SumTree::new(),
|
||||||
leaf_items: ArrayVec::new(),
|
leaf_items: ArrayVec::new(),
|
||||||
leaf_item_summaries: ArrayVec::new(),
|
leaf_item_summaries: ArrayVec::new(),
|
||||||
leaf_summary: <T::Summary as Summary>::zero(self.cx),
|
leaf_summary: <T::Summary as Summary>::zero(self.cx),
|
||||||
|
@ -632,7 +641,7 @@ pub struct FilterCursor<'a, F, T: Item, D> {
|
||||||
|
|
||||||
impl<'a, F, T: Item, D> FilterCursor<'a, F, T, D>
|
impl<'a, F, T: Item, D> FilterCursor<'a, F, T, D>
|
||||||
where
|
where
|
||||||
F: FnMut(&T::Summary) -> bool,
|
F: FnMut(&T::Summary) -> Ordering,
|
||||||
T: Item,
|
T: Item,
|
||||||
D: Dimension<'a, T::Summary>,
|
D: Dimension<'a, T::Summary>,
|
||||||
{
|
{
|
||||||
|
@ -675,7 +684,7 @@ where
|
||||||
|
|
||||||
impl<'a, F, T: Item, U> Iterator for FilterCursor<'a, F, T, U>
|
impl<'a, F, T: Item, U> Iterator for FilterCursor<'a, F, T, U>
|
||||||
where
|
where
|
||||||
F: FnMut(&T::Summary) -> bool,
|
F: FnMut(&T::Summary) -> Ordering,
|
||||||
U: Dimension<'a, T::Summary>,
|
U: Dimension<'a, T::Summary>,
|
||||||
{
|
{
|
||||||
type Item = &'a T;
|
type Item = &'a T;
|
||||||
|
@ -732,7 +741,6 @@ impl<T: Item> SeekAggregate<'_, T> for SliceSeekAggregate<T> {
|
||||||
fn end_leaf(&mut self, cx: &<T::Summary as Summary>::Context) {
|
fn end_leaf(&mut self, cx: &<T::Summary as Summary>::Context) {
|
||||||
self.tree.append(
|
self.tree.append(
|
||||||
SumTree(Arc::new(Node::Leaf {
|
SumTree(Arc::new(Node::Leaf {
|
||||||
summary: mem::replace(&mut self.leaf_summary, <T::Summary as Summary>::zero(cx)),
|
|
||||||
items: mem::take(&mut self.leaf_items),
|
items: mem::take(&mut self.leaf_items),
|
||||||
item_summaries: mem::take(&mut self.leaf_item_summaries),
|
item_summaries: mem::take(&mut self.leaf_item_summaries),
|
||||||
})),
|
})),
|
||||||
|
|
|
@ -4,6 +4,8 @@ mod tree_map;
|
||||||
use arrayvec::ArrayVec;
|
use arrayvec::ArrayVec;
|
||||||
pub use cursor::{Cursor, FilterCursor, Iter};
|
pub use cursor::{Cursor, FilterCursor, Iter};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::fmt::Debug;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::{cmp::Ordering, fmt, iter::FromIterator, sync::Arc};
|
use std::{cmp::Ordering, fmt, iter::FromIterator, sync::Arc};
|
||||||
|
@ -39,6 +41,7 @@ pub trait Summary: Clone {
|
||||||
|
|
||||||
fn zero(cx: &Self::Context) -> Self;
|
fn zero(cx: &Self::Context) -> Self;
|
||||||
fn add_summary(&mut self, summary: &Self, cx: &Self::Context);
|
fn add_summary(&mut self, summary: &Self, cx: &Self::Context);
|
||||||
|
fn sub_summary(&mut self, _: &Self, _: &Self::Context) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Catch-all implementation for when you need something that implements [`Summary`] without a specific type.
|
/// Catch-all implementation for when you need something that implements [`Summary`] without a specific type.
|
||||||
|
@ -187,25 +190,15 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Item> SumTree<T> {
|
impl<T: Item> SumTree<T> {
|
||||||
pub fn new(cx: &<T::Summary as Summary>::Context) -> Self {
|
pub fn new() -> Self {
|
||||||
SumTree(Arc::new(Node::Leaf {
|
SumTree(Arc::new(Node::Leaf {
|
||||||
summary: <T::Summary as Summary>::zero(cx),
|
|
||||||
items: ArrayVec::new(),
|
|
||||||
item_summaries: ArrayVec::new(),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Useful in cases where the item type has a non-trivial context type, but the zero value of the summary type doesn't depend on that context.
|
|
||||||
pub fn from_summary(summary: T::Summary) -> Self {
|
|
||||||
SumTree(Arc::new(Node::Leaf {
|
|
||||||
summary,
|
|
||||||
items: ArrayVec::new(),
|
items: ArrayVec::new(),
|
||||||
item_summaries: ArrayVec::new(),
|
item_summaries: ArrayVec::new(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_item(item: T, cx: &<T::Summary as Summary>::Context) -> Self {
|
pub fn from_item(item: T, cx: &<T::Summary as Summary>::Context) -> Self {
|
||||||
let mut tree = Self::new(cx);
|
let mut tree = Self::new();
|
||||||
tree.push(item, cx);
|
tree.push(item, cx);
|
||||||
tree
|
tree
|
||||||
}
|
}
|
||||||
|
@ -219,16 +212,21 @@ impl<T: Item> SumTree<T> {
|
||||||
let mut iter = iter.into_iter().fuse().peekable();
|
let mut iter = iter.into_iter().fuse().peekable();
|
||||||
while iter.peek().is_some() {
|
while iter.peek().is_some() {
|
||||||
let items: ArrayVec<T, { 2 * TREE_BASE }> = iter.by_ref().take(2 * TREE_BASE).collect();
|
let items: ArrayVec<T, { 2 * TREE_BASE }> = iter.by_ref().take(2 * TREE_BASE).collect();
|
||||||
let item_summaries: ArrayVec<T::Summary, { 2 * TREE_BASE }> =
|
let item_summaries: ArrayVec<T::Summary, { 2 * TREE_BASE }> = items
|
||||||
items.iter().map(|item| item.summary(cx)).collect();
|
.iter()
|
||||||
|
.scan(None, |previous_item, item| {
|
||||||
let mut summary = item_summaries[0].clone();
|
let summary = item.summary(cx);
|
||||||
for item_summary in &item_summaries[1..] {
|
let current_item = if let Some(mut base) = previous_item.take() {
|
||||||
<T::Summary as Summary>::add_summary(&mut summary, item_summary, cx);
|
<T::Summary as Summary>::add_summary(&mut base, &summary, cx);
|
||||||
}
|
base
|
||||||
|
} else {
|
||||||
|
summary
|
||||||
|
};
|
||||||
|
_ = previous_item.insert(current_item.clone());
|
||||||
|
Some(current_item)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
nodes.push(Node::Leaf {
|
nodes.push(Node::Leaf {
|
||||||
summary,
|
|
||||||
items,
|
items,
|
||||||
item_summaries,
|
item_summaries,
|
||||||
});
|
});
|
||||||
|
@ -241,13 +239,11 @@ impl<T: Item> SumTree<T> {
|
||||||
let mut current_parent_node = None;
|
let mut current_parent_node = None;
|
||||||
for child_node in nodes.drain(..) {
|
for child_node in nodes.drain(..) {
|
||||||
let parent_node = current_parent_node.get_or_insert_with(|| Node::Internal {
|
let parent_node = current_parent_node.get_or_insert_with(|| Node::Internal {
|
||||||
summary: <T::Summary as Summary>::zero(cx),
|
|
||||||
height,
|
height,
|
||||||
child_summaries: ArrayVec::new(),
|
child_summaries: ArrayVec::new(),
|
||||||
child_trees: ArrayVec::new(),
|
child_trees: ArrayVec::new(),
|
||||||
});
|
});
|
||||||
let Node::Internal {
|
let Node::Internal {
|
||||||
summary,
|
|
||||||
child_summaries,
|
child_summaries,
|
||||||
child_trees,
|
child_trees,
|
||||||
..
|
..
|
||||||
|
@ -255,9 +251,15 @@ impl<T: Item> SumTree<T> {
|
||||||
else {
|
else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
let child_summary = child_node.summary();
|
let child_summary = child_node.summary_or_zero(cx);
|
||||||
<T::Summary as Summary>::add_summary(summary, child_summary, cx);
|
let child_summary = if let Some(mut last) = child_summaries.last().cloned() {
|
||||||
child_summaries.push(child_summary.clone());
|
<T::Summary as Summary>::add_summary(&mut last, &child_summary, cx);
|
||||||
|
last
|
||||||
|
} else {
|
||||||
|
child_summary.into_owned()
|
||||||
|
};
|
||||||
|
|
||||||
|
child_summaries.push(child_summary);
|
||||||
child_trees.push(Self(Arc::new(child_node)));
|
child_trees.push(Self(Arc::new(child_node)));
|
||||||
|
|
||||||
if child_trees.len() == 2 * TREE_BASE {
|
if child_trees.len() == 2 * TREE_BASE {
|
||||||
|
@ -269,7 +271,7 @@ impl<T: Item> SumTree<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if nodes.is_empty() {
|
if nodes.is_empty() {
|
||||||
Self::new(cx)
|
Self::new()
|
||||||
} else {
|
} else {
|
||||||
debug_assert_eq!(nodes.len(), 1);
|
debug_assert_eq!(nodes.len(), 1);
|
||||||
Self(Arc::new(nodes.pop().unwrap()))
|
Self(Arc::new(nodes.pop().unwrap()))
|
||||||
|
@ -289,14 +291,22 @@ impl<T: Item> SumTree<T> {
|
||||||
.chunks(2 * TREE_BASE)
|
.chunks(2 * TREE_BASE)
|
||||||
.map(|items| {
|
.map(|items| {
|
||||||
let items: ArrayVec<T, { 2 * TREE_BASE }> = items.into_iter().collect();
|
let items: ArrayVec<T, { 2 * TREE_BASE }> = items.into_iter().collect();
|
||||||
let item_summaries: ArrayVec<T::Summary, { 2 * TREE_BASE }> =
|
let item_summaries: ArrayVec<T::Summary, { 2 * TREE_BASE }> = items
|
||||||
items.iter().map(|item| item.summary(cx)).collect();
|
.iter()
|
||||||
let mut summary = item_summaries[0].clone();
|
.scan(None, |previous_item, item| {
|
||||||
for item_summary in &item_summaries[1..] {
|
let summary = item.summary(cx);
|
||||||
<T::Summary as Summary>::add_summary(&mut summary, item_summary, cx);
|
let current_item = if let Some(mut base) = previous_item.take() {
|
||||||
}
|
<T::Summary as Summary>::add_summary(&mut base, &summary, cx);
|
||||||
|
base
|
||||||
|
} else {
|
||||||
|
summary
|
||||||
|
};
|
||||||
|
_ = previous_item.insert(current_item.clone());
|
||||||
|
Some(current_item)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
SumTree(Arc::new(Node::Leaf {
|
SumTree(Arc::new(Node::Leaf {
|
||||||
summary,
|
|
||||||
items,
|
items,
|
||||||
item_summaries,
|
item_summaries,
|
||||||
}))
|
}))
|
||||||
|
@ -314,7 +324,7 @@ impl<T: Item> SumTree<T> {
|
||||||
child_nodes.into_iter().collect();
|
child_nodes.into_iter().collect();
|
||||||
let child_summaries: ArrayVec<T::Summary, { 2 * TREE_BASE }> = child_trees
|
let child_summaries: ArrayVec<T::Summary, { 2 * TREE_BASE }> = child_trees
|
||||||
.iter()
|
.iter()
|
||||||
.map(|child_tree| child_tree.summary().clone())
|
.map(|child_tree| child_tree.0.summary_or_zero(cx).into_owned())
|
||||||
.collect();
|
.collect();
|
||||||
let mut summary = child_summaries[0].clone();
|
let mut summary = child_summaries[0].clone();
|
||||||
for child_summary in &child_summaries[1..] {
|
for child_summary in &child_summaries[1..] {
|
||||||
|
@ -322,7 +332,7 @@ impl<T: Item> SumTree<T> {
|
||||||
}
|
}
|
||||||
SumTree(Arc::new(Node::Internal {
|
SumTree(Arc::new(Node::Internal {
|
||||||
height,
|
height,
|
||||||
summary,
|
|
||||||
child_summaries,
|
child_summaries,
|
||||||
child_trees,
|
child_trees,
|
||||||
}))
|
}))
|
||||||
|
@ -331,7 +341,7 @@ impl<T: Item> SumTree<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if nodes.is_empty() {
|
if nodes.is_empty() {
|
||||||
Self::new(cx)
|
Self::new()
|
||||||
} else {
|
} else {
|
||||||
debug_assert_eq!(nodes.len(), 1);
|
debug_assert_eq!(nodes.len(), 1);
|
||||||
nodes.pop().unwrap()
|
nodes.pop().unwrap()
|
||||||
|
@ -369,7 +379,7 @@ impl<T: Item> SumTree<T> {
|
||||||
filter_node: F,
|
filter_node: F,
|
||||||
) -> FilterCursor<'a, F, T, U>
|
) -> FilterCursor<'a, F, T, U>
|
||||||
where
|
where
|
||||||
F: FnMut(&T::Summary) -> bool,
|
F: FnMut(&T::Summary) -> Ordering,
|
||||||
U: Dimension<'a, T::Summary>,
|
U: Dimension<'a, T::Summary>,
|
||||||
{
|
{
|
||||||
FilterCursor::new(self, cx, filter_node)
|
FilterCursor::new(self, cx, filter_node)
|
||||||
|
@ -395,28 +405,57 @@ impl<T: Item> SumTree<T> {
|
||||||
) -> Option<T::Summary> {
|
) -> Option<T::Summary> {
|
||||||
match Arc::make_mut(&mut self.0) {
|
match Arc::make_mut(&mut self.0) {
|
||||||
Node::Internal {
|
Node::Internal {
|
||||||
summary,
|
|
||||||
child_summaries,
|
child_summaries,
|
||||||
child_trees,
|
child_trees,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let last_summary = child_summaries.last_mut().unwrap();
|
|
||||||
let last_child = child_trees.last_mut().unwrap();
|
let last_child = child_trees.last_mut().unwrap();
|
||||||
*last_summary = last_child.update_last_recursive(f, cx).unwrap();
|
|
||||||
*summary = sum(child_summaries.iter(), cx);
|
let mut bare_summary = last_child.update_last_recursive(f, cx).unwrap();
|
||||||
Some(summary.clone())
|
|
||||||
|
if let Some(mut second_to_last_summary) = child_summaries
|
||||||
|
.len()
|
||||||
|
.checked_sub(2)
|
||||||
|
.and_then(|ix| child_summaries.get(ix))
|
||||||
|
.cloned()
|
||||||
|
{
|
||||||
|
<T::Summary as Summary>::add_summary(
|
||||||
|
&mut second_to_last_summary,
|
||||||
|
&bare_summary,
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
bare_summary = second_to_last_summary;
|
||||||
|
}
|
||||||
|
let last_summary = child_summaries.last_mut().unwrap();
|
||||||
|
*last_summary = bare_summary;
|
||||||
|
|
||||||
|
Some(last_summary.clone())
|
||||||
}
|
}
|
||||||
Node::Leaf {
|
Node::Leaf {
|
||||||
summary,
|
|
||||||
items,
|
items,
|
||||||
item_summaries,
|
item_summaries,
|
||||||
} => {
|
} => {
|
||||||
|
let preceding_summary = item_summaries
|
||||||
|
.len()
|
||||||
|
.checked_sub(2)
|
||||||
|
.and_then(|ix| item_summaries.get(ix))
|
||||||
|
.cloned();
|
||||||
if let Some((item, item_summary)) = items.last_mut().zip(item_summaries.last_mut())
|
if let Some((item, item_summary)) = items.last_mut().zip(item_summaries.last_mut())
|
||||||
{
|
{
|
||||||
(f)(item);
|
(f)(item);
|
||||||
*item_summary = item.summary(cx);
|
let mut bare_summary = item.summary(cx);
|
||||||
*summary = sum(item_summaries.iter(), cx);
|
|
||||||
Some(summary.clone())
|
if let Some(mut second_to_last_summary) = preceding_summary {
|
||||||
|
<T::Summary as Summary>::add_summary(
|
||||||
|
&mut second_to_last_summary,
|
||||||
|
&bare_summary,
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
bare_summary = second_to_last_summary;
|
||||||
|
}
|
||||||
|
*item_summary = bare_summary.clone();
|
||||||
|
|
||||||
|
Some(item_summary.clone())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -429,19 +468,11 @@ impl<T: Item> SumTree<T> {
|
||||||
cx: &<T::Summary as Summary>::Context,
|
cx: &<T::Summary as Summary>::Context,
|
||||||
) -> D {
|
) -> D {
|
||||||
let mut extent = D::zero(cx);
|
let mut extent = D::zero(cx);
|
||||||
match self.0.as_ref() {
|
if let Some(last) = self.0.child_summaries().last() {
|
||||||
Node::Internal { summary, .. } | Node::Leaf { summary, .. } => {
|
extent.add_summary(last, cx);
|
||||||
extent.add_summary(summary, cx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
extent
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn summary(&self) -> &T::Summary {
|
extent
|
||||||
match self.0.as_ref() {
|
|
||||||
Node::Internal { summary, .. } => summary,
|
|
||||||
Node::Leaf { summary, .. } => summary,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
|
@ -473,7 +504,6 @@ impl<T: Item> SumTree<T> {
|
||||||
let summary = item.summary(cx);
|
let summary = item.summary(cx);
|
||||||
self.append(
|
self.append(
|
||||||
SumTree(Arc::new(Node::Leaf {
|
SumTree(Arc::new(Node::Leaf {
|
||||||
summary: summary.clone(),
|
|
||||||
items: ArrayVec::from_iter(Some(item)),
|
items: ArrayVec::from_iter(Some(item)),
|
||||||
item_summaries: ArrayVec::from_iter(Some(summary)),
|
item_summaries: ArrayVec::from_iter(Some(summary)),
|
||||||
})),
|
})),
|
||||||
|
@ -503,13 +533,11 @@ impl<T: Item> SumTree<T> {
|
||||||
match Arc::make_mut(&mut self.0) {
|
match Arc::make_mut(&mut self.0) {
|
||||||
Node::Internal {
|
Node::Internal {
|
||||||
height,
|
height,
|
||||||
summary,
|
|
||||||
child_summaries,
|
child_summaries,
|
||||||
child_trees,
|
child_trees,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let other_node = other.0.clone();
|
let other_node = other.0.clone();
|
||||||
<T::Summary as Summary>::add_summary(summary, other_node.summary(), cx);
|
|
||||||
|
|
||||||
let height_delta = *height - other_node.height();
|
let height_delta = *height - other_node.height();
|
||||||
let mut summaries_to_append = ArrayVec::<T::Summary, { 2 * TREE_BASE }>::new();
|
let mut summaries_to_append = ArrayVec::<T::Summary, { 2 * TREE_BASE }>::new();
|
||||||
|
@ -518,18 +546,22 @@ impl<T: Item> SumTree<T> {
|
||||||
summaries_to_append.extend(other_node.child_summaries().iter().cloned());
|
summaries_to_append.extend(other_node.child_summaries().iter().cloned());
|
||||||
trees_to_append.extend(other_node.child_trees().iter().cloned());
|
trees_to_append.extend(other_node.child_trees().iter().cloned());
|
||||||
} else if height_delta == 1 && !other_node.is_underflowing() {
|
} else if height_delta == 1 && !other_node.is_underflowing() {
|
||||||
summaries_to_append.push(other_node.summary().clone());
|
summaries_to_append.push(other_node.summary_or_zero(cx).into_owned());
|
||||||
trees_to_append.push(other)
|
trees_to_append.push(other)
|
||||||
} else {
|
} else {
|
||||||
let tree_to_append = child_trees
|
let tree_to_append = child_trees
|
||||||
.last_mut()
|
.last_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.push_tree_recursive(other, cx);
|
.push_tree_recursive(other, cx);
|
||||||
*child_summaries.last_mut().unwrap() =
|
*child_summaries.last_mut().unwrap() = child_trees
|
||||||
child_trees.last().unwrap().0.summary().clone();
|
.last()
|
||||||
|
.unwrap()
|
||||||
|
.0
|
||||||
|
.summary_or_zero(cx)
|
||||||
|
.into_owned();
|
||||||
|
|
||||||
if let Some(split_tree) = tree_to_append {
|
if let Some(split_tree) = tree_to_append {
|
||||||
summaries_to_append.push(split_tree.0.summary().clone());
|
summaries_to_append.push(split_tree.0.summary_or_zero(cx).into_owned());
|
||||||
trees_to_append.push(split_tree);
|
trees_to_append.push(split_tree);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -554,13 +586,12 @@ impl<T: Item> SumTree<T> {
|
||||||
left_trees = all_trees.by_ref().take(midpoint).collect();
|
left_trees = all_trees.by_ref().take(midpoint).collect();
|
||||||
right_trees = all_trees.collect();
|
right_trees = all_trees.collect();
|
||||||
}
|
}
|
||||||
*summary = sum(left_summaries.iter(), cx);
|
|
||||||
*child_summaries = left_summaries;
|
*child_summaries = left_summaries;
|
||||||
*child_trees = left_trees;
|
*child_trees = left_trees;
|
||||||
|
|
||||||
Some(SumTree(Arc::new(Node::Internal {
|
Some(SumTree(Arc::new(Node::Internal {
|
||||||
height: *height,
|
height: *height,
|
||||||
summary: sum(right_summaries.iter(), cx),
|
|
||||||
child_summaries: right_summaries,
|
child_summaries: right_summaries,
|
||||||
child_trees: right_trees,
|
child_trees: right_trees,
|
||||||
})))
|
})))
|
||||||
|
@ -571,7 +602,6 @@ impl<T: Item> SumTree<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Node::Leaf {
|
Node::Leaf {
|
||||||
summary,
|
|
||||||
items,
|
items,
|
||||||
item_summaries,
|
item_summaries,
|
||||||
} => {
|
} => {
|
||||||
|
@ -599,16 +629,24 @@ impl<T: Item> SumTree<T> {
|
||||||
}
|
}
|
||||||
*items = left_items;
|
*items = left_items;
|
||||||
*item_summaries = left_summaries;
|
*item_summaries = left_summaries;
|
||||||
*summary = sum(item_summaries.iter(), cx);
|
|
||||||
Some(SumTree(Arc::new(Node::Leaf {
|
Some(SumTree(Arc::new(Node::Leaf {
|
||||||
items: right_items,
|
items: right_items,
|
||||||
summary: sum(right_summaries.iter(), cx),
|
|
||||||
item_summaries: right_summaries,
|
item_summaries: right_summaries,
|
||||||
})))
|
})))
|
||||||
} else {
|
} else {
|
||||||
<T::Summary as Summary>::add_summary(summary, other_node.summary(), cx);
|
let baseline = item_summaries.last().cloned();
|
||||||
|
|
||||||
items.extend(other_node.items().iter().cloned());
|
items.extend(other_node.items().iter().cloned());
|
||||||
item_summaries.extend(other_node.child_summaries().iter().cloned());
|
item_summaries.extend(other_node.child_summaries().iter().map(|summary| {
|
||||||
|
if let Some(mut baseline) = baseline.clone() {
|
||||||
|
<T::Summary as Summary>::add_summary(&mut baseline, summary, cx);
|
||||||
|
baseline
|
||||||
|
} else {
|
||||||
|
summary.clone()
|
||||||
|
}
|
||||||
|
}));
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -622,14 +660,14 @@ impl<T: Item> SumTree<T> {
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let height = left.0.height() + 1;
|
let height = left.0.height() + 1;
|
||||||
let mut child_summaries = ArrayVec::new();
|
let mut child_summaries = ArrayVec::new();
|
||||||
child_summaries.push(left.0.summary().clone());
|
child_summaries.push(left.0.summary_or_zero(cx).into_owned());
|
||||||
child_summaries.push(right.0.summary().clone());
|
child_summaries.push(right.0.summary_or_zero(cx).into_owned());
|
||||||
let mut child_trees = ArrayVec::new();
|
let mut child_trees = ArrayVec::new();
|
||||||
child_trees.push(left);
|
child_trees.push(left);
|
||||||
child_trees.push(right);
|
child_trees.push(right);
|
||||||
SumTree(Arc::new(Node::Internal {
|
SumTree(Arc::new(Node::Internal {
|
||||||
height,
|
height,
|
||||||
summary: sum(child_summaries.iter(), cx),
|
|
||||||
child_summaries,
|
child_summaries,
|
||||||
child_trees,
|
child_trees,
|
||||||
}))
|
}))
|
||||||
|
@ -716,7 +754,7 @@ impl<T: KeyedItem> SumTree<T> {
|
||||||
|
|
||||||
*self = {
|
*self = {
|
||||||
let mut cursor = self.cursor::<T::Key>(cx);
|
let mut cursor = self.cursor::<T::Key>(cx);
|
||||||
let mut new_tree = SumTree::new(cx);
|
let mut new_tree = SumTree::new();
|
||||||
let mut buffered_items = Vec::new();
|
let mut buffered_items = Vec::new();
|
||||||
|
|
||||||
cursor.seek(&T::Key::zero(cx), Bias::Left);
|
cursor.seek(&T::Key::zero(cx), Bias::Left);
|
||||||
|
@ -771,13 +809,9 @@ impl<T: KeyedItem> SumTree<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, S> Default for SumTree<T>
|
impl<T: Item> Default for SumTree<T> {
|
||||||
where
|
|
||||||
T: Item<Summary = S>,
|
|
||||||
S: Summary<Context = ()>,
|
|
||||||
{
|
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new(&())
|
Self::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -785,12 +819,10 @@ where
|
||||||
pub enum Node<T: Item> {
|
pub enum Node<T: Item> {
|
||||||
Internal {
|
Internal {
|
||||||
height: u8,
|
height: u8,
|
||||||
summary: T::Summary,
|
|
||||||
child_summaries: ArrayVec<T::Summary, { 2 * TREE_BASE }>,
|
child_summaries: ArrayVec<T::Summary, { 2 * TREE_BASE }>,
|
||||||
child_trees: ArrayVec<SumTree<T>, { 2 * TREE_BASE }>,
|
child_trees: ArrayVec<SumTree<T>, { 2 * TREE_BASE }>,
|
||||||
},
|
},
|
||||||
Leaf {
|
Leaf {
|
||||||
summary: T::Summary,
|
|
||||||
items: ArrayVec<T, { 2 * TREE_BASE }>,
|
items: ArrayVec<T, { 2 * TREE_BASE }>,
|
||||||
item_summaries: ArrayVec<T::Summary, { 2 * TREE_BASE }>,
|
item_summaries: ArrayVec<T::Summary, { 2 * TREE_BASE }>,
|
||||||
},
|
},
|
||||||
|
@ -805,23 +837,19 @@ where
|
||||||
match self {
|
match self {
|
||||||
Node::Internal {
|
Node::Internal {
|
||||||
height,
|
height,
|
||||||
summary,
|
|
||||||
child_summaries,
|
child_summaries,
|
||||||
child_trees,
|
child_trees,
|
||||||
} => f
|
} => f
|
||||||
.debug_struct("Internal")
|
.debug_struct("Internal")
|
||||||
.field("height", height)
|
.field("height", height)
|
||||||
.field("summary", summary)
|
|
||||||
.field("child_summaries", child_summaries)
|
.field("child_summaries", child_summaries)
|
||||||
.field("child_trees", child_trees)
|
.field("child_trees", child_trees)
|
||||||
.finish(),
|
.finish(),
|
||||||
Node::Leaf {
|
Node::Leaf {
|
||||||
summary,
|
|
||||||
items,
|
items,
|
||||||
item_summaries,
|
item_summaries,
|
||||||
} => f
|
} => f
|
||||||
.debug_struct("Leaf")
|
.debug_struct("Leaf")
|
||||||
.field("summary", summary)
|
|
||||||
.field("items", items)
|
.field("items", items)
|
||||||
.field("item_summaries", item_summaries)
|
.field("item_summaries", item_summaries)
|
||||||
.finish(),
|
.finish(),
|
||||||
|
@ -841,11 +869,16 @@ impl<T: Item> Node<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn summary(&self) -> &T::Summary {
|
fn summary<'a>(&'a self) -> Option<&'a T::Summary> {
|
||||||
match self {
|
let child_summaries = self.child_summaries();
|
||||||
Node::Internal { summary, .. } => summary,
|
child_summaries.last()
|
||||||
Node::Leaf { summary, .. } => summary,
|
}
|
||||||
}
|
|
||||||
|
fn summary_or_zero<'a>(&'a self, cx: &<T::Summary as Summary>::Context) -> Cow<'a, T::Summary> {
|
||||||
|
self.summary().map_or_else(
|
||||||
|
|| Cow::Owned(<T::Summary as Summary>::zero(cx)),
|
||||||
|
|last_summary| Cow::Borrowed(last_summary),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn child_summaries(&self) -> &[T::Summary] {
|
fn child_summaries(&self) -> &[T::Summary] {
|
||||||
|
@ -894,18 +927,6 @@ impl<T: KeyedItem> Edit<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sum<'a, T, I>(iter: I, cx: &T::Context) -> T
|
|
||||||
where
|
|
||||||
T: 'a + Summary,
|
|
||||||
I: Iterator<Item = &'a T>,
|
|
||||||
{
|
|
||||||
let mut sum = T::zero(cx);
|
|
||||||
for value in iter {
|
|
||||||
sum.add_summary(value, cx);
|
|
||||||
}
|
|
||||||
sum
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -997,7 +1018,7 @@ mod tests {
|
||||||
log::info!("tree items: {:?}", tree.items(&()));
|
log::info!("tree items: {:?}", tree.items(&()));
|
||||||
|
|
||||||
let mut filter_cursor =
|
let mut filter_cursor =
|
||||||
tree.filter::<_, Count>(&(), |summary| summary.contains_even);
|
tree.filter::<_, Count>(&(), |summary| summary.contains_even.cmp(&false));
|
||||||
let expected_filtered_items = tree
|
let expected_filtered_items = tree
|
||||||
.items(&())
|
.items(&())
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -1096,7 +1117,7 @@ mod tests {
|
||||||
cursor.seek(&Count(start), start_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.0, slice.summary().sum);
|
assert_eq!(summary.0, slice.0.summary_or_zero(&()).sum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1172,9 +1193,11 @@ mod tests {
|
||||||
// Multiple-element tree
|
// Multiple-element tree
|
||||||
let mut tree = SumTree::default();
|
let mut tree = SumTree::default();
|
||||||
tree.extend(vec![1, 2, 3, 4, 5, 6], &());
|
tree.extend(vec![1, 2, 3, 4, 5, 6], &());
|
||||||
|
|
||||||
let mut cursor = tree.cursor::<IntegersSummary>(&());
|
let mut cursor = tree.cursor::<IntegersSummary>(&());
|
||||||
|
|
||||||
assert_eq!(cursor.slice(&Count(2), Bias::Right).items(&()), [1, 2]);
|
let slice = cursor.slice(&Count(2), Bias::Right);
|
||||||
|
assert_eq!(slice.items(&()), [1, 2]);
|
||||||
assert_eq!(cursor.item(), Some(&3));
|
assert_eq!(cursor.item(), Some(&3));
|
||||||
assert_eq!(cursor.prev_item(), Some(&2));
|
assert_eq!(cursor.prev_item(), Some(&2));
|
||||||
assert_eq!(cursor.next_item(), Some(&4));
|
assert_eq!(cursor.next_item(), Some(&4));
|
||||||
|
|
|
@ -407,12 +407,12 @@ mod tests {
|
||||||
map.insert("baaab", 4);
|
map.insert("baaab", 4);
|
||||||
map.insert("c", 5);
|
map.insert("c", 5);
|
||||||
|
|
||||||
let result = map
|
let items = map.iter_from(&"ba");
|
||||||
.iter_from(&"ba")
|
let result = items
|
||||||
.take_while(|(key, _)| key.starts_with("ba"))
|
.take_while(|(key, _)| key.starts_with("ba"))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
assert_eq!(result.len(), 2);
|
assert_eq!(result.len(), 2, "{result:?}");
|
||||||
assert!(result.iter().any(|(k, _)| k == &&"baa"));
|
assert!(result.iter().any(|(k, _)| k == &&"baa"));
|
||||||
assert!(result.iter().any(|(k, _)| k == &&"baaab"));
|
assert!(result.iter().any(|(k, _)| k == &&"baaab"));
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue