mirror of
https://github.com/loro-dev/loro.git
synced 2024-11-28 17:41:49 +00:00
feat: impl yata
This commit is contained in:
parent
5f6d66368e
commit
670d194aeb
6 changed files with 94 additions and 16 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -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",
|
||||
]
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)]
|
||||
|
|
7
crates/rle/src/rle_impl.rs
Normal file
7
crates/rle/src/rle_impl.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
use crate::Sliceable;
|
||||
|
||||
impl Sliceable for bool {
|
||||
fn slice(&self, _: usize, _: usize) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue