mirror of
https://github.com/loro-dev/loro.git
synced 2025-02-08 21:47:41 +00:00
* feat: delta rope support init * perf: use generic-btree v0.9.0 * refactor: improve readability and maintainability * fix: fix several issues about composing * fix: a few more issue about composing deletions * test: rich text * fix: cover more edge cases * refactor: use deltarope for list event * refactor: replace text delta with DeltaRope * fix: list fuzz err * fix: safety issue on insert_many * chore: refine impl of text delta * refactor: use Replace instead of insert+del in DeltaItem (#330) * refactor: use Replace instead of insert+del in DeltaItem * fix: each deltaitem should have non-zero rle_len Updated generic-btree dependency to version 0.10.3 and refactored DeltaItem and DeltaRope implementations in loro-delta. Refine compose impl * fix: update generic-btree to fix the update leaf issue * chore: lockfile * chore: clippy fix * refactor: make composing easier to understand * refactor: simplify the impl of composing
132 lines
3.6 KiB
Rust
132 lines
3.6 KiB
Rust
use generic_btree::{Cursor, LeafIndex};
|
|
|
|
use crate::{
|
|
delta_trait::{DeltaAttr, DeltaValue},
|
|
DeltaItem, DeltaRope,
|
|
};
|
|
|
|
pub struct Iter<'a, V: DeltaValue, Attr: DeltaAttr> {
|
|
delta: &'a DeltaRope<V, Attr>,
|
|
cursor: Option<LeafIndex>,
|
|
current: Option<DeltaItem<V, Attr>>,
|
|
}
|
|
|
|
impl<'a, V: DeltaValue, Attr: DeltaAttr> Iter<'a, V, Attr> {
|
|
pub fn new(delta: &'a DeltaRope<V, Attr>) -> Self {
|
|
let leaf = delta.tree.first_leaf();
|
|
let mut current = None;
|
|
if let Some(leaf) = leaf {
|
|
current = delta.tree.get_elem(leaf).cloned();
|
|
}
|
|
|
|
Self {
|
|
delta,
|
|
cursor: leaf,
|
|
current,
|
|
}
|
|
}
|
|
|
|
pub fn peek(&self) -> Option<&'_ DeltaItem<V, Attr>> {
|
|
self.current.as_ref()
|
|
}
|
|
|
|
pub fn next_with(&mut self, mut len: usize) -> Result<(), usize> {
|
|
while len > 0 {
|
|
let Some(current) = self.current.as_mut() else {
|
|
return Err(len);
|
|
};
|
|
|
|
if len >= current.delta_len() {
|
|
len -= current.delta_len();
|
|
self.cursor = self
|
|
.delta
|
|
.tree
|
|
.next_elem(Cursor {
|
|
leaf: self.cursor.unwrap(),
|
|
offset: 0,
|
|
})
|
|
.map(|x| x.leaf);
|
|
if let Some(leaf) = self.cursor {
|
|
self.current = self.delta.tree.get_elem(leaf).cloned();
|
|
} else {
|
|
self.current = None;
|
|
}
|
|
} else {
|
|
match current {
|
|
DeltaItem::Retain {
|
|
len: retain,
|
|
attr: _,
|
|
} => {
|
|
*retain -= len;
|
|
}
|
|
DeltaItem::Replace {
|
|
value,
|
|
attr: _,
|
|
delete,
|
|
} => {
|
|
if value.rle_len() > 0 {
|
|
value.slice_(len..);
|
|
} else {
|
|
*delete -= len;
|
|
}
|
|
}
|
|
}
|
|
len = 0;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Consume next `len` deletions in the current item
|
|
pub(crate) fn next_with_del(&mut self, mut len: usize) -> Result<(), usize> {
|
|
let Some(current) = self.current.as_mut() else {
|
|
return Err(len);
|
|
};
|
|
|
|
match current {
|
|
DeltaItem::Retain { .. } => return Err(len),
|
|
DeltaItem::Replace { delete, .. } => {
|
|
if *delete >= len {
|
|
*delete -= len;
|
|
len = 0;
|
|
} else {
|
|
len -= *delete;
|
|
*delete = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if current.delta_len() == 0 {
|
|
self.next();
|
|
}
|
|
|
|
if len > 0 {
|
|
Err(len)
|
|
} else {
|
|
Ok(())
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a, V: DeltaValue, Attr: DeltaAttr> Iterator for Iter<'a, V, Attr> {
|
|
type Item = DeltaItem<V, Attr>;
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
self.cursor = self
|
|
.delta
|
|
.tree
|
|
.next_elem(Cursor {
|
|
leaf: self.cursor.unwrap(),
|
|
offset: 0,
|
|
})
|
|
.map(|x| x.leaf);
|
|
let old_current = std::mem::take(&mut self.current);
|
|
if let Some(c) = self.cursor {
|
|
self.current = self.delta.tree.get_elem(c).cloned();
|
|
} else {
|
|
self.current = None;
|
|
}
|
|
old_current
|
|
}
|
|
}
|