Remove anchor collections
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
67686dd1c2
commit
65711b2256
18 changed files with 659 additions and 322 deletions
|
@ -1,9 +1,15 @@
|
|||
use super::Operation;
|
||||
use std::{fmt::Debug, ops::Add};
|
||||
use sum_tree::{Cursor, Dimension, Edit, Item, KeyedItem, SumTree, Summary};
|
||||
use sum_tree::{Dimension, Edit, Item, KeyedItem, SumTree, Summary};
|
||||
|
||||
pub trait Operation: Clone + Debug {
|
||||
fn lamport_timestamp(&self) -> clock::Lamport;
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OperationQueue(SumTree<Operation>);
|
||||
struct OperationItem<T>(T);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OperationQueue<T: Operation>(SumTree<OperationItem<T>>);
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
|
||||
pub struct OperationKey(clock::Lamport);
|
||||
|
@ -20,7 +26,7 @@ impl OperationKey {
|
|||
}
|
||||
}
|
||||
|
||||
impl OperationQueue {
|
||||
impl<T: Operation> OperationQueue<T> {
|
||||
pub fn new() -> Self {
|
||||
OperationQueue(SumTree::new())
|
||||
}
|
||||
|
@ -29,11 +35,15 @@ impl OperationQueue {
|
|||
self.0.summary().len
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, mut ops: Vec<Operation>) {
|
||||
pub fn insert(&mut self, mut ops: Vec<T>) {
|
||||
ops.sort_by_key(|op| op.lamport_timestamp());
|
||||
ops.dedup_by_key(|op| op.lamport_timestamp());
|
||||
self.0
|
||||
.edit(ops.into_iter().map(Edit::Insert).collect(), &());
|
||||
self.0.edit(
|
||||
ops.into_iter()
|
||||
.map(|op| Edit::Insert(OperationItem(op)))
|
||||
.collect(),
|
||||
&(),
|
||||
);
|
||||
}
|
||||
|
||||
pub fn drain(&mut self) -> Self {
|
||||
|
@ -42,8 +52,8 @@ impl OperationQueue {
|
|||
clone
|
||||
}
|
||||
|
||||
pub fn cursor(&self) -> Cursor<Operation, ()> {
|
||||
self.0.cursor()
|
||||
pub fn iter(&self) -> impl Iterator<Item = &T> {
|
||||
self.0.cursor::<()>().map(|i| &i.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,22 +86,22 @@ impl<'a> Dimension<'a, OperationSummary> for OperationKey {
|
|||
}
|
||||
}
|
||||
|
||||
impl Item for Operation {
|
||||
impl<T: Operation> Item for OperationItem<T> {
|
||||
type Summary = OperationSummary;
|
||||
|
||||
fn summary(&self) -> Self::Summary {
|
||||
OperationSummary {
|
||||
key: OperationKey::new(self.lamport_timestamp()),
|
||||
key: OperationKey::new(self.0.lamport_timestamp()),
|
||||
len: 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl KeyedItem for Operation {
|
||||
impl<T: Operation> KeyedItem for OperationItem<T> {
|
||||
type Key = OperationKey;
|
||||
|
||||
fn key(&self) -> Self::Key {
|
||||
OperationKey::new(self.lamport_timestamp())
|
||||
OperationKey::new(self.0.lamport_timestamp())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,21 +117,27 @@ mod tests {
|
|||
assert_eq!(queue.len(), 0);
|
||||
|
||||
queue.insert(vec![
|
||||
Operation::Test(clock.tick()),
|
||||
Operation::Test(clock.tick()),
|
||||
TestOperation(clock.tick()),
|
||||
TestOperation(clock.tick()),
|
||||
]);
|
||||
assert_eq!(queue.len(), 2);
|
||||
|
||||
queue.insert(vec![Operation::Test(clock.tick())]);
|
||||
queue.insert(vec![TestOperation(clock.tick())]);
|
||||
assert_eq!(queue.len(), 3);
|
||||
|
||||
drop(queue.drain());
|
||||
assert_eq!(queue.len(), 0);
|
||||
|
||||
queue.insert(vec![Operation::Test(clock.tick())]);
|
||||
queue.insert(vec![TestOperation(clock.tick())]);
|
||||
assert_eq!(queue.len(), 1);
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
struct TestOperation(clock::Lamport);
|
||||
|
||||
impl Operation for TestOperation {
|
||||
fn lamport_timestamp(&self) -> clock::Lamport {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -141,13 +141,13 @@ impl SelectionSet {
|
|||
let end = snapshot.anchor_at(range.end.0, range.end.1);
|
||||
let start_ix = match self
|
||||
.selections
|
||||
.binary_search_by(|probe| probe.start.cmp(&start, snapshot).unwrap())
|
||||
.binary_search_by(|probe| probe.end.cmp(&start, snapshot).unwrap())
|
||||
{
|
||||
Ok(ix) | Err(ix) => ix,
|
||||
};
|
||||
let end_ix = match self
|
||||
.selections
|
||||
.binary_search_by(|probe| probe.end.cmp(&end, snapshot).unwrap())
|
||||
.binary_search_by(|probe| probe.start.cmp(&end, snapshot).unwrap())
|
||||
{
|
||||
Ok(ix) | Err(ix) => ix,
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
mod anchor;
|
||||
mod locator;
|
||||
mod operation_queue;
|
||||
pub mod operation_queue;
|
||||
mod patch;
|
||||
mod point;
|
||||
mod point_utf16;
|
||||
|
@ -42,7 +42,7 @@ pub struct Buffer {
|
|||
last_edit: clock::Local,
|
||||
history: History,
|
||||
selections: HashMap<SelectionSetId, SelectionSet>,
|
||||
deferred_ops: OperationQueue,
|
||||
deferred_ops: OperationQueue<Operation>,
|
||||
deferred_replicas: HashSet<ReplicaId>,
|
||||
replica_id: ReplicaId,
|
||||
remote_id: u64,
|
||||
|
@ -441,8 +441,6 @@ pub enum Operation {
|
|||
set_id: Option<SelectionSetId>,
|
||||
lamport_timestamp: clock::Lamport,
|
||||
},
|
||||
#[cfg(test)]
|
||||
Test(clock::Lamport),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
|
@ -527,6 +525,10 @@ impl Buffer {
|
|||
self.local_clock.replica_id
|
||||
}
|
||||
|
||||
pub fn lamport_timestamp(&self) -> clock::Lamport {
|
||||
self.lamport_clock
|
||||
}
|
||||
|
||||
pub fn remote_id(&self) -> u64 {
|
||||
self.remote_id
|
||||
}
|
||||
|
@ -808,8 +810,6 @@ impl Buffer {
|
|||
}
|
||||
self.lamport_clock.observe(lamport_timestamp);
|
||||
}
|
||||
#[cfg(test)]
|
||||
Operation::Test(_) => {}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1103,7 +1103,7 @@ impl Buffer {
|
|||
fn flush_deferred_ops(&mut self) -> Result<()> {
|
||||
self.deferred_replicas.clear();
|
||||
let mut deferred_ops = Vec::new();
|
||||
for op in self.deferred_ops.drain().cursor().cloned() {
|
||||
for op in self.deferred_ops.drain().iter().cloned() {
|
||||
if self.can_apply_op(&op) {
|
||||
self.apply_op(op)?;
|
||||
} else {
|
||||
|
@ -1129,13 +1129,11 @@ impl Buffer {
|
|||
Operation::SetActiveSelections { set_id, .. } => {
|
||||
set_id.map_or(true, |set_id| self.selections.contains_key(&set_id))
|
||||
}
|
||||
#[cfg(test)]
|
||||
Operation::Test(_) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn can_resolve(&self, anchor: &Anchor) -> bool {
|
||||
pub fn can_resolve(&self, anchor: &Anchor) -> bool {
|
||||
*anchor == Anchor::min()
|
||||
|| *anchor == Anchor::max()
|
||||
|| self.version.observed(anchor.timestamp)
|
||||
|
@ -2176,9 +2174,18 @@ impl<'a> sum_tree::SeekTarget<'a, FragmentSummary, Self> for VersionedFullOffset
|
|||
|
||||
impl Operation {
|
||||
fn replica_id(&self) -> ReplicaId {
|
||||
self.lamport_timestamp().replica_id
|
||||
operation_queue::Operation::lamport_timestamp(self).replica_id
|
||||
}
|
||||
|
||||
pub fn is_edit(&self) -> bool {
|
||||
match self {
|
||||
Operation::Edit { .. } => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl operation_queue::Operation for Operation {
|
||||
fn lamport_timestamp(&self) -> clock::Lamport {
|
||||
match self {
|
||||
Operation::Edit(edit) => edit.timestamp.lamport(),
|
||||
|
@ -2194,15 +2201,6 @@ impl Operation {
|
|||
Operation::SetActiveSelections {
|
||||
lamport_timestamp, ..
|
||||
} => *lamport_timestamp,
|
||||
#[cfg(test)]
|
||||
Operation::Test(lamport_timestamp) => *lamport_timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_edit(&self) -> bool {
|
||||
match self {
|
||||
Operation::Edit { .. } => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue