feat: impl yata

This commit is contained in:
Zixuan Chen 2022-10-08 16:04:25 +08:00
parent 5f6d66368e
commit 670d194aeb
6 changed files with 94 additions and 16 deletions

4
Cargo.lock generated
View file

@ -152,9 +152,9 @@ dependencies = [
[[package]]
name = "crdt-list"
version = "0.1.1"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4a759e0bf62cfa3fbc92c569e0ef8d133f8e3c0fc28ff743f43af9da923d068"
checksum = "5ccf4b02e0ea18624e24710c974bdeab38a060cb572e97e56c7f675547ac917e"
dependencies = [
"arref",
]

View file

@ -19,7 +19,7 @@ thiserror = "1.0.31"
im = "15.1.0"
enum-as-inner = "0.5.1"
num = "0.4.0"
crdt-list = "0.1.1"
crdt-list = "0.1.2"
[dev-dependencies]
proptest = "1.0.0"

View file

@ -1,5 +1,5 @@
use crdt_list::{crdt::{ListCrdt, OpSet}, yata::Yata};
use rle::rle_tree::{iter::IterMut, SafeCursorMut, RleTreeRaw};
use rle::{rle_tree::{iter::IterMut, SafeCursorMut, RleTreeRaw}, range_map::{RangeMap, WithStartEnd}};
use crate::id::{ID, Counter};
@ -9,19 +9,21 @@ use super::{
};
#[derive(Default, Debug)]
struct OpSpanSet {}
struct OpSpanSet {
map: RangeMap<u128, WithStartEnd<u128, bool>>
}
impl OpSet<YSpan, ID> for OpSpanSet {
fn insert(&mut self, _value: &YSpan) {
todo!()
fn insert(&mut self, value: &YSpan) {
self.map.set(value.id.into(), WithStartEnd { start: value.id.into(), end: value.id.inc(value.len as i32).into(), value: true })
}
fn contain(&self, _id: ID) -> bool {
todo!()
fn contain(&self, id: ID) -> bool {
self.map.has(id.into())
}
fn clear(&mut self) {
todo!()
self.map.clear();
}
}
@ -87,11 +89,24 @@ impl ListCrdt for YataImpl {
}
fn integrate(container: &mut Self::Container, op: Self::OpUnit) {
crdt_list::yata::integrate::<Self>(container, op)
// SAFETY: we know this is safe because in [YataImpl::insert_after] there is no access to shared elements
unsafe {crdt_list::yata::integrate::<Self>(container, op)}
}
fn can_integrate(_container: &Self::Container, _op: &Self::OpUnit) -> bool {
todo!()
fn can_integrate(container: &Self::Container, op: &Self::OpUnit) -> bool {
if let Some(value) = op.origin_left {
if !container.id_to_cursor.has(value.into()) {
return false;
}
}
if let Some(value) = op.origin_right {
if !container.id_to_cursor.has(value.into()) {
return false;
}
}
true
}
fn len(container: &Self::Container) -> usize {
@ -109,7 +124,41 @@ impl Yata for YataImpl {
op.origin_right
}
fn insert_after(anchor: &mut Self::Cursor<'_>, op: Self::OpUnit) {
todo!()
fn insert_after(container: &mut Self::Container, anchor: Self::Cursor<'_>, op: Self::OpUnit) {
let mut notify = make_notify(&mut container.id_to_cursor);
anchor.insert_after_notify(op, &mut notify)
}
}
#[cfg(test)]
mod test {
use crdt_list::crdt::OpSet;
use crate::{container::text::tracker::y_span::{YSpan, Status}, id::ID};
use super::OpSpanSet;
#[test]
fn test() {
let mut set = OpSpanSet::default();
set.insert(
&YSpan {
id: ID::new(1, 10),
len: 10,
origin_left: Some(ID::new(0, 1)),
origin_right: Some(ID::new(0, 2)),
status: Status::new()
}
);
assert!(set.contain(ID::new(1, 10)));
assert!(set.contain(ID::new(1, 11)));
assert!(set.contain(ID::new(1, 18)));
assert!(set.contain(ID::new(1, 19)));
assert!(!set.contain(ID::new(1, 8)));
assert!(!set.contain(ID::new(1, 9)));
assert!(!set.contain(ID::new(1, 20)));
assert!(!set.contain(ID::new(1, 21)));
}
}

View file

@ -27,5 +27,6 @@ pub mod rle_tree;
mod rle_vec;
pub use crate::rle_trait::{HasLength, Mergable, Rle, Slice, Sliceable};
pub use crate::rle_vec::{RleVec, SearchResult, SliceIterator};
pub mod rle_impl;
pub use rle_tree::tree_trait::RleTreeTrait;
pub use rle_tree::RleTree;

View file

@ -100,9 +100,30 @@ impl<Index: GlobalIndex + 'static, Value: Rle + 'static> RangeMap<Index, Value>
pub fn get(&self, index: Index) -> Option<&Value> {
self.tree.with_tree(|tree| {
let cursor = tree.get(index);
cursor.map(|x| &x.as_tree_ref().value)
if let Some(cursor) = cursor {
match cursor.pos() {
crate::rle_tree::Position::Before
| crate::rle_tree::Position::End
| crate::rle_tree::Position::After => None,
crate::rle_tree::Position::Start | crate::rle_tree::Position::Middle => {
Some(&cursor.as_tree_ref().value)
}
}
} else {
None
}
})
}
#[inline]
pub fn has(&self, index: Index) -> bool {
self.get(index).is_some()
}
#[inline]
pub fn clear(&mut self) {
self.tree = Default::default();
}
}
#[derive(Debug)]

View file

@ -0,0 +1,7 @@
use crate::Sliceable;
impl Sliceable for bool {
fn slice(&self, _: usize, _: usize) -> Self {
*self
}
}