mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-07 20:39:04 +03:00
Merge pull request #81 from zed-industries/versioned-anchors
Represent edit positions and anchors as versioned offsets
This commit is contained in:
commit
4a07e48bf0
@ -5,7 +5,7 @@ pub mod movement;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
settings::{Settings, StyleId},
|
settings::{Settings, StyleId},
|
||||||
util::post_inc,
|
util::{post_inc, Bias},
|
||||||
workspace,
|
workspace,
|
||||||
worktree::FileHandle,
|
worktree::FileHandle,
|
||||||
};
|
};
|
||||||
@ -723,9 +723,7 @@ impl Editor {
|
|||||||
let mut new_selections = Vec::new();
|
let mut new_selections = Vec::new();
|
||||||
self.buffer.update(cx, |buffer, cx| {
|
self.buffer.update(cx, |buffer, cx| {
|
||||||
let edit_ranges = old_selections.iter().map(|(_, range)| range.clone());
|
let edit_ranges = old_selections.iter().map(|(_, range)| range.clone());
|
||||||
if let Err(error) = buffer.edit(edit_ranges, text.as_str(), Some(cx)) {
|
buffer.edit(edit_ranges, text.as_str(), Some(cx));
|
||||||
log::error!("error inserting text: {}", error);
|
|
||||||
};
|
|
||||||
let text_len = text.len() as isize;
|
let text_len = text.len() as isize;
|
||||||
let mut delta = 0_isize;
|
let mut delta = 0_isize;
|
||||||
new_selections = old_selections
|
new_selections = old_selections
|
||||||
@ -4139,12 +4137,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
pub enum Bias {
|
|
||||||
Left,
|
|
||||||
Right,
|
|
||||||
}
|
|
||||||
|
|
||||||
trait RangeExt<T> {
|
trait RangeExt<T> {
|
||||||
fn sorted(&self) -> Range<T>;
|
fn sorted(&self) -> Range<T>;
|
||||||
fn to_inclusive(&self) -> RangeInclusive<T>;
|
fn to_inclusive(&self) -> RangeInclusive<T>;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,47 +1,19 @@
|
|||||||
use super::Buffer;
|
use super::Buffer;
|
||||||
use crate::time;
|
use crate::{time, util::Bias};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use std::cmp::Ordering;
|
use std::{cmp::Ordering, ops::Range};
|
||||||
use std::ops::Range;
|
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq, Debug, Hash)]
|
#[derive(Clone, Eq, PartialEq, Debug, Hash)]
|
||||||
pub enum Anchor {
|
pub enum Anchor {
|
||||||
Start,
|
Start,
|
||||||
End,
|
End,
|
||||||
Middle {
|
Middle {
|
||||||
insertion_id: time::Local,
|
|
||||||
offset: usize,
|
offset: usize,
|
||||||
bias: AnchorBias,
|
bias: Bias,
|
||||||
|
version: time::Global,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Eq, PartialEq, Debug, Hash)]
|
|
||||||
pub enum AnchorBias {
|
|
||||||
Left,
|
|
||||||
Right,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialOrd for AnchorBias {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
||||||
Some(self.cmp(other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ord for AnchorBias {
|
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
|
||||||
use AnchorBias::*;
|
|
||||||
|
|
||||||
if self == other {
|
|
||||||
return Ordering::Equal;
|
|
||||||
}
|
|
||||||
|
|
||||||
match (self, other) {
|
|
||||||
(Left, _) => Ordering::Less,
|
|
||||||
(Right, _) => Ordering::Greater,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Anchor {
|
impl Anchor {
|
||||||
pub fn cmp(&self, other: &Anchor, buffer: &Buffer) -> Result<Ordering> {
|
pub fn cmp(&self, other: &Anchor, buffer: &Buffer) -> Result<Ordering> {
|
||||||
if self == other {
|
if self == other {
|
||||||
@ -55,18 +27,24 @@ impl Anchor {
|
|||||||
Anchor::Middle {
|
Anchor::Middle {
|
||||||
offset: self_offset,
|
offset: self_offset,
|
||||||
bias: self_bias,
|
bias: self_bias,
|
||||||
..
|
version: self_version,
|
||||||
},
|
},
|
||||||
Anchor::Middle {
|
Anchor::Middle {
|
||||||
offset: other_offset,
|
offset: other_offset,
|
||||||
bias: other_bias,
|
bias: other_bias,
|
||||||
..
|
version: other_version,
|
||||||
},
|
},
|
||||||
) => buffer
|
) => {
|
||||||
.fragment_id_for_anchor(self)?
|
let offset_comparison = if self_version == other_version {
|
||||||
.cmp(buffer.fragment_id_for_anchor(other)?)
|
self_offset.cmp(other_offset)
|
||||||
.then_with(|| self_offset.cmp(other_offset))
|
} else {
|
||||||
.then_with(|| self_bias.cmp(other_bias)),
|
buffer
|
||||||
|
.full_offset_for_anchor(self)
|
||||||
|
.cmp(&buffer.full_offset_for_anchor(other))
|
||||||
|
};
|
||||||
|
|
||||||
|
offset_comparison.then_with(|| self_bias.cmp(&other_bias))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,8 +52,7 @@ impl Anchor {
|
|||||||
match self {
|
match self {
|
||||||
Anchor::Start
|
Anchor::Start
|
||||||
| Anchor::Middle {
|
| Anchor::Middle {
|
||||||
bias: AnchorBias::Left,
|
bias: Bias::Left, ..
|
||||||
..
|
|
||||||
} => self.clone(),
|
} => self.clone(),
|
||||||
_ => buffer.anchor_before(self),
|
_ => buffer.anchor_before(self),
|
||||||
}
|
}
|
||||||
@ -85,8 +62,7 @@ impl Anchor {
|
|||||||
match self {
|
match self {
|
||||||
Anchor::End
|
Anchor::End
|
||||||
| Anchor::Middle {
|
| Anchor::Middle {
|
||||||
bias: AnchorBias::Right,
|
bias: Bias::Right, ..
|
||||||
..
|
|
||||||
} => self.clone(),
|
} => self.clone(),
|
||||||
_ => buffer.anchor_after(self),
|
_ => buffer.anchor_after(self),
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::Point;
|
use super::Point;
|
||||||
use crate::{
|
use crate::{
|
||||||
editor::Bias,
|
sum_tree::{self, SumTree},
|
||||||
sum_tree::{self, SeekBias, SumTree},
|
util::Bias,
|
||||||
};
|
};
|
||||||
use arrayvec::ArrayString;
|
use arrayvec::ArrayString;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
@ -25,13 +25,13 @@ impl Rope {
|
|||||||
|
|
||||||
pub fn append(&mut self, rope: Rope) {
|
pub fn append(&mut self, rope: Rope) {
|
||||||
let mut chunks = rope.chunks.cursor::<(), ()>();
|
let mut chunks = rope.chunks.cursor::<(), ()>();
|
||||||
chunks.next();
|
chunks.next(&());
|
||||||
if let Some(chunk) = chunks.item() {
|
if let Some(chunk) = chunks.item() {
|
||||||
if self.chunks.last().map_or(false, |c| c.0.len() < CHUNK_BASE)
|
if self.chunks.last().map_or(false, |c| c.0.len() < CHUNK_BASE)
|
||||||
|| chunk.0.len() < CHUNK_BASE
|
|| chunk.0.len() < CHUNK_BASE
|
||||||
{
|
{
|
||||||
self.push(&chunk.0);
|
self.push(&chunk.0);
|
||||||
chunks.next();
|
chunks.next(&());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,11 +99,11 @@ impl Rope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.chunks.extent()
|
self.chunks.extent(&())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn max_point(&self) -> Point {
|
pub fn max_point(&self) -> Point {
|
||||||
self.chunks.extent()
|
self.chunks.extent(&())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cursor(&self, offset: usize) -> Cursor {
|
pub fn cursor(&self, offset: usize) -> Cursor {
|
||||||
@ -129,7 +129,7 @@ impl Rope {
|
|||||||
pub fn to_point(&self, offset: usize) -> Point {
|
pub fn to_point(&self, offset: usize) -> Point {
|
||||||
assert!(offset <= self.summary().bytes);
|
assert!(offset <= self.summary().bytes);
|
||||||
let mut cursor = self.chunks.cursor::<usize, TextSummary>();
|
let mut cursor = self.chunks.cursor::<usize, TextSummary>();
|
||||||
cursor.seek(&offset, SeekBias::Left, &());
|
cursor.seek(&offset, Bias::Left, &());
|
||||||
let overshoot = offset - cursor.start().bytes;
|
let overshoot = offset - cursor.start().bytes;
|
||||||
cursor.start().lines
|
cursor.start().lines
|
||||||
+ cursor
|
+ cursor
|
||||||
@ -140,14 +140,14 @@ impl Rope {
|
|||||||
pub fn to_offset(&self, point: Point) -> usize {
|
pub fn to_offset(&self, point: Point) -> usize {
|
||||||
assert!(point <= self.summary().lines);
|
assert!(point <= self.summary().lines);
|
||||||
let mut cursor = self.chunks.cursor::<Point, TextSummary>();
|
let mut cursor = self.chunks.cursor::<Point, TextSummary>();
|
||||||
cursor.seek(&point, SeekBias::Left, &());
|
cursor.seek(&point, Bias::Left, &());
|
||||||
let overshoot = point - cursor.start().lines;
|
let overshoot = point - cursor.start().lines;
|
||||||
cursor.start().bytes + cursor.item().map_or(0, |chunk| chunk.to_offset(overshoot))
|
cursor.start().bytes + cursor.item().map_or(0, |chunk| chunk.to_offset(overshoot))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clip_offset(&self, mut offset: usize, bias: Bias) -> usize {
|
pub fn clip_offset(&self, mut offset: usize, bias: Bias) -> usize {
|
||||||
let mut cursor = self.chunks.cursor::<usize, usize>();
|
let mut cursor = self.chunks.cursor::<usize, usize>();
|
||||||
cursor.seek(&offset, SeekBias::Left, &());
|
cursor.seek(&offset, Bias::Left, &());
|
||||||
if let Some(chunk) = cursor.item() {
|
if let Some(chunk) = cursor.item() {
|
||||||
let mut ix = offset - cursor.start();
|
let mut ix = offset - cursor.start();
|
||||||
while !chunk.0.is_char_boundary(ix) {
|
while !chunk.0.is_char_boundary(ix) {
|
||||||
@ -170,7 +170,7 @@ impl Rope {
|
|||||||
|
|
||||||
pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
|
pub fn clip_point(&self, point: Point, bias: Bias) -> Point {
|
||||||
let mut cursor = self.chunks.cursor::<Point, Point>();
|
let mut cursor = self.chunks.cursor::<Point, Point>();
|
||||||
cursor.seek(&point, SeekBias::Right, &());
|
cursor.seek(&point, Bias::Right, &());
|
||||||
if let Some(chunk) = cursor.item() {
|
if let Some(chunk) = cursor.item() {
|
||||||
let overshoot = point - cursor.start();
|
let overshoot = point - cursor.start();
|
||||||
*cursor.start() + chunk.clip_point(overshoot, bias)
|
*cursor.start() + chunk.clip_point(overshoot, bias)
|
||||||
@ -197,7 +197,7 @@ pub struct Cursor<'a> {
|
|||||||
impl<'a> Cursor<'a> {
|
impl<'a> Cursor<'a> {
|
||||||
pub fn new(rope: &'a Rope, offset: usize) -> Self {
|
pub fn new(rope: &'a Rope, offset: usize) -> Self {
|
||||||
let mut chunks = rope.chunks.cursor();
|
let mut chunks = rope.chunks.cursor();
|
||||||
chunks.seek(&offset, SeekBias::Right, &());
|
chunks.seek(&offset, Bias::Right, &());
|
||||||
Self {
|
Self {
|
||||||
rope,
|
rope,
|
||||||
chunks,
|
chunks,
|
||||||
@ -208,24 +208,29 @@ impl<'a> Cursor<'a> {
|
|||||||
pub fn seek_forward(&mut self, end_offset: usize) {
|
pub fn seek_forward(&mut self, end_offset: usize) {
|
||||||
debug_assert!(end_offset >= self.offset);
|
debug_assert!(end_offset >= self.offset);
|
||||||
|
|
||||||
self.chunks.seek_forward(&end_offset, SeekBias::Right, &());
|
self.chunks.seek_forward(&end_offset, Bias::Right, &());
|
||||||
self.offset = end_offset;
|
self.offset = end_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn slice(&mut self, end_offset: usize) -> Rope {
|
pub fn slice(&mut self, end_offset: usize) -> Rope {
|
||||||
debug_assert!(end_offset >= self.offset);
|
debug_assert!(
|
||||||
|
end_offset >= self.offset,
|
||||||
|
"cannot slice backwards from {} to {}",
|
||||||
|
self.offset,
|
||||||
|
end_offset
|
||||||
|
);
|
||||||
|
|
||||||
let mut slice = Rope::new();
|
let mut slice = Rope::new();
|
||||||
if let Some(start_chunk) = self.chunks.item() {
|
if let Some(start_chunk) = self.chunks.item() {
|
||||||
let start_ix = self.offset - self.chunks.start();
|
let start_ix = self.offset - self.chunks.start();
|
||||||
let end_ix = cmp::min(end_offset, self.chunks.end()) - self.chunks.start();
|
let end_ix = cmp::min(end_offset, self.chunks.end(&())) - self.chunks.start();
|
||||||
slice.push(&start_chunk.0[start_ix..end_ix]);
|
slice.push(&start_chunk.0[start_ix..end_ix]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if end_offset > self.chunks.end() {
|
if end_offset > self.chunks.end(&()) {
|
||||||
self.chunks.next();
|
self.chunks.next(&());
|
||||||
slice.append(Rope {
|
slice.append(Rope {
|
||||||
chunks: self.chunks.slice(&end_offset, SeekBias::Right, &()),
|
chunks: self.chunks.slice(&end_offset, Bias::Right, &()),
|
||||||
});
|
});
|
||||||
if let Some(end_chunk) = self.chunks.item() {
|
if let Some(end_chunk) = self.chunks.item() {
|
||||||
let end_ix = end_offset - self.chunks.start();
|
let end_ix = end_offset - self.chunks.start();
|
||||||
@ -243,13 +248,13 @@ impl<'a> Cursor<'a> {
|
|||||||
let mut summary = TextSummary::default();
|
let mut summary = TextSummary::default();
|
||||||
if let Some(start_chunk) = self.chunks.item() {
|
if let Some(start_chunk) = self.chunks.item() {
|
||||||
let start_ix = self.offset - self.chunks.start();
|
let start_ix = self.offset - self.chunks.start();
|
||||||
let end_ix = cmp::min(end_offset, self.chunks.end()) - self.chunks.start();
|
let end_ix = cmp::min(end_offset, self.chunks.end(&())) - self.chunks.start();
|
||||||
summary = TextSummary::from(&start_chunk.0[start_ix..end_ix]);
|
summary = TextSummary::from(&start_chunk.0[start_ix..end_ix]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if end_offset > self.chunks.end() {
|
if end_offset > self.chunks.end(&()) {
|
||||||
self.chunks.next();
|
self.chunks.next(&());
|
||||||
summary += &self.chunks.summary(&end_offset, SeekBias::Right, &());
|
summary += &self.chunks.summary(&end_offset, Bias::Right, &());
|
||||||
if let Some(end_chunk) = self.chunks.item() {
|
if let Some(end_chunk) = self.chunks.item() {
|
||||||
let end_ix = end_offset - self.chunks.start();
|
let end_ix = end_offset - self.chunks.start();
|
||||||
summary += TextSummary::from(&end_chunk.0[..end_ix]);
|
summary += TextSummary::from(&end_chunk.0[..end_ix]);
|
||||||
@ -260,7 +265,7 @@ impl<'a> Cursor<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn suffix(mut self) -> Rope {
|
pub fn suffix(mut self) -> Rope {
|
||||||
self.slice(self.rope.chunks.extent())
|
self.slice(self.rope.chunks.extent(&()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn offset(&self) -> usize {
|
pub fn offset(&self) -> usize {
|
||||||
@ -276,7 +281,7 @@ pub struct Chunks<'a> {
|
|||||||
impl<'a> Chunks<'a> {
|
impl<'a> Chunks<'a> {
|
||||||
pub fn new(rope: &'a Rope, range: Range<usize>) -> Self {
|
pub fn new(rope: &'a Rope, range: Range<usize>) -> Self {
|
||||||
let mut chunks = rope.chunks.cursor();
|
let mut chunks = rope.chunks.cursor();
|
||||||
chunks.seek(&range.start, SeekBias::Right, &());
|
chunks.seek(&range.start, Bias::Right, &());
|
||||||
Self { chunks, range }
|
Self { chunks, range }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,10 +290,10 @@ impl<'a> Chunks<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn seek(&mut self, offset: usize) {
|
pub fn seek(&mut self, offset: usize) {
|
||||||
if offset >= self.chunks.end() {
|
if offset >= self.chunks.end(&()) {
|
||||||
self.chunks.seek_forward(&offset, SeekBias::Right, &());
|
self.chunks.seek_forward(&offset, Bias::Right, &());
|
||||||
} else {
|
} else {
|
||||||
self.chunks.seek(&offset, SeekBias::Right, &());
|
self.chunks.seek(&offset, Bias::Right, &());
|
||||||
}
|
}
|
||||||
self.range.start = offset;
|
self.range.start = offset;
|
||||||
}
|
}
|
||||||
@ -312,7 +317,7 @@ impl<'a> Iterator for Chunks<'a> {
|
|||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let result = self.peek();
|
let result = self.peek();
|
||||||
if result.is_some() {
|
if result.is_some() {
|
||||||
self.chunks.next();
|
self.chunks.next(&());
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
@ -478,19 +483,19 @@ impl std::ops::AddAssign<Self> for TextSummary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> sum_tree::Dimension<'a, TextSummary> for TextSummary {
|
impl<'a> sum_tree::Dimension<'a, TextSummary> for TextSummary {
|
||||||
fn add_summary(&mut self, summary: &'a TextSummary) {
|
fn add_summary(&mut self, summary: &'a TextSummary, _: &()) {
|
||||||
*self += summary;
|
*self += summary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> sum_tree::Dimension<'a, TextSummary> for usize {
|
impl<'a> sum_tree::Dimension<'a, TextSummary> for usize {
|
||||||
fn add_summary(&mut self, summary: &'a TextSummary) {
|
fn add_summary(&mut self, summary: &'a TextSummary, _: &()) {
|
||||||
*self += summary.bytes;
|
*self += summary.bytes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> sum_tree::Dimension<'a, TextSummary> for Point {
|
impl<'a> sum_tree::Dimension<'a, TextSummary> for Point {
|
||||||
fn add_summary(&mut self, summary: &'a TextSummary) {
|
fn add_summary(&mut self, summary: &'a TextSummary, _: &()) {
|
||||||
*self += &summary.lines;
|
*self += &summary.lines;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
use super::{
|
use super::{
|
||||||
buffer::{AnchorRangeExt, TextSummary},
|
buffer::{AnchorRangeExt, TextSummary},
|
||||||
Anchor, Bias, Buffer, DisplayPoint, Edit, Point, ToOffset,
|
Anchor, Buffer, DisplayPoint, Edit, Point, ToOffset,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
editor::buffer,
|
editor::buffer,
|
||||||
settings::StyleId,
|
settings::StyleId,
|
||||||
sum_tree::{self, Cursor, FilterCursor, SeekBias, SumTree},
|
sum_tree::{self, Cursor, FilterCursor, SumTree},
|
||||||
time,
|
time,
|
||||||
|
util::Bias,
|
||||||
};
|
};
|
||||||
use gpui::{AppContext, ModelHandle};
|
use gpui::{AppContext, ModelHandle};
|
||||||
use parking_lot::{Mutex, MutexGuard};
|
use parking_lot::{Mutex, MutexGuard};
|
||||||
use std::{
|
use std::{
|
||||||
cmp::{self, Ordering},
|
cmp::{self, Ordering},
|
||||||
|
iter,
|
||||||
ops::Range,
|
ops::Range,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -80,7 +82,13 @@ impl FoldMap {
|
|||||||
where
|
where
|
||||||
T: ToOffset,
|
T: ToOffset,
|
||||||
{
|
{
|
||||||
self.intersecting_folds(range, cx).map(|f| &f.0)
|
let buffer = self.buffer.read(cx);
|
||||||
|
let mut folds = self.intersecting_folds(range, cx);
|
||||||
|
iter::from_fn(move || {
|
||||||
|
let item = folds.item().map(|f| &f.0);
|
||||||
|
folds.next(buffer);
|
||||||
|
item
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fold<T: ToOffset>(
|
pub fn fold<T: ToOffset>(
|
||||||
@ -118,7 +126,7 @@ impl FoldMap {
|
|||||||
let mut new_tree = SumTree::new();
|
let mut new_tree = SumTree::new();
|
||||||
let mut cursor = self.folds.cursor::<_, ()>();
|
let mut cursor = self.folds.cursor::<_, ()>();
|
||||||
for fold in folds {
|
for fold in folds {
|
||||||
new_tree.push_tree(cursor.slice(&fold, SeekBias::Right, buffer), buffer);
|
new_tree.push_tree(cursor.slice(&fold, Bias::Right, buffer), buffer);
|
||||||
new_tree.push(fold, buffer);
|
new_tree.push(fold, buffer);
|
||||||
}
|
}
|
||||||
new_tree.push_tree(cursor.suffix(buffer), buffer);
|
new_tree.push_tree(cursor.suffix(buffer), buffer);
|
||||||
@ -149,7 +157,7 @@ impl FoldMap {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
fold_ixs_to_delete.push(*folds_cursor.start());
|
fold_ixs_to_delete.push(*folds_cursor.start());
|
||||||
folds_cursor.next();
|
folds_cursor.next(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,8 +174,8 @@ impl FoldMap {
|
|||||||
let mut cursor = self.folds.cursor::<_, ()>();
|
let mut cursor = self.folds.cursor::<_, ()>();
|
||||||
let mut folds = SumTree::new();
|
let mut folds = SumTree::new();
|
||||||
for fold_ix in fold_ixs_to_delete {
|
for fold_ix in fold_ixs_to_delete {
|
||||||
folds.push_tree(cursor.slice(&fold_ix, SeekBias::Right, buffer), buffer);
|
folds.push_tree(cursor.slice(&fold_ix, Bias::Right, buffer), buffer);
|
||||||
cursor.next();
|
cursor.next(buffer);
|
||||||
}
|
}
|
||||||
folds.push_tree(cursor.suffix(buffer), buffer);
|
folds.push_tree(cursor.suffix(buffer), buffer);
|
||||||
folds
|
folds
|
||||||
@ -186,10 +194,13 @@ impl FoldMap {
|
|||||||
let buffer = self.buffer.read(cx);
|
let buffer = self.buffer.read(cx);
|
||||||
let start = buffer.anchor_before(range.start.to_offset(buffer));
|
let start = buffer.anchor_before(range.start.to_offset(buffer));
|
||||||
let end = buffer.anchor_after(range.end.to_offset(buffer));
|
let end = buffer.anchor_after(range.end.to_offset(buffer));
|
||||||
self.folds.filter::<_, usize>(move |summary| {
|
self.folds.filter::<_, usize>(
|
||||||
start.cmp(&summary.max_end, buffer).unwrap() == Ordering::Less
|
move |summary| {
|
||||||
&& end.cmp(&summary.min_start, buffer).unwrap() == Ordering::Greater
|
start.cmp(&summary.max_end, buffer).unwrap() == Ordering::Less
|
||||||
})
|
&& end.cmp(&summary.min_start, buffer).unwrap() == Ordering::Greater
|
||||||
|
},
|
||||||
|
buffer,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn intersects_fold<T>(&self, offset: T, cx: &AppContext) -> bool
|
pub fn intersects_fold<T>(&self, offset: T, cx: &AppContext) -> bool
|
||||||
@ -200,20 +211,20 @@ impl FoldMap {
|
|||||||
let offset = offset.to_offset(buffer);
|
let offset = offset.to_offset(buffer);
|
||||||
let transforms = self.sync(cx);
|
let transforms = self.sync(cx);
|
||||||
let mut cursor = transforms.cursor::<usize, usize>();
|
let mut cursor = transforms.cursor::<usize, usize>();
|
||||||
cursor.seek(&offset, SeekBias::Right, &());
|
cursor.seek(&offset, Bias::Right, &());
|
||||||
cursor.item().map_or(false, |t| t.display_text.is_some())
|
cursor.item().map_or(false, |t| t.display_text.is_some())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_line_folded(&self, display_row: u32, cx: &AppContext) -> bool {
|
pub fn is_line_folded(&self, display_row: u32, cx: &AppContext) -> bool {
|
||||||
let transforms = self.sync(cx);
|
let transforms = self.sync(cx);
|
||||||
let mut cursor = transforms.cursor::<DisplayPoint, DisplayPoint>();
|
let mut cursor = transforms.cursor::<DisplayPoint, DisplayPoint>();
|
||||||
cursor.seek(&DisplayPoint::new(display_row, 0), SeekBias::Right, &());
|
cursor.seek(&DisplayPoint::new(display_row, 0), Bias::Right, &());
|
||||||
while let Some(transform) = cursor.item() {
|
while let Some(transform) = cursor.item() {
|
||||||
if transform.display_text.is_some() {
|
if transform.display_text.is_some() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if cursor.end().row() == display_row {
|
if cursor.end(&()).row() == display_row {
|
||||||
cursor.next()
|
cursor.next(&())
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -232,7 +243,7 @@ impl FoldMap {
|
|||||||
pub fn to_buffer_point(&self, display_point: DisplayPoint, cx: &AppContext) -> Point {
|
pub fn to_buffer_point(&self, display_point: DisplayPoint, cx: &AppContext) -> Point {
|
||||||
let transforms = self.sync(cx);
|
let transforms = self.sync(cx);
|
||||||
let mut cursor = transforms.cursor::<DisplayPoint, TransformSummary>();
|
let mut cursor = transforms.cursor::<DisplayPoint, TransformSummary>();
|
||||||
cursor.seek(&display_point, SeekBias::Right, &());
|
cursor.seek(&display_point, Bias::Right, &());
|
||||||
let overshoot = display_point.0 - cursor.start().display.lines;
|
let overshoot = display_point.0 - cursor.start().display.lines;
|
||||||
cursor.start().buffer.lines + overshoot
|
cursor.start().buffer.lines + overshoot
|
||||||
}
|
}
|
||||||
@ -240,11 +251,11 @@ impl FoldMap {
|
|||||||
pub fn to_display_point(&self, point: Point, cx: &AppContext) -> DisplayPoint {
|
pub fn to_display_point(&self, point: Point, cx: &AppContext) -> DisplayPoint {
|
||||||
let transforms = self.sync(cx);
|
let transforms = self.sync(cx);
|
||||||
let mut cursor = transforms.cursor::<Point, TransformSummary>();
|
let mut cursor = transforms.cursor::<Point, TransformSummary>();
|
||||||
cursor.seek(&point, SeekBias::Right, &());
|
cursor.seek(&point, Bias::Right, &());
|
||||||
let overshoot = point - cursor.start().buffer.lines;
|
let overshoot = point - cursor.start().buffer.lines;
|
||||||
DisplayPoint(cmp::min(
|
DisplayPoint(cmp::min(
|
||||||
cursor.start().display.lines + overshoot,
|
cursor.start().display.lines + overshoot,
|
||||||
cursor.end().display.lines,
|
cursor.end(&()).display.lines,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,18 +276,15 @@ impl FoldMap {
|
|||||||
let mut new_transforms = SumTree::new();
|
let mut new_transforms = SumTree::new();
|
||||||
let mut transforms = self.transforms.lock();
|
let mut transforms = self.transforms.lock();
|
||||||
let mut cursor = transforms.cursor::<usize, usize>();
|
let mut cursor = transforms.cursor::<usize, usize>();
|
||||||
cursor.seek(&0, SeekBias::Right, &());
|
cursor.seek(&0, Bias::Right, &());
|
||||||
|
|
||||||
while let Some(mut edit) = edits.next() {
|
while let Some(mut edit) = edits.next() {
|
||||||
new_transforms.push_tree(
|
new_transforms.push_tree(cursor.slice(&edit.old_range.start, Bias::Left, &()), &());
|
||||||
cursor.slice(&edit.old_range.start, SeekBias::Left, &()),
|
|
||||||
&(),
|
|
||||||
);
|
|
||||||
edit.new_range.start -= edit.old_range.start - cursor.start();
|
edit.new_range.start -= edit.old_range.start - cursor.start();
|
||||||
edit.old_range.start = *cursor.start();
|
edit.old_range.start = *cursor.start();
|
||||||
|
|
||||||
cursor.seek(&edit.old_range.end, SeekBias::Right, &());
|
cursor.seek(&edit.old_range.end, Bias::Right, &());
|
||||||
cursor.next();
|
cursor.next(&());
|
||||||
|
|
||||||
let mut delta = edit.delta();
|
let mut delta = edit.delta();
|
||||||
loop {
|
loop {
|
||||||
@ -292,8 +300,8 @@ impl FoldMap {
|
|||||||
|
|
||||||
if next_edit.old_range.end >= edit.old_range.end {
|
if next_edit.old_range.end >= edit.old_range.end {
|
||||||
edit.old_range.end = next_edit.old_range.end;
|
edit.old_range.end = next_edit.old_range.end;
|
||||||
cursor.seek(&edit.old_range.end, SeekBias::Right, &());
|
cursor.seek(&edit.old_range.end, Bias::Right, &());
|
||||||
cursor.next();
|
cursor.next(&());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
@ -305,10 +313,15 @@ impl FoldMap {
|
|||||||
|
|
||||||
let anchor = buffer.anchor_before(edit.new_range.start);
|
let anchor = buffer.anchor_before(edit.new_range.start);
|
||||||
let mut folds_cursor = self.folds.cursor::<_, ()>();
|
let mut folds_cursor = self.folds.cursor::<_, ()>();
|
||||||
folds_cursor.seek(&Fold(anchor..Anchor::End), SeekBias::Left, buffer);
|
folds_cursor.seek(&Fold(anchor..Anchor::End), Bias::Left, buffer);
|
||||||
let mut folds = folds_cursor
|
let mut folds = iter::from_fn(move || {
|
||||||
.map(|f| f.0.start.to_offset(buffer)..f.0.end.to_offset(buffer))
|
let item = folds_cursor
|
||||||
.peekable();
|
.item()
|
||||||
|
.map(|f| f.0.start.to_offset(buffer)..f.0.end.to_offset(buffer));
|
||||||
|
folds_cursor.next(buffer);
|
||||||
|
item
|
||||||
|
})
|
||||||
|
.peekable();
|
||||||
|
|
||||||
while folds
|
while folds
|
||||||
.peek()
|
.peek()
|
||||||
@ -417,7 +430,7 @@ impl FoldMapSnapshot {
|
|||||||
|
|
||||||
let display_point = Point::new(start_row, 0);
|
let display_point = Point::new(start_row, 0);
|
||||||
let mut cursor = self.transforms.cursor();
|
let mut cursor = self.transforms.cursor();
|
||||||
cursor.seek(&DisplayPoint(display_point), SeekBias::Left, &());
|
cursor.seek(&DisplayPoint(display_point), Bias::Left, &());
|
||||||
|
|
||||||
BufferRows {
|
BufferRows {
|
||||||
display_point,
|
display_point,
|
||||||
@ -431,7 +444,7 @@ impl FoldMapSnapshot {
|
|||||||
|
|
||||||
pub fn chunks_at(&self, offset: DisplayOffset) -> Chunks {
|
pub fn chunks_at(&self, offset: DisplayOffset) -> Chunks {
|
||||||
let mut transform_cursor = self.transforms.cursor::<DisplayOffset, TransformSummary>();
|
let mut transform_cursor = self.transforms.cursor::<DisplayOffset, TransformSummary>();
|
||||||
transform_cursor.seek(&offset, SeekBias::Right, &());
|
transform_cursor.seek(&offset, Bias::Right, &());
|
||||||
let overshoot = offset.0 - transform_cursor.start().display.bytes;
|
let overshoot = offset.0 - transform_cursor.start().display.bytes;
|
||||||
let buffer_offset = transform_cursor.start().buffer.bytes + overshoot;
|
let buffer_offset = transform_cursor.start().buffer.bytes + overshoot;
|
||||||
Chunks {
|
Chunks {
|
||||||
@ -444,11 +457,11 @@ impl FoldMapSnapshot {
|
|||||||
pub fn highlighted_chunks(&mut self, range: Range<DisplayOffset>) -> HighlightedChunks {
|
pub fn highlighted_chunks(&mut self, range: Range<DisplayOffset>) -> HighlightedChunks {
|
||||||
let mut transform_cursor = self.transforms.cursor::<DisplayOffset, TransformSummary>();
|
let mut transform_cursor = self.transforms.cursor::<DisplayOffset, TransformSummary>();
|
||||||
|
|
||||||
transform_cursor.seek(&range.end, SeekBias::Right, &());
|
transform_cursor.seek(&range.end, Bias::Right, &());
|
||||||
let overshoot = range.end.0 - transform_cursor.start().display.bytes;
|
let overshoot = range.end.0 - transform_cursor.start().display.bytes;
|
||||||
let buffer_end = transform_cursor.start().buffer.bytes + overshoot;
|
let buffer_end = transform_cursor.start().buffer.bytes + overshoot;
|
||||||
|
|
||||||
transform_cursor.seek(&range.start, SeekBias::Right, &());
|
transform_cursor.seek(&range.start, Bias::Right, &());
|
||||||
let overshoot = range.start.0 - transform_cursor.start().display.bytes;
|
let overshoot = range.start.0 - transform_cursor.start().display.bytes;
|
||||||
let buffer_start = transform_cursor.start().buffer.bytes + overshoot;
|
let buffer_start = transform_cursor.start().buffer.bytes + overshoot;
|
||||||
|
|
||||||
@ -469,7 +482,7 @@ impl FoldMapSnapshot {
|
|||||||
|
|
||||||
pub fn to_display_offset(&self, point: DisplayPoint) -> DisplayOffset {
|
pub fn to_display_offset(&self, point: DisplayPoint) -> DisplayOffset {
|
||||||
let mut cursor = self.transforms.cursor::<DisplayPoint, TransformSummary>();
|
let mut cursor = self.transforms.cursor::<DisplayPoint, TransformSummary>();
|
||||||
cursor.seek(&point, SeekBias::Right, &());
|
cursor.seek(&point, Bias::Right, &());
|
||||||
let overshoot = point.0 - cursor.start().display.lines;
|
let overshoot = point.0 - cursor.start().display.lines;
|
||||||
let mut offset = cursor.start().display.bytes;
|
let mut offset = cursor.start().display.bytes;
|
||||||
if !overshoot.is_zero() {
|
if !overshoot.is_zero() {
|
||||||
@ -485,7 +498,7 @@ impl FoldMapSnapshot {
|
|||||||
|
|
||||||
pub fn to_buffer_offset(&self, point: DisplayPoint) -> usize {
|
pub fn to_buffer_offset(&self, point: DisplayPoint) -> usize {
|
||||||
let mut cursor = self.transforms.cursor::<DisplayPoint, TransformSummary>();
|
let mut cursor = self.transforms.cursor::<DisplayPoint, TransformSummary>();
|
||||||
cursor.seek(&point, SeekBias::Right, &());
|
cursor.seek(&point, Bias::Right, &());
|
||||||
let overshoot = point.0 - cursor.start().display.lines;
|
let overshoot = point.0 - cursor.start().display.lines;
|
||||||
self.buffer
|
self.buffer
|
||||||
.to_offset(cursor.start().buffer.lines + overshoot)
|
.to_offset(cursor.start().buffer.lines + overshoot)
|
||||||
@ -494,14 +507,14 @@ impl FoldMapSnapshot {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub fn clip_offset(&self, offset: DisplayOffset, bias: Bias) -> DisplayOffset {
|
pub fn clip_offset(&self, offset: DisplayOffset, bias: Bias) -> DisplayOffset {
|
||||||
let mut cursor = self.transforms.cursor::<DisplayOffset, TransformSummary>();
|
let mut cursor = self.transforms.cursor::<DisplayOffset, TransformSummary>();
|
||||||
cursor.seek(&offset, SeekBias::Right, &());
|
cursor.seek(&offset, Bias::Right, &());
|
||||||
if let Some(transform) = cursor.item() {
|
if let Some(transform) = cursor.item() {
|
||||||
let transform_start = cursor.start().display.bytes;
|
let transform_start = cursor.start().display.bytes;
|
||||||
if transform.display_text.is_some() {
|
if transform.display_text.is_some() {
|
||||||
if offset.0 == transform_start || matches!(bias, Bias::Left) {
|
if offset.0 == transform_start || matches!(bias, Bias::Left) {
|
||||||
DisplayOffset(transform_start)
|
DisplayOffset(transform_start)
|
||||||
} else {
|
} else {
|
||||||
DisplayOffset(cursor.end().display.bytes)
|
DisplayOffset(cursor.end(&()).display.bytes)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let overshoot = offset.0 - transform_start;
|
let overshoot = offset.0 - transform_start;
|
||||||
@ -519,14 +532,14 @@ impl FoldMapSnapshot {
|
|||||||
|
|
||||||
pub fn clip_point(&self, point: DisplayPoint, bias: Bias) -> DisplayPoint {
|
pub fn clip_point(&self, point: DisplayPoint, bias: Bias) -> DisplayPoint {
|
||||||
let mut cursor = self.transforms.cursor::<DisplayPoint, TransformSummary>();
|
let mut cursor = self.transforms.cursor::<DisplayPoint, TransformSummary>();
|
||||||
cursor.seek(&point, SeekBias::Right, &());
|
cursor.seek(&point, Bias::Right, &());
|
||||||
if let Some(transform) = cursor.item() {
|
if let Some(transform) = cursor.item() {
|
||||||
let transform_start = cursor.start().display.lines;
|
let transform_start = cursor.start().display.lines;
|
||||||
if transform.display_text.is_some() {
|
if transform.display_text.is_some() {
|
||||||
if point.0 == transform_start || matches!(bias, Bias::Left) {
|
if point.0 == transform_start || matches!(bias, Bias::Left) {
|
||||||
DisplayPoint(transform_start)
|
DisplayPoint(transform_start)
|
||||||
} else {
|
} else {
|
||||||
DisplayPoint(cursor.end().display.lines)
|
DisplayPoint(cursor.end(&()).display.lines)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let overshoot = point.0 - transform_start;
|
let overshoot = point.0 - transform_start;
|
||||||
@ -574,7 +587,7 @@ impl sum_tree::Summary for TransformSummary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> sum_tree::Dimension<'a, TransformSummary> for TransformSummary {
|
impl<'a> sum_tree::Dimension<'a, TransformSummary> for TransformSummary {
|
||||||
fn add_summary(&mut self, summary: &'a TransformSummary) {
|
fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
|
||||||
sum_tree::Summary::add_summary(self, summary, &());
|
sum_tree::Summary::add_summary(self, summary, &());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -649,7 +662,7 @@ impl sum_tree::Summary for FoldSummary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> sum_tree::Dimension<'a, FoldSummary> for Fold {
|
impl<'a> sum_tree::Dimension<'a, FoldSummary> for Fold {
|
||||||
fn add_summary(&mut self, summary: &'a FoldSummary) {
|
fn add_summary(&mut self, summary: &'a FoldSummary, _: &Buffer) {
|
||||||
self.0.start = summary.start.clone();
|
self.0.start = summary.start.clone();
|
||||||
self.0.end = summary.end.clone();
|
self.0.end = summary.end.clone();
|
||||||
}
|
}
|
||||||
@ -662,7 +675,7 @@ impl<'a> sum_tree::SeekDimension<'a, FoldSummary> for Fold {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> sum_tree::Dimension<'a, FoldSummary> for usize {
|
impl<'a> sum_tree::Dimension<'a, FoldSummary> for usize {
|
||||||
fn add_summary(&mut self, summary: &'a FoldSummary) {
|
fn add_summary(&mut self, summary: &'a FoldSummary, _: &Buffer) {
|
||||||
*self += summary.count;
|
*self += summary.count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -676,8 +689,8 @@ impl<'a> Iterator for BufferRows<'a> {
|
|||||||
type Item = u32;
|
type Item = u32;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
while self.display_point > self.cursor.end().display.lines {
|
while self.display_point > self.cursor.end(&()).display.lines {
|
||||||
self.cursor.next();
|
self.cursor.next(&());
|
||||||
if self.cursor.item().is_none() {
|
if self.cursor.item().is_none() {
|
||||||
// TODO: Return a bool from next?
|
// TODO: Return a bool from next?
|
||||||
break;
|
break;
|
||||||
@ -717,10 +730,10 @@ impl<'a> Iterator for Chunks<'a> {
|
|||||||
self.buffer_offset += transform.summary.buffer.bytes;
|
self.buffer_offset += transform.summary.buffer.bytes;
|
||||||
self.buffer_chunks.seek(self.buffer_offset);
|
self.buffer_chunks.seek(self.buffer_offset);
|
||||||
|
|
||||||
while self.buffer_offset >= self.transform_cursor.end().buffer.bytes
|
while self.buffer_offset >= self.transform_cursor.end(&()).buffer.bytes
|
||||||
&& self.transform_cursor.item().is_some()
|
&& self.transform_cursor.item().is_some()
|
||||||
{
|
{
|
||||||
self.transform_cursor.next();
|
self.transform_cursor.next(&());
|
||||||
}
|
}
|
||||||
|
|
||||||
return Some(display_text);
|
return Some(display_text);
|
||||||
@ -732,10 +745,10 @@ impl<'a> Iterator for Chunks<'a> {
|
|||||||
chunk = &chunk[offset_in_chunk..];
|
chunk = &chunk[offset_in_chunk..];
|
||||||
|
|
||||||
// Truncate the chunk so that it ends at the next fold.
|
// Truncate the chunk so that it ends at the next fold.
|
||||||
let region_end = self.transform_cursor.end().buffer.bytes - self.buffer_offset;
|
let region_end = self.transform_cursor.end(&()).buffer.bytes - self.buffer_offset;
|
||||||
if chunk.len() >= region_end {
|
if chunk.len() >= region_end {
|
||||||
chunk = &chunk[0..region_end];
|
chunk = &chunk[0..region_end];
|
||||||
self.transform_cursor.next();
|
self.transform_cursor.next(&());
|
||||||
} else {
|
} else {
|
||||||
self.buffer_chunks.next();
|
self.buffer_chunks.next();
|
||||||
}
|
}
|
||||||
@ -772,10 +785,10 @@ impl<'a> Iterator for HighlightedChunks<'a> {
|
|||||||
self.buffer_offset += transform.summary.buffer.bytes;
|
self.buffer_offset += transform.summary.buffer.bytes;
|
||||||
self.buffer_chunks.seek(self.buffer_offset);
|
self.buffer_chunks.seek(self.buffer_offset);
|
||||||
|
|
||||||
while self.buffer_offset >= self.transform_cursor.end().buffer.bytes
|
while self.buffer_offset >= self.transform_cursor.end(&()).buffer.bytes
|
||||||
&& self.transform_cursor.item().is_some()
|
&& self.transform_cursor.item().is_some()
|
||||||
{
|
{
|
||||||
self.transform_cursor.next();
|
self.transform_cursor.next(&());
|
||||||
}
|
}
|
||||||
|
|
||||||
return Some((display_text, StyleId::default()));
|
return Some((display_text, StyleId::default()));
|
||||||
@ -796,10 +809,10 @@ impl<'a> Iterator for HighlightedChunks<'a> {
|
|||||||
chunk = &chunk[offset_in_chunk..];
|
chunk = &chunk[offset_in_chunk..];
|
||||||
|
|
||||||
// Truncate the chunk so that it ends at the next fold.
|
// Truncate the chunk so that it ends at the next fold.
|
||||||
let region_end = self.transform_cursor.end().buffer.bytes - self.buffer_offset;
|
let region_end = self.transform_cursor.end(&()).buffer.bytes - self.buffer_offset;
|
||||||
if chunk.len() >= region_end {
|
if chunk.len() >= region_end {
|
||||||
chunk = &chunk[0..region_end];
|
chunk = &chunk[0..region_end];
|
||||||
self.transform_cursor.next();
|
self.transform_cursor.next(&());
|
||||||
} else {
|
} else {
|
||||||
self.buffer_chunk.take();
|
self.buffer_chunk.take();
|
||||||
}
|
}
|
||||||
@ -813,7 +826,7 @@ impl<'a> Iterator for HighlightedChunks<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> sum_tree::Dimension<'a, TransformSummary> for DisplayPoint {
|
impl<'a> sum_tree::Dimension<'a, TransformSummary> for DisplayPoint {
|
||||||
fn add_summary(&mut self, summary: &'a TransformSummary) {
|
fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
|
||||||
self.0 += &summary.display.lines;
|
self.0 += &summary.display.lines;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -822,19 +835,19 @@ impl<'a> sum_tree::Dimension<'a, TransformSummary> for DisplayPoint {
|
|||||||
pub struct DisplayOffset(usize);
|
pub struct DisplayOffset(usize);
|
||||||
|
|
||||||
impl<'a> sum_tree::Dimension<'a, TransformSummary> for DisplayOffset {
|
impl<'a> sum_tree::Dimension<'a, TransformSummary> for DisplayOffset {
|
||||||
fn add_summary(&mut self, summary: &'a TransformSummary) {
|
fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
|
||||||
self.0 += &summary.display.bytes;
|
self.0 += &summary.display.bytes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> sum_tree::Dimension<'a, TransformSummary> for Point {
|
impl<'a> sum_tree::Dimension<'a, TransformSummary> for Point {
|
||||||
fn add_summary(&mut self, summary: &'a TransformSummary) {
|
fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
|
||||||
*self += &summary.buffer.lines;
|
*self += &summary.buffer.lines;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> sum_tree::Dimension<'a, TransformSummary> for usize {
|
impl<'a> sum_tree::Dimension<'a, TransformSummary> for usize {
|
||||||
fn add_summary(&mut self, summary: &'a TransformSummary) {
|
fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
|
||||||
*self += &summary.buffer.bytes;
|
*self += &summary.buffer.bytes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1031,7 +1044,7 @@ mod tests {
|
|||||||
0..=34 => {
|
0..=34 => {
|
||||||
let buffer = buffer.read(cx);
|
let buffer = buffer.read(cx);
|
||||||
let mut to_fold = Vec::new();
|
let mut to_fold = Vec::new();
|
||||||
for _ in 0..rng.gen_range(1..=5) {
|
for _ in 0..rng.gen_range(1..=2) {
|
||||||
let end = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Right);
|
let end = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Right);
|
||||||
let start = buffer.clip_offset(rng.gen_range(0..=end), Left);
|
let start = buffer.clip_offset(rng.gen_range(0..=end), Left);
|
||||||
to_fold.push(start..end);
|
to_fold.push(start..end);
|
||||||
@ -1172,7 +1185,7 @@ mod tests {
|
|||||||
let start = buffer.clip_offset(rng.gen_range(0..=end), Left);
|
let start = buffer.clip_offset(rng.gen_range(0..=end), Left);
|
||||||
let expected_folds = map
|
let expected_folds = map
|
||||||
.folds
|
.folds
|
||||||
.items()
|
.items(buffer)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|fold| {
|
.filter(|fold| {
|
||||||
let start = buffer.anchor_before(start);
|
let start = buffer.anchor_before(start);
|
||||||
@ -1227,7 +1240,7 @@ mod tests {
|
|||||||
|
|
||||||
fn merged_fold_ranges(&self, cx: &AppContext) -> Vec<Range<usize>> {
|
fn merged_fold_ranges(&self, cx: &AppContext) -> Vec<Range<usize>> {
|
||||||
let buffer = self.buffer.read(cx);
|
let buffer = self.buffer.read(cx);
|
||||||
let mut folds = self.folds.items();
|
let mut folds = self.folds.items(buffer);
|
||||||
// Ensure sorting doesn't change how folds get merged and displayed.
|
// Ensure sorting doesn't change how folds get merged and displayed.
|
||||||
folds.sort_by(|a, b| a.0.cmp(&b.0, buffer).unwrap());
|
folds.sort_by(|a, b| a.0.cmp(&b.0, buffer).unwrap());
|
||||||
let mut fold_ranges = folds
|
let mut fold_ranges = folds
|
||||||
|
@ -89,7 +89,7 @@ impl<'a> Add<&'a Self> for OperationSummary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Dimension<'a, OperationSummary> for OperationKey {
|
impl<'a> Dimension<'a, OperationSummary> for OperationKey {
|
||||||
fn add_summary(&mut self, summary: &OperationSummary) {
|
fn add_summary(&mut self, summary: &OperationSummary, _: &()) {
|
||||||
assert!(*self <= summary.key);
|
assert!(*self <= summary.key);
|
||||||
*self = summary.key;
|
*self = summary.key;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
mod cursor;
|
mod cursor;
|
||||||
|
|
||||||
|
use crate::util::Bias;
|
||||||
use arrayvec::ArrayVec;
|
use arrayvec::ArrayVec;
|
||||||
pub use cursor::Cursor;
|
pub use cursor::Cursor;
|
||||||
pub use cursor::FilterCursor;
|
pub use cursor::FilterCursor;
|
||||||
@ -29,11 +30,23 @@ pub trait Summary: Default + Clone + fmt::Debug {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait Dimension<'a, S: Summary>: Clone + fmt::Debug + Default {
|
pub trait Dimension<'a, S: Summary>: Clone + fmt::Debug + Default {
|
||||||
fn add_summary(&mut self, _summary: &'a S);
|
fn add_summary(&mut self, _summary: &'a S, _: &S::Context);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Summary> Dimension<'a, T> for () {
|
impl<'a, T: Summary> Dimension<'a, T> for () {
|
||||||
fn add_summary(&mut self, _: &'a T) {}
|
fn add_summary(&mut self, _: &'a T, _: &T::Context) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, S, D1, D2> Dimension<'a, S> for (D1, D2)
|
||||||
|
where
|
||||||
|
S: Summary,
|
||||||
|
D1: Dimension<'a, S>,
|
||||||
|
D2: Dimension<'a, S>,
|
||||||
|
{
|
||||||
|
fn add_summary(&mut self, summary: &'a S, cx: &S::Context) {
|
||||||
|
self.0.add_summary(summary, cx);
|
||||||
|
self.1.add_summary(summary, cx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait SeekDimension<'a, T: Summary>: Dimension<'a, T> {
|
pub trait SeekDimension<'a, T: Summary>: Dimension<'a, T> {
|
||||||
@ -46,12 +59,6 @@ impl<'a, S: Summary, T: Dimension<'a, S> + Ord> SeekDimension<'a, S> for T {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
|
||||||
pub enum SeekBias {
|
|
||||||
Left,
|
|
||||||
Right,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct SumTree<T: Item>(Arc<Node<T>>);
|
pub struct SumTree<T: Item>(Arc<Node<T>>);
|
||||||
|
|
||||||
@ -71,9 +78,15 @@ impl<T: Item> SumTree<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn items(&self) -> Vec<T> {
|
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.cloned().collect()
|
cursor.next(cx);
|
||||||
|
while let Some(item) = cursor.item() {
|
||||||
|
items.push(item.clone());
|
||||||
|
cursor.next(cx);
|
||||||
|
}
|
||||||
|
items
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cursor<'a, S, U>(&'a self) -> Cursor<T, S, U>
|
pub fn cursor<'a, S, U>(&'a self) -> Cursor<T, S, U>
|
||||||
@ -84,12 +97,16 @@ impl<T: Item> SumTree<T> {
|
|||||||
Cursor::new(self)
|
Cursor::new(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn filter<'a, F, U>(&'a self, filter_node: F) -> FilterCursor<F, T, U>
|
pub fn filter<'a, F, U>(
|
||||||
|
&'a self,
|
||||||
|
filter_node: F,
|
||||||
|
cx: &<T::Summary as Summary>::Context,
|
||||||
|
) -> FilterCursor<F, T, U>
|
||||||
where
|
where
|
||||||
F: Fn(&T::Summary) -> bool,
|
F: Fn(&T::Summary) -> bool,
|
||||||
U: Dimension<'a, T::Summary>,
|
U: Dimension<'a, T::Summary>,
|
||||||
{
|
{
|
||||||
FilterCursor::new(self, filter_node)
|
FilterCursor::new(self, filter_node, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -141,11 +158,14 @@ impl<T: Item> SumTree<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extent<'a, D: Dimension<'a, T::Summary>>(&'a self) -> D {
|
pub fn extent<'a, D: Dimension<'a, T::Summary>>(
|
||||||
|
&'a self,
|
||||||
|
cx: &<T::Summary as Summary>::Context,
|
||||||
|
) -> D {
|
||||||
let mut extent = D::default();
|
let mut extent = D::default();
|
||||||
match self.0.as_ref() {
|
match self.0.as_ref() {
|
||||||
Node::Internal { summary, .. } | Node::Leaf { summary, .. } => {
|
Node::Internal { summary, .. } | Node::Leaf { summary, .. } => {
|
||||||
extent.add_summary(summary);
|
extent.add_summary(summary, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
extent
|
extent
|
||||||
@ -392,7 +412,7 @@ impl<T: KeyedItem> SumTree<T> {
|
|||||||
pub fn insert(&mut self, item: T, cx: &<T::Summary as Summary>::Context) {
|
pub fn insert(&mut self, item: T, cx: &<T::Summary as Summary>::Context) {
|
||||||
*self = {
|
*self = {
|
||||||
let mut cursor = self.cursor::<T::Key, ()>();
|
let mut cursor = self.cursor::<T::Key, ()>();
|
||||||
let mut new_tree = cursor.slice(&item.key(), SeekBias::Left, cx);
|
let mut new_tree = cursor.slice(&item.key(), Bias::Left, cx);
|
||||||
new_tree.push(item, cx);
|
new_tree.push(item, cx);
|
||||||
new_tree.push_tree(cursor.suffix(cx), cx);
|
new_tree.push_tree(cursor.suffix(cx), cx);
|
||||||
new_tree
|
new_tree
|
||||||
@ -416,7 +436,7 @@ impl<T: KeyedItem> SumTree<T> {
|
|||||||
let mut new_tree = SumTree::new();
|
let mut new_tree = SumTree::new();
|
||||||
let mut buffered_items = Vec::new();
|
let mut buffered_items = Vec::new();
|
||||||
|
|
||||||
cursor.seek(&T::Key::default(), SeekBias::Left, cx);
|
cursor.seek(&T::Key::default(), Bias::Left, cx);
|
||||||
for edit in edits {
|
for edit in edits {
|
||||||
let new_key = edit.key();
|
let new_key = edit.key();
|
||||||
let mut old_item = cursor.item();
|
let mut old_item = cursor.item();
|
||||||
@ -426,7 +446,7 @@ impl<T: KeyedItem> SumTree<T> {
|
|||||||
.map_or(false, |old_item| old_item.key() < new_key)
|
.map_or(false, |old_item| old_item.key() < new_key)
|
||||||
{
|
{
|
||||||
new_tree.extend(buffered_items.drain(..), cx);
|
new_tree.extend(buffered_items.drain(..), cx);
|
||||||
let slice = cursor.slice(&new_key, SeekBias::Left, cx);
|
let slice = cursor.slice(&new_key, Bias::Left, cx);
|
||||||
new_tree.push_tree(slice, cx);
|
new_tree.push_tree(slice, cx);
|
||||||
old_item = cursor.item();
|
old_item = cursor.item();
|
||||||
}
|
}
|
||||||
@ -434,7 +454,7 @@ impl<T: KeyedItem> SumTree<T> {
|
|||||||
if let Some(old_item) = old_item {
|
if let Some(old_item) = old_item {
|
||||||
if old_item.key() == new_key {
|
if old_item.key() == new_key {
|
||||||
removed.push(old_item.clone());
|
removed.push(old_item.clone());
|
||||||
cursor.next();
|
cursor.next(cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -456,7 +476,7 @@ impl<T: KeyedItem> SumTree<T> {
|
|||||||
|
|
||||||
pub fn get(&self, key: &T::Key, cx: &<T::Summary as Summary>::Context) -> Option<&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, SeekBias::Left, cx) {
|
if cursor.seek(key, Bias::Left, cx) {
|
||||||
cursor.item()
|
cursor.item()
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -580,7 +600,10 @@ mod tests {
|
|||||||
tree2.extend(50..100, &());
|
tree2.extend(50..100, &());
|
||||||
|
|
||||||
tree1.push_tree(tree2, &());
|
tree1.push_tree(tree2, &());
|
||||||
assert_eq!(tree1.items(), (0..20).chain(50..100).collect::<Vec<u8>>());
|
assert_eq!(
|
||||||
|
tree1.items(&()),
|
||||||
|
(0..20).chain(50..100).collect::<Vec<u8>>()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -596,32 +619,33 @@ mod tests {
|
|||||||
tree.extend(rng.sample_iter(distributions::Standard).take(count), &());
|
tree.extend(rng.sample_iter(distributions::Standard).take(count), &());
|
||||||
|
|
||||||
for _ in 0..5 {
|
for _ in 0..5 {
|
||||||
let splice_end = rng.gen_range(0..tree.extent::<Count>().0 + 1);
|
let splice_end = rng.gen_range(0..tree.extent::<Count>(&()).0 + 1);
|
||||||
let splice_start = rng.gen_range(0..splice_end + 1);
|
let splice_start = rng.gen_range(0..splice_end + 1);
|
||||||
let count = rng.gen_range(0..3);
|
let count = rng.gen_range(0..3);
|
||||||
let tree_end = tree.extent::<Count>();
|
let tree_end = tree.extent::<Count>(&());
|
||||||
let new_items = rng
|
let new_items = rng
|
||||||
.sample_iter(distributions::Standard)
|
.sample_iter(distributions::Standard)
|
||||||
.take(count)
|
.take(count)
|
||||||
.collect::<Vec<u8>>();
|
.collect::<Vec<u8>>();
|
||||||
|
|
||||||
let mut reference_items = tree.items();
|
let mut reference_items = tree.items(&());
|
||||||
reference_items.splice(splice_start..splice_end, new_items.clone());
|
reference_items.splice(splice_start..splice_end, new_items.clone());
|
||||||
|
|
||||||
tree = {
|
tree = {
|
||||||
let mut cursor = tree.cursor::<Count, ()>();
|
let mut cursor = tree.cursor::<Count, ()>();
|
||||||
let mut new_tree = cursor.slice(&Count(splice_start), SeekBias::Right, &());
|
let mut new_tree = cursor.slice(&Count(splice_start), Bias::Right, &());
|
||||||
new_tree.extend(new_items, &());
|
new_tree.extend(new_items, &());
|
||||||
cursor.seek(&Count(splice_end), SeekBias::Right, &());
|
cursor.seek(&Count(splice_end), Bias::Right, &());
|
||||||
new_tree.push_tree(cursor.slice(&tree_end, SeekBias::Right, &()), &());
|
new_tree.push_tree(cursor.slice(&tree_end, Bias::Right, &()), &());
|
||||||
new_tree
|
new_tree
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(tree.items(), reference_items);
|
assert_eq!(tree.items(&()), reference_items);
|
||||||
|
|
||||||
let mut filter_cursor = tree.filter::<_, Count>(|summary| summary.contains_even);
|
let mut filter_cursor =
|
||||||
|
tree.filter::<_, Count>(|summary| summary.contains_even, &());
|
||||||
let mut reference_filter = tree
|
let mut reference_filter = tree
|
||||||
.items()
|
.items(&())
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter(|(_, item)| (item & 1) == 0);
|
.filter(|(_, item)| (item & 1) == 0);
|
||||||
@ -629,14 +653,14 @@ mod tests {
|
|||||||
let (reference_index, reference_item) = reference_filter.next().unwrap();
|
let (reference_index, reference_item) = reference_filter.next().unwrap();
|
||||||
assert_eq!(actual_item, &reference_item);
|
assert_eq!(actual_item, &reference_item);
|
||||||
assert_eq!(filter_cursor.start().0, reference_index);
|
assert_eq!(filter_cursor.start().0, reference_index);
|
||||||
filter_cursor.next();
|
filter_cursor.next(&());
|
||||||
}
|
}
|
||||||
assert!(reference_filter.next().is_none());
|
assert!(reference_filter.next().is_none());
|
||||||
|
|
||||||
let mut pos = rng.gen_range(0..tree.extent::<Count>().0 + 1);
|
let mut pos = rng.gen_range(0..tree.extent::<Count>(&()).0 + 1);
|
||||||
let mut before_start = false;
|
let mut before_start = false;
|
||||||
let mut cursor = tree.cursor::<Count, Count>();
|
let mut cursor = tree.cursor::<Count, Count>();
|
||||||
cursor.seek(&Count(pos), SeekBias::Right, &());
|
cursor.seek(&Count(pos), Bias::Right, &());
|
||||||
|
|
||||||
for i in 0..10 {
|
for i in 0..10 {
|
||||||
assert_eq!(cursor.start().0, pos);
|
assert_eq!(cursor.start().0, pos);
|
||||||
@ -654,13 +678,13 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if i < 5 {
|
if i < 5 {
|
||||||
cursor.next();
|
cursor.next(&());
|
||||||
if pos < reference_items.len() {
|
if pos < reference_items.len() {
|
||||||
pos += 1;
|
pos += 1;
|
||||||
before_start = false;
|
before_start = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cursor.prev();
|
cursor.prev(&());
|
||||||
if pos == 0 {
|
if pos == 0 {
|
||||||
before_start = true;
|
before_start = true;
|
||||||
}
|
}
|
||||||
@ -670,18 +694,10 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _ in 0..10 {
|
for _ in 0..10 {
|
||||||
let end = rng.gen_range(0..tree.extent::<Count>().0 + 1);
|
let end = rng.gen_range(0..tree.extent::<Count>(&()).0 + 1);
|
||||||
let start = rng.gen_range(0..end + 1);
|
let start = rng.gen_range(0..end + 1);
|
||||||
let start_bias = if rng.gen() {
|
let start_bias = if rng.gen() { Bias::Left } else { Bias::Right };
|
||||||
SeekBias::Left
|
let end_bias = if rng.gen() { Bias::Left } else { Bias::Right };
|
||||||
} else {
|
|
||||||
SeekBias::Right
|
|
||||||
};
|
|
||||||
let end_bias = if rng.gen() {
|
|
||||||
SeekBias::Left
|
|
||||||
} else {
|
|
||||||
SeekBias::Right
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut cursor = tree.cursor::<Count, ()>();
|
let mut cursor = tree.cursor::<Count, ()>();
|
||||||
cursor.seek(&Count(start), start_bias, &());
|
cursor.seek(&Count(start), start_bias, &());
|
||||||
@ -701,7 +717,7 @@ mod tests {
|
|||||||
let tree = SumTree::<u8>::new();
|
let tree = SumTree::<u8>::new();
|
||||||
let mut cursor = tree.cursor::<Count, Sum>();
|
let mut cursor = tree.cursor::<Count, Sum>();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cursor.slice(&Count(0), SeekBias::Right, &()).items(),
|
cursor.slice(&Count(0), Bias::Right, &()).items(&()),
|
||||||
Vec::<u8>::new()
|
Vec::<u8>::new()
|
||||||
);
|
);
|
||||||
assert_eq!(cursor.item(), None);
|
assert_eq!(cursor.item(), None);
|
||||||
@ -713,34 +729,34 @@ mod tests {
|
|||||||
tree.extend(vec![1], &());
|
tree.extend(vec![1], &());
|
||||||
let mut cursor = tree.cursor::<Count, Sum>();
|
let mut cursor = tree.cursor::<Count, Sum>();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cursor.slice(&Count(0), SeekBias::Right, &()).items(),
|
cursor.slice(&Count(0), Bias::Right, &()).items(&()),
|
||||||
Vec::<u8>::new()
|
Vec::<u8>::new()
|
||||||
);
|
);
|
||||||
assert_eq!(cursor.item(), Some(&1));
|
assert_eq!(cursor.item(), Some(&1));
|
||||||
assert_eq!(cursor.prev_item(), None);
|
assert_eq!(cursor.prev_item(), None);
|
||||||
assert_eq!(cursor.start(), &Sum(0));
|
assert_eq!(cursor.start(), &Sum(0));
|
||||||
|
|
||||||
cursor.next();
|
cursor.next(&());
|
||||||
assert_eq!(cursor.item(), None);
|
assert_eq!(cursor.item(), None);
|
||||||
assert_eq!(cursor.prev_item(), Some(&1));
|
assert_eq!(cursor.prev_item(), Some(&1));
|
||||||
assert_eq!(cursor.start(), &Sum(1));
|
assert_eq!(cursor.start(), &Sum(1));
|
||||||
|
|
||||||
cursor.prev();
|
cursor.prev(&());
|
||||||
assert_eq!(cursor.item(), Some(&1));
|
assert_eq!(cursor.item(), Some(&1));
|
||||||
assert_eq!(cursor.prev_item(), None);
|
assert_eq!(cursor.prev_item(), None);
|
||||||
assert_eq!(cursor.start(), &Sum(0));
|
assert_eq!(cursor.start(), &Sum(0));
|
||||||
|
|
||||||
let mut cursor = tree.cursor::<Count, Sum>();
|
let mut cursor = tree.cursor::<Count, Sum>();
|
||||||
assert_eq!(cursor.slice(&Count(1), SeekBias::Right, &()).items(), [1]);
|
assert_eq!(cursor.slice(&Count(1), Bias::Right, &()).items(&()), [1]);
|
||||||
assert_eq!(cursor.item(), None);
|
assert_eq!(cursor.item(), None);
|
||||||
assert_eq!(cursor.prev_item(), Some(&1));
|
assert_eq!(cursor.prev_item(), Some(&1));
|
||||||
assert_eq!(cursor.start(), &Sum(1));
|
assert_eq!(cursor.start(), &Sum(1));
|
||||||
|
|
||||||
cursor.seek(&Count(0), SeekBias::Right, &());
|
cursor.seek(&Count(0), Bias::Right, &());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cursor
|
cursor
|
||||||
.slice(&tree.extent::<Count>(), SeekBias::Right, &())
|
.slice(&tree.extent::<Count>(&()), Bias::Right, &())
|
||||||
.items(),
|
.items(&()),
|
||||||
[1]
|
[1]
|
||||||
);
|
);
|
||||||
assert_eq!(cursor.item(), None);
|
assert_eq!(cursor.item(), None);
|
||||||
@ -752,71 +768,68 @@ mod tests {
|
|||||||
tree.extend(vec![1, 2, 3, 4, 5, 6], &());
|
tree.extend(vec![1, 2, 3, 4, 5, 6], &());
|
||||||
let mut cursor = tree.cursor::<Count, Sum>();
|
let mut cursor = tree.cursor::<Count, Sum>();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(cursor.slice(&Count(2), Bias::Right, &()).items(&()), [1, 2]);
|
||||||
cursor.slice(&Count(2), SeekBias::Right, &()).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.start(), &Sum(3));
|
assert_eq!(cursor.start(), &Sum(3));
|
||||||
|
|
||||||
cursor.next();
|
cursor.next(&());
|
||||||
assert_eq!(cursor.item(), Some(&4));
|
assert_eq!(cursor.item(), Some(&4));
|
||||||
assert_eq!(cursor.prev_item(), Some(&3));
|
assert_eq!(cursor.prev_item(), Some(&3));
|
||||||
assert_eq!(cursor.start(), &Sum(6));
|
assert_eq!(cursor.start(), &Sum(6));
|
||||||
|
|
||||||
cursor.next();
|
cursor.next(&());
|
||||||
assert_eq!(cursor.item(), Some(&5));
|
assert_eq!(cursor.item(), Some(&5));
|
||||||
assert_eq!(cursor.prev_item(), Some(&4));
|
assert_eq!(cursor.prev_item(), Some(&4));
|
||||||
assert_eq!(cursor.start(), &Sum(10));
|
assert_eq!(cursor.start(), &Sum(10));
|
||||||
|
|
||||||
cursor.next();
|
cursor.next(&());
|
||||||
assert_eq!(cursor.item(), Some(&6));
|
assert_eq!(cursor.item(), Some(&6));
|
||||||
assert_eq!(cursor.prev_item(), Some(&5));
|
assert_eq!(cursor.prev_item(), Some(&5));
|
||||||
assert_eq!(cursor.start(), &Sum(15));
|
assert_eq!(cursor.start(), &Sum(15));
|
||||||
|
|
||||||
cursor.next();
|
cursor.next(&());
|
||||||
cursor.next();
|
cursor.next(&());
|
||||||
assert_eq!(cursor.item(), None);
|
assert_eq!(cursor.item(), None);
|
||||||
assert_eq!(cursor.prev_item(), Some(&6));
|
assert_eq!(cursor.prev_item(), Some(&6));
|
||||||
assert_eq!(cursor.start(), &Sum(21));
|
assert_eq!(cursor.start(), &Sum(21));
|
||||||
|
|
||||||
cursor.prev();
|
cursor.prev(&());
|
||||||
assert_eq!(cursor.item(), Some(&6));
|
assert_eq!(cursor.item(), Some(&6));
|
||||||
assert_eq!(cursor.prev_item(), Some(&5));
|
assert_eq!(cursor.prev_item(), Some(&5));
|
||||||
assert_eq!(cursor.start(), &Sum(15));
|
assert_eq!(cursor.start(), &Sum(15));
|
||||||
|
|
||||||
cursor.prev();
|
cursor.prev(&());
|
||||||
assert_eq!(cursor.item(), Some(&5));
|
assert_eq!(cursor.item(), Some(&5));
|
||||||
assert_eq!(cursor.prev_item(), Some(&4));
|
assert_eq!(cursor.prev_item(), Some(&4));
|
||||||
assert_eq!(cursor.start(), &Sum(10));
|
assert_eq!(cursor.start(), &Sum(10));
|
||||||
|
|
||||||
cursor.prev();
|
cursor.prev(&());
|
||||||
assert_eq!(cursor.item(), Some(&4));
|
assert_eq!(cursor.item(), Some(&4));
|
||||||
assert_eq!(cursor.prev_item(), Some(&3));
|
assert_eq!(cursor.prev_item(), Some(&3));
|
||||||
assert_eq!(cursor.start(), &Sum(6));
|
assert_eq!(cursor.start(), &Sum(6));
|
||||||
|
|
||||||
cursor.prev();
|
cursor.prev(&());
|
||||||
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.start(), &Sum(3));
|
assert_eq!(cursor.start(), &Sum(3));
|
||||||
|
|
||||||
cursor.prev();
|
cursor.prev(&());
|
||||||
assert_eq!(cursor.item(), Some(&2));
|
assert_eq!(cursor.item(), Some(&2));
|
||||||
assert_eq!(cursor.prev_item(), Some(&1));
|
assert_eq!(cursor.prev_item(), Some(&1));
|
||||||
assert_eq!(cursor.start(), &Sum(1));
|
assert_eq!(cursor.start(), &Sum(1));
|
||||||
|
|
||||||
cursor.prev();
|
cursor.prev(&());
|
||||||
assert_eq!(cursor.item(), Some(&1));
|
assert_eq!(cursor.item(), Some(&1));
|
||||||
assert_eq!(cursor.prev_item(), None);
|
assert_eq!(cursor.prev_item(), None);
|
||||||
assert_eq!(cursor.start(), &Sum(0));
|
assert_eq!(cursor.start(), &Sum(0));
|
||||||
|
|
||||||
cursor.prev();
|
cursor.prev(&());
|
||||||
assert_eq!(cursor.item(), None);
|
assert_eq!(cursor.item(), None);
|
||||||
assert_eq!(cursor.prev_item(), None);
|
assert_eq!(cursor.prev_item(), None);
|
||||||
assert_eq!(cursor.start(), &Sum(0));
|
assert_eq!(cursor.start(), &Sum(0));
|
||||||
|
|
||||||
cursor.next();
|
cursor.next(&());
|
||||||
assert_eq!(cursor.item(), Some(&1));
|
assert_eq!(cursor.item(), Some(&1));
|
||||||
assert_eq!(cursor.prev_item(), None);
|
assert_eq!(cursor.prev_item(), None);
|
||||||
assert_eq!(cursor.start(), &Sum(0));
|
assert_eq!(cursor.start(), &Sum(0));
|
||||||
@ -824,19 +837,19 @@ mod tests {
|
|||||||
let mut cursor = tree.cursor::<Count, Sum>();
|
let mut cursor = tree.cursor::<Count, Sum>();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cursor
|
cursor
|
||||||
.slice(&tree.extent::<Count>(), SeekBias::Right, &())
|
.slice(&tree.extent::<Count>(&()), Bias::Right, &())
|
||||||
.items(),
|
.items(&()),
|
||||||
tree.items()
|
tree.items(&())
|
||||||
);
|
);
|
||||||
assert_eq!(cursor.item(), None);
|
assert_eq!(cursor.item(), None);
|
||||||
assert_eq!(cursor.prev_item(), Some(&6));
|
assert_eq!(cursor.prev_item(), Some(&6));
|
||||||
assert_eq!(cursor.start(), &Sum(21));
|
assert_eq!(cursor.start(), &Sum(21));
|
||||||
|
|
||||||
cursor.seek(&Count(3), SeekBias::Right, &());
|
cursor.seek(&Count(3), Bias::Right, &());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cursor
|
cursor
|
||||||
.slice(&tree.extent::<Count>(), SeekBias::Right, &())
|
.slice(&tree.extent::<Count>(&()), Bias::Right, &())
|
||||||
.items(),
|
.items(&()),
|
||||||
[4, 5, 6]
|
[4, 5, 6]
|
||||||
);
|
);
|
||||||
assert_eq!(cursor.item(), None);
|
assert_eq!(cursor.item(), None);
|
||||||
@ -844,23 +857,23 @@ mod tests {
|
|||||||
assert_eq!(cursor.start(), &Sum(21));
|
assert_eq!(cursor.start(), &Sum(21));
|
||||||
|
|
||||||
// Seeking can bias left or right
|
// Seeking can bias left or right
|
||||||
cursor.seek(&Count(1), SeekBias::Left, &());
|
cursor.seek(&Count(1), Bias::Left, &());
|
||||||
assert_eq!(cursor.item(), Some(&1));
|
assert_eq!(cursor.item(), Some(&1));
|
||||||
cursor.seek(&Count(1), SeekBias::Right, &());
|
cursor.seek(&Count(1), Bias::Right, &());
|
||||||
assert_eq!(cursor.item(), Some(&2));
|
assert_eq!(cursor.item(), Some(&2));
|
||||||
|
|
||||||
// Slicing without resetting starts from where the cursor is parked at.
|
// Slicing without resetting starts from where the cursor is parked at.
|
||||||
cursor.seek(&Count(1), SeekBias::Right, &());
|
cursor.seek(&Count(1), Bias::Right, &());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cursor.slice(&Count(3), SeekBias::Right, &()).items(),
|
cursor.slice(&Count(3), Bias::Right, &()).items(&()),
|
||||||
vec![2, 3]
|
vec![2, 3]
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cursor.slice(&Count(6), SeekBias::Left, &()).items(),
|
cursor.slice(&Count(6), Bias::Left, &()).items(&()),
|
||||||
vec![4, 5]
|
vec![4, 5]
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cursor.slice(&Count(6), SeekBias::Right, &()).items(),
|
cursor.slice(&Count(6), Bias::Right, &()).items(&()),
|
||||||
vec![6]
|
vec![6]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -870,7 +883,7 @@ mod tests {
|
|||||||
let mut tree = SumTree::<u8>::new();
|
let mut tree = SumTree::<u8>::new();
|
||||||
|
|
||||||
let removed = tree.edit(vec![Edit::Insert(1), Edit::Insert(2), Edit::Insert(0)], &());
|
let removed = tree.edit(vec![Edit::Insert(1), Edit::Insert(2), Edit::Insert(0)], &());
|
||||||
assert_eq!(tree.items(), vec![0, 1, 2]);
|
assert_eq!(tree.items(&()), vec![0, 1, 2]);
|
||||||
assert_eq!(removed, Vec::<u8>::new());
|
assert_eq!(removed, Vec::<u8>::new());
|
||||||
assert_eq!(tree.get(&0, &()), Some(&0));
|
assert_eq!(tree.get(&0, &()), Some(&0));
|
||||||
assert_eq!(tree.get(&1, &()), Some(&1));
|
assert_eq!(tree.get(&1, &()), Some(&1));
|
||||||
@ -878,7 +891,7 @@ mod tests {
|
|||||||
assert_eq!(tree.get(&4, &()), None);
|
assert_eq!(tree.get(&4, &()), None);
|
||||||
|
|
||||||
let removed = tree.edit(vec![Edit::Insert(2), Edit::Insert(4), Edit::Remove(0)], &());
|
let removed = tree.edit(vec![Edit::Insert(2), Edit::Insert(4), Edit::Remove(0)], &());
|
||||||
assert_eq!(tree.items(), vec![1, 2, 4]);
|
assert_eq!(tree.items(&()), vec![1, 2, 4]);
|
||||||
assert_eq!(removed, vec![0, 2]);
|
assert_eq!(removed, vec![0, 2]);
|
||||||
assert_eq!(tree.get(&0, &()), None);
|
assert_eq!(tree.get(&0, &()), None);
|
||||||
assert_eq!(tree.get(&1, &()), Some(&1));
|
assert_eq!(tree.get(&1, &()), Some(&1));
|
||||||
@ -933,19 +946,19 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Dimension<'a, IntegersSummary> for u8 {
|
impl<'a> Dimension<'a, IntegersSummary> for u8 {
|
||||||
fn add_summary(&mut self, summary: &IntegersSummary) {
|
fn add_summary(&mut self, summary: &IntegersSummary, _: &()) {
|
||||||
*self = summary.max;
|
*self = summary.max;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Dimension<'a, IntegersSummary> for Count {
|
impl<'a> Dimension<'a, IntegersSummary> for Count {
|
||||||
fn add_summary(&mut self, summary: &IntegersSummary) {
|
fn add_summary(&mut self, summary: &IntegersSummary, _: &()) {
|
||||||
self.0 += summary.count.0;
|
self.0 += summary.count.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Dimension<'a, IntegersSummary> for Sum {
|
impl<'a> Dimension<'a, IntegersSummary> for Sum {
|
||||||
fn add_summary(&mut self, summary: &IntegersSummary) {
|
fn add_summary(&mut self, summary: &IntegersSummary, _: &()) {
|
||||||
self.0 += summary.sum.0;
|
self.0 += summary.sum.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,10 +49,10 @@ where
|
|||||||
&self.sum_dimension
|
&self.sum_dimension
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn end(&self) -> U {
|
pub fn end(&self, cx: &<T::Summary as Summary>::Context) -> U {
|
||||||
if let Some(item_summary) = self.item_summary() {
|
if let Some(item_summary) = self.item_summary() {
|
||||||
let mut end = self.start().clone();
|
let mut end = self.start().clone();
|
||||||
end.add_summary(item_summary);
|
end.add_summary(item_summary, cx);
|
||||||
end
|
end
|
||||||
} else {
|
} else {
|
||||||
self.start().clone()
|
self.start().clone()
|
||||||
@ -134,13 +134,13 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn prev(&mut self) {
|
pub fn prev(&mut self, cx: &<T::Summary as Summary>::Context) {
|
||||||
assert!(self.did_seek, "Must seek before calling this method");
|
assert!(self.did_seek, "Must seek before calling this method");
|
||||||
|
|
||||||
if self.at_end {
|
if self.at_end {
|
||||||
self.seek_dimension = S::default();
|
self.seek_dimension = S::default();
|
||||||
self.sum_dimension = U::default();
|
self.sum_dimension = U::default();
|
||||||
self.descend_to_last_item(self.tree);
|
self.descend_to_last_item(self.tree, cx);
|
||||||
self.at_end = false;
|
self.at_end = false;
|
||||||
} else {
|
} else {
|
||||||
while let Some(entry) = self.stack.pop() {
|
while let Some(entry) = self.stack.pop() {
|
||||||
@ -167,8 +167,8 @@ where
|
|||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
for summary in &child_summaries[0..new_index] {
|
for summary in &child_summaries[0..new_index] {
|
||||||
self.seek_dimension.add_summary(summary);
|
self.seek_dimension.add_summary(summary, cx);
|
||||||
self.sum_dimension.add_summary(summary);
|
self.sum_dimension.add_summary(summary, cx);
|
||||||
}
|
}
|
||||||
self.stack.push(StackEntry {
|
self.stack.push(StackEntry {
|
||||||
tree: entry.tree,
|
tree: entry.tree,
|
||||||
@ -176,12 +176,12 @@ where
|
|||||||
seek_dimension: self.seek_dimension.clone(),
|
seek_dimension: self.seek_dimension.clone(),
|
||||||
sum_dimension: self.sum_dimension.clone(),
|
sum_dimension: self.sum_dimension.clone(),
|
||||||
});
|
});
|
||||||
self.descend_to_last_item(&child_trees[new_index]);
|
self.descend_to_last_item(&child_trees[new_index], cx);
|
||||||
}
|
}
|
||||||
Node::Leaf { item_summaries, .. } => {
|
Node::Leaf { item_summaries, .. } => {
|
||||||
for item_summary in &item_summaries[0..new_index] {
|
for item_summary in &item_summaries[0..new_index] {
|
||||||
self.seek_dimension.add_summary(item_summary);
|
self.seek_dimension.add_summary(item_summary, cx);
|
||||||
self.sum_dimension.add_summary(item_summary);
|
self.sum_dimension.add_summary(item_summary, cx);
|
||||||
}
|
}
|
||||||
self.stack.push(StackEntry {
|
self.stack.push(StackEntry {
|
||||||
tree: entry.tree,
|
tree: entry.tree,
|
||||||
@ -198,11 +198,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next(&mut self) {
|
pub fn next(&mut self, cx: &<T::Summary as Summary>::Context) {
|
||||||
self.next_internal(|_| true)
|
self.next_internal(|_| true, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_internal<F>(&mut self, filter_node: F)
|
fn next_internal<F>(&mut self, filter_node: F, cx: &<T::Summary as Summary>::Context)
|
||||||
where
|
where
|
||||||
F: Fn(&T::Summary) -> bool,
|
F: Fn(&T::Summary) -> bool,
|
||||||
{
|
{
|
||||||
@ -229,9 +229,8 @@ where
|
|||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
if !descend {
|
if !descend {
|
||||||
let summary = &child_summaries[entry.index];
|
entry.seek_dimension = self.seek_dimension.clone();
|
||||||
entry.seek_dimension.add_summary(summary);
|
entry.sum_dimension = self.sum_dimension.clone();
|
||||||
entry.sum_dimension.add_summary(summary);
|
|
||||||
entry.index += 1;
|
entry.index += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,8 +239,8 @@ where
|
|||||||
if filter_node(next_summary) {
|
if filter_node(next_summary) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
self.seek_dimension.add_summary(next_summary);
|
self.seek_dimension.add_summary(next_summary, cx);
|
||||||
self.sum_dimension.add_summary(next_summary);
|
self.sum_dimension.add_summary(next_summary, cx);
|
||||||
}
|
}
|
||||||
entry.index += 1;
|
entry.index += 1;
|
||||||
}
|
}
|
||||||
@ -251,10 +250,10 @@ where
|
|||||||
Node::Leaf { item_summaries, .. } => {
|
Node::Leaf { item_summaries, .. } => {
|
||||||
if !descend {
|
if !descend {
|
||||||
let item_summary = &item_summaries[entry.index];
|
let item_summary = &item_summaries[entry.index];
|
||||||
self.seek_dimension.add_summary(item_summary);
|
self.seek_dimension.add_summary(item_summary, cx);
|
||||||
entry.seek_dimension.add_summary(item_summary);
|
entry.seek_dimension.add_summary(item_summary, cx);
|
||||||
self.sum_dimension.add_summary(item_summary);
|
self.sum_dimension.add_summary(item_summary, cx);
|
||||||
entry.sum_dimension.add_summary(item_summary);
|
entry.sum_dimension.add_summary(item_summary, cx);
|
||||||
entry.index += 1;
|
entry.index += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,10 +262,10 @@ where
|
|||||||
if filter_node(next_item_summary) {
|
if filter_node(next_item_summary) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
self.seek_dimension.add_summary(next_item_summary);
|
self.seek_dimension.add_summary(next_item_summary, cx);
|
||||||
entry.seek_dimension.add_summary(next_item_summary);
|
entry.seek_dimension.add_summary(next_item_summary, cx);
|
||||||
self.sum_dimension.add_summary(next_item_summary);
|
self.sum_dimension.add_summary(next_item_summary, cx);
|
||||||
entry.sum_dimension.add_summary(next_item_summary);
|
entry.sum_dimension.add_summary(next_item_summary, cx);
|
||||||
entry.index += 1;
|
entry.index += 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -295,7 +294,11 @@ where
|
|||||||
debug_assert!(self.stack.is_empty() || self.stack.last().unwrap().tree.0.is_leaf());
|
debug_assert!(self.stack.is_empty() || self.stack.last().unwrap().tree.0.is_leaf());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn descend_to_last_item(&mut self, mut subtree: &'a SumTree<T>) {
|
fn descend_to_last_item(
|
||||||
|
&mut self,
|
||||||
|
mut subtree: &'a SumTree<T>,
|
||||||
|
cx: &<T::Summary as Summary>::Context,
|
||||||
|
) {
|
||||||
self.did_seek = true;
|
self.did_seek = true;
|
||||||
loop {
|
loop {
|
||||||
match subtree.0.as_ref() {
|
match subtree.0.as_ref() {
|
||||||
@ -305,8 +308,8 @@ where
|
|||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
for summary in &child_summaries[0..child_summaries.len() - 1] {
|
for summary in &child_summaries[0..child_summaries.len() - 1] {
|
||||||
self.seek_dimension.add_summary(summary);
|
self.seek_dimension.add_summary(summary, cx);
|
||||||
self.sum_dimension.add_summary(summary);
|
self.sum_dimension.add_summary(summary, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.stack.push(StackEntry {
|
self.stack.push(StackEntry {
|
||||||
@ -320,8 +323,8 @@ where
|
|||||||
Node::Leaf { item_summaries, .. } => {
|
Node::Leaf { item_summaries, .. } => {
|
||||||
let last_index = item_summaries.len().saturating_sub(1);
|
let last_index = item_summaries.len().saturating_sub(1);
|
||||||
for item_summary in &item_summaries[0..last_index] {
|
for item_summary in &item_summaries[0..last_index] {
|
||||||
self.seek_dimension.add_summary(item_summary);
|
self.seek_dimension.add_summary(item_summary, cx);
|
||||||
self.sum_dimension.add_summary(item_summary);
|
self.sum_dimension.add_summary(item_summary, cx);
|
||||||
}
|
}
|
||||||
self.stack.push(StackEntry {
|
self.stack.push(StackEntry {
|
||||||
tree: subtree,
|
tree: subtree,
|
||||||
@ -342,28 +345,28 @@ where
|
|||||||
S: SeekDimension<'a, T::Summary>,
|
S: SeekDimension<'a, T::Summary>,
|
||||||
U: Dimension<'a, T::Summary>,
|
U: Dimension<'a, T::Summary>,
|
||||||
{
|
{
|
||||||
pub fn seek(&mut self, pos: &S, bias: SeekBias, cx: &<T::Summary as Summary>::Context) -> bool {
|
pub fn seek(&mut self, pos: &S, bias: Bias, cx: &<T::Summary as Summary>::Context) -> bool {
|
||||||
self.reset();
|
self.reset();
|
||||||
self.seek_internal::<()>(pos, bias, &mut SeekAggregate::None, cx)
|
self.seek_internal::<()>(Some(pos), bias, &mut SeekAggregate::None, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn seek_forward(
|
pub fn seek_forward(
|
||||||
&mut self,
|
&mut self,
|
||||||
pos: &S,
|
pos: &S,
|
||||||
bias: SeekBias,
|
bias: Bias,
|
||||||
cx: &<T::Summary as Summary>::Context,
|
cx: &<T::Summary as Summary>::Context,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
self.seek_internal::<()>(pos, bias, &mut SeekAggregate::None, cx)
|
self.seek_internal::<()>(Some(pos), bias, &mut SeekAggregate::None, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn slice(
|
pub fn slice(
|
||||||
&mut self,
|
&mut self,
|
||||||
end: &S,
|
end: &S,
|
||||||
bias: SeekBias,
|
bias: Bias,
|
||||||
cx: &<T::Summary as Summary>::Context,
|
cx: &<T::Summary as Summary>::Context,
|
||||||
) -> SumTree<T> {
|
) -> SumTree<T> {
|
||||||
let mut slice = SeekAggregate::Slice(SumTree::new());
|
let mut slice = SeekAggregate::Slice(SumTree::new());
|
||||||
self.seek_internal::<()>(end, bias, &mut slice, cx);
|
self.seek_internal::<()>(Some(end), bias, &mut slice, cx);
|
||||||
if let SeekAggregate::Slice(slice) = slice {
|
if let SeekAggregate::Slice(slice) = slice {
|
||||||
slice
|
slice
|
||||||
} else {
|
} else {
|
||||||
@ -372,9 +375,8 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 extent = self.tree.extent::<S>();
|
|
||||||
let mut slice = SeekAggregate::Slice(SumTree::new());
|
let mut slice = SeekAggregate::Slice(SumTree::new());
|
||||||
self.seek_internal::<()>(&extent, SeekBias::Right, &mut slice, cx);
|
self.seek_internal::<()>(None, Bias::Right, &mut slice, cx);
|
||||||
if let SeekAggregate::Slice(slice) = slice {
|
if let SeekAggregate::Slice(slice) = slice {
|
||||||
slice
|
slice
|
||||||
} else {
|
} else {
|
||||||
@ -382,17 +384,12 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn summary<D>(
|
pub fn summary<D>(&mut self, end: &S, bias: Bias, cx: &<T::Summary as Summary>::Context) -> D
|
||||||
&mut self,
|
|
||||||
end: &S,
|
|
||||||
bias: SeekBias,
|
|
||||||
cx: &<T::Summary as Summary>::Context,
|
|
||||||
) -> D
|
|
||||||
where
|
where
|
||||||
D: Dimension<'a, T::Summary>,
|
D: Dimension<'a, T::Summary>,
|
||||||
{
|
{
|
||||||
let mut summary = SeekAggregate::Summary(D::default());
|
let mut summary = SeekAggregate::Summary(D::default());
|
||||||
self.seek_internal(end, bias, &mut summary, cx);
|
self.seek_internal(Some(end), bias, &mut summary, cx);
|
||||||
if let SeekAggregate::Summary(summary) = summary {
|
if let SeekAggregate::Summary(summary) = summary {
|
||||||
summary
|
summary
|
||||||
} else {
|
} else {
|
||||||
@ -402,229 +399,126 @@ where
|
|||||||
|
|
||||||
fn seek_internal<D>(
|
fn seek_internal<D>(
|
||||||
&mut self,
|
&mut self,
|
||||||
target: &S,
|
target: Option<&S>,
|
||||||
bias: SeekBias,
|
bias: Bias,
|
||||||
aggregate: &mut SeekAggregate<T, D>,
|
aggregate: &mut SeekAggregate<T, D>,
|
||||||
cx: &<T::Summary as Summary>::Context,
|
cx: &<T::Summary as Summary>::Context,
|
||||||
) -> bool
|
) -> bool
|
||||||
where
|
where
|
||||||
D: Dimension<'a, T::Summary>,
|
D: Dimension<'a, T::Summary>,
|
||||||
{
|
{
|
||||||
debug_assert!(target.cmp(&self.seek_dimension, cx) >= Ordering::Equal);
|
if let Some(target) = target {
|
||||||
let mut containing_subtree = None;
|
debug_assert!(
|
||||||
|
target.cmp(&self.seek_dimension, cx) >= Ordering::Equal,
|
||||||
|
"cannot seek backward from {:?} to {:?}",
|
||||||
|
self.seek_dimension,
|
||||||
|
target
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if self.did_seek {
|
if !self.did_seek {
|
||||||
'outer: while let Some(entry) = self.stack.last_mut() {
|
self.did_seek = true;
|
||||||
{
|
self.stack.push(StackEntry {
|
||||||
match *entry.tree.0 {
|
tree: self.tree,
|
||||||
Node::Internal {
|
index: 0,
|
||||||
ref child_summaries,
|
seek_dimension: Default::default(),
|
||||||
ref child_trees,
|
sum_dimension: Default::default(),
|
||||||
..
|
});
|
||||||
} => {
|
}
|
||||||
|
|
||||||
|
let mut ascending = false;
|
||||||
|
'outer: while let Some(entry) = self.stack.last_mut() {
|
||||||
|
match *entry.tree.0 {
|
||||||
|
Node::Internal {
|
||||||
|
ref child_summaries,
|
||||||
|
ref child_trees,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
if ascending {
|
||||||
|
entry.index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (child_tree, child_summary) in child_trees[entry.index..]
|
||||||
|
.iter()
|
||||||
|
.zip(&child_summaries[entry.index..])
|
||||||
|
{
|
||||||
|
let mut child_end = self.seek_dimension.clone();
|
||||||
|
child_end.add_summary(&child_summary, cx);
|
||||||
|
|
||||||
|
let comparison =
|
||||||
|
target.map_or(Ordering::Greater, |t| t.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);
|
||||||
|
match aggregate {
|
||||||
|
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;
|
||||||
for (child_tree, child_summary) in child_trees[entry.index..]
|
entry.seek_dimension = self.seek_dimension.clone();
|
||||||
.iter()
|
entry.sum_dimension = self.sum_dimension.clone();
|
||||||
.zip(&child_summaries[entry.index..])
|
} else {
|
||||||
{
|
self.stack.push(StackEntry {
|
||||||
let mut child_end = self.seek_dimension.clone();
|
tree: child_tree,
|
||||||
child_end.add_summary(&child_summary);
|
index: 0,
|
||||||
|
seek_dimension: self.seek_dimension.clone(),
|
||||||
let comparison = target.cmp(&child_end, cx);
|
sum_dimension: self.sum_dimension.clone(),
|
||||||
if comparison == Ordering::Greater
|
});
|
||||||
|| (comparison == Ordering::Equal && bias == SeekBias::Right)
|
ascending = false;
|
||||||
{
|
continue 'outer;
|
||||||
self.seek_dimension = child_end;
|
|
||||||
self.sum_dimension.add_summary(child_summary);
|
|
||||||
match aggregate {
|
|
||||||
SeekAggregate::None => {}
|
|
||||||
SeekAggregate::Slice(slice) => {
|
|
||||||
slice.push_tree(child_tree.clone(), cx);
|
|
||||||
}
|
|
||||||
SeekAggregate::Summary(summary) => {
|
|
||||||
summary.add_summary(child_summary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
entry.index += 1;
|
|
||||||
} else {
|
|
||||||
containing_subtree = Some(child_tree);
|
|
||||||
break 'outer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Node::Leaf {
|
|
||||||
ref items,
|
|
||||||
ref item_summaries,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let mut slice_items = ArrayVec::<[T; 2 * TREE_BASE]>::new();
|
|
||||||
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..]
|
|
||||||
.iter()
|
|
||||||
.zip(&item_summaries[entry.index..])
|
|
||||||
{
|
|
||||||
let mut child_end = self.seek_dimension.clone();
|
|
||||||
child_end.add_summary(item_summary);
|
|
||||||
|
|
||||||
let comparison = target.cmp(&child_end, cx);
|
|
||||||
if comparison == Ordering::Greater
|
|
||||||
|| (comparison == Ordering::Equal && bias == SeekBias::Right)
|
|
||||||
{
|
|
||||||
self.seek_dimension = child_end;
|
|
||||||
self.sum_dimension.add_summary(item_summary);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
SeekAggregate::Summary(summary) => {
|
|
||||||
summary.add_summary(item_summary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
entry.index += 1;
|
|
||||||
} else {
|
|
||||||
if let SeekAggregate::Slice(slice) = aggregate {
|
|
||||||
slice.push_tree(
|
|
||||||
SumTree(Arc::new(Node::Leaf {
|
|
||||||
summary: slice_items_summary.unwrap(),
|
|
||||||
items: slice_items,
|
|
||||||
item_summaries: slice_item_summaries,
|
|
||||||
})),
|
|
||||||
cx,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
break 'outer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let SeekAggregate::Slice(slice) = aggregate {
|
|
||||||
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,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Node::Leaf {
|
||||||
|
ref items,
|
||||||
|
ref item_summaries,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
let mut slice_items = ArrayVec::<[T; 2 * TREE_BASE]>::new();
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
self.stack.pop();
|
for (item, item_summary) in items[entry.index..]
|
||||||
}
|
.iter()
|
||||||
} else {
|
.zip(&item_summaries[entry.index..])
|
||||||
self.did_seek = true;
|
{
|
||||||
containing_subtree = Some(self.tree);
|
let mut child_end = self.seek_dimension.clone();
|
||||||
}
|
child_end.add_summary(item_summary, cx);
|
||||||
|
|
||||||
if let Some(mut subtree) = containing_subtree {
|
let comparison =
|
||||||
loop {
|
target.map_or(Ordering::Greater, |t| t.cmp(&child_end, cx));
|
||||||
let mut next_subtree = None;
|
if comparison == Ordering::Greater
|
||||||
match *subtree.0 {
|
|| (comparison == Ordering::Equal && bias == Bias::Right)
|
||||||
Node::Internal {
|
|
||||||
ref child_summaries,
|
|
||||||
ref child_trees,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
for (index, (child_tree, child_summary)) in
|
|
||||||
child_trees.iter().zip(child_summaries).enumerate()
|
|
||||||
{
|
{
|
||||||
let mut child_end = self.seek_dimension.clone();
|
self.seek_dimension = child_end;
|
||||||
child_end.add_summary(child_summary);
|
self.sum_dimension.add_summary(item_summary, cx);
|
||||||
|
match aggregate {
|
||||||
let comparison = target.cmp(&child_end, cx);
|
SeekAggregate::None => {}
|
||||||
if comparison == Ordering::Greater
|
SeekAggregate::Slice(_) => {
|
||||||
|| (comparison == Ordering::Equal && bias == SeekBias::Right)
|
slice_items.push(item.clone());
|
||||||
{
|
slice_item_summaries.push(item_summary.clone());
|
||||||
self.seek_dimension = child_end;
|
slice_items_summary
|
||||||
self.sum_dimension.add_summary(child_summary);
|
.as_mut()
|
||||||
match aggregate {
|
.unwrap()
|
||||||
SeekAggregate::None => {}
|
.add_summary(item_summary, cx);
|
||||||
SeekAggregate::Slice(slice) => {
|
|
||||||
slice.push_tree(child_trees[index].clone(), cx);
|
|
||||||
}
|
|
||||||
SeekAggregate::Summary(summary) => {
|
|
||||||
summary.add_summary(child_summary);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
SeekAggregate::Summary(summary) => {
|
||||||
self.stack.push(StackEntry {
|
summary.add_summary(item_summary, cx);
|
||||||
tree: subtree,
|
|
||||||
index,
|
|
||||||
seek_dimension: self.seek_dimension.clone(),
|
|
||||||
sum_dimension: self.sum_dimension.clone(),
|
|
||||||
});
|
|
||||||
next_subtree = Some(child_tree);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Node::Leaf {
|
|
||||||
ref items,
|
|
||||||
ref item_summaries,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let mut slice_items = ArrayVec::<[T; 2 * TREE_BASE]>::new();
|
|
||||||
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 (index, (item, item_summary)) in
|
|
||||||
items.iter().zip(item_summaries).enumerate()
|
|
||||||
{
|
|
||||||
let mut child_end = self.seek_dimension.clone();
|
|
||||||
child_end.add_summary(item_summary);
|
|
||||||
|
|
||||||
let comparison = target.cmp(&child_end, cx);
|
|
||||||
if comparison == Ordering::Greater
|
|
||||||
|| (comparison == Ordering::Equal && bias == SeekBias::Right)
|
|
||||||
{
|
|
||||||
self.seek_dimension = child_end;
|
|
||||||
self.sum_dimension.add_summary(item_summary);
|
|
||||||
match aggregate {
|
|
||||||
SeekAggregate::None => {}
|
|
||||||
SeekAggregate::Slice(_) => {
|
|
||||||
slice_items.push(item.clone());
|
|
||||||
slice_items_summary
|
|
||||||
.as_mut()
|
|
||||||
.unwrap()
|
|
||||||
.add_summary(item_summary, cx);
|
|
||||||
slice_item_summaries.push(item_summary.clone());
|
|
||||||
}
|
|
||||||
SeekAggregate::Summary(summary) => {
|
|
||||||
summary.add_summary(item_summary);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
self.stack.push(StackEntry {
|
|
||||||
tree: subtree,
|
|
||||||
index,
|
|
||||||
seek_dimension: self.seek_dimension.clone(),
|
|
||||||
sum_dimension: self.sum_dimension.clone(),
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
entry.index += 1;
|
||||||
|
} else {
|
||||||
if let SeekAggregate::Slice(slice) = aggregate {
|
if let SeekAggregate::Slice(slice) = aggregate {
|
||||||
if !slice_items.is_empty() {
|
|
||||||
slice.push_tree(
|
slice.push_tree(
|
||||||
SumTree(Arc::new(Node::Leaf {
|
SumTree(Arc::new(Node::Leaf {
|
||||||
summary: slice_items_summary.unwrap(),
|
summary: slice_items_summary.unwrap(),
|
||||||
@ -634,47 +528,59 @@ where
|
|||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
break 'outer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(next_subtree) = next_subtree {
|
if let SeekAggregate::Slice(slice) = aggregate {
|
||||||
subtree = next_subtree;
|
if !slice_items.is_empty() {
|
||||||
} else {
|
slice.push_tree(
|
||||||
break;
|
SumTree(Arc::new(Node::Leaf {
|
||||||
|
summary: slice_items_summary.unwrap(),
|
||||||
|
items: slice_items,
|
||||||
|
item_summaries: slice_item_summaries,
|
||||||
|
})),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.stack.pop();
|
||||||
|
ascending = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.at_end = self.stack.is_empty();
|
self.at_end = self.stack.is_empty();
|
||||||
debug_assert!(self.stack.is_empty() || self.stack.last().unwrap().tree.0.is_leaf());
|
debug_assert!(self.stack.is_empty() || self.stack.last().unwrap().tree.0.is_leaf());
|
||||||
if bias == SeekBias::Left {
|
|
||||||
let mut end = self.seek_dimension.clone();
|
let mut end = self.seek_dimension.clone();
|
||||||
|
if bias == Bias::Left {
|
||||||
if let Some(summary) = self.item_summary() {
|
if let Some(summary) = self.item_summary() {
|
||||||
end.add_summary(summary);
|
end.add_summary(summary, cx);
|
||||||
}
|
}
|
||||||
target.cmp(&end, cx) == Ordering::Equal
|
|
||||||
} else {
|
|
||||||
target.cmp(&self.seek_dimension, cx) == Ordering::Equal
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
target.map_or(false, |t| t.cmp(&end, cx) == Ordering::Equal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T, S, U> Iterator for Cursor<'a, T, S, U>
|
impl<'a, T, S, Seek, Sum> Iterator for Cursor<'a, T, Seek, Sum>
|
||||||
where
|
where
|
||||||
T: Item,
|
T: Item<Summary = S>,
|
||||||
S: Dimension<'a, T::Summary>,
|
S: Summary<Context = ()>,
|
||||||
U: Dimension<'a, T::Summary>,
|
Seek: Dimension<'a, T::Summary>,
|
||||||
|
Sum: Dimension<'a, T::Summary>,
|
||||||
{
|
{
|
||||||
type Item = &'a T;
|
type Item = &'a T;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
if !self.did_seek {
|
if !self.did_seek {
|
||||||
self.next();
|
self.next(&());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(item) = self.item() {
|
if let Some(item) = self.item() {
|
||||||
self.next();
|
self.next(&());
|
||||||
Some(item)
|
Some(item)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -693,9 +599,13 @@ where
|
|||||||
T: Item,
|
T: Item,
|
||||||
U: Dimension<'a, T::Summary>,
|
U: Dimension<'a, T::Summary>,
|
||||||
{
|
{
|
||||||
pub fn new(tree: &'a SumTree<T>, filter_node: F) -> Self {
|
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::<(), U>();
|
||||||
cursor.next_internal(&filter_node);
|
cursor.next_internal(&filter_node, cx);
|
||||||
Self {
|
Self {
|
||||||
cursor,
|
cursor,
|
||||||
filter_node,
|
filter_node,
|
||||||
@ -710,22 +620,23 @@ where
|
|||||||
self.cursor.item()
|
self.cursor.item()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next(&mut self) {
|
pub fn next(&mut self, cx: &<T::Summary as Summary>::Context) {
|
||||||
self.cursor.next_internal(&self.filter_node);
|
self.cursor.next_internal(&self.filter_node, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, F, T, U> Iterator for FilterCursor<'a, F, T, U>
|
impl<'a, F, T, S, U> Iterator for FilterCursor<'a, F, T, U>
|
||||||
where
|
where
|
||||||
F: Fn(&T::Summary) -> bool,
|
F: Fn(&T::Summary) -> bool,
|
||||||
T: Item,
|
T: Item<Summary = S>,
|
||||||
|
S: Summary<Context = ()>,
|
||||||
U: Dimension<'a, T::Summary>,
|
U: Dimension<'a, T::Summary>,
|
||||||
{
|
{
|
||||||
type Item = &'a T;
|
type Item = &'a T;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
if let Some(item) = self.item() {
|
if let Some(item) = self.item() {
|
||||||
self.cursor.next_internal(&self.filter_node);
|
self.cursor.next_internal(&self.filter_node, &());
|
||||||
Some(item)
|
Some(item)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -1,20 +1,24 @@
|
|||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::cmp::{self, Ordering};
|
use std::{
|
||||||
use std::ops::{Add, AddAssign};
|
cmp::{self, Ordering},
|
||||||
|
fmt,
|
||||||
|
ops::{Add, AddAssign},
|
||||||
|
slice,
|
||||||
|
};
|
||||||
|
|
||||||
pub type ReplicaId = u16;
|
pub type ReplicaId = u16;
|
||||||
pub type Seq = u32;
|
pub type Seq = u32;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq, Ord, PartialOrd)]
|
#[derive(Clone, Copy, Default, Eq, Hash, PartialEq, Ord, PartialOrd)]
|
||||||
pub struct Local {
|
pub struct Local {
|
||||||
pub replica_id: ReplicaId,
|
pub replica_id: ReplicaId,
|
||||||
pub value: Seq,
|
pub value: Seq,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
#[derive(Clone, Copy, Default, Eq, Hash, PartialEq)]
|
||||||
pub struct Lamport {
|
pub struct Lamport {
|
||||||
pub value: Seq,
|
|
||||||
pub replica_id: ReplicaId,
|
pub replica_id: ReplicaId,
|
||||||
|
pub value: Seq,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Local {
|
impl Local {
|
||||||
@ -54,7 +58,7 @@ impl<'a> AddAssign<&'a Local> for Local {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Eq, PartialEq)]
|
#[derive(Clone, Default, Hash, Eq, PartialEq)]
|
||||||
pub struct Global(SmallVec<[Local; 3]>);
|
pub struct Global(SmallVec<[Local; 3]>);
|
||||||
|
|
||||||
impl Global {
|
impl Global {
|
||||||
@ -81,12 +85,26 @@ impl Global {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn observe_all(&mut self, other: &Self) {
|
pub fn join(&mut self, other: &Self) {
|
||||||
for timestamp in other.0.iter() {
|
for timestamp in other.0.iter() {
|
||||||
self.observe(*timestamp);
|
self.observe(*timestamp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn meet(&mut self, other: &Self) {
|
||||||
|
for timestamp in other.0.iter() {
|
||||||
|
if let Some(entry) = self
|
||||||
|
.0
|
||||||
|
.iter_mut()
|
||||||
|
.find(|t| t.replica_id == timestamp.replica_id)
|
||||||
|
{
|
||||||
|
entry.value = cmp::min(entry.value, timestamp.value);
|
||||||
|
} else {
|
||||||
|
self.0.push(*timestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn observed(&self, timestamp: Local) -> bool {
|
pub fn observed(&self, timestamp: Local) -> bool {
|
||||||
self.get(timestamp.replica_id) >= timestamp.value
|
self.get(timestamp.replica_id) >= timestamp.value
|
||||||
}
|
}
|
||||||
@ -94,6 +112,10 @@ impl Global {
|
|||||||
pub fn changed_since(&self, other: &Self) -> bool {
|
pub fn changed_since(&self, other: &Self) -> bool {
|
||||||
self.0.iter().any(|t| t.value > other.get(t.replica_id))
|
self.0.iter().any(|t| t.value > other.get(t.replica_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn iter(&self) -> slice::Iter<Local> {
|
||||||
|
self.0.iter()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialOrd for Global {
|
impl PartialOrd for Global {
|
||||||
@ -117,6 +139,21 @@ impl PartialOrd for Global {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Ord for Lamport {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
// Use the replica id to break ties between concurrent events.
|
||||||
|
self.value
|
||||||
|
.cmp(&other.value)
|
||||||
|
.then_with(|| self.replica_id.cmp(&other.replica_id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for Lamport {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Lamport {
|
impl Lamport {
|
||||||
pub fn new(replica_id: ReplicaId) -> Self {
|
pub fn new(replica_id: ReplicaId) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -135,3 +172,28 @@ impl Lamport {
|
|||||||
self.value = cmp::max(self.value, timestamp.value) + 1;
|
self.value = cmp::max(self.value, timestamp.value) + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Local {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "Local {{{}: {}}}", self.replica_id, self.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Lamport {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "Lamport {{{}: {}}}", self.replica_id, self.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Global {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "Global {{")?;
|
||||||
|
for (i, element) in self.0.iter().enumerate() {
|
||||||
|
if i > 0 {
|
||||||
|
write!(f, ", ")?;
|
||||||
|
}
|
||||||
|
write!(f, "{}: {}", element.replica_id, element.value)?;
|
||||||
|
}
|
||||||
|
write!(f, "}}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,29 @@
|
|||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
|
||||||
|
pub enum Bias {
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for Bias {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ord for Bias {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
match (self, other) {
|
||||||
|
(Self::Left, Self::Left) => Ordering::Equal,
|
||||||
|
(Self::Left, Self::Right) => Ordering::Less,
|
||||||
|
(Self::Right, Self::Right) => Ordering::Equal,
|
||||||
|
(Self::Right, Self::Left) => Ordering::Greater,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn post_inc(value: &mut usize) -> usize {
|
pub fn post_inc(value: &mut usize) -> usize {
|
||||||
let prev = *value;
|
let prev = *value;
|
||||||
*value += 1;
|
*value += 1;
|
||||||
|
@ -4,7 +4,8 @@ mod ignore;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
editor::{History, Rope},
|
editor::{History, Rope},
|
||||||
sum_tree::{self, Cursor, Edit, SeekBias, SumTree},
|
sum_tree::{self, Cursor, Edit, SumTree},
|
||||||
|
util::Bias,
|
||||||
};
|
};
|
||||||
use ::ignore::gitignore::Gitignore;
|
use ::ignore::gitignore::Gitignore;
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
@ -295,7 +296,7 @@ impl Snapshot {
|
|||||||
}
|
}
|
||||||
let path = path.as_ref();
|
let path = path.as_ref();
|
||||||
let mut cursor = self.entries.cursor::<_, ()>();
|
let mut cursor = self.entries.cursor::<_, ()>();
|
||||||
if cursor.seek(&PathSearch::Exact(path), SeekBias::Left, &()) {
|
if cursor.seek(&PathSearch::Exact(path), Bias::Left, &()) {
|
||||||
let entry = cursor.item().unwrap();
|
let entry = cursor.item().unwrap();
|
||||||
if entry.path.as_ref() == path {
|
if entry.path.as_ref() == path {
|
||||||
return matches!(entry.kind, EntryKind::PendingDir);
|
return matches!(entry.kind, EntryKind::PendingDir);
|
||||||
@ -310,7 +311,7 @@ impl Snapshot {
|
|||||||
|
|
||||||
fn entry_for_path(&self, path: impl AsRef<Path>) -> Option<&Entry> {
|
fn entry_for_path(&self, path: impl AsRef<Path>) -> Option<&Entry> {
|
||||||
let mut cursor = self.entries.cursor::<_, ()>();
|
let mut cursor = self.entries.cursor::<_, ()>();
|
||||||
if cursor.seek(&PathSearch::Exact(path.as_ref()), SeekBias::Left, &()) {
|
if cursor.seek(&PathSearch::Exact(path.as_ref()), Bias::Left, &()) {
|
||||||
cursor.item()
|
cursor.item()
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -367,8 +368,8 @@ impl Snapshot {
|
|||||||
fn remove_path(&mut self, path: &Path) {
|
fn remove_path(&mut self, path: &Path) {
|
||||||
let new_entries = {
|
let new_entries = {
|
||||||
let mut cursor = self.entries.cursor::<_, ()>();
|
let mut cursor = self.entries.cursor::<_, ()>();
|
||||||
let mut new_entries = cursor.slice(&PathSearch::Exact(path), SeekBias::Left, &());
|
let mut new_entries = cursor.slice(&PathSearch::Exact(path), Bias::Left, &());
|
||||||
cursor.seek_forward(&PathSearch::Successor(path), SeekBias::Left, &());
|
cursor.seek_forward(&PathSearch::Successor(path), Bias::Left, &());
|
||||||
new_entries.push_tree(cursor.suffix(&()), &());
|
new_entries.push_tree(cursor.suffix(&()), &());
|
||||||
new_entries
|
new_entries
|
||||||
};
|
};
|
||||||
@ -603,7 +604,7 @@ impl Default for PathKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> sum_tree::Dimension<'a, EntrySummary> for PathKey {
|
impl<'a> sum_tree::Dimension<'a, EntrySummary> for PathKey {
|
||||||
fn add_summary(&mut self, summary: &'a EntrySummary) {
|
fn add_summary(&mut self, summary: &'a EntrySummary, _: &()) {
|
||||||
self.0 = summary.max_path.clone();
|
self.0 = summary.max_path.clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -643,7 +644,7 @@ impl<'a> Default for PathSearch<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a: 'b, 'b> sum_tree::Dimension<'a, EntrySummary> for PathSearch<'b> {
|
impl<'a: 'b, 'b> sum_tree::Dimension<'a, EntrySummary> for PathSearch<'b> {
|
||||||
fn add_summary(&mut self, summary: &'a EntrySummary) {
|
fn add_summary(&mut self, summary: &'a EntrySummary, _: &()) {
|
||||||
*self = Self::Exact(summary.max_path.as_ref());
|
*self = Self::Exact(summary.max_path.as_ref());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -652,7 +653,7 @@ impl<'a: 'b, 'b> sum_tree::Dimension<'a, EntrySummary> for PathSearch<'b> {
|
|||||||
pub struct FileCount(usize);
|
pub struct FileCount(usize);
|
||||||
|
|
||||||
impl<'a> sum_tree::Dimension<'a, EntrySummary> for FileCount {
|
impl<'a> sum_tree::Dimension<'a, EntrySummary> for FileCount {
|
||||||
fn add_summary(&mut self, summary: &'a EntrySummary) {
|
fn add_summary(&mut self, summary: &'a EntrySummary, _: &()) {
|
||||||
self.0 += summary.file_count;
|
self.0 += summary.file_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -661,7 +662,7 @@ impl<'a> sum_tree::Dimension<'a, EntrySummary> for FileCount {
|
|||||||
pub struct VisibleFileCount(usize);
|
pub struct VisibleFileCount(usize);
|
||||||
|
|
||||||
impl<'a> sum_tree::Dimension<'a, EntrySummary> for VisibleFileCount {
|
impl<'a> sum_tree::Dimension<'a, EntrySummary> for VisibleFileCount {
|
||||||
fn add_summary(&mut self, summary: &'a EntrySummary) {
|
fn add_summary(&mut self, summary: &'a EntrySummary, _: &()) {
|
||||||
self.0 += summary.visible_file_count;
|
self.0 += summary.visible_file_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1296,13 +1297,13 @@ pub enum FileIter<'a> {
|
|||||||
impl<'a> FileIter<'a> {
|
impl<'a> FileIter<'a> {
|
||||||
fn all(snapshot: &'a Snapshot, start: usize) -> Self {
|
fn all(snapshot: &'a Snapshot, start: usize) -> Self {
|
||||||
let mut cursor = snapshot.entries.cursor();
|
let mut cursor = snapshot.entries.cursor();
|
||||||
cursor.seek(&FileCount(start), SeekBias::Right, &());
|
cursor.seek(&FileCount(start), Bias::Right, &());
|
||||||
Self::All(cursor)
|
Self::All(cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visible(snapshot: &'a Snapshot, start: usize) -> Self {
|
fn visible(snapshot: &'a Snapshot, start: usize) -> Self {
|
||||||
let mut cursor = snapshot.entries.cursor();
|
let mut cursor = snapshot.entries.cursor();
|
||||||
cursor.seek(&VisibleFileCount(start), SeekBias::Right, &());
|
cursor.seek(&VisibleFileCount(start), Bias::Right, &());
|
||||||
Self::Visible(cursor)
|
Self::Visible(cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1310,11 +1311,11 @@ impl<'a> FileIter<'a> {
|
|||||||
match self {
|
match self {
|
||||||
Self::All(cursor) => {
|
Self::All(cursor) => {
|
||||||
let ix = *cursor.start();
|
let ix = *cursor.start();
|
||||||
cursor.seek_forward(&FileCount(ix.0 + 1), SeekBias::Right, &());
|
cursor.seek_forward(&FileCount(ix.0 + 1), Bias::Right, &());
|
||||||
}
|
}
|
||||||
Self::Visible(cursor) => {
|
Self::Visible(cursor) => {
|
||||||
let ix = *cursor.start();
|
let ix = *cursor.start();
|
||||||
cursor.seek_forward(&VisibleFileCount(ix.0 + 1), SeekBias::Right, &());
|
cursor.seek_forward(&VisibleFileCount(ix.0 + 1), Bias::Right, &());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1348,7 +1349,7 @@ struct ChildEntriesIter<'a> {
|
|||||||
impl<'a> ChildEntriesIter<'a> {
|
impl<'a> ChildEntriesIter<'a> {
|
||||||
fn new(parent_path: &'a Path, snapshot: &'a Snapshot) -> Self {
|
fn new(parent_path: &'a Path, snapshot: &'a Snapshot) -> Self {
|
||||||
let mut cursor = snapshot.entries.cursor();
|
let mut cursor = snapshot.entries.cursor();
|
||||||
cursor.seek(&PathSearch::Exact(parent_path), SeekBias::Right, &());
|
cursor.seek(&PathSearch::Exact(parent_path), Bias::Right, &());
|
||||||
Self {
|
Self {
|
||||||
parent_path,
|
parent_path,
|
||||||
cursor,
|
cursor,
|
||||||
@ -1363,7 +1364,7 @@ impl<'a> Iterator for ChildEntriesIter<'a> {
|
|||||||
if let Some(item) = self.cursor.item() {
|
if let Some(item) = self.cursor.item() {
|
||||||
if item.path().starts_with(self.parent_path) {
|
if item.path().starts_with(self.parent_path) {
|
||||||
self.cursor
|
self.cursor
|
||||||
.seek_forward(&PathSearch::Successor(item.path()), SeekBias::Left, &());
|
.seek_forward(&PathSearch::Successor(item.path()), Bias::Left, &());
|
||||||
Some(item)
|
Some(item)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
Loading…
Reference in New Issue
Block a user