Get buffer compiling with new SelectionSets based on AnchorRangeMap

One test is failing however.
This commit is contained in:
Nathan Sobo 2021-10-22 14:12:16 -06:00
parent 6ba4af3e26
commit 60a8e74430
4 changed files with 156 additions and 62 deletions

View file

@ -87,7 +87,7 @@ impl Anchor {
} }
impl<T> AnchorMap<T> { impl<T> AnchorMap<T> {
pub fn to_points<'a>( pub fn points<'a>(
&'a self, &'a self,
content: impl Into<Content<'a>> + 'a, content: impl Into<Content<'a>> + 'a,
) -> impl Iterator<Item = (Point, &'a T)> + 'a { ) -> impl Iterator<Item = (Point, &'a T)> + 'a {
@ -103,11 +103,11 @@ impl<T> AnchorMap<T> {
} }
impl AnchorSet { impl AnchorSet {
pub fn to_points<'a>( pub fn points<'a>(
&'a self, &'a self,
content: impl Into<Content<'a>> + 'a, content: impl Into<Content<'a>> + 'a,
) -> impl Iterator<Item = Point> + 'a { ) -> impl Iterator<Item = Point> + 'a {
self.0.to_points(content).map(move |(point, _)| point) self.0.points(content).map(move |(point, _)| point)
} }
} }
@ -120,7 +120,7 @@ impl<T> AnchorRangeMap<T> {
&self.entries &self.entries
} }
pub fn to_point_ranges<'a>( pub fn point_ranges<'a>(
&'a self, &'a self,
content: impl Into<Content<'a>> + 'a, content: impl Into<Content<'a>> + 'a,
) -> impl Iterator<Item = (Range<Point>, &'a T)> + 'a { ) -> impl Iterator<Item = (Range<Point>, &'a T)> + 'a {
@ -130,6 +130,16 @@ impl<T> AnchorRangeMap<T> {
.map(move |(range, value)| ((range.start.lines..range.end.lines), value)) .map(move |(range, value)| ((range.start.lines..range.end.lines), value))
} }
pub fn offset_ranges<'a>(
&'a self,
content: impl Into<Content<'a>> + 'a,
) -> impl Iterator<Item = (Range<usize>, &'a T)> + 'a {
let content = content.into();
content
.summaries_for_anchor_ranges(self)
.map(move |(range, value)| ((range.start.bytes..range.end.bytes), value))
}
pub fn version(&self) -> &clock::Global { pub fn version(&self) -> &clock::Global {
&self.version &self.version
} }
@ -145,7 +155,7 @@ impl<T: Eq> Eq for AnchorRangeMap<T> {}
impl<T: Debug> Debug for AnchorRangeMap<T> { impl<T: Debug> Debug for AnchorRangeMap<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
let f = f.debug_map(); let mut f = f.debug_map();
for (range, value) in &self.entries { for (range, value) in &self.entries {
f.key(range); f.key(range);
f.value(value); f.value(value);
@ -159,7 +169,7 @@ impl AnchorRangeSet {
&'a self, &'a self,
content: impl Into<Content<'a>> + 'a, content: impl Into<Content<'a>> + 'a,
) -> impl Iterator<Item = Range<Point>> + 'a { ) -> impl Iterator<Item = Range<Point>> + 'a {
self.0.to_point_ranges(content).map(|(range, _)| range) self.0.point_ranges(content).map(|(range, _)| range)
} }
pub fn version(&self) -> &clock::Global { pub fn version(&self) -> &clock::Global {

View file

@ -79,8 +79,8 @@ pub struct Transaction {
end: clock::Global, end: clock::Global,
edits: Vec<clock::Local>, edits: Vec<clock::Local>,
ranges: Vec<Range<usize>>, ranges: Vec<Range<usize>>,
selections_before: HashMap<SelectionSetId, Arc<[Selection]>>, selections_before: HashMap<SelectionSetId, Arc<AnchorRangeMap<SelectionState>>>,
selections_after: HashMap<SelectionSetId, Arc<[Selection]>>, selections_after: HashMap<SelectionSetId, Arc<AnchorRangeMap<SelectionState>>>,
first_edit_at: Instant, first_edit_at: Instant,
last_edit_at: Instant, last_edit_at: Instant,
} }
@ -167,7 +167,7 @@ impl History {
fn start_transaction( fn start_transaction(
&mut self, &mut self,
start: clock::Global, start: clock::Global,
selections_before: HashMap<SelectionSetId, Arc<[Selection]>>, selections_before: HashMap<SelectionSetId, Arc<AnchorRangeMap<SelectionState>>>,
now: Instant, now: Instant,
) { ) {
self.transaction_depth += 1; self.transaction_depth += 1;
@ -187,7 +187,7 @@ impl History {
fn end_transaction( fn end_transaction(
&mut self, &mut self,
selections_after: HashMap<SelectionSetId, Arc<[Selection]>>, selections_after: HashMap<SelectionSetId, Arc<AnchorRangeMap<SelectionState>>>,
now: Instant, now: Instant,
) -> Option<&Transaction> { ) -> Option<&Transaction> {
assert_ne!(self.transaction_depth, 0); assert_ne!(self.transaction_depth, 0);
@ -499,11 +499,7 @@ impl Buffer {
id: self.remote_id, id: self.remote_id,
content: self.history.base_text.to_string(), content: self.history.base_text.to_string(),
history: ops, history: ops,
selections: self selections: self.selections.iter().map(|(_, set)| set.into()).collect(),
.selections
.iter()
.map(|(set_id, set)| set.into())
.collect(),
} }
} }
@ -1201,7 +1197,7 @@ impl Buffer {
let selections = transaction.selections_before.clone(); let selections = transaction.selections_before.clone();
ops.push(self.undo_or_redo(transaction).unwrap()); ops.push(self.undo_or_redo(transaction).unwrap());
for (set_id, selections) in selections { for (set_id, selections) in selections {
ops.extend(self.update_selection_set(set_id, selections)); ops.extend(self.restore_selection_set(set_id, selections));
} }
} }
ops ops
@ -1213,7 +1209,7 @@ impl Buffer {
let selections = transaction.selections_after.clone(); let selections = transaction.selections_after.clone();
ops.push(self.undo_or_redo(transaction).unwrap()); ops.push(self.undo_or_redo(transaction).unwrap());
for (set_id, selections) in selections { for (set_id, selections) in selections {
ops.extend(self.update_selection_set(set_id, selections)); ops.extend(self.restore_selection_set(set_id, selections));
} }
} }
ops ops
@ -1250,17 +1246,37 @@ impl Buffer {
self.selections.iter() self.selections.iter()
} }
pub fn update_selection_set( fn build_selection_anchor_range_map<T: ToOffset>(
&self,
selections: &[Selection<T>],
) -> Arc<AnchorRangeMap<SelectionState>> {
Arc::new(
self.content()
.anchor_range_map(selections.iter().map(|selection| {
let start = selection.start.to_offset(self);
let end = selection.end.to_offset(self);
let range = (start, Bias::Left)..(end, Bias::Left);
let state = SelectionState {
id: selection.id,
reversed: selection.reversed,
goal: selection.goal,
};
(range, state)
})),
)
}
pub fn update_selection_set<T: ToOffset>(
&mut self, &mut self,
set_id: SelectionSetId, set_id: SelectionSetId,
selections: &[Selection], selections: &[Selection<T>],
) -> Result<Operation> { ) -> Result<Operation> {
let selections = selections.into(); let selections = self.build_selection_anchor_range_map(selections);
let set = self let set = self
.selections .selections
.get_mut(&set_id) .get_mut(&set_id)
.ok_or_else(|| anyhow!("invalid selection set id {:?}", set_id))?; .ok_or_else(|| anyhow!("invalid selection set id {:?}", set_id))?;
set.selections = todo!(); set.selections = selections.clone();
Ok(Operation::UpdateSelections { Ok(Operation::UpdateSelections {
set_id, set_id,
selections, selections,
@ -1268,8 +1284,25 @@ impl Buffer {
}) })
} }
pub fn add_selection_set(&mut self, selections: impl Into<Arc<[Selection]>>) -> Operation { pub fn restore_selection_set(
let selections = selections.into(); &mut self,
set_id: SelectionSetId,
selections: Arc<AnchorRangeMap<SelectionState>>,
) -> Result<Operation> {
let set = self
.selections
.get_mut(&set_id)
.ok_or_else(|| anyhow!("invalid selection set id {:?}", set_id))?;
set.selections = selections.clone();
Ok(Operation::UpdateSelections {
set_id,
selections,
lamport_timestamp: self.lamport_clock.tick(),
})
}
pub fn add_selection_set<T: ToOffset>(&mut self, selections: &[Selection<T>]) -> Operation {
let selections = self.build_selection_anchor_range_map(selections);
let set_id = self.lamport_clock.tick(); let set_id = self.lamport_clock.tick();
self.selections.insert( self.selections.insert(
set_id, set_id,
@ -1408,9 +1441,9 @@ impl Buffer {
let new_selections = self.selections_from_ranges(ranges).unwrap(); let new_selections = self.selections_from_ranges(ranges).unwrap();
let op = if set_id.is_none() || rng.gen_bool(1.0 / 5.0) { let op = if set_id.is_none() || rng.gen_bool(1.0 / 5.0) {
self.add_selection_set(new_selections) self.add_selection_set(&new_selections)
} else { } else {
self.update_selection_set(*set_id.unwrap(), new_selections) self.update_selection_set(*set_id.unwrap(), &new_selections)
.unwrap() .unwrap()
}; };
ops.push(op); ops.push(op);
@ -1436,7 +1469,7 @@ impl Buffer {
ops ops
} }
fn selections_from_ranges<I>(&self, ranges: I) -> Result<Vec<Selection>> fn selections_from_ranges<I>(&self, ranges: I) -> Result<Vec<Selection<usize>>>
where where
I: IntoIterator<Item = Range<usize>>, I: IntoIterator<Item = Range<usize>>,
{ {
@ -1452,16 +1485,16 @@ impl Buffer {
if range.start > range.end { if range.start > range.end {
selections.push(Selection { selections.push(Selection {
id: NEXT_SELECTION_ID.fetch_add(1, atomic::Ordering::SeqCst), id: NEXT_SELECTION_ID.fetch_add(1, atomic::Ordering::SeqCst),
start: self.anchor_before(range.end), start: range.end,
end: self.anchor_before(range.start), end: range.start,
reversed: true, reversed: true,
goal: SelectionGoal::None, goal: SelectionGoal::None,
}); });
} else { } else {
selections.push(Selection { selections.push(Selection {
id: NEXT_SELECTION_ID.fetch_add(1, atomic::Ordering::SeqCst), id: NEXT_SELECTION_ID.fetch_add(1, atomic::Ordering::SeqCst),
start: self.anchor_after(range.start), start: range.start,
end: self.anchor_before(range.end), end: range.end,
reversed: false, reversed: false,
goal: SelectionGoal::None, goal: SelectionGoal::None,
}); });
@ -1473,15 +1506,12 @@ impl Buffer {
pub fn selection_ranges<'a>(&'a self, set_id: SelectionSetId) -> Result<Vec<Range<usize>>> { pub fn selection_ranges<'a>(&'a self, set_id: SelectionSetId) -> Result<Vec<Range<usize>>> {
Ok(self Ok(self
.selection_set(set_id)? .selection_set(set_id)?
.selections .offset_selections(self)
.iter()
.map(move |selection| { .map(move |selection| {
let start = selection.start.to_offset(self);
let end = selection.end.to_offset(self);
if selection.reversed { if selection.reversed {
end..start selection.end..selection.start
} else { } else {
start..end selection.start..selection.end
} }
}) })
.collect()) .collect())
@ -2173,7 +2203,17 @@ impl<'a> Into<proto::Operation> for &'a Operation {
replica_id: set_id.replica_id as u32, replica_id: set_id.replica_id as u32,
local_timestamp: set_id.value, local_timestamp: set_id.value,
lamport_timestamp: lamport_timestamp.value, lamport_timestamp: lamport_timestamp.value,
selections: selections.iter().map(Into::into).collect(), version: selections.version().into(),
selections: selections
.raw_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(),
}, },
), ),
Operation::RemoveSelections { Operation::RemoveSelections {
@ -2279,11 +2319,23 @@ impl TryFrom<proto::Operation> for Operation {
}, },
}, },
proto::operation::Variant::UpdateSelections(message) => { proto::operation::Variant::UpdateSelections(message) => {
let selections: Vec<Selection> = message let version = message.version.into();
let entries = message
.selections .selections
.into_iter() .iter()
.map(TryFrom::try_from) .map(|selection| {
.collect::<Result<_, _>>()?; 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();
let selections = AnchorRangeMap::from_raw(version, entries);
Operation::UpdateSelections { Operation::UpdateSelections {
set_id: clock::Lamport { set_id: clock::Lamport {
replica_id: message.replica_id as ReplicaId, replica_id: message.replica_id as ReplicaId,

View file

@ -1,6 +1,6 @@
use crate::{Anchor, AnchorRangeMap, Buffer, Point, ToOffset as _, ToPoint as _}; use crate::{AnchorRangeMap, Buffer, Content, Point, ToOffset, ToPoint};
use rpc::proto; use rpc::proto;
use std::{cmp::Ordering, mem, ops::Range, sync::Arc}; use std::{cmp::Ordering, ops::Range, sync::Arc};
use sum_tree::Bias; use sum_tree::Bias;
pub type SelectionSetId = clock::Lamport; pub type SelectionSetId = clock::Lamport;
@ -14,10 +14,10 @@ pub enum SelectionGoal {
} }
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub struct Selection { pub struct Selection<T> {
pub id: usize, pub id: usize,
pub start: Anchor, pub start: T,
pub end: Anchor, pub end: T,
pub reversed: bool, pub reversed: bool,
pub goal: SelectionGoal, pub goal: SelectionGoal,
} }
@ -36,36 +36,36 @@ pub struct SelectionState {
pub goal: SelectionGoal, pub goal: SelectionGoal,
} }
impl Selection { impl<T: ToOffset + ToPoint + Copy + Ord> Selection<T> {
pub fn head(&self) -> &Anchor { pub fn head(&self) -> T {
if self.reversed { if self.reversed {
&self.start self.start
} else { } else {
&self.end self.end
} }
} }
pub fn set_head(&mut self, buffer: &Buffer, cursor: Anchor) { pub fn set_head(&mut self, head: T) {
if cursor.cmp(self.tail(), buffer).unwrap() < Ordering::Equal { if head.cmp(&self.tail()) < Ordering::Equal {
if !self.reversed { if !self.reversed {
mem::swap(&mut self.start, &mut self.end); self.end = self.start;
self.reversed = true; self.reversed = true;
} }
self.start = cursor; self.start = head;
} else { } else {
if self.reversed { if self.reversed {
mem::swap(&mut self.start, &mut self.end); self.start = self.end;
self.reversed = false; self.reversed = false;
} }
self.end = cursor; self.end = head;
} }
} }
pub fn tail(&self) -> &Anchor { pub fn tail(&self) -> T {
if self.reversed { if self.reversed {
&self.end self.end
} else { } else {
&self.start self.start
} }
} }
@ -90,6 +90,38 @@ impl Selection {
} }
} }
impl SelectionSet {
pub fn offset_selections<'a>(
&'a self,
content: impl Into<Content<'a>> + 'a,
) -> impl 'a + Iterator<Item = Selection<usize>> {
self.selections
.offset_ranges(content)
.map(|(range, state)| Selection {
id: state.id,
start: range.start,
end: range.end,
reversed: state.reversed,
goal: state.goal,
})
}
pub fn point_selections<'a>(
&'a self,
content: impl Into<Content<'a>> + 'a,
) -> impl 'a + Iterator<Item = Selection<Point>> {
self.selections
.point_ranges(content)
.map(|(range, state)| Selection {
id: state.id,
start: range.start,
end: range.end,
reversed: state.reversed,
goal: state.goal,
})
}
}
impl<'a> Into<proto::SelectionSet> for &'a SelectionSet { impl<'a> Into<proto::SelectionSet> for &'a SelectionSet {
fn into(self) -> proto::SelectionSet { fn into(self) -> proto::SelectionSet {
let version = self.selections.version(); let version = self.selections.version();

View file

@ -408,7 +408,7 @@ fn test_history() {
let mut buffer = Buffer::new(0, 0, History::new("123456".into())); let mut buffer = Buffer::new(0, 0, History::new("123456".into()));
let set_id = if let Operation::UpdateSelections { set_id, .. } = let set_id = if let Operation::UpdateSelections { set_id, .. } =
buffer.add_selection_set(buffer.selections_from_ranges(vec![4..4]).unwrap()) buffer.add_selection_set(&buffer.selections_from_ranges(vec![4..4]).unwrap())
{ {
set_id set_id
} else { } else {
@ -422,7 +422,7 @@ fn test_history() {
buffer.start_transaction_at(Some(set_id), now).unwrap(); buffer.start_transaction_at(Some(set_id), now).unwrap();
buffer buffer
.update_selection_set(set_id, buffer.selections_from_ranges(vec![1..3]).unwrap()) .update_selection_set(set_id, &buffer.selections_from_ranges(vec![1..3]).unwrap())
.unwrap(); .unwrap();
buffer.edit(vec![4..5], "e"); buffer.edit(vec![4..5], "e");
buffer.end_transaction_at(Some(set_id), now).unwrap(); buffer.end_transaction_at(Some(set_id), now).unwrap();
@ -432,7 +432,7 @@ fn test_history() {
now += buffer.history.group_interval + Duration::from_millis(1); now += buffer.history.group_interval + Duration::from_millis(1);
buffer.start_transaction_at(Some(set_id), now).unwrap(); buffer.start_transaction_at(Some(set_id), now).unwrap();
buffer buffer
.update_selection_set(set_id, buffer.selections_from_ranges(vec![2..2]).unwrap()) .update_selection_set(set_id, &buffer.selections_from_ranges(vec![2..2]).unwrap())
.unwrap(); .unwrap();
buffer.edit(vec![0..1], "a"); buffer.edit(vec![0..1], "a");
buffer.edit(vec![1..1], "b"); buffer.edit(vec![1..1], "b");