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:
Max Brunsfeld 2021-10-27 11:02:12 -07:00 committed by Nathan Sobo
parent bc076c1cc1
commit 0c10d6c82d
2 changed files with 154 additions and 98 deletions

View file

@ -1,3 +1,5 @@
use crate::FullOffset;
use super::{Buffer, Content, FromAnchor, Point, ToOffset}; use super::{Buffer, Content, FromAnchor, Point, ToOffset};
use anyhow::Result; use anyhow::Result;
use std::{cmp::Ordering, ops::Range}; use std::{cmp::Ordering, ops::Range};
@ -5,7 +7,7 @@ use sum_tree::{Bias, SumTree};
#[derive(Clone, Eq, PartialEq, Debug, Hash)] #[derive(Clone, Eq, PartialEq, Debug, Hash)]
pub struct Anchor { pub struct Anchor {
pub full_offset: usize, pub full_offset: FullOffset,
pub bias: Bias, pub bias: Bias,
pub version: clock::Global, pub version: clock::Global,
} }
@ -13,7 +15,7 @@ pub struct Anchor {
#[derive(Clone)] #[derive(Clone)]
pub struct AnchorMap<T> { pub struct AnchorMap<T> {
pub(crate) version: clock::Global, pub(crate) version: clock::Global,
pub(crate) entries: Vec<((usize, Bias), T)>, pub(crate) entries: Vec<((FullOffset, Bias), T)>,
} }
#[derive(Clone)] #[derive(Clone)]
@ -22,7 +24,7 @@ pub struct AnchorSet(pub(crate) AnchorMap<()>);
#[derive(Clone)] #[derive(Clone)]
pub struct AnchorRangeMap<T> { pub struct AnchorRangeMap<T> {
pub(crate) version: clock::Global, pub(crate) version: clock::Global,
pub(crate) entries: Vec<(Range<(usize, Bias)>, T)>, pub(crate) entries: Vec<(Range<(FullOffset, Bias)>, T)>,
} }
#[derive(Clone)] #[derive(Clone)]
@ -44,23 +46,23 @@ pub(crate) struct AnchorRangeMultimapEntry<T> {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub(crate) struct FullOffsetRange { pub(crate) struct FullOffsetRange {
pub(crate) start: usize, pub(crate) start: FullOffset,
pub(crate) end: usize, pub(crate) end: FullOffset,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub(crate) struct AnchorRangeMultimapSummary { pub(crate) struct AnchorRangeMultimapSummary {
start: usize, start: FullOffset,
end: usize, end: FullOffset,
min_start: usize, min_start: FullOffset,
max_end: usize, max_end: FullOffset,
count: usize, count: usize,
} }
impl Anchor { impl Anchor {
pub fn min() -> Self { pub fn min() -> Self {
Self { Self {
full_offset: 0, full_offset: FullOffset(0),
bias: Bias::Left, bias: Bias::Left,
version: Default::default(), version: Default::default(),
} }
@ -68,7 +70,7 @@ impl Anchor {
pub fn max() -> Self { pub fn max() -> Self {
Self { Self {
full_offset: usize::MAX, full_offset: FullOffset::MAX,
bias: Bias::Right, bias: Bias::Right,
version: Default::default(), version: Default::default(),
} }
@ -192,7 +194,7 @@ impl<T: Clone> AnchorRangeMultimap<T> {
{ {
let content = content.clone(); let content = content.clone();
let mut endpoint = Anchor { let mut endpoint = Anchor {
full_offset: 0, full_offset: FullOffset(0),
bias: Bias::Right, bias: Bias::Right,
version: self.version.clone(), version: self.version.clone(),
}; };
@ -219,7 +221,7 @@ impl<T: Clone> AnchorRangeMultimap<T> {
std::iter::from_fn({ std::iter::from_fn({
let mut endpoint = Anchor { let mut endpoint = Anchor {
full_offset: 0, full_offset: FullOffset(0),
bias: Bias::Left, bias: Bias::Left,
version: self.version.clone(), version: self.version.clone(),
}; };
@ -260,10 +262,10 @@ impl<T: Clone> sum_tree::Item for AnchorRangeMultimapEntry<T> {
impl Default for AnchorRangeMultimapSummary { impl Default for AnchorRangeMultimapSummary {
fn default() -> Self { fn default() -> Self {
Self { Self {
start: 0, start: FullOffset(0),
end: usize::MAX, end: FullOffset::MAX,
min_start: usize::MAX, min_start: FullOffset::MAX,
max_end: 0, max_end: FullOffset(0),
count: 0, count: 0,
} }
} }
@ -294,8 +296,8 @@ impl sum_tree::Summary for AnchorRangeMultimapSummary {
impl Default for FullOffsetRange { impl Default for FullOffsetRange {
fn default() -> Self { fn default() -> Self {
Self { Self {
start: 0, start: FullOffset(0),
end: usize::MAX, end: FullOffset::MAX,
} }
} }
} }

View file

@ -22,7 +22,7 @@ use std::{
cmp::{self, Reverse}, cmp::{self, Reverse},
convert::{TryFrom, TryInto}, convert::{TryFrom, TryInto},
iter::Iterator, iter::Iterator,
ops::Range, ops::{self, Range},
str, str,
sync::Arc, sync::Arc,
time::{Duration, Instant}, time::{Duration, Instant},
@ -84,7 +84,7 @@ pub struct Transaction {
start: clock::Global, start: clock::Global,
end: clock::Global, end: clock::Global,
edits: Vec<clock::Local>, edits: Vec<clock::Local>,
ranges: Vec<Range<usize>>, ranges: Vec<Range<FullOffset>>,
selections_before: HashMap<SelectionSetId, Arc<[Selection]>>, selections_before: HashMap<SelectionSetId, Arc<[Selection]>>,
selections_after: HashMap<SelectionSetId, Arc<[Selection]>>, selections_after: HashMap<SelectionSetId, Arc<[Selection]>>,
first_edit_at: Instant, first_edit_at: Instant,
@ -101,7 +101,7 @@ impl Transaction {
self.end.observe(edit.timestamp.local()); self.end.observe(edit.timestamp.local());
let mut other_ranges = edit.ranges.iter().peekable(); 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 insertion_len = edit.new_text.as_ref().map_or(0, |t| t.len());
let mut delta = 0; let mut delta = 0;
@ -429,7 +429,7 @@ pub enum Operation {
pub struct EditOperation { pub struct EditOperation {
timestamp: InsertionTimestamp, timestamp: InsertionTimestamp,
version: clock::Global, version: clock::Global,
ranges: Vec<Range<usize>>, ranges: Vec<Range<FullOffset>>,
new_text: Option<String>, new_text: Option<String>,
} }
@ -437,7 +437,7 @@ pub struct EditOperation {
pub struct UndoOperation { pub struct UndoOperation {
id: clock::Local, id: clock::Local,
counts: HashMap<clock::Local, u32>, counts: HashMap<clock::Local, u32>,
ranges: Vec<Range<usize>>, ranges: Vec<Range<FullOffset>>,
version: clock::Global, version: clock::Global,
} }
@ -735,7 +735,7 @@ impl Buffer {
fragment_start = old_fragments.start().visible; 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. // Preserve any portion of the current fragment that precedes this range.
if fragment_start < range.start { 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); edit.ranges.push(full_range_start..full_range_end);
} }
@ -898,7 +898,7 @@ impl Buffer {
fn apply_remote_edit( fn apply_remote_edit(
&mut self, &mut self,
version: &clock::Global, version: &clock::Global,
ranges: &[Range<usize>], ranges: &[Range<FullOffset>],
new_text: Option<&str>, new_text: Option<&str>,
timestamp: InsertionTimestamp, timestamp: InsertionTimestamp,
) { ) {
@ -909,24 +909,27 @@ impl Buffer {
let cx = Some(version.clone()); let cx = Some(version.clone());
let mut new_ropes = let mut new_ropes =
RopeBuilder::new(self.visible_text.cursor(0), self.deleted_text.cursor(0)); RopeBuilder::new(self.visible_text.cursor(0), self.deleted_text.cursor(0));
let mut old_fragments = self.fragments.cursor::<VersionedOffset>(); let mut old_fragments = self.fragments.cursor::<VersionedFullOffset>();
let mut new_fragments = let mut new_fragments = old_fragments.slice(
old_fragments.slice(&VersionedOffset::Offset(ranges[0].start), Bias::Left, &cx); &VersionedFullOffset::Offset(ranges[0].start),
Bias::Left,
&cx,
);
new_ropes.push_tree(new_fragments.summary().text); 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 { 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 // 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. // that extends past the start of this range, reusing any intervening fragments.
if fragment_end < range.start { if fragment_end < range.start {
// If the current fragment has been partially consumed, then consume the rest of it // If the current fragment has been partially consumed, then consume the rest of it
// and advance to the next fragment before slicing. // 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 { if fragment_end > fragment_start {
let mut suffix = old_fragments.item().unwrap().clone(); 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_ropes.push_fragment(&suffix, suffix.visible);
new_fragments.push(suffix, &None); new_fragments.push(suffix, &None);
} }
@ -934,21 +937,21 @@ impl Buffer {
} }
let slice = 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_ropes.push_tree(slice.summary().text);
new_fragments.push_tree(slice, &None); 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. // 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 { if fragment_end == range.start && fragment_end > fragment_start {
let mut fragment = old_fragments.item().unwrap().clone(); 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_ropes.push_fragment(&fragment, fragment.visible);
new_fragments.push(fragment, &None); new_fragments.push(fragment, &None);
old_fragments.next(&cx); 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 // 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. // Preserve any portion of the current fragment that precedes this range.
if fragment_start < range.start { if fragment_start < range.start {
let mut prefix = old_fragments.item().unwrap().clone(); 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; fragment_start = range.start;
new_ropes.push_fragment(&prefix, prefix.visible); new_ropes.push_fragment(&prefix, prefix.visible);
new_fragments.push(prefix, &None); new_fragments.push(prefix, &None);
@ -995,11 +998,11 @@ impl Buffer {
// portions as deleted. // portions as deleted.
while fragment_start < range.end { while fragment_start < range.end {
let fragment = old_fragments.item().unwrap(); 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 mut intersection = fragment.clone();
let intersection_end = cmp::min(range.end, fragment_end); let intersection_end = cmp::min(range.end, fragment_end);
if fragment.was_visible(version, &self.undo_map) { 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.deletions.insert(timestamp.local());
intersection.visible = false; intersection.visible = false;
} }
@ -1016,11 +1019,11 @@ impl Buffer {
// If the current fragment has been partially consumed, then consume the rest of it // If the current fragment has been partially consumed, then consume the rest of it
// and advance to the next fragment before slicing. // and advance to the next fragment before slicing.
if fragment_start > old_fragments.start().offset() { if fragment_start > old_fragments.start().full_offset() {
let fragment_end = old_fragments.end(&cx).offset(); let fragment_end = old_fragments.end(&cx).full_offset();
if fragment_end > fragment_start { if fragment_end > fragment_start {
let mut suffix = old_fragments.item().unwrap().clone(); 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_ropes.push_fragment(&suffix, suffix.visible);
new_fragments.push(suffix, &None); new_fragments.push(suffix, &None);
} }
@ -1049,9 +1052,9 @@ impl Buffer {
} }
let cx = Some(cx); 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( let mut new_fragments = old_fragments.slice(
&VersionedOffset::Offset(undo.ranges[0].start), &VersionedFullOffset::Offset(undo.ranges[0].start),
Bias::Right, Bias::Right,
&cx, &cx,
); );
@ -1060,11 +1063,14 @@ impl Buffer {
new_ropes.push_tree(new_fragments.summary().text); new_ropes.push_tree(new_fragments.summary().text);
for range in &undo.ranges { 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 { if end_offset < range.start {
let preceding_fragments = let preceding_fragments = old_fragments.slice(
old_fragments.slice(&VersionedOffset::Offset(range.start), Bias::Right, &cx); &VersionedFullOffset::Offset(range.start),
Bias::Right,
&cx,
);
new_ropes.push_tree(preceding_fragments.summary().text); new_ropes.push_tree(preceding_fragments.summary().text);
new_fragments.push_tree(preceding_fragments, &None); new_fragments.push_tree(preceding_fragments, &None);
} }
@ -1084,16 +1090,16 @@ impl Buffer {
new_fragments.push(fragment, &None); new_fragments.push(fragment, &None);
old_fragments.next(&cx); 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( let unseen_fragments = old_fragments.slice(
&VersionedOffset::Offset(end_offset), &VersionedFullOffset::Offset(end_offset),
Bias::Right, Bias::Right,
&cx, &cx,
); );
new_ropes.push_tree(unseen_fragments.summary().text); new_ropes.push_tree(unseen_fragments.summary().text);
new_fragments.push_tree(unseen_fragments, &None); new_fragments.push_tree(unseen_fragments, &None);
} }
end_offset = old_fragments.end(&cx).offset(); end_offset = old_fragments.end(&cx).full_offset();
} else { } else {
break; break;
} }
@ -1698,14 +1704,14 @@ impl<'a> Content<'a> {
fn summary_for_anchor(&self, anchor: &Anchor) -> TextSummary { fn summary_for_anchor(&self, anchor: &Anchor) -> TextSummary {
let cx = Some(anchor.version.clone()); let cx = Some(anchor.version.clone());
let mut cursor = self.fragments.cursor::<(VersionedOffset, usize)>(); let mut cursor = self.fragments.cursor::<(VersionedFullOffset, usize)>();
cursor.seek( cursor.seek(
&VersionedOffset::Offset(anchor.full_offset), &VersionedFullOffset::Offset(anchor.full_offset),
anchor.bias, anchor.bias,
&cx, &cx,
); );
let overshoot = if cursor.item().map_or(false, |fragment| fragment.visible) { 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 { } else {
0 0
}; };
@ -1723,11 +1729,11 @@ impl<'a> Content<'a> {
let cx = Some(map.version.clone()); let cx = Some(map.version.clone());
let mut summary = TextSummary::default(); let mut summary = TextSummary::default();
let mut rope_cursor = self.visible_text.cursor(0); 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)| { 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) { let overshoot = if cursor.item().map_or(false, |fragment| fragment.visible) {
offset - cursor.start().0.offset() *offset - cursor.start().0.full_offset()
} else { } else {
0 0
}; };
@ -1743,25 +1749,29 @@ impl<'a> Content<'a> {
let cx = Some(map.version.clone()); let cx = Some(map.version.clone());
let mut summary = TextSummary::default(); let mut summary = TextSummary::default();
let mut rope_cursor = self.visible_text.cursor(0); 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)| { map.entries.iter().map(move |(range, value)| {
let Range { let Range {
start: (start_offset, start_bias), start: (start_offset, start_bias),
end: (end_offset, end_bias), end: (end_offset, end_bias),
} = range; } = 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) { 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 { } else {
0 0
}; };
summary += rope_cursor.summary(cursor.start().1 + overshoot); summary += rope_cursor.summary(cursor.start().1 + overshoot);
let start_summary = summary.clone(); 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) { 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 { } else {
0 0
}; };
@ -1790,7 +1800,7 @@ impl<'a> Content<'a> {
.into_iter() .into_iter()
.map(|((offset, bias), value)| { .map(|((offset, bias), value)| {
cursor.seek_forward(&offset, bias, &None); 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) ((full_offset, bias), value)
}) })
.collect(); .collect();
@ -1812,9 +1822,9 @@ impl<'a> Content<'a> {
end: (end_offset, end_bias), end: (end_offset, end_bias),
} = range; } = range;
cursor.seek_forward(&start_offset, start_bias, &None); 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); 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), (full_start_offset, start_bias)..(full_end_offset, end_bias),
value, 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 cx = Some(anchor.version.clone());
let mut cursor = self let mut cursor = self
.fragments .fragments
.cursor::<(VersionedOffset, FragmentTextSummary)>(); .cursor::<(VersionedFullOffset, FragmentTextSummary)>();
cursor.seek( cursor.seek(
&VersionedOffset::Offset(anchor.full_offset), &VersionedFullOffset::Offset(anchor.full_offset),
anchor.bias, anchor.bias,
&cx, &cx,
); );
let overshoot = if cursor.item().is_some() { let overshoot = if cursor.item().is_some() {
anchor.full_offset - cursor.start().0.offset() anchor.full_offset - cursor.start().0.full_offset()
} else { } else {
0 0
}; };
let summary = cursor.start().1; 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> { 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 { impl<'a> sum_tree::Dimension<'a, FragmentSummary> for usize {
fn add_summary(&mut self, summary: &FragmentSummary, _: &Option<clock::Global>) { fn add_summary(&mut self, summary: &FragmentSummary, _: &Option<clock::Global>) {
*self += summary.text.visible; *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 { impl<'a> sum_tree::SeekTarget<'a, FragmentSummary, FragmentTextSummary> for usize {
fn cmp( fn cmp(
&self, &self,
@ -2135,28 +2189,28 @@ impl<'a> sum_tree::SeekTarget<'a, FragmentSummary, FragmentTextSummary> for usiz
} }
#[derive(Copy, Clone, Debug, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum VersionedOffset { enum VersionedFullOffset {
Offset(usize), Offset(FullOffset),
InvalidVersion, Invalid,
} }
impl VersionedOffset { impl VersionedFullOffset {
fn offset(&self) -> usize { fn full_offset(&self) -> FullOffset {
if let Self::Offset(offset) = self { if let Self::Offset(position) = self {
*offset *position
} else { } else {
panic!("invalid version") panic!("invalid version")
} }
} }
} }
impl Default for VersionedOffset { impl Default for VersionedFullOffset {
fn default() -> Self { 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>) { fn add_summary(&mut self, summary: &'a FragmentSummary, cx: &Option<clock::Global>) {
if let Self::Offset(offset) = self { if let Self::Offset(offset) = self {
let version = cx.as_ref().unwrap(); let version = cx.as_ref().unwrap();
@ -2167,18 +2221,18 @@ impl<'a> sum_tree::Dimension<'a, FragmentSummary> for VersionedOffset {
.iter() .iter()
.all(|t| !version.observed(*t)) .all(|t| !version.observed(*t))
{ {
*self = Self::InvalidVersion; *self = Self::Invalid;
} }
} }
} }
} }
impl<'a> sum_tree::SeekTarget<'a, FragmentSummary, Self> for VersionedOffset { impl<'a> sum_tree::SeekTarget<'a, FragmentSummary, Self> for VersionedFullOffset {
fn cmp(&self, other: &Self, _: &Option<clock::Global>) -> cmp::Ordering { fn cmp(&self, cursor_position: &Self, _: &Option<clock::Global>) -> cmp::Ordering {
match (self, other) { match (self, cursor_position) {
(Self::Offset(a), Self::Offset(b)) => Ord::cmp(a, b), (Self::Offset(a), Self::Offset(b)) => Ord::cmp(a, b),
(Self::Offset(_), Self::InvalidVersion) => cmp::Ordering::Less, (Self::Offset(_), Self::Invalid) => cmp::Ordering::Less,
(Self::InvalidVersion, _) => unreachable!(), (Self::Invalid, _) => unreachable!(),
} }
} }
} }
@ -2229,8 +2283,8 @@ impl<'a> Into<proto::Operation> for &'a Operation {
.ranges .ranges
.iter() .iter()
.map(|r| proto::Range { .map(|r| proto::Range {
start: r.start as u64, start: r.start.to_proto(),
end: r.end as u64, end: r.end.to_proto(),
}) })
.collect(), .collect(),
counts: undo counts: undo
@ -2281,8 +2335,8 @@ impl<'a> Into<proto::operation::Edit> for &'a EditOperation {
.ranges .ranges
.iter() .iter()
.map(|range| proto::Range { .map(|range| proto::Range {
start: range.start as u64, start: range.start.to_proto(),
end: range.end as u64, end: range.end.to_proto(),
}) })
.collect(); .collect();
proto::operation::Edit { proto::operation::Edit {
@ -2300,7 +2354,7 @@ impl<'a> Into<proto::Anchor> for &'a Anchor {
fn into(self) -> proto::Anchor { fn into(self) -> proto::Anchor {
proto::Anchor { proto::Anchor {
version: (&self.version).into(), version: (&self.version).into(),
offset: self.full_offset as u64, offset: self.full_offset.to_proto(),
bias: match self.bias { bias: match self.bias {
Bias::Left => proto::anchor::Bias::Left as i32, Bias::Left => proto::anchor::Bias::Left as i32,
Bias::Right => proto::anchor::Bias::Right as i32, Bias::Right => proto::anchor::Bias::Right as i32,
@ -2356,7 +2410,7 @@ impl TryFrom<proto::Operation> for Operation {
ranges: undo ranges: undo
.ranges .ranges
.into_iter() .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(), .collect(),
version: undo.version.into(), version: undo.version.into(),
}, },
@ -2406,7 +2460,7 @@ impl From<proto::operation::Edit> for EditOperation {
let ranges = edit let ranges = edit
.ranges .ranges
.into_iter() .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(); .collect();
EditOperation { EditOperation {
timestamp: InsertionTimestamp { timestamp: InsertionTimestamp {
@ -2434,7 +2488,7 @@ impl TryFrom<proto::Anchor> for Anchor {
} }
Ok(Self { 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: if message.bias == proto::anchor::Bias::Left as i32 {
Bias::Left Bias::Left
} else if message.bias == proto::anchor::Bias::Right as i32 { } else if message.bias == proto::anchor::Bias::Right as i32 {
@ -2470,12 +2524,12 @@ impl TryFrom<proto::Selection> for Selection {
pub trait ToOffset { pub trait ToOffset {
fn to_offset<'a>(&self, content: impl Into<Content<'a>>) -> usize; 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 content = content.into();
let offset = self.to_offset(&content); let offset = self.to_offset(&content);
let mut cursor = content.fragments.cursor::<FragmentTextSummary>(); let mut cursor = content.fragments.cursor::<FragmentTextSummary>();
cursor.seek(&offset, bias, &None); cursor.seek(&offset, bias, &None);
offset + cursor.start().deleted FullOffset(offset + cursor.start().deleted)
} }
} }