diff --git a/Cargo.lock b/Cargo.lock index 08cb49a8..469b3895 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -147,6 +147,15 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitmaps" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +dependencies = [ + "typenum", +] + [[package]] name = "block-buffer" version = "0.10.3" @@ -666,6 +675,20 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "im" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" +dependencies = [ + "bitmaps", + "rand_core", + "rand_xoshiro", + "sized-chunks", + "typenum", + "version_check", +] + [[package]] name = "indexmap" version = "1.9.2" @@ -801,6 +824,7 @@ dependencies = [ "enum_dispatch", "flate2", "fxhash", + "im", "itertools", "js-sys", "num", @@ -1395,6 +1419,15 @@ dependencies = [ "rand_core", ] +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core", +] + [[package]] name = "rayon" version = "1.6.1" @@ -1635,6 +1668,16 @@ version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" +[[package]] +name = "sized-chunks" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" +dependencies = [ + "bitmaps", + "typenum", +] + [[package]] name = "smallvec" version = "1.10.0" diff --git a/crates/loro-internal/Cargo.toml b/crates/loro-internal/Cargo.toml index 9f766ec3..ae0069c9 100644 --- a/crates/loro-internal/Cargo.toml +++ b/crates/loro-internal/Cargo.toml @@ -32,6 +32,7 @@ tracing = { version = "0.1.37" } append-only-bytes = { version = "0.1.4", features = ["u32_range"] } itertools = "0.10.5" enum_dispatch = "0.3.11" +im = "15.1.0" [dev-dependencies] serde_json = "1.0.87" diff --git a/crates/loro-internal/src/refactor/arena.rs b/crates/loro-internal/src/refactor/arena.rs new file mode 100644 index 00000000..8470a880 --- /dev/null +++ b/crates/loro-internal/src/refactor/arena.rs @@ -0,0 +1,13 @@ +use im::Vector; + +use crate::container::{ContainerID, ContainerIdx}; + +/// This is shared between [OpLog] and [AppState]. +/// It uses a immutable data structure inside so that we have O(1) clone time. +/// It can make sharing data between threads easier. +/// +#[derive(Clone)] +pub(super) struct SharedArena { + containers: Vector, + id_to_idx: im::HashMap, +} diff --git a/crates/loro-internal/src/refactor/diff_calc.rs b/crates/loro-internal/src/refactor/diff_calc.rs new file mode 100644 index 00000000..7afc84fb --- /dev/null +++ b/crates/loro-internal/src/refactor/diff_calc.rs @@ -0,0 +1,19 @@ +use fxhash::FxHashMap; + +use crate::container::ContainerIdx; + +/// Calculate the diff between two versions. given [OpLog][super::oplog::OpLog] +/// and [AppState][super::state::AppState]. +pub(super) struct DiffCalculator { + calc: FxHashMap, +} + +enum ContainerDiffCalculator { + Text(TextDiffCalculator), + Map(MapDiffCalculator), + List(MapDiffCalculator), +} + +struct TextDiffCalculator {} +struct MapDiffCalculator {} +struct ListDiffCalculator {} diff --git a/crates/loro-internal/src/refactor/mod.rs b/crates/loro-internal/src/refactor/mod.rs index 3b6df870..2d7b2f7d 100644 --- a/crates/loro-internal/src/refactor/mod.rs +++ b/crates/loro-internal/src/refactor/mod.rs @@ -1,3 +1,5 @@ +pub(super) mod arena; mod container; +pub(super) mod diff_calc; pub mod oplog; mod state; diff --git a/crates/loro-internal/src/refactor/state.rs b/crates/loro-internal/src/refactor/state.rs index 288c3628..4461793e 100644 --- a/crates/loro-internal/src/refactor/state.rs +++ b/crates/loro-internal/src/refactor/state.rs @@ -1,7 +1,14 @@ use enum_dispatch::enum_dispatch; use fxhash::FxHashMap; -use crate::{container::ContainerID, InternalString, VersionVector}; +use crate::{ + container::{ContainerID, ContainerIdx}, + event::Diff, + version::Frontiers, + InternalString, VersionVector, +}; + +use super::arena::SharedArena; mod list; mod map; @@ -9,12 +16,15 @@ mod text; #[enum_dispatch] pub trait ContainerState: Clone { - fn apply_diff(&mut self); + fn apply_diff(&mut self, diff: Diff); } +#[derive(Clone)] pub struct AppState { vv: VersionVector, - state: FxHashMap, + frontiers: Frontiers, + state: FxHashMap, + arena: SharedArena, } #[enum_dispatch(ContainerState)] @@ -28,8 +38,29 @@ pub enum State { #[derive(Clone)] pub struct ListState {} +impl ContainerState for ListState { + fn apply_diff(&mut self, diff: Diff) {} +} + #[derive(Clone)] pub struct MapState {} +impl ContainerState for MapState { + fn apply_diff(&mut self, diff: Diff) {} +} #[derive(Clone)] pub struct TextState {} +impl ContainerState for TextState { + fn apply_diff(&mut self, diff: Diff) {} +} + +pub struct AppStateDiff { + from: VersionVector, + to: VersionVector, + changes: Vec, +} + +pub struct ContainerStateDiff { + id: ContainerIdx, + diff: Diff, +}