Introduce FullOffset type
Co-Authored-By: Nathan Sobo <nathan@zed.dev> Co-Authored-By: Antonio Scandurra <me@as-cii.com>
This commit is contained in:
parent
bc076c1cc1
commit
0c10d6c82d
2 changed files with 154 additions and 98 deletions
|
@ -1,3 +1,5 @@
|
|||
use crate::FullOffset;
|
||||
|
||||
use super::{Buffer, Content, FromAnchor, Point, ToOffset};
|
||||
use anyhow::Result;
|
||||
use std::{cmp::Ordering, ops::Range};
|
||||
|
@ -5,7 +7,7 @@ use sum_tree::{Bias, SumTree};
|
|||
|
||||
#[derive(Clone, Eq, PartialEq, Debug, Hash)]
|
||||
pub struct Anchor {
|
||||
pub full_offset: usize,
|
||||
pub full_offset: FullOffset,
|
||||
pub bias: Bias,
|
||||
pub version: clock::Global,
|
||||
}
|
||||
|
@ -13,7 +15,7 @@ pub struct Anchor {
|
|||
#[derive(Clone)]
|
||||
pub struct AnchorMap<T> {
|
||||
pub(crate) version: clock::Global,
|
||||
pub(crate) entries: Vec<((usize, Bias), T)>,
|
||||
pub(crate) entries: Vec<((FullOffset, Bias), T)>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -22,7 +24,7 @@ pub struct AnchorSet(pub(crate) AnchorMap<()>);
|
|||
#[derive(Clone)]
|
||||
pub struct AnchorRangeMap<T> {
|
||||
pub(crate) version: clock::Global,
|
||||
pub(crate) entries: Vec<(Range<(usize, Bias)>, T)>,
|
||||
pub(crate) entries: Vec<(Range<(FullOffset, Bias)>, T)>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -44,23 +46,23 @@ pub(crate) struct AnchorRangeMultimapEntry<T> {
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct FullOffsetRange {
|
||||
pub(crate) start: usize,
|
||||
pub(crate) end: usize,
|
||||
pub(crate) start: FullOffset,
|
||||
pub(crate) end: FullOffset,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct AnchorRangeMultimapSummary {
|
||||
start: usize,
|
||||
end: usize,
|
||||
min_start: usize,
|
||||
max_end: usize,
|
||||
start: FullOffset,
|
||||
end: FullOffset,
|
||||
min_start: FullOffset,
|
||||
max_end: FullOffset,
|
||||
count: usize,
|
||||
}
|
||||
|
||||
impl Anchor {
|
||||
pub fn min() -> Self {
|
||||
Self {
|
||||
full_offset: 0,
|
||||
full_offset: FullOffset(0),
|
||||
bias: Bias::Left,
|
||||
version: Default::default(),
|
||||
}
|
||||
|
@ -68,7 +70,7 @@ impl Anchor {
|
|||
|
||||
pub fn max() -> Self {
|
||||
Self {
|
||||
full_offset: usize::MAX,
|
||||
full_offset: FullOffset::MAX,
|
||||
bias: Bias::Right,
|
||||
version: Default::default(),
|
||||
}
|
||||
|
@ -192,7 +194,7 @@ impl<T: Clone> AnchorRangeMultimap<T> {
|
|||
{
|
||||
let content = content.clone();
|
||||
let mut endpoint = Anchor {
|
||||
full_offset: 0,
|
||||
full_offset: FullOffset(0),
|
||||
bias: Bias::Right,
|
||||
version: self.version.clone(),
|
||||
};
|
||||
|
@ -219,7 +221,7 @@ impl<T: Clone> AnchorRangeMultimap<T> {
|
|||
|
||||
std::iter::from_fn({
|
||||
let mut endpoint = Anchor {
|
||||
full_offset: 0,
|
||||
full_offset: FullOffset(0),
|
||||
bias: Bias::Left,
|
||||
version: self.version.clone(),
|
||||
};
|
||||
|
@ -260,10 +262,10 @@ impl<T: Clone> sum_tree::Item for AnchorRangeMultimapEntry<T> {
|
|||
impl Default for AnchorRangeMultimapSummary {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
start: 0,
|
||||
end: usize::MAX,
|
||||
min_start: usize::MAX,
|
||||
max_end: 0,
|
||||
start: FullOffset(0),
|
||||
end: FullOffset::MAX,
|
||||
min_start: FullOffset::MAX,
|
||||
max_end: FullOffset(0),
|
||||
count: 0,
|
||||
}
|
||||
}
|
||||
|
@ -294,8 +296,8 @@ impl sum_tree::Summary for AnchorRangeMultimapSummary {
|
|||
impl Default for FullOffsetRange {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
start: 0,
|
||||
end: usize::MAX,
|
||||
start: FullOffset(0),
|
||||
end: FullOffset::MAX,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ use std::{
|
|||
cmp::{self, Reverse},
|
||||
convert::{TryFrom, TryInto},
|
||||
iter::Iterator,
|
||||
ops::Range,
|
||||
ops::{self, Range},
|
||||
str,
|
||||
sync::Arc,
|
||||
time::{Duration, Instant},
|
||||
|
@ -84,7 +84,7 @@ pub struct Transaction {
|
|||
start: clock::Global,
|
||||
end: clock::Global,
|
||||
edits: Vec<clock::Local>,
|
||||
ranges: Vec<Range<usize>>,
|
||||
ranges: Vec<Range<FullOffset>>,
|
||||
selections_before: HashMap<SelectionSetId, Arc<[Selection]>>,
|
||||
selections_after: HashMap<SelectionSetId, Arc<[Selection]>>,
|
||||
first_edit_at: Instant,
|
||||
|
@ -101,7 +101,7 @@ impl Transaction {
|
|||
self.end.observe(edit.timestamp.local());
|
||||
|
||||
let mut other_ranges = edit.ranges.iter().peekable();
|
||||
let mut new_ranges: Vec<Range<usize>> = Vec::new();
|
||||
let mut new_ranges = Vec::new();
|
||||
let insertion_len = edit.new_text.as_ref().map_or(0, |t| t.len());
|
||||
let mut delta = 0;
|
||||
|
||||
|
@ -429,7 +429,7 @@ pub enum Operation {
|
|||
pub struct EditOperation {
|
||||
timestamp: InsertionTimestamp,
|
||||
version: clock::Global,
|
||||
ranges: Vec<Range<usize>>,
|
||||
ranges: Vec<Range<FullOffset>>,
|
||||
new_text: Option<String>,
|
||||
}
|
||||
|
||||
|
@ -437,7 +437,7 @@ pub struct EditOperation {
|
|||
pub struct UndoOperation {
|
||||
id: clock::Local,
|
||||
counts: HashMap<clock::Local, u32>,
|
||||
ranges: Vec<Range<usize>>,
|
||||
ranges: Vec<Range<FullOffset>>,
|
||||
version: clock::Global,
|
||||
}
|
||||
|
||||
|
@ -735,7 +735,7 @@ impl Buffer {
|
|||
fragment_start = old_fragments.start().visible;
|
||||
}
|
||||
|
||||
let full_range_start = range.start + old_fragments.start().deleted;
|
||||
let full_range_start = FullOffset(range.start + old_fragments.start().deleted);
|
||||
|
||||
// Preserve any portion of the current fragment that precedes this range.
|
||||
if fragment_start < range.start {
|
||||
|
@ -783,7 +783,7 @@ impl Buffer {
|
|||
}
|
||||
}
|
||||
|
||||
let full_range_end = range.end + old_fragments.start().deleted;
|
||||
let full_range_end = FullOffset(range.end + old_fragments.start().deleted);
|
||||
edit.ranges.push(full_range_start..full_range_end);
|
||||
}
|
||||
|
||||
|
@ -898,7 +898,7 @@ impl Buffer {
|
|||
fn apply_remote_edit(
|
||||
&mut self,
|
||||
version: &clock::Global,
|
||||
ranges: &[Range<usize>],
|
||||
ranges: &[Range<FullOffset>],
|
||||
new_text: Option<&str>,
|
||||
timestamp: InsertionTimestamp,
|
||||
) {
|
||||
|
@ -909,24 +909,27 @@ impl Buffer {
|
|||
let cx = Some(version.clone());
|
||||
let mut new_ropes =
|
||||
RopeBuilder::new(self.visible_text.cursor(0), self.deleted_text.cursor(0));
|
||||
let mut old_fragments = self.fragments.cursor::<VersionedOffset>();
|
||||
let mut new_fragments =
|
||||
old_fragments.slice(&VersionedOffset::Offset(ranges[0].start), Bias::Left, &cx);
|
||||
let mut old_fragments = self.fragments.cursor::<VersionedFullOffset>();
|
||||
let mut new_fragments = old_fragments.slice(
|
||||
&VersionedFullOffset::Offset(ranges[0].start),
|
||||
Bias::Left,
|
||||
&cx,
|
||||
);
|
||||
new_ropes.push_tree(new_fragments.summary().text);
|
||||
|
||||
let mut fragment_start = old_fragments.start().offset();
|
||||
let mut fragment_start = old_fragments.start().full_offset();
|
||||
for range in ranges {
|
||||
let fragment_end = old_fragments.end(&cx).offset();
|
||||
let fragment_end = old_fragments.end(&cx).full_offset();
|
||||
|
||||
// If the current fragment ends before this range, then jump ahead to the first fragment
|
||||
// that extends past the start of this range, reusing any intervening fragments.
|
||||
if fragment_end < range.start {
|
||||
// If the current fragment has been partially consumed, then consume the rest of it
|
||||
// and advance to the next fragment before slicing.
|
||||
if fragment_start > old_fragments.start().offset() {
|
||||
if fragment_start > old_fragments.start().full_offset() {
|
||||
if fragment_end > fragment_start {
|
||||
let mut suffix = old_fragments.item().unwrap().clone();
|
||||
suffix.len = fragment_end - fragment_start;
|
||||
suffix.len = fragment_end.0 - fragment_start.0;
|
||||
new_ropes.push_fragment(&suffix, suffix.visible);
|
||||
new_fragments.push(suffix, &None);
|
||||
}
|
||||
|
@ -934,21 +937,21 @@ impl Buffer {
|
|||
}
|
||||
|
||||
let slice =
|
||||
old_fragments.slice(&VersionedOffset::Offset(range.start), Bias::Left, &cx);
|
||||
old_fragments.slice(&VersionedFullOffset::Offset(range.start), Bias::Left, &cx);
|
||||
new_ropes.push_tree(slice.summary().text);
|
||||
new_fragments.push_tree(slice, &None);
|
||||
fragment_start = old_fragments.start().offset();
|
||||
fragment_start = old_fragments.start().full_offset();
|
||||
}
|
||||
|
||||
// If we are at the end of a non-concurrent fragment, advance to the next one.
|
||||
let fragment_end = old_fragments.end(&cx).offset();
|
||||
let fragment_end = old_fragments.end(&cx).full_offset();
|
||||
if fragment_end == range.start && fragment_end > fragment_start {
|
||||
let mut fragment = old_fragments.item().unwrap().clone();
|
||||
fragment.len = fragment_end - fragment_start;
|
||||
fragment.len = fragment_end.0 - fragment_start.0;
|
||||
new_ropes.push_fragment(&fragment, fragment.visible);
|
||||
new_fragments.push(fragment, &None);
|
||||
old_fragments.next(&cx);
|
||||
fragment_start = old_fragments.start().offset();
|
||||
fragment_start = old_fragments.start().full_offset();
|
||||
}
|
||||
|
||||
// Skip over insertions that are concurrent to this edit, but have a lower lamport
|
||||
|
@ -970,7 +973,7 @@ impl Buffer {
|
|||
// Preserve any portion of the current fragment that precedes this range.
|
||||
if fragment_start < range.start {
|
||||
let mut prefix = old_fragments.item().unwrap().clone();
|
||||
prefix.len = range.start - fragment_start;
|
||||
prefix.len = range.start.0 - fragment_start.0;
|
||||
fragment_start = range.start;
|
||||
new_ropes.push_fragment(&prefix, prefix.visible);
|
||||
new_fragments.push(prefix, &None);
|
||||
|
@ -995,11 +998,11 @@ impl Buffer {
|
|||
// portions as deleted.
|
||||
while fragment_start < range.end {
|
||||
let fragment = old_fragments.item().unwrap();
|
||||
let fragment_end = old_fragments.end(&cx).offset();
|
||||
let fragment_end = old_fragments.end(&cx).full_offset();
|
||||
let mut intersection = fragment.clone();
|
||||
let intersection_end = cmp::min(range.end, fragment_end);
|
||||
if fragment.was_visible(version, &self.undo_map) {
|
||||
intersection.len = intersection_end - fragment_start;
|
||||
intersection.len = intersection_end.0 - fragment_start.0;
|
||||
intersection.deletions.insert(timestamp.local());
|
||||
intersection.visible = false;
|
||||
}
|
||||
|
@ -1016,11 +1019,11 @@ impl Buffer {
|
|||
|
||||
// If the current fragment has been partially consumed, then consume the rest of it
|
||||
// and advance to the next fragment before slicing.
|
||||
if fragment_start > old_fragments.start().offset() {
|
||||
let fragment_end = old_fragments.end(&cx).offset();
|
||||
if fragment_start > old_fragments.start().full_offset() {
|
||||
let fragment_end = old_fragments.end(&cx).full_offset();
|
||||
if fragment_end > fragment_start {
|
||||
let mut suffix = old_fragments.item().unwrap().clone();
|
||||
suffix.len = fragment_end - fragment_start;
|
||||
suffix.len = fragment_end.0 - fragment_start.0;
|
||||
new_ropes.push_fragment(&suffix, suffix.visible);
|
||||
new_fragments.push(suffix, &None);
|
||||
}
|
||||
|
@ -1049,9 +1052,9 @@ impl Buffer {
|
|||
}
|
||||
let cx = Some(cx);
|
||||
|
||||
let mut old_fragments = self.fragments.cursor::<VersionedOffset>();
|
||||
let mut old_fragments = self.fragments.cursor::<VersionedFullOffset>();
|
||||
let mut new_fragments = old_fragments.slice(
|
||||
&VersionedOffset::Offset(undo.ranges[0].start),
|
||||
&VersionedFullOffset::Offset(undo.ranges[0].start),
|
||||
Bias::Right,
|
||||
&cx,
|
||||
);
|
||||
|
@ -1060,11 +1063,14 @@ impl Buffer {
|
|||
new_ropes.push_tree(new_fragments.summary().text);
|
||||
|
||||
for range in &undo.ranges {
|
||||
let mut end_offset = old_fragments.end(&cx).offset();
|
||||
let mut end_offset = old_fragments.end(&cx).full_offset();
|
||||
|
||||
if end_offset < range.start {
|
||||
let preceding_fragments =
|
||||
old_fragments.slice(&VersionedOffset::Offset(range.start), Bias::Right, &cx);
|
||||
let preceding_fragments = old_fragments.slice(
|
||||
&VersionedFullOffset::Offset(range.start),
|
||||
Bias::Right,
|
||||
&cx,
|
||||
);
|
||||
new_ropes.push_tree(preceding_fragments.summary().text);
|
||||
new_fragments.push_tree(preceding_fragments, &None);
|
||||
}
|
||||
|
@ -1084,16 +1090,16 @@ impl Buffer {
|
|||
new_fragments.push(fragment, &None);
|
||||
|
||||
old_fragments.next(&cx);
|
||||
if end_offset == old_fragments.end(&cx).offset() {
|
||||
if end_offset == old_fragments.end(&cx).full_offset() {
|
||||
let unseen_fragments = old_fragments.slice(
|
||||
&VersionedOffset::Offset(end_offset),
|
||||
&VersionedFullOffset::Offset(end_offset),
|
||||
Bias::Right,
|
||||
&cx,
|
||||
);
|
||||
new_ropes.push_tree(unseen_fragments.summary().text);
|
||||
new_fragments.push_tree(unseen_fragments, &None);
|
||||
}
|
||||
end_offset = old_fragments.end(&cx).offset();
|
||||
end_offset = old_fragments.end(&cx).full_offset();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
@ -1698,14 +1704,14 @@ impl<'a> Content<'a> {
|
|||
|
||||
fn summary_for_anchor(&self, anchor: &Anchor) -> TextSummary {
|
||||
let cx = Some(anchor.version.clone());
|
||||
let mut cursor = self.fragments.cursor::<(VersionedOffset, usize)>();
|
||||
let mut cursor = self.fragments.cursor::<(VersionedFullOffset, usize)>();
|
||||
cursor.seek(
|
||||
&VersionedOffset::Offset(anchor.full_offset),
|
||||
&VersionedFullOffset::Offset(anchor.full_offset),
|
||||
anchor.bias,
|
||||
&cx,
|
||||
);
|
||||
let overshoot = if cursor.item().map_or(false, |fragment| fragment.visible) {
|
||||
anchor.full_offset - cursor.start().0.offset()
|
||||
anchor.full_offset - cursor.start().0.full_offset()
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
@ -1723,11 +1729,11 @@ impl<'a> Content<'a> {
|
|||
let cx = Some(map.version.clone());
|
||||
let mut summary = TextSummary::default();
|
||||
let mut rope_cursor = self.visible_text.cursor(0);
|
||||
let mut cursor = self.fragments.cursor::<(VersionedOffset, usize)>();
|
||||
let mut cursor = self.fragments.cursor::<(VersionedFullOffset, usize)>();
|
||||
map.entries.iter().map(move |((offset, bias), value)| {
|
||||
cursor.seek_forward(&VersionedOffset::Offset(*offset), *bias, &cx);
|
||||
cursor.seek_forward(&VersionedFullOffset::Offset(*offset), *bias, &cx);
|
||||
let overshoot = if cursor.item().map_or(false, |fragment| fragment.visible) {
|
||||
offset - cursor.start().0.offset()
|
||||
*offset - cursor.start().0.full_offset()
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
@ -1743,25 +1749,29 @@ impl<'a> Content<'a> {
|
|||
let cx = Some(map.version.clone());
|
||||
let mut summary = TextSummary::default();
|
||||
let mut rope_cursor = self.visible_text.cursor(0);
|
||||
let mut cursor = self.fragments.cursor::<(VersionedOffset, usize)>();
|
||||
let mut cursor = self.fragments.cursor::<(VersionedFullOffset, usize)>();
|
||||
map.entries.iter().map(move |(range, value)| {
|
||||
let Range {
|
||||
start: (start_offset, start_bias),
|
||||
end: (end_offset, end_bias),
|
||||
} = range;
|
||||
|
||||
cursor.seek_forward(&VersionedOffset::Offset(*start_offset), *start_bias, &cx);
|
||||
cursor.seek_forward(
|
||||
&VersionedFullOffset::Offset(*start_offset),
|
||||
*start_bias,
|
||||
&cx,
|
||||
);
|
||||
let overshoot = if cursor.item().map_or(false, |fragment| fragment.visible) {
|
||||
start_offset - cursor.start().0.offset()
|
||||
*start_offset - cursor.start().0.full_offset()
|
||||
} else {
|
||||
0
|
||||
};
|
||||
summary += rope_cursor.summary(cursor.start().1 + overshoot);
|
||||
let start_summary = summary.clone();
|
||||
|
||||
cursor.seek_forward(&VersionedOffset::Offset(*end_offset), *end_bias, &cx);
|
||||
cursor.seek_forward(&VersionedFullOffset::Offset(*end_offset), *end_bias, &cx);
|
||||
let overshoot = if cursor.item().map_or(false, |fragment| fragment.visible) {
|
||||
end_offset - cursor.start().0.offset()
|
||||
*end_offset - cursor.start().0.full_offset()
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
@ -1790,7 +1800,7 @@ impl<'a> Content<'a> {
|
|||
.into_iter()
|
||||
.map(|((offset, bias), value)| {
|
||||
cursor.seek_forward(&offset, bias, &None);
|
||||
let full_offset = cursor.start().deleted + offset;
|
||||
let full_offset = FullOffset(cursor.start().deleted + offset);
|
||||
((full_offset, bias), value)
|
||||
})
|
||||
.collect();
|
||||
|
@ -1812,9 +1822,9 @@ impl<'a> Content<'a> {
|
|||
end: (end_offset, end_bias),
|
||||
} = range;
|
||||
cursor.seek_forward(&start_offset, start_bias, &None);
|
||||
let full_start_offset = cursor.start().deleted + start_offset;
|
||||
let full_start_offset = FullOffset(cursor.start().deleted + start_offset);
|
||||
cursor.seek_forward(&end_offset, end_bias, &None);
|
||||
let full_end_offset = cursor.start().deleted + end_offset;
|
||||
let full_end_offset = FullOffset(cursor.start().deleted + end_offset);
|
||||
(
|
||||
(full_start_offset, start_bias)..(full_end_offset, end_bias),
|
||||
value,
|
||||
|
@ -1869,23 +1879,23 @@ impl<'a> Content<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn full_offset_for_anchor(&self, anchor: &Anchor) -> usize {
|
||||
fn full_offset_for_anchor(&self, anchor: &Anchor) -> FullOffset {
|
||||
let cx = Some(anchor.version.clone());
|
||||
let mut cursor = self
|
||||
.fragments
|
||||
.cursor::<(VersionedOffset, FragmentTextSummary)>();
|
||||
.cursor::<(VersionedFullOffset, FragmentTextSummary)>();
|
||||
cursor.seek(
|
||||
&VersionedOffset::Offset(anchor.full_offset),
|
||||
&VersionedFullOffset::Offset(anchor.full_offset),
|
||||
anchor.bias,
|
||||
&cx,
|
||||
);
|
||||
let overshoot = if cursor.item().is_some() {
|
||||
anchor.full_offset - cursor.start().0.offset()
|
||||
anchor.full_offset - cursor.start().0.full_offset()
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let summary = cursor.start().1;
|
||||
summary.visible + summary.deleted + overshoot
|
||||
FullOffset(summary.visible + summary.deleted + overshoot)
|
||||
}
|
||||
|
||||
fn point_for_offset(&self, offset: usize) -> Result<Point> {
|
||||
|
@ -2118,12 +2128,56 @@ impl Default for FragmentSummary {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct FullOffset(usize);
|
||||
|
||||
impl FullOffset {
|
||||
const MAX: Self = FullOffset(usize::MAX);
|
||||
|
||||
fn to_proto(self) -> u64 {
|
||||
self.0 as u64
|
||||
}
|
||||
|
||||
fn from_proto(value: u64) -> Self {
|
||||
Self(value as usize)
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::AddAssign<usize> for FullOffset {
|
||||
fn add_assign(&mut self, rhs: usize) {
|
||||
self.0 += rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Add<usize> for FullOffset {
|
||||
type Output = Self;
|
||||
|
||||
fn add(mut self, rhs: usize) -> Self::Output {
|
||||
self += rhs;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Sub for FullOffset {
|
||||
type Output = usize;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
self.0 - rhs.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> sum_tree::Dimension<'a, FragmentSummary> for usize {
|
||||
fn add_summary(&mut self, summary: &FragmentSummary, _: &Option<clock::Global>) {
|
||||
*self += summary.text.visible;
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> sum_tree::Dimension<'a, FragmentSummary> for FullOffset {
|
||||
fn add_summary(&mut self, summary: &FragmentSummary, _: &Option<clock::Global>) {
|
||||
self.0 += summary.text.visible + summary.text.deleted;
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> sum_tree::SeekTarget<'a, FragmentSummary, FragmentTextSummary> for usize {
|
||||
fn cmp(
|
||||
&self,
|
||||
|
@ -2135,28 +2189,28 @@ impl<'a> sum_tree::SeekTarget<'a, FragmentSummary, FragmentTextSummary> for usiz
|
|||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
enum VersionedOffset {
|
||||
Offset(usize),
|
||||
InvalidVersion,
|
||||
enum VersionedFullOffset {
|
||||
Offset(FullOffset),
|
||||
Invalid,
|
||||
}
|
||||
|
||||
impl VersionedOffset {
|
||||
fn offset(&self) -> usize {
|
||||
if let Self::Offset(offset) = self {
|
||||
*offset
|
||||
impl VersionedFullOffset {
|
||||
fn full_offset(&self) -> FullOffset {
|
||||
if let Self::Offset(position) = self {
|
||||
*position
|
||||
} else {
|
||||
panic!("invalid version")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for VersionedOffset {
|
||||
impl Default for VersionedFullOffset {
|
||||
fn default() -> Self {
|
||||
Self::Offset(0)
|
||||
Self::Offset(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> sum_tree::Dimension<'a, FragmentSummary> for VersionedOffset {
|
||||
impl<'a> sum_tree::Dimension<'a, FragmentSummary> for VersionedFullOffset {
|
||||
fn add_summary(&mut self, summary: &'a FragmentSummary, cx: &Option<clock::Global>) {
|
||||
if let Self::Offset(offset) = self {
|
||||
let version = cx.as_ref().unwrap();
|
||||
|
@ -2167,18 +2221,18 @@ impl<'a> sum_tree::Dimension<'a, FragmentSummary> for VersionedOffset {
|
|||
.iter()
|
||||
.all(|t| !version.observed(*t))
|
||||
{
|
||||
*self = Self::InvalidVersion;
|
||||
*self = Self::Invalid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> sum_tree::SeekTarget<'a, FragmentSummary, Self> for VersionedOffset {
|
||||
fn cmp(&self, other: &Self, _: &Option<clock::Global>) -> cmp::Ordering {
|
||||
match (self, other) {
|
||||
impl<'a> sum_tree::SeekTarget<'a, FragmentSummary, Self> for VersionedFullOffset {
|
||||
fn cmp(&self, cursor_position: &Self, _: &Option<clock::Global>) -> cmp::Ordering {
|
||||
match (self, cursor_position) {
|
||||
(Self::Offset(a), Self::Offset(b)) => Ord::cmp(a, b),
|
||||
(Self::Offset(_), Self::InvalidVersion) => cmp::Ordering::Less,
|
||||
(Self::InvalidVersion, _) => unreachable!(),
|
||||
(Self::Offset(_), Self::Invalid) => cmp::Ordering::Less,
|
||||
(Self::Invalid, _) => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2229,8 +2283,8 @@ impl<'a> Into<proto::Operation> for &'a Operation {
|
|||
.ranges
|
||||
.iter()
|
||||
.map(|r| proto::Range {
|
||||
start: r.start as u64,
|
||||
end: r.end as u64,
|
||||
start: r.start.to_proto(),
|
||||
end: r.end.to_proto(),
|
||||
})
|
||||
.collect(),
|
||||
counts: undo
|
||||
|
@ -2281,8 +2335,8 @@ impl<'a> Into<proto::operation::Edit> for &'a EditOperation {
|
|||
.ranges
|
||||
.iter()
|
||||
.map(|range| proto::Range {
|
||||
start: range.start as u64,
|
||||
end: range.end as u64,
|
||||
start: range.start.to_proto(),
|
||||
end: range.end.to_proto(),
|
||||
})
|
||||
.collect();
|
||||
proto::operation::Edit {
|
||||
|
@ -2300,7 +2354,7 @@ impl<'a> Into<proto::Anchor> for &'a Anchor {
|
|||
fn into(self) -> proto::Anchor {
|
||||
proto::Anchor {
|
||||
version: (&self.version).into(),
|
||||
offset: self.full_offset as u64,
|
||||
offset: self.full_offset.to_proto(),
|
||||
bias: match self.bias {
|
||||
Bias::Left => proto::anchor::Bias::Left as i32,
|
||||
Bias::Right => proto::anchor::Bias::Right as i32,
|
||||
|
@ -2356,7 +2410,7 @@ impl TryFrom<proto::Operation> for Operation {
|
|||
ranges: undo
|
||||
.ranges
|
||||
.into_iter()
|
||||
.map(|r| r.start as usize..r.end as usize)
|
||||
.map(|r| FullOffset::from_proto(r.start)..FullOffset::from_proto(r.end))
|
||||
.collect(),
|
||||
version: undo.version.into(),
|
||||
},
|
||||
|
@ -2406,7 +2460,7 @@ impl From<proto::operation::Edit> for EditOperation {
|
|||
let ranges = edit
|
||||
.ranges
|
||||
.into_iter()
|
||||
.map(|range| range.start as usize..range.end as usize)
|
||||
.map(|range| FullOffset::from_proto(range.start)..FullOffset::from_proto(range.end))
|
||||
.collect();
|
||||
EditOperation {
|
||||
timestamp: InsertionTimestamp {
|
||||
|
@ -2434,7 +2488,7 @@ impl TryFrom<proto::Anchor> for Anchor {
|
|||
}
|
||||
|
||||
Ok(Self {
|
||||
full_offset: message.offset as usize,
|
||||
full_offset: FullOffset::from_proto(message.offset),
|
||||
bias: if message.bias == proto::anchor::Bias::Left as i32 {
|
||||
Bias::Left
|
||||
} else if message.bias == proto::anchor::Bias::Right as i32 {
|
||||
|
@ -2470,12 +2524,12 @@ impl TryFrom<proto::Selection> for Selection {
|
|||
pub trait ToOffset {
|
||||
fn to_offset<'a>(&self, content: impl Into<Content<'a>>) -> usize;
|
||||
|
||||
fn to_full_offset<'a>(&self, content: impl Into<Content<'a>>, bias: Bias) -> usize {
|
||||
fn to_full_offset<'a>(&self, content: impl Into<Content<'a>>, bias: Bias) -> FullOffset {
|
||||
let content = content.into();
|
||||
let offset = self.to_offset(&content);
|
||||
let mut cursor = content.fragments.cursor::<FragmentTextSummary>();
|
||||
cursor.seek(&offset, bias, &None);
|
||||
offset + cursor.start().deleted
|
||||
FullOffset(offset + cursor.start().deleted)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue