diff --git a/crates/loro-core/src/dag.rs b/crates/loro-core/src/dag.rs new file mode 100644 index 00000000..e69de29b diff --git a/crates/loro-core/src/lib.rs b/crates/loro-core/src/lib.rs index a8ff0038..b8c91195 100644 --- a/crates/loro-core/src/lib.rs +++ b/crates/loro-core/src/lib.rs @@ -6,16 +6,17 @@ pub mod change; pub mod configure; pub mod container; +pub mod dag; pub mod id; pub mod op; pub mod version; mod error; -mod id_span; mod log_store; mod loro; mod smstring; mod snapshot; +mod span; mod tests; mod value; diff --git a/crates/loro-core/src/log_store.rs b/crates/loro-core/src/log_store.rs index e6bf1039..453e9388 100644 --- a/crates/loro-core/src/log_store.rs +++ b/crates/loro-core/src/log_store.rs @@ -14,8 +14,8 @@ use crate::{ configure::Configure, container::{Container, ContainerID, ContainerManager}, id::{ClientID, Counter}, - id_span::IdSpan, op::OpProxy, + span::IdSpan, version::TotalOrderStamp, Lamport, Op, Timestamp, ID, }; diff --git a/crates/loro-core/src/op.rs b/crates/loro-core/src/op.rs index a5dac56c..7d6712f0 100644 --- a/crates/loro-core/src/op.rs +++ b/crates/loro-core/src/op.rs @@ -1,4 +1,8 @@ -use crate::{container::ContainerID, id::ID, id_span::IdSpan}; +use crate::{ + container::ContainerID, + id::ID, + span::{CounterSpan, IdSpan}, +}; use rle::{HasLength, Mergable, RleVec, Sliceable}; mod insert_content; mod op_content; @@ -47,7 +51,7 @@ impl Op { } #[inline] - pub fn new_delete_op(id: ID, container: ContainerID, target: RleVec) -> Self { + pub fn new_delete_op(id: ID, container: ContainerID, target: RleVec) -> Self { Op::new(id, OpContent::Undo { target }, container) } diff --git a/crates/loro-core/src/op/insert_content.rs b/crates/loro-core/src/op/insert_content.rs index e46151a6..7fb08a59 100644 --- a/crates/loro-core/src/op/insert_content.rs +++ b/crates/loro-core/src/op/insert_content.rs @@ -32,6 +32,7 @@ pub trait InsertContent: HasLength + std::fmt::Debug + Any + MergeableContent + SliceableContent + CloneContent { fn id(&self) -> ContentType; + // TODO: provide an encoding method } impl SliceableContent for T { diff --git a/crates/loro-core/src/op/op_content.rs b/crates/loro-core/src/op/op_content.rs index cdc3e66c..77372483 100644 --- a/crates/loro-core/src/op/op_content.rs +++ b/crates/loro-core/src/op/op_content.rs @@ -1,14 +1,19 @@ use rle::{HasLength, Mergable, RleVec, Sliceable}; -use crate::{container::ContainerID, id::ID, id_span::IdSpan, OpType}; +use crate::{ + container::ContainerID, + id::ID, + span::{CounterSpan, IdSpan}, + OpType, +}; use super::{InsertContent, MergeableContent}; #[derive(Debug)] pub enum OpContent { Normal { content: Box }, - Undo { target: RleVec }, - Redo { target: RleVec }, + Undo { target: RleVec }, + Redo { target: RleVec }, } impl OpContent { diff --git a/crates/loro-core/src/id_span.rs b/crates/loro-core/src/span.rs similarity index 60% rename from crates/loro-core/src/id_span.rs rename to crates/loro-core/src/span.rs index 23d2e954..966bf20d 100644 --- a/crates/loro-core/src/id_span.rs +++ b/crates/loro-core/src/span.rs @@ -1,16 +1,20 @@ -use crate::id::{ClientID, ID}; +use crate::id::{ClientID, Counter, ID}; use rle::{HasLength, Mergable, Slice, Sliceable}; #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct IdSpan { - pub client_id: ClientID, - pub from: usize, - pub to: usize, +pub struct CounterSpan { + pub from: Counter, + pub to: Counter, } -impl IdSpan { +impl CounterSpan { #[inline] - pub fn min(&self) -> usize { + pub fn new(from: Counter, to: Counter) -> Self { + CounterSpan { from, to } + } + + #[inline] + pub fn min(&self) -> Counter { if self.from < self.to { self.from } else { @@ -19,7 +23,7 @@ impl IdSpan { } #[inline] - pub fn max(&self) -> usize { + pub fn max(&self) -> Counter { if self.from > self.to { self.from } else { @@ -28,44 +32,90 @@ impl IdSpan { } } -impl HasLength for IdSpan { +impl HasLength for CounterSpan { + #[inline] fn len(&self) -> usize { if self.to > self.from { - self.to - self.from + (self.to - self.from) as usize } else { - self.from - self.to + (self.from - self.to) as usize } } } -impl Sliceable for IdSpan { +impl Sliceable for CounterSpan { fn slice(&self, from: usize, to: usize) -> Self { assert!(from <= to); let len = to - from; assert!(len <= self.len()); if self.from < self.to { - IdSpan { - client_id: self.client_id, - from: self.from + from, - to: self.from + to, + CounterSpan { + from: self.from + from as Counter, + to: self.from + to as Counter, } } else { - IdSpan { - client_id: self.client_id, - from: self.from - from, - to: self.from - to, + CounterSpan { + from: self.from - from as Counter, + to: self.from - to as Counter, } } } } +impl Mergable for CounterSpan { + #[inline] + fn is_mergable(&self, other: &Self, _: &()) -> bool { + self.to == other.from + } + + #[inline] + fn merge(&mut self, other: &Self, _: &()) { + self.to = other.to; + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub struct IdSpan { + pub client_id: ClientID, + pub counter: CounterSpan, +} + +impl IdSpan { + #[inline] + pub fn min(&self) -> Counter { + self.counter.min() + } + + #[inline] + pub fn max(&self) -> Counter { + self.counter.max() + } +} + +impl HasLength for IdSpan { + #[inline] + fn len(&self) -> usize { + self.counter.len() + } +} + +impl Sliceable for IdSpan { + #[inline] + fn slice(&self, from: usize, to: usize) -> Self { + IdSpan { + client_id: self.client_id, + counter: self.counter.slice(from, to), + } + } +} + impl Mergable for IdSpan { fn is_mergable(&self, other: &Self, _: &()) -> bool { - self.client_id == other.client_id && self.to == other.from + self.client_id == other.client_id && self.counter.is_mergable(&other.counter, &()) } fn merge(&mut self, other: &Self, _: &()) { - self.to = other.to; + self.counter.merge(&other.counter, &()) } } @@ -82,8 +132,7 @@ mod test_id_span { $( id_spans.push(IdSpan { client_id: $client_id, - from: $from, - to: $to, + counter: CounterSpan::new($from, $to), }); )* id_spans @@ -96,22 +145,19 @@ mod test_id_span { let mut id_span_vec = RleVec::new(); id_span_vec.push(IdSpan { client_id: 0, - from: 0, - to: 2, + counter: CounterSpan::new(0, 2), }); assert_eq!(id_span_vec.merged_len(), 1); assert_eq!(id_span_vec.len(), 2); id_span_vec.push(IdSpan { client_id: 0, - from: 2, - to: 4, + counter: CounterSpan::new(2, 4), }); assert_eq!(id_span_vec.merged_len(), 1); assert_eq!(id_span_vec.len(), 4); id_span_vec.push(IdSpan { client_id: 2, - from: 2, - to: 4, + counter: CounterSpan::new(2, 4), }); assert_eq!(id_span_vec.merged_len(), 2); assert_eq!(id_span_vec.len(), 6);