crdt: Remove some `Semilattice` instances
These instances were not safe to have around, as they allow removal of items in a non-commutative way. Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
This commit is contained in:
parent
06d658dba4
commit
56f9af650e
|
|
@ -25,9 +25,6 @@ pub use redactable::Redactable;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
use std::collections::{BTreeMap, HashMap};
|
|
||||||
use std::hash::Hash;
|
|
||||||
|
|
||||||
/// A join-semilattice.
|
/// A join-semilattice.
|
||||||
pub trait Semilattice: Sized {
|
pub trait Semilattice: Sized {
|
||||||
/// Merge an other semilattice into this one.
|
/// Merge an other semilattice into this one.
|
||||||
|
|
@ -43,40 +40,6 @@ pub trait Semilattice: Sized {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<K: Ord, V: Semilattice> Semilattice for BTreeMap<K, V> {
|
|
||||||
fn merge(&mut self, other: Self) {
|
|
||||||
use std::collections::btree_map::Entry;
|
|
||||||
|
|
||||||
for (k, v) in other {
|
|
||||||
match self.entry(k) {
|
|
||||||
Entry::Occupied(mut e) => {
|
|
||||||
e.get_mut().merge(v);
|
|
||||||
}
|
|
||||||
Entry::Vacant(e) => {
|
|
||||||
e.insert(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<K: Hash + PartialEq + Eq, V: Semilattice> Semilattice for HashMap<K, V> {
|
|
||||||
fn merge(&mut self, other: Self) {
|
|
||||||
use std::collections::hash_map::Entry;
|
|
||||||
|
|
||||||
for (k, v) in other {
|
|
||||||
match self.entry(k) {
|
|
||||||
Entry::Occupied(mut e) => {
|
|
||||||
e.get_mut().merge(v);
|
|
||||||
}
|
|
||||||
Entry::Vacant(e) => {
|
|
||||||
e.insert(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Semilattice> Semilattice for Option<T> {
|
impl<T: Semilattice> Semilattice for Option<T> {
|
||||||
fn merge(&mut self, other: Self) {
|
fn merge(&mut self, other: Self) {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::btree_map::Entry;
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::ops::{ControlFlow, Deref, DerefMut};
|
use std::ops::{ControlFlow, Deref, DerefMut};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
@ -15,6 +14,7 @@ use crate::cob::{ActorId, History, Op, OpId, TypeName};
|
||||||
use crate::crypto::Signer;
|
use crate::crypto::Signer;
|
||||||
|
|
||||||
use crdt::clock::Lamport;
|
use crdt::clock::Lamport;
|
||||||
|
use crdt::gmap::GMap;
|
||||||
use crdt::lwwset::LWWSet;
|
use crdt::lwwset::LWWSet;
|
||||||
use crdt::redactable::Redactable;
|
use crdt::redactable::Redactable;
|
||||||
use crdt::Semilattice;
|
use crdt::Semilattice;
|
||||||
|
|
@ -85,9 +85,9 @@ pub enum Action {
|
||||||
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||||
pub struct Thread {
|
pub struct Thread {
|
||||||
/// The comments under the thread.
|
/// The comments under the thread.
|
||||||
comments: BTreeMap<CommentId, Redactable<Comment>>,
|
comments: GMap<CommentId, Redactable<Comment>>,
|
||||||
/// Reactions to changes.
|
/// Reactions to changes.
|
||||||
reactions: BTreeMap<CommentId, LWWSet<(ActorId, Reaction), Lamport>>,
|
reactions: GMap<CommentId, LWWSet<(ActorId, Reaction), Lamport>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl store::FromHistory for Thread {
|
impl store::FromHistory for Thread {
|
||||||
|
|
@ -126,10 +126,6 @@ impl Deref for Thread {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Thread {
|
impl Thread {
|
||||||
pub fn clear(&mut self) {
|
|
||||||
self.comments.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn comment(&self, id: &CommentId) -> Option<&Comment> {
|
pub fn comment(&self, id: &CommentId) -> Option<&Comment> {
|
||||||
if let Some(Redactable::Present(comment)) = self.comments.get(id) {
|
if let Some(Redactable::Present(comment)) = self.comments.get(id) {
|
||||||
Some(comment)
|
Some(comment)
|
||||||
|
|
@ -179,45 +175,25 @@ impl Thread {
|
||||||
Action::Comment { body, reply_to } => {
|
Action::Comment { body, reply_to } => {
|
||||||
let present =
|
let present =
|
||||||
Redactable::Present(Comment::new(body, reply_to, change.timestamp));
|
Redactable::Present(Comment::new(body, reply_to, change.timestamp));
|
||||||
|
self.comments.insert(id, present);
|
||||||
match self.comments.entry(id) {
|
|
||||||
Entry::Vacant(e) => {
|
|
||||||
e.insert(present);
|
|
||||||
}
|
|
||||||
Entry::Occupied(mut e) => {
|
|
||||||
e.get_mut().merge(present);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Action::Redact { id } => {
|
Action::Redact { id } => {
|
||||||
self.comments
|
self.comments.insert(id, Redactable::Redacted);
|
||||||
.entry(id)
|
|
||||||
.and_modify(|e| e.merge(Redactable::Redacted))
|
|
||||||
.or_insert(Redactable::Redacted);
|
|
||||||
}
|
}
|
||||||
Action::React {
|
Action::React {
|
||||||
to,
|
to,
|
||||||
reaction,
|
reaction,
|
||||||
active,
|
active,
|
||||||
} => {
|
} => {
|
||||||
self.reactions
|
let key = (change.author, reaction);
|
||||||
.entry(to)
|
let reactions = if active {
|
||||||
.and_modify(|reactions| {
|
LWWSet::singleton(key, change.clock)
|
||||||
if active {
|
} else {
|
||||||
reactions.insert((change.author, reaction), change.clock);
|
let mut set = LWWSet::default();
|
||||||
} else {
|
set.remove(key, change.clock);
|
||||||
reactions.remove((change.author, reaction), change.clock);
|
set
|
||||||
}
|
};
|
||||||
})
|
self.reactions.insert(to, reactions);
|
||||||
.or_insert_with(|| {
|
|
||||||
if active {
|
|
||||||
LWWSet::singleton((change.author, reaction), change.clock)
|
|
||||||
} else {
|
|
||||||
let mut set = LWWSet::default();
|
|
||||||
set.remove((change.author, reaction), change.clock);
|
|
||||||
set
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue