From 6ba4af3e260b68bec2ba20003085b38c940041bb Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 22 Oct 2021 13:19:19 -0600 Subject: [PATCH] WIP: Start converting SelectionSet to use AnchorRangeMap --- crates/buffer/src/anchor.rs | 33 +++++++++++- crates/buffer/src/lib.rs | 19 ++----- crates/buffer/src/selection.rs | 94 +++++++++++++++++----------------- crates/clock/src/lib.rs | 6 +++ crates/rpc/proto/zed.proto | 12 +++-- 5 files changed, 97 insertions(+), 67 deletions(-) diff --git a/crates/buffer/src/anchor.rs b/crates/buffer/src/anchor.rs index 1ac82727df..58673a3301 100644 --- a/crates/buffer/src/anchor.rs +++ b/crates/buffer/src/anchor.rs @@ -2,7 +2,11 @@ use crate::Point; use super::{Buffer, Content}; use anyhow::Result; -use std::{cmp::Ordering, ops::Range}; +use std::{ + cmp::Ordering, + fmt::{Debug, Formatter}, + ops::Range, +}; use sum_tree::Bias; #[derive(Clone, Eq, PartialEq, Debug, Hash)] @@ -108,6 +112,14 @@ impl AnchorSet { } impl AnchorRangeMap { + pub fn from_raw(version: clock::Global, entries: Vec<(Range<(usize, Bias)>, T)>) -> Self { + Self { version, entries } + } + + pub fn raw_entries(&self) -> &[(Range<(usize, Bias)>, T)] { + &self.entries + } + pub fn to_point_ranges<'a>( &'a self, content: impl Into> + 'a, @@ -123,6 +135,25 @@ impl AnchorRangeMap { } } +impl PartialEq for AnchorRangeMap { + fn eq(&self, other: &Self) -> bool { + self.version == other.version && self.entries == other.entries + } +} + +impl Eq for AnchorRangeMap {} + +impl Debug for AnchorRangeMap { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { + let f = f.debug_map(); + for (range, value) in &self.entries { + f.key(range); + f.value(value); + } + f.finish() + } +} + impl AnchorRangeSet { pub fn to_point_ranges<'a>( &'a self, diff --git a/crates/buffer/src/lib.rs b/crates/buffer/src/lib.rs index 6deaf228a1..f780d2590c 100644 --- a/crates/buffer/src/lib.rs +++ b/crates/buffer/src/lib.rs @@ -408,7 +408,7 @@ pub enum Operation { }, UpdateSelections { set_id: SelectionSetId, - selections: Arc<[Selection]>, + selections: Arc>, lamport_timestamp: clock::Lamport, }, RemoveSelections { @@ -502,12 +502,7 @@ impl Buffer { selections: self .selections .iter() - .map(|(set_id, set)| proto::SelectionSet { - replica_id: set_id.replica_id as u32, - lamport_timestamp: set_id.value, - selections: set.selections.iter().map(Into::into).collect(), - is_active: set.active, - }) + .map(|(set_id, set)| set.into()) .collect(), } } @@ -1123,11 +1118,7 @@ impl Buffer { Operation::Edit(edit) => self.version >= edit.version, Operation::Undo { undo, .. } => self.version >= undo.version, Operation::UpdateSelections { selections, .. } => { - selections.iter().all(|selection| { - let contains_start = self.version >= selection.start.version; - let contains_end = self.version >= selection.end.version; - contains_start && contains_end - }) + self.version >= *selections.version() } Operation::RemoveSelections { .. } => true, Operation::SetActiveSelections { set_id, .. } => { @@ -1262,14 +1253,14 @@ impl Buffer { pub fn update_selection_set( &mut self, set_id: SelectionSetId, - selections: impl Into>, + selections: &[Selection], ) -> Result { let selections = selections.into(); let set = self .selections .get_mut(&set_id) .ok_or_else(|| anyhow!("invalid selection set id {:?}", set_id))?; - set.selections = selections.clone(); + set.selections = todo!(); Ok(Operation::UpdateSelections { set_id, selections, diff --git a/crates/buffer/src/selection.rs b/crates/buffer/src/selection.rs index 589746803b..03b394252b 100644 --- a/crates/buffer/src/selection.rs +++ b/crates/buffer/src/selection.rs @@ -1,13 +1,7 @@ -use crate::{Anchor, Buffer, Point, ToOffset as _, ToPoint as _}; -use anyhow::anyhow; +use crate::{Anchor, AnchorRangeMap, Buffer, Point, ToOffset as _, ToPoint as _}; use rpc::proto; -use std::{ - cmp::Ordering, - convert::{TryFrom, TryInto}, - mem, - ops::Range, - sync::Arc, -}; +use std::{cmp::Ordering, mem, ops::Range, sync::Arc}; +use sum_tree::Bias; pub type SelectionSetId = clock::Lamport; pub type SelectionsVersion = usize; @@ -32,7 +26,14 @@ pub struct Selection { pub struct SelectionSet { pub id: SelectionSetId, pub active: bool, - pub selections: Arc<[Selection]>, + pub selections: Arc>, +} + +#[derive(Debug, Eq, PartialEq)] +pub struct SelectionState { + pub id: usize, + pub reversed: bool, + pub goal: SelectionGoal, } impl Selection { @@ -89,53 +90,52 @@ impl Selection { } } -impl<'a> Into for &'a Selection { - fn into(self) -> proto::Selection { - proto::Selection { - id: self.id as u64, - start: Some((&self.start).into()), - end: Some((&self.end).into()), - reversed: self.reversed, +impl<'a> Into for &'a SelectionSet { + fn into(self) -> proto::SelectionSet { + let version = self.selections.version(); + let entries = self.selections.raw_entries(); + proto::SelectionSet { + replica_id: self.id.replica_id as u32, + lamport_timestamp: self.id.value as u32, + is_active: self.active, + version: version.into(), + selections: entries + .iter() + .map(|(range, state)| proto::Selection { + id: state.id as u64, + start: range.start.0 as u64, + end: range.end.0 as u64, + reversed: state.reversed, + }) + .collect(), } } } -impl TryFrom for Selection { - type Error = anyhow::Error; - - fn try_from(selection: proto::Selection) -> Result { - Ok(Selection { - id: selection.id as usize, - start: selection - .start - .ok_or_else(|| anyhow!("missing selection start"))? - .try_into()?, - end: selection - .end - .ok_or_else(|| anyhow!("missing selection end"))? - .try_into()?, - reversed: selection.reversed, - goal: SelectionGoal::None, - }) - } -} - -impl TryFrom for SelectionSet { - type Error = anyhow::Error; - - fn try_from(set: proto::SelectionSet) -> Result { - Ok(Self { +impl From for SelectionSet { + fn from(set: proto::SelectionSet) -> Self { + Self { id: clock::Lamport { replica_id: set.replica_id as u16, value: set.lamport_timestamp, }, active: set.is_active, - selections: Arc::from( + selections: Arc::new(AnchorRangeMap::from_raw( + set.version.into(), set.selections .into_iter() - .map(TryInto::try_into) - .collect::, _>>()?, - ), - }) + .map(|selection| { + let range = (selection.start as usize, Bias::Left) + ..(selection.end as usize, Bias::Right); + let state = SelectionState { + id: selection.id as usize, + reversed: selection.reversed, + goal: SelectionGoal::None, + }; + (range, state) + }) + .collect(), + )), + } } } diff --git a/crates/clock/src/lib.rs b/crates/clock/src/lib.rs index ee5c0dba03..b3158d99dd 100644 --- a/crates/clock/src/lib.rs +++ b/crates/clock/src/lib.rs @@ -86,6 +86,12 @@ impl<'a> From<&'a Global> for Vec { } } +impl From for Vec { + fn from(version: Global) -> Self { + (&version).into() + } +} + impl Global { pub fn new() -> Self { Self::default() diff --git a/crates/rpc/proto/zed.proto b/crates/rpc/proto/zed.proto index 939c39829b..0678215ef8 100644 --- a/crates/rpc/proto/zed.proto +++ b/crates/rpc/proto/zed.proto @@ -233,14 +233,15 @@ message Buffer { message SelectionSet { uint32 replica_id = 1; uint32 lamport_timestamp = 2; - repeated Selection selections = 3; - bool is_active = 4; + bool is_active = 3; + repeated VectorClockEntry version = 4; + repeated Selection selections = 5; } message Selection { uint64 id = 1; - Anchor start = 2; - Anchor end = 3; + uint64 start = 2; + uint64 end = 3; bool reversed = 4; } @@ -291,7 +292,8 @@ message Operation { uint32 replica_id = 1; uint32 local_timestamp = 2; uint32 lamport_timestamp = 3; - repeated Selection selections = 4; + repeated VectorClockEntry version = 4; + repeated Selection selections = 5; } message RemoveSelections {