From f0f82fb581c034b7b725d1e8451aff5c201be0c7 Mon Sep 17 00:00:00 2001 From: Zixuan Chen Date: Wed, 5 Jul 2023 14:43:58 +0800 Subject: [PATCH] refactor: seal change exp impl --- crates/bench-utils/src/lib.rs | 2 +- crates/loro-ffi/build.rs | 2 +- crates/loro-internal/benches/encode.rs | 10 +-- crates/loro-internal/src/change.rs | 77 +++++++------------ crates/loro-internal/src/configure.rs | 5 +- .../src/container/list/list_container.rs | 1 - .../loro-internal/src/container/registry.rs | 5 +- .../src/container/text/text_content.rs | 6 +- crates/loro-internal/src/dag/iter.rs | 9 --- crates/loro-internal/src/log_store.rs | 39 +++------- .../src/log_store/encoding/encode_snapshot.rs | 16 ++-- crates/loro-internal/src/log_store/import.rs | 10 +-- crates/loro-internal/src/log_store/iter.rs | 17 ++-- crates/loro-internal/src/loro.rs | 13 ---- crates/loro-internal/src/refactor/arena.rs | 4 +- .../loro-internal/src/refactor/diff_calc.rs | 2 +- .../loro-internal/src/refactor/oplog/dag.rs | 6 +- crates/loro-internal/src/refactor/state.rs | 7 +- crates/loro-wasm/src/lib.rs | 1 - crates/rle/src/range_map.rs | 1 - crates/rle/src/rle_vec.rs | 54 ++++++++++++- crates/rle/src/rle_vec_old.rs | 2 +- 22 files changed, 116 insertions(+), 173 deletions(-) diff --git a/crates/bench-utils/src/lib.rs b/crates/bench-utils/src/lib.rs index 295f30b9..fcab8e8c 100644 --- a/crates/bench-utils/src/lib.rs +++ b/crates/bench-utils/src/lib.rs @@ -69,7 +69,7 @@ pub fn gen_realtime_actions(action_num: usize, client_num: usize, seed: u64) -> Action::Text { client, action } => { *client %= client_num; if !action.ins.is_empty() { - action.ins = (action.ins.as_bytes()[0] as u8).to_string(); + action.ins = (action.ins.as_bytes()[0]).to_string(); } } Action::SyncAll => { diff --git a/crates/loro-ffi/build.rs b/crates/loro-ffi/build.rs index d8460b5c..d621ee55 100644 --- a/crates/loro-ffi/build.rs +++ b/crates/loro-ffi/build.rs @@ -2,7 +2,7 @@ fn main() { let crate_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); let config = cbindgen::Config::from_file("cbindgen.toml") .expect("Unable to find cbindgen.toml configuration file"); - cbindgen::generate_with_config(&crate_dir, config) + cbindgen::generate_with_config(crate_dir, config) .unwrap() .write_to_file("target/loro_ffi.h"); } diff --git a/crates/loro-internal/benches/encode.rs b/crates/loro-internal/benches/encode.rs index e05a2e61..0b5b3350 100644 --- a/crates/loro-internal/benches/encode.rs +++ b/crates/loro-internal/benches/encode.rs @@ -124,7 +124,7 @@ mod run { mod import { use criterion::Criterion; - use loro_internal::{change::ChangeMergeCfg, configure::Configure, LoroCore}; + use loro_internal::{configure::Configure, LoroCore}; pub fn causal_iter(c: &mut Criterion) { let mut b = c.benchmark_group("causal_iter"); @@ -133,20 +133,12 @@ mod import { b.iter(|| { let mut c1 = LoroCore::new( Configure { - change: ChangeMergeCfg { - max_change_length: 0, - max_change_interval: 0, - }, ..Default::default() }, Some(1), ); let mut c2 = LoroCore::new( Configure { - change: ChangeMergeCfg { - max_change_length: 0, - max_change_interval: 0, - }, ..Default::default() }, Some(2), diff --git a/crates/loro-internal/src/change.rs b/crates/loro-internal/src/change.rs index 970eaafa..8dd000be 100644 --- a/crates/loro-internal/src/change.rs +++ b/crates/loro-internal/src/change.rs @@ -9,11 +9,11 @@ use crate::{ dag::DagNode, id::{Counter, ID}, op::Op, - span::{HasId, HasIdSpan, HasLamport}, + span::{HasId, HasLamport}, version::Frontiers, }; use num::traits::AsPrimitive; -use rle::{HasIndex, HasLength, Mergable, Rle, RleVec, Sliceable}; +use rle::{HasIndex, HasLength, Mergable, RleVec, Sliceable}; pub type Timestamp = i64; pub type Lamport = u32; @@ -52,6 +52,14 @@ impl Change { } } +impl HasIndex for Change { + type Int = Counter; + + fn get_start_index(&self) -> Self::Int { + self.id.counter + } +} + impl HasId for Change { fn id_start(&self) -> ID { self.id @@ -63,6 +71,23 @@ impl HasLamport for Change { self.lamport } } + +impl Mergable for Change { + fn is_mergable(&self, _other: &Self, _conf: &()) -> bool + where + Self: Sized, + { + false + } + + fn merge(&mut self, _other: &Self, _conf: &()) + where + Self: Sized, + { + unreachable!() + } +} + use std::fmt::Debug; impl HasLength for Change { fn content_len(&self) -> usize { @@ -70,54 +95,6 @@ impl HasLength for Change { } } -#[derive(Debug, Clone)] -pub struct ChangeMergeCfg { - pub max_change_length: usize, - pub max_change_interval: usize, -} - -impl ChangeMergeCfg { - pub fn new() -> Self { - ChangeMergeCfg { - max_change_length: 1024, - max_change_interval: 60, - } - } -} - -impl Default for ChangeMergeCfg { - fn default() -> Self { - Self { - max_change_length: 1024, - max_change_interval: 60, - } - } -} - -impl Mergable for Change { - fn merge(&mut self, other: &Self, _: &ChangeMergeCfg) { - self.ops.merge(&other.ops, &()); - } - - fn is_mergable(&self, other: &Self, cfg: &ChangeMergeCfg) -> bool { - if other.deps.is_empty() || !(other.deps.len() == 1 && self.id_last() == other.deps[0]) { - return false; - } - - if self.content_len() > cfg.max_change_length { - return false; - } - - if other.timestamp - self.timestamp > cfg.max_change_interval as i64 { - return false; - } - - self.id.peer == other.id.peer - && self.id.counter + self.content_len() as Counter == other.id.counter - && self.lamport + self.content_len() as Lamport == other.lamport - } -} - impl Sliceable for Change { // TODO: feels slow, need to confirm whether this affects performance fn slice(&self, from: usize, to: usize) -> Self { diff --git a/crates/loro-internal/src/configure.rs b/crates/loro-internal/src/configure.rs index 7817bced..ec11ef70 100644 --- a/crates/loro-internal/src/configure.rs +++ b/crates/loro-internal/src/configure.rs @@ -1,11 +1,10 @@ use std::{fmt::Debug, sync::Arc}; -use crate::{change::ChangeMergeCfg, log_store::GcConfig, Timestamp}; +use crate::{log_store::GcConfig, Timestamp}; use ring::rand::{SecureRandom, SystemRandom}; #[derive(Clone)] pub struct Configure { - pub change: ChangeMergeCfg, pub gc: GcConfig, pub get_time: fn() -> Timestamp, pub rand: Arc, @@ -14,7 +13,6 @@ pub struct Configure { impl Debug for Configure { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Configure") - .field("change", &self.change) .field("gc", &self.gc) .field("get_time", &self.get_time) .finish() @@ -57,7 +55,6 @@ impl SecureRandomGenerator for SystemRandom { impl Default for Configure { fn default() -> Self { Self { - change: ChangeMergeCfg::default(), gc: GcConfig::default(), get_time: || 0, rand: Arc::new(SystemRandom::new()), diff --git a/crates/loro-internal/src/container/list/list_container.rs b/crates/loro-internal/src/container/list/list_container.rs index de0fabcb..66cf2e63 100644 --- a/crates/loro-internal/src/container/list/list_container.rs +++ b/crates/loro-internal/src/container/list/list_container.rs @@ -27,7 +27,6 @@ use crate::{ prelim::Prelim, transaction::Transaction, value::LoroValue, - version::PatchedVersionVector, LoroError, Transact, VersionVector, }; diff --git a/crates/loro-internal/src/container/registry.rs b/crates/loro-internal/src/container/registry.rs index b08e83c2..ea83def1 100644 --- a/crates/loro-internal/src/container/registry.rs +++ b/crates/loro-internal/src/container/registry.rs @@ -1,5 +1,5 @@ use std::{ - ops::{Deref, DerefMut}, + ops::Deref, sync::{ atomic::{AtomicU32, Ordering}, Arc, Mutex, Weak, @@ -20,7 +20,6 @@ use crate::{ log_store::ImportContext, op::{RemoteContent, RichOp}, transaction::Transaction, - version::PatchedVersionVector, LoroError, LoroValue, Transact, VersionVector, }; @@ -346,6 +345,8 @@ impl ContainerRegistry { #[cfg(feature = "test_utils")] pub fn debug_inspect(&mut self) { + use std::ops::DerefMut; + for (_, ContainerAndId { container, id: _ }) in self.containers.iter_mut() { if let ContainerInstance::Text(x) = container.try_lock().unwrap().deref_mut() { x.debug_inspect() diff --git a/crates/loro-internal/src/container/text/text_content.rs b/crates/loro-internal/src/container/text/text_content.rs index ec9dbdcb..ab8ff8e7 100644 --- a/crates/loro-internal/src/container/text/text_content.rs +++ b/crates/loro-internal/src/container/text/text_content.rs @@ -5,11 +5,7 @@ use rle::{HasLength, Mergable, Sliceable}; use serde::{Deserialize, Serialize}; use smallvec::{smallvec, SmallVec}; -use crate::{ - delta::{DeltaItem, DeltaValue}, - smstring::SmString, - LoroValue, -}; +use crate::{delta::DeltaValue, smstring::SmString, LoroValue}; use super::string_pool::PoolString; diff --git a/crates/loro-internal/src/dag/iter.rs b/crates/loro-internal/src/dag/iter.rs index 386f0c77..901aa38e 100644 --- a/crates/loro-internal/src/dag/iter.rs +++ b/crates/loro-internal/src/dag/iter.rs @@ -365,7 +365,6 @@ impl<'a, T: DagNode + 'a, D: Dag> Iterator for DagCausalIter<'a, D> { #[cfg(test)] mod test { use crate::{ - change::ChangeMergeCfg, configure::Configure, dag::DagUtils, id::{Counter, ID}, @@ -441,20 +440,12 @@ mod test { fn parallel_case() { let mut c1 = LoroCore::new( Configure { - change: ChangeMergeCfg { - max_change_length: 0, - max_change_interval: 0, - }, ..Default::default() }, Some(1), ); let mut c2 = LoroCore::new( Configure { - change: ChangeMergeCfg { - max_change_length: 0, - max_change_interval: 0, - }, ..Default::default() }, Some(2), diff --git a/crates/loro-internal/src/log_store.rs b/crates/loro-internal/src/log_store.rs index c7190888..21655c71 100644 --- a/crates/loro-internal/src/log_store.rs +++ b/crates/loro-internal/src/log_store.rs @@ -16,10 +16,10 @@ use std::{ use fxhash::FxHashMap; -use rle::{HasLength, RleVec, RleVecWithIndex, Sliceable}; +use rle::{HasLength, RleVec, Sliceable}; use crate::{ - change::{Change, ChangeMergeCfg}, + change::Change, configure::Configure, container::{ registry::{ContainerIdx, ContainerInstance, ContainerRegistry}, @@ -59,7 +59,7 @@ impl GcConfig { } } -pub(crate) type ClientChanges = FxHashMap>; +pub(crate) type ClientChanges = FxHashMap>; pub(crate) type RemoteClientChanges = FxHashMap>>; #[derive(Debug)] @@ -107,7 +107,7 @@ impl LogStore { pub fn lookup_change(&self, id: ID) -> Option<&Change> { self.changes.get(&id.peer).and_then(|changes| { if id.counter <= changes.last().unwrap().id_last().counter { - Some(changes.get(id.counter as usize).unwrap().element) + Some(changes.get_by_atom_index(id.counter).unwrap().element) } else { None } @@ -131,10 +131,7 @@ impl LogStore { fn get_changes_slice(&self, id_span: IdSpan) -> Vec { if let Some(changes) = self.changes.get(&id_span.client_id) { 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.norm_end() as usize, - ) { + for change in changes.slice_iter(id_span.counter.min(), id_span.counter.norm_end()) { let change = change.value.slice(change.start, change.end); ans.push(change); } @@ -273,10 +270,9 @@ impl LogStore { self.latest_lamport = lamport + change.content_len() as u32 - 1; self.latest_timestamp = timestamp; self.vv.set_end(change.id_end()); - let cfg = self.get_change_merge_cfg(); self.changes .entry(self.this_client_id) - .or_insert_with(|| RleVecWithIndex::new_with_conf(cfg)) + .or_default() .push(change); } @@ -295,7 +291,7 @@ impl LogStore { self.changes .get(&id.peer) .map_or(0, |changes| changes.atom_len()) - > id.counter as usize + > id.counter } #[inline] @@ -325,21 +321,6 @@ impl LogStore { &self.vv } - fn get_change_merge_cfg(&self) -> ChangeMergeCfg { - ChangeMergeCfg { - max_change_length: self.cfg.change.max_change_length, - max_change_interval: self.cfg.change.max_change_interval, - } - } - - pub(crate) fn max_change_length(&mut self, max_change_length: usize) { - self.cfg.change.max_change_length = max_change_length - } - - pub(crate) fn max_change_interval(&mut self, max_change_interval: usize) { - self.cfg.change.max_change_interval = max_change_interval - } - pub(crate) fn gc(&mut self, gc: bool) { self.cfg.gc.gc = gc; } @@ -355,12 +336,12 @@ impl LogStore { self.changes.len(), self.changes .values() - .map(|v| format!("{}", v.vec().len())) + .map(|v| format!("{}", v.len())) .collect::>() .join(", "), self.changes .values() - .map(|v| format!("{}", v.vec().iter().map(|x| x.ops.len()).sum::())) + .map(|v| format!("{}", v.iter().map(|x| x.ops.len()).sum::())) .collect::>() .join(", "), self.changes @@ -415,7 +396,7 @@ impl Dag for LogStore { fn get(&self, id: ID) -> Option<&Self::Node> { self.changes .get(&id.peer) - .and_then(|x| x.get(id.counter as usize).map(|x| x.element)) + .and_then(|x| x.get_by_atom_index(id.counter).map(|x| x.element)) } fn frontier(&self) -> &[ID] { diff --git a/crates/loro-internal/src/log_store/encoding/encode_snapshot.rs b/crates/loro-internal/src/log_store/encoding/encode_snapshot.rs index ae9a4c0c..5df024a0 100644 --- a/crates/loro-internal/src/log_store/encoding/encode_snapshot.rs +++ b/crates/loro-internal/src/log_store/encoding/encode_snapshot.rs @@ -2,13 +2,12 @@ use std::collections::VecDeque; use fxhash::FxHashMap; use itertools::Itertools; -use rle::{HasLength, RleVec, RleVecWithIndex}; +use rle::{HasLength, RleVec, RleVecWithLen}; use serde::{Deserialize, Serialize}; use serde_columnar::{columnar, from_bytes, to_vec}; -use smallvec::SmallVec; use crate::{ - change::{Change, ChangeMergeCfg}, + change::Change, container::text::text_content::SliceRange, container::{ list::list_op::{DeleteSpan, InnerListOp}, @@ -21,7 +20,7 @@ use crate::{ event::EventDiff, hierarchy::Hierarchy, id::{Counter, PeerID, ID}, - log_store::{encoding::encode_changes::get_lamport_by_deps, ImportContext}, + log_store::{encoding::encode_changes::get_lamport_by_deps, ClientChanges, ImportContext}, op::{InnerContent, Op}, span::HasLamportSpan, version::{Frontiers, TotalOrderStamp}, @@ -454,7 +453,7 @@ pub(super) fn decode_snapshot( } // calculate lamport let mut lamport_map = FxHashMap::default(); - let mut changes = FxHashMap::default(); + let mut changes: ClientChanges = FxHashMap::default(); let mut client_ids: VecDeque<_> = changes_dq.keys().copied().collect(); let len = client_ids.len(); let mut loop_time = len; @@ -468,10 +467,7 @@ pub(super) fn decode_snapshot( change.id.counter..change.id.counter + change.content_len() as Counter, lamport, )); - changes - .entry(client_id) - .or_insert_with(|| RleVecWithIndex::new_with_conf(ChangeMergeCfg::new())) - .push(change); + changes.entry(client_id).or_default().push(change); loop_time = len; } Err(_not_found_client) => { @@ -531,7 +527,7 @@ fn load_snapshot( new_store: &mut LogStore, new_hierarchy: &mut Hierarchy, vv: VersionVector, - changes: FxHashMap>, + changes: ClientChanges, containers: Vec, container_states: Vec, keys: &[InternalString], diff --git a/crates/loro-internal/src/log_store/import.rs b/crates/loro-internal/src/log_store/import.rs index 6afaca96..a7493cef 100644 --- a/crates/loro-internal/src/log_store/import.rs +++ b/crates/loro-internal/src/log_store/import.rs @@ -4,7 +4,6 @@ use crate::hierarchy::Hierarchy; use crate::id::{Counter, PeerID, ID}; use crate::op::RemoteOp; use crate::span::{CounterSpan, HasCounter, HasCounterSpan}; -use crate::version::PatchedVersionVector; use crate::LogStore; use crate::{ container::registry::ContainerIdx, @@ -13,13 +12,12 @@ use crate::{ }; use itertools::Itertools; use smallvec::{smallvec, SmallVec}; -use std::sync::Arc; use std::{collections::VecDeque, sync::MutexGuard}; use tracing::instrument; use fxhash::{FxHashMap, FxHashSet}; -use rle::{slice_vec_by, HasLength, RleVecWithIndex, Sliceable}; +use rle::{slice_vec_by, HasLength, Sliceable}; use crate::{ container::{registry::ContainerInstance, ContainerID, ContainerTrait}, @@ -173,7 +171,6 @@ impl LogStore { next_vv.set_end(changes.last().unwrap().id_end()); } // push changes to log stores - let cfg = self.get_change_merge_cfg(); for (client_id, changes) in changes.iter() { let mut inner_changes = Vec::with_capacity(changes.len()); for change in changes.iter() { @@ -182,10 +179,7 @@ impl LogStore { inner_changes.push(change); } - let rle = self - .changes - .entry(*client_id) - .or_insert_with(|| RleVecWithIndex::new_cfg(cfg.clone())); + let rle = self.changes.entry(*client_id).or_default(); for change in inner_changes { // if let Some(last) = rle.last() { // assert_eq!( diff --git a/crates/loro-internal/src/log_store/iter.rs b/crates/loro-internal/src/log_store/iter.rs index b30ca66c..e1f3fabc 100644 --- a/crates/loro-internal/src/log_store/iter.rs +++ b/crates/loro-internal/src/log_store/iter.rs @@ -9,17 +9,15 @@ use crate::span::IdSpan; use fxhash::FxHashMap; use rle::HasLength; - -use crate::change::ChangeMergeCfg; +use rle::RleVec; +use rle::RleVecWithLen; use crate::change::Change; -use rle::RleVecWithIndex; - pub struct ClientOpIter<'a> { pub(crate) change_index: usize, pub(crate) op_index: usize, - pub(crate) changes: Option<&'a RleVecWithIndex>, + pub(crate) changes: Option<&'a RleVec<[Change; 0]>>, } impl<'a> Iterator for ClientOpIter<'a> { @@ -50,14 +48,11 @@ pub struct OpSpanIter<'a> { } impl<'a> OpSpanIter<'a> { - pub fn new( - changes: &'a FxHashMap>, - target_span: IdSpan, - ) -> Self { + pub fn new(changes: &'a FxHashMap>, target_span: IdSpan) -> Self { let rle_changes = changes.get(&target_span.client_id).unwrap(); let changes = rle_changes.vec(); let change_index = rle_changes - .get(target_span.id_start().counter as usize) + .get_by_atom_index(target_span.id_start().counter) .map(|x| x.merged_index) .unwrap_or(changes.len()); @@ -67,7 +62,7 @@ impl<'a> OpSpanIter<'a> { change_index, op_index: rle_changes[change_index] .ops - .get(target_span.counter.start) + .get_by_atom_index(target_span.counter.start) .unwrap() .merged_index, } diff --git a/crates/loro-internal/src/loro.rs b/crates/loro-internal/src/loro.rs index 9c67661c..3fe0cc98 100644 --- a/crates/loro-internal/src/loro.rs +++ b/crates/loro-internal/src/loro.rs @@ -200,19 +200,6 @@ impl LoroCore { } // config - pub fn max_change_length(&mut self, max_change_length: usize) { - self.log_store - .write() - .unwrap() - .max_change_length(max_change_length); - } - - pub fn max_change_interval(&mut self, max_change_interval: usize) { - self.log_store - .write() - .unwrap() - .max_change_interval(max_change_interval); - } pub fn gc(&mut self, gc: bool) { self.log_store.write().unwrap().gc(gc) diff --git a/crates/loro-internal/src/refactor/arena.rs b/crates/loro-internal/src/refactor/arena.rs index 11db3026..105a07b3 100644 --- a/crates/loro-internal/src/refactor/arena.rs +++ b/crates/loro-internal/src/refactor/arena.rs @@ -1,6 +1,4 @@ -use im::Vector; - -use crate::container::{ContainerID, ContainerIdx}; +use crate::container::ContainerID; /// This is shared between [OpLog] and [AppState]. /// It uses a immutable data structure inside so that we have O(1) clone time. diff --git a/crates/loro-internal/src/refactor/diff_calc.rs b/crates/loro-internal/src/refactor/diff_calc.rs index f63f2aa8..2c2a5e6b 100644 --- a/crates/loro-internal/src/refactor/diff_calc.rs +++ b/crates/loro-internal/src/refactor/diff_calc.rs @@ -1,6 +1,6 @@ use fxhash::FxHashMap; -use crate::container::{ContainerID, ContainerIdx}; +use crate::container::ContainerID; /// Calculate the diff between two versions. given [OpLog][super::oplog::OpLog] /// and [AppState][super::state::AppState]. diff --git a/crates/loro-internal/src/refactor/oplog/dag.rs b/crates/loro-internal/src/refactor/oplog/dag.rs index fa064397..a497dabd 100644 --- a/crates/loro-internal/src/refactor/oplog/dag.rs +++ b/crates/loro-internal/src/refactor/oplog/dag.rs @@ -72,7 +72,7 @@ impl Dag for AppDag { } = id; self.map .get(&client_id) - .and_then(|rle| rle.get(counter).map(|x| x.element)) + .and_then(|rle| rle.get_by_atom_index(counter).map(|x| x.element)) } fn vv(&self) -> VersionVector { @@ -85,7 +85,7 @@ impl AppDag { /// It's the version when the op is applied pub fn get_vv(&self, id: ID) -> Option { self.map.get(&id.peer).and_then(|rle| { - rle.get(id.counter).map(|x| { + rle.get_by_atom_index(id.counter).map(|x| { let mut vv = x.element.vv.clone(); vv.insert(id.peer, id.counter); vv @@ -107,7 +107,7 @@ impl AppDag { pub fn get_lamport(&self, id: &ID) -> Option { self.map.get(&id.peer).and_then(|rle| { - rle.get(id.counter) + rle.get_by_atom_index(id.counter) .map(|x| x.element.lamport + (id.counter - x.element.cnt) as Lamport) }) } diff --git a/crates/loro-internal/src/refactor/state.rs b/crates/loro-internal/src/refactor/state.rs index 5b28fedf..e4e813f7 100644 --- a/crates/loro-internal/src/refactor/state.rs +++ b/crates/loro-internal/src/refactor/state.rs @@ -1,12 +1,7 @@ use enum_dispatch::enum_dispatch; use fxhash::FxHashMap; -use crate::{ - container::{ContainerID, ContainerIdx}, - event::Diff, - version::Frontiers, - VersionVector, -}; +use crate::{container::ContainerID, event::Diff, version::Frontiers, VersionVector}; use super::arena::SharedArena; diff --git a/crates/loro-wasm/src/lib.rs b/crates/loro-wasm/src/lib.rs index ed825e5b..38d96f2c 100644 --- a/crates/loro-wasm/src/lib.rs +++ b/crates/loro-wasm/src/lib.rs @@ -112,7 +112,6 @@ impl Loro { #[wasm_bindgen(constructor)] pub fn new() -> Self { let cfg: Configure = Configure { - change: Default::default(), gc: GcConfig::default().with_gc(false), get_time: || js_sys::Date::now() as i64, rand: Arc::new(MathRandom), diff --git a/crates/rle/src/range_map.rs b/crates/rle/src/range_map.rs index 940bef62..ebfdc19b 100644 --- a/crates/rle/src/range_map.rs +++ b/crates/rle/src/range_map.rs @@ -485,7 +485,6 @@ impl Mergable for WithStartEnd #[cfg(test)] mod test { - use std::ops::Range; use super::*; #[derive(Debug, PartialEq, Eq, Clone)] diff --git a/crates/rle/src/rle_vec.rs b/crates/rle/src/rle_vec.rs index 0884976a..e3917802 100644 --- a/crates/rle/src/rle_vec.rs +++ b/crates/rle/src/rle_vec.rs @@ -96,7 +96,7 @@ where &self, index: ::Int, ) -> Option::Int>> { - self.vec.get(index) + self.vec.get_by_atom_index(index) } pub fn iter_by_index( @@ -279,13 +279,13 @@ where return SliceIterator::new_empty(); } - let start = self.get(from); + let start = self.get_by_atom_index(from); if start.is_none() { return SliceIterator::new_empty(); } let start = start.unwrap(); - let end = self.get(to); + let end = self.get_by_atom_index(to); if let Some(end) = end { SliceIterator { vec: &self.vec, @@ -317,7 +317,7 @@ where /// get the element at the given atom index. /// return: (element, merged_index, offset) - pub fn get( + pub fn get_by_atom_index( &self, index: ::Int, ) -> Option::Int>> { @@ -355,10 +355,56 @@ where }) } + pub fn slice_iter( + &self, + from: ::Int, + to: ::Int, + ) -> SliceIterator { + if from == to || self.merged_len() == 0 { + return SliceIterator::new_empty(); + } + + let from_result = self.get_by_atom_index(from); + if from_result.is_none() { + return SliceIterator::new_empty(); + } + + let from_result = from_result.unwrap(); + let to_result = if to == self.atom_len() { + None + } else { + self.get_by_atom_index(to) + }; + if let Some(to_result) = to_result { + SliceIterator { + vec: &self.vec, + cur_index: from_result.merged_index, + cur_offset: from_result.offset.as_(), + end_index: Some(to_result.merged_index), + end_offset: Some(to_result.offset.as_()), + } + } else { + SliceIterator { + vec: &self.vec, + cur_index: from_result.merged_index, + cur_offset: from_result.offset.as_(), + end_index: None, + end_offset: None, + } + } + } + #[inline] pub fn slice_merged(&self, range: Range) -> &[A::Item] { &self.vec[range] } + + pub fn atom_len(&self) -> ::Int { + self.vec + .last() + .map(|x| x.get_end_index()) + .unwrap_or(::Int::from_usize(0).unwrap()) + } } impl RleVec where diff --git a/crates/rle/src/rle_vec_old.rs b/crates/rle/src/rle_vec_old.rs index 1105c253..d0b8a7b4 100644 --- a/crates/rle/src/rle_vec_old.rs +++ b/crates/rle/src/rle_vec_old.rs @@ -345,7 +345,7 @@ impl Deref for RleVecWithIndex { #[cfg(test)] mod test { mod prime_value { - use crate::{Mergable, RleVecWithIndex, Sliceable}; + use crate::{Mergable, RleVecWithIndex}; impl Mergable for String { fn is_mergable(&self, _: &Self, _: &()) -> bool {