Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

impl crdt types #420

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions libs/jwst-codec/src/doc/codec/content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,15 +171,18 @@ impl Content {
}
}

pub fn split(&self, diff: u64) -> JwstCodecResult<(Self, Self)> {
pub fn countable(&self) -> bool {
!matches!(self, Content::Format { .. } | Content::Deleted(_))
}

pub fn split(&mut self, diff: u64) -> JwstCodecResult<Self> {
// TODO: implement split for other types
match self {
Self::String(str) => {
let (left, right) = str.split_at(diff as usize);
Ok((
Self::String(left.to_string()),
Self::String(right.to_string()),
))
let right = right.to_string();
*str = left.to_string();
Ok(Self::String(right))
}
_ => Err(JwstCodecError::ContentSplitNotSupport(diff)),
}
Expand Down
33 changes: 0 additions & 33 deletions libs/jwst-codec/src/doc/codec/delete.rs

This file was deleted.

116 changes: 116 additions & 0 deletions libs/jwst-codec/src/doc/codec/delete_set.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
use crate::doc::OrderRange;

use super::*;
use std::{
collections::{hash_map::Entry, HashMap},
ops::{Deref, DerefMut, Range},
};

impl<R: CrdtReader> CrdtRead<R> for Range<u64> {
fn read(decoder: &mut R) -> JwstCodecResult<Self> {
let clock = decoder.read_var_u64()?;
let len = decoder.read_var_u64()?;
Ok(clock..clock + len)
}
}

impl<R: CrdtReader> CrdtRead<R> for OrderRange {
fn read(decoder: &mut R) -> JwstCodecResult<Self> {
let num_of_deletes = decoder.read_var_u64()? as usize;
let mut deletes = Vec::with_capacity(num_of_deletes);

for _ in 0..num_of_deletes {
deletes.push(Range::<u64>::read(decoder)?);
}

Ok(OrderRange::Fragment(deletes))
}
}

impl<R: CrdtReader> CrdtRead<R> for DeleteSet {
fn read(decoder: &mut R) -> JwstCodecResult<Self> {
let num_of_clients = decoder.read_var_u64()? as usize;
let mut map = HashMap::with_capacity(num_of_clients);

for _ in 0..num_of_clients {
let client = decoder.read_var_u64()?;
let deletes = OrderRange::read(decoder)?;
map.insert(client, deletes);
}

Ok(DeleteSet(map))
}
}

#[derive(Debug, Default)]
pub struct DeleteSet(pub HashMap<Client, OrderRange>);

impl Deref for DeleteSet {
type Target = HashMap<Client, OrderRange>;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl<const N: usize> From<[(Client, Vec<Range<u64>>); N]> for DeleteSet {
fn from(value: [(Client, Vec<Range<u64>>); N]) -> Self {
let mut map = HashMap::with_capacity(N);
for (client, ranges) in value {
map.insert(client, ranges.into());
}
Self(map)
}
}

impl DerefMut for DeleteSet {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

impl DeleteSet {
pub fn add(&mut self, client: Client, from: Clock, len: Clock) {
self.add_range(client, from..from + len);
}

pub fn add_range(&mut self, client: Client, range: Range<u64>) {
match self.0.entry(client) {
Entry::Occupied(e) => {
let r = e.into_mut();
if r.is_empty() {
*r = range.into();
} else {
r.push(range);
}
}
Entry::Vacant(e) => {
e.insert(range.into());
}
}
}

pub fn batch_push(&mut self, client: Client, ranges: Vec<Range<u64>>) {
match self.0.entry(client) {
Entry::Occupied(e) => {
e.into_mut().extends(ranges);
}
Entry::Vacant(e) => {
e.insert(ranges.into());
}
}
}

pub fn merge(&mut self, other: Self) {
for (client, range) in other.0 {
match self.0.entry(client) {
Entry::Occupied(e) => {
e.into_mut().merge(range);
}
Entry::Vacant(e) => {
e.insert(range);
}
}
}
}
}
18 changes: 17 additions & 1 deletion libs/jwst-codec/src/doc/codec/id.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use std::{
cmp::Ordering,
hash::Hash,
ops::{Add, Sub},
};

pub type Client = u64;
pub type Clock = u64;

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Default)]
pub struct Id {
pub client: Client,
pub clock: Clock,
Expand Down Expand Up @@ -39,3 +40,18 @@ impl Add<Clock> for Id {
(self.client, self.clock + rhs).into()
}
}

impl PartialOrd for Id {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match self.client.cmp(&other.client) {
Ordering::Equal => Some(self.clock.cmp(&other.clock)),
_ => None,
}
}
}

impl Ord for Id {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.clock.cmp(&other.clock)
}
}
Loading