mirror of
https://github.com/loro-dev/loro.git
synced 2024-11-28 01:06:50 +00:00
docs: add comment for last&end
This commit is contained in:
parent
850cd722a4
commit
11b16e85cd
7 changed files with 38 additions and 23 deletions
|
@ -121,7 +121,7 @@ impl Tracker {
|
|||
let mut len = 0;
|
||||
for marker in self
|
||||
.id_to_cursor
|
||||
.get_range(id_span.min_id().into(), id_span.end_id().into())
|
||||
.get_range(id_span.norm_id_start().into(), id_span.norm_id_end().into())
|
||||
{
|
||||
for span in marker.get_spans(id_span) {
|
||||
len += span.len;
|
||||
|
|
|
@ -245,7 +245,9 @@ impl CursorMap {
|
|||
let mut deletes: Vec<(ID, RleVecWithLen<[IdSpan; 2]>)> =
|
||||
Vec::with_capacity(span.atom_len() / 10);
|
||||
let mut inserted_set = fxhash::FxHashSet::default();
|
||||
for (id, marker) in self.get_range_with_index(span.min_id().into(), span.end_id().into()) {
|
||||
for (id, marker) in
|
||||
self.get_range_with_index(span.norm_id_start().into(), span.norm_id_end().into())
|
||||
{
|
||||
let id: ID = id.into();
|
||||
match marker {
|
||||
Marker::Insert { .. } => {
|
||||
|
@ -265,7 +267,8 @@ impl CursorMap {
|
|||
Marker::Delete(del) => {
|
||||
if span.intersect(&id.to_span(del.atom_len())) {
|
||||
let from = (span.counter.min() - id.counter).max(0);
|
||||
let to = (span.counter.end() - id.counter).min(del.atom_len() as Counter);
|
||||
let to =
|
||||
(span.counter.norm_end() - id.counter).min(del.atom_len() as Counter);
|
||||
if to - from > 0 {
|
||||
deletes.push((id.inc(from), del.slice(from as usize, to as usize)));
|
||||
}
|
||||
|
@ -278,7 +281,9 @@ impl CursorMap {
|
|||
}
|
||||
|
||||
pub fn get_first_cursors_at_id_span(&self, span: IdSpan) -> Option<FirstCursorResult> {
|
||||
for (id, marker) in self.get_range_with_index(span.min_id().into(), span.end_id().into()) {
|
||||
for (id, marker) in
|
||||
self.get_range_with_index(span.norm_id_start().into(), span.norm_id_end().into())
|
||||
{
|
||||
let start_id: u128 = id.max(span.id_start().into());
|
||||
let end_id: u128 = span.id_end().into();
|
||||
let from = (start_id - id) as usize;
|
||||
|
|
|
@ -125,7 +125,7 @@ impl LogStore {
|
|||
let mut ans = Vec::with_capacity(id_span.atom_len() / 30);
|
||||
for change in changes.slice_iter(
|
||||
id_span.counter.min() as usize,
|
||||
id_span.counter.end() as usize,
|
||||
id_span.counter.norm_end() as usize,
|
||||
) {
|
||||
let change = change.value.slice(change.start, change.end);
|
||||
ans.push(change);
|
||||
|
|
|
@ -94,7 +94,7 @@ impl<'a> Iterator for OpSpanIter<'a> {
|
|||
let op = RichOp::new_by_slice_on_change(
|
||||
change,
|
||||
self.span.counter.min() - change.id.counter,
|
||||
self.span.counter.end() - change.id.counter,
|
||||
self.span.counter.norm_end() - change.id.counter,
|
||||
op,
|
||||
);
|
||||
if op.atom_len() == 0 {
|
||||
|
|
|
@ -88,7 +88,8 @@ impl CounterSpan {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn end(&self) -> i32 {
|
||||
/// This is different from end. start may be greater than end. This is the max of start+1 and end
|
||||
pub fn norm_end(&self) -> i32 {
|
||||
if self.start < self.end {
|
||||
self.end
|
||||
} else {
|
||||
|
@ -195,11 +196,6 @@ impl IdSpan {
|
|||
self.counter.end < self.counter.start
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn id_at_begin(&self) -> ID {
|
||||
ID::new(self.client_id, self.counter.start)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn reverse(&mut self) {
|
||||
self.counter.reverse();
|
||||
|
@ -210,14 +206,16 @@ impl IdSpan {
|
|||
self.counter.normalize_();
|
||||
}
|
||||
|
||||
/// This is different from id_start. id_start may be greater than id_end, but this is the min of id_start and id_end-1
|
||||
#[inline]
|
||||
pub fn min_id(&self) -> ID {
|
||||
pub fn norm_id_start(&self) -> ID {
|
||||
ID::new(self.client_id, self.counter.min())
|
||||
}
|
||||
|
||||
/// This is different from id_end. id_start may be greater than id_end. This is the max of id_start+1 and id_end
|
||||
#[inline]
|
||||
pub fn end_id(&self) -> ID {
|
||||
ID::new(self.client_id, self.counter.end())
|
||||
pub fn norm_id_end(&self) -> ID {
|
||||
ID::new(self.client_id, self.counter.norm_end())
|
||||
}
|
||||
|
||||
pub fn to_id_span_vec(self) -> IdSpanVector {
|
||||
|
@ -263,10 +261,12 @@ pub trait HasCounter {
|
|||
}
|
||||
|
||||
pub trait HasCounterSpan: HasCounter + HasLength {
|
||||
/// end is the exclusive end, last the inclusive end.
|
||||
fn ctr_end(&self) -> Counter {
|
||||
self.ctr_start() + self.atom_len() as Counter
|
||||
}
|
||||
|
||||
/// end is the exclusive end, last the inclusive end.
|
||||
fn ctr_last(&self) -> Counter {
|
||||
self.ctr_start() + self.atom_len() as Counter - 1
|
||||
}
|
||||
|
@ -312,10 +312,12 @@ pub trait HasIdSpan: HasId + HasLength {
|
|||
)
|
||||
}
|
||||
|
||||
/// end is the exclusive end, last the inclusive end.
|
||||
fn id_end(&self) -> ID {
|
||||
self.id_start().inc(self.content_len() as i32)
|
||||
}
|
||||
|
||||
/// end is the exclusive end, last the inclusive end.
|
||||
fn id_last(&self) -> ID {
|
||||
self.id_start().inc(self.content_len() as i32 - 1)
|
||||
}
|
||||
|
@ -337,10 +339,12 @@ pub trait HasLamport {
|
|||
}
|
||||
|
||||
pub trait HasLamportSpan: HasLamport + HasLength {
|
||||
/// end is the exclusive end, last the inclusive end.
|
||||
fn lamport_end(&self) -> Lamport {
|
||||
self.lamport() + self.content_len() as Lamport
|
||||
}
|
||||
|
||||
/// end is the exclusive end, last the inclusive end.
|
||||
fn lamport_last(&self) -> Lamport {
|
||||
self.lamport() + self.content_len() as Lamport - 1
|
||||
}
|
||||
|
@ -350,7 +354,7 @@ impl<T: HasLamport + HasLength> HasLamportSpan for T {}
|
|||
impl HasId for IdSpan {
|
||||
#[inline]
|
||||
fn id_start(&self) -> ID {
|
||||
self.min_id()
|
||||
self.norm_id_start()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -430,11 +430,11 @@ impl VersionVector {
|
|||
|
||||
pub fn extend_to_include(&mut self, span: IdSpan) {
|
||||
if let Some(counter) = self.get_mut(&span.client_id) {
|
||||
if *counter < span.counter.end() {
|
||||
*counter = span.counter.end();
|
||||
if *counter < span.counter.norm_end() {
|
||||
*counter = span.counter.norm_end();
|
||||
}
|
||||
} else {
|
||||
self.insert(span.client_id, span.counter.end());
|
||||
self.insert(span.client_id, span.counter.norm_end());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -667,12 +667,12 @@ impl PatchedVersionVector {
|
|||
};
|
||||
|
||||
if let Some(counter) = self.patch.get_mut(&span.client_id) {
|
||||
if *counter < span.counter.end() {
|
||||
*counter = span.counter.end();
|
||||
if *counter < span.counter.norm_end() {
|
||||
*counter = span.counter.norm_end();
|
||||
self.omit_if_needless(span.client_id);
|
||||
}
|
||||
} else {
|
||||
let target = span.counter.end();
|
||||
let target = span.counter.norm_end();
|
||||
if self.base.get(&span.client_id) == Some(&target) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
| Lamport | [Lamport timestamp](https://en.wikipedia.org/wiki/Lamport_timestamp) | |
|
||||
| Span | A series of continuous things | |
|
||||
| Causal Order | The order of happen-before relationship | The DAG expresses the causal order of the changes |
|
||||
| VV | [Version Vector](https://en.wikipedia.org/wiki/Version_vector) | |
|
||||
| VV | [Version Vector](https://en.wikipedia.org/wiki/Version_vector) | In code, it has exclusive end, `VV {0: 8}` means the last op id of client 0 is `0-7` |
|
||||
|
||||
|
||||
### RLE
|
||||
|
@ -32,3 +32,9 @@ This gives us a compact way to represent the mergeable elements.
|
|||
### Container
|
||||
|
||||
Each op is associated with one container. Different CRDT algorithms use different types of containers. There are hierarchical relationship between containers, but they cannot affect each other
|
||||
|
||||
# Convention
|
||||
|
||||
- There are methods like `id_last`, `id_end`, `lamport_last`, `lamport_end`. `last` refers to the last one, but
|
||||
`end` refers to the exclusive end of a range. For example, OpSpan ranging from 0-0 till 0-8 has id_last of 0-8
|
||||
and id_end of 0-9
|
||||
|
|
Loading…
Reference in a new issue