diff --git a/Cargo.lock b/Cargo.lock index a618abd0b..caefad866 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1528,22 +1528,56 @@ name = "loro" version = "1.10.3" dependencies = [ "anyhow", + "append-only-bytes", + "arbitrary", + "arref", "base64", + "bench-utils", + "bytes", + "criterion 0.7.0", "ctor 0.2.9", "dev-utils", + "either", + "ensure-cov", "enum-as-inner 0.6.1", + "enum_dispatch", "generic-btree", + "getrandom 0.2.16", + "im", + "itertools 0.12.1", + "js-sys", + "leb128", "loom", "loro-common 1.10.0", "loro-delta 1.9.1", - "loro-internal 1.10.3", "loro-kv-store 1.10.0", + "loro-rle 1.6.0", + "loro_fractional_index 1.6.0", + "md5", + "miniz_oxide 0.7.4", + "nonmax", + "num", + "num-traits", + "once_cell", + "parking_lot", + "pest", + "pest_derive", + "postcard", "pretty_assertions", "rand 0.8.5", "rustc-hash", + "serde", + "serde_columnar", "serde_json", "serial_test", + "smallvec", + "tabled 0.10.0", + "thiserror 1.0.69", + "thread_local", "tracing", + "wasm-bindgen", + "xxhash-rust", + "zstd", ] [[package]] @@ -1724,60 +1758,6 @@ dependencies = [ "xxhash-rust", ] -[[package]] -name = "loro-internal" -version = "1.10.3" -dependencies = [ - "append-only-bytes", - "arbitrary", - "arref", - "bench-utils", - "bytes", - "criterion 0.7.0", - "ctor 0.1.26", - "dev-utils", - "either", - "ensure-cov", - "enum-as-inner 0.6.1", - "enum_dispatch", - "generic-btree", - "getrandom 0.2.16", - "im", - "itertools 0.12.1", - "js-sys", - "leb128", - "loom", - "loro-common 1.10.0", - "loro-delta 1.9.1", - "loro-kv-store 1.10.0", - "loro-rle 1.6.0", - "loro_fractional_index 1.6.0", - "md5", - "miniz_oxide 0.7.4", - "nonmax", - "num", - "num-traits", - "once_cell", - "parking_lot", - "pest", - "pest_derive", - "postcard", - "pretty_assertions", - "rand 0.8.5", - "rustc-hash", - "serde", - "serde_columnar", - "serde_json", - "smallvec", - "tabled 0.10.0", - "thiserror 1.0.69", - "thread_local", - "tracing", - "wasm-bindgen", - "xxhash-rust", - "zstd", -] - [[package]] name = "loro-kv-store" version = "0.16.2" @@ -1873,13 +1853,13 @@ checksum = "3f3d053a135388e6b1df14e8af1212af5064746e9b87a06a345a7a779ee9695a" [[package]] name = "loro-wasm" -version = "1.10.4" +version = "1.10.5" dependencies = [ "console_error_panic_hook", "js-sys", + "loro 1.10.3", "loro-common 1.10.0", "loro-delta 1.9.1", - "loro-internal 1.10.3", "loro-rle 1.6.0", "parking_lot", "serde", diff --git a/Cargo.toml b/Cargo.toml index 51abe7d37..3c792e90f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,6 @@ members = [ "crates/bench-utils", "crates/rle", "crates/loro-common", - "crates/loro-internal", "crates/loro-wasm", "crates/fuzz", "crates/fractional_index", diff --git a/crates/loro-internal/benches/automerge-paper.json.gz b/crates/bench-utils/data/automerge-paper.json.gz similarity index 100% rename from crates/loro-internal/benches/automerge-paper.json.gz rename to crates/bench-utils/data/automerge-paper.json.gz diff --git a/crates/bench-utils/src/lib.rs b/crates/bench-utils/src/lib.rs index 49534cb28..d17a4ab7e 100644 --- a/crates/bench-utils/src/lib.rs +++ b/crates/bench-utils/src/lib.rs @@ -26,7 +26,7 @@ pub trait ActionTrait: Clone + std::fmt::Debug { pub fn get_automerge_actions() -> Vec { const RAW_DATA: &[u8; 901823] = - include_bytes!("../../loro-internal/benches/automerge-paper.json.gz"); + include_bytes!("../data/automerge-paper.json.gz"); let mut actions = Vec::new(); let mut d = GzDecoder::new(&RAW_DATA[..]); let mut s = String::new(); diff --git a/crates/fuzz/src/crdt_fuzzer.rs b/crates/fuzz/src/crdt_fuzzer.rs index c9c759760..231e72e1c 100644 --- a/crates/fuzz/src/crdt_fuzzer.rs +++ b/crates/fuzz/src/crdt_fuzzer.rs @@ -591,14 +591,14 @@ pub fn test_multi_sites_with_gc( "export_shallow_snapshot", "shallow_snapshot::need_calc", "shallow_snapshot::dont_need_calc", - "loro_internal::history_cache::find_text_chunks_in", - "loro_internal::history_cache::find_list_chunks_in", - "loro_internal::import", - "loro_internal::import::fast_snapshot::decode_snapshot", - "loro_internal::import::snapshot", - "loro_internal::import::snapshot::gc", - "loro_internal::import::snapshot::normal", - "loro_internal::history_cache::init_cache_by_visit_all_change_slow::visit_gc", + "loro::internal::history_cache::find_text_chunks_in", + "loro::internal::history_cache::find_list_chunks_in", + "loro::internal::import", + "loro::internal::import::fast_snapshot::decode_snapshot", + "loro::internal::import::snapshot", + "loro::internal::import::snapshot::gc", + "loro::internal::import::snapshot::normal", + "loro::internal::history_cache::init_cache_by_visit_all_change_slow::visit_gc", "kv-store::SstableIter::new_scan::start included", "kv-store::SstableIter::new_scan::start excluded", "kv-store::SstableIter::new_scan::start unbounded", @@ -606,8 +606,8 @@ pub fn test_multi_sites_with_gc( "kv-store::SstableIter::new_scan::end excluded", "kv-store::SstableIter::new_scan::end unbounded", "kv-store::SstableIter::new_scan::end unbounded equal", - "loro_internal::handler::movable_list_apply_delta::process_replacements::mov_0", - "loro_internal::handler::movable_list_apply_delta::process_replacements::mov_1", + "loro::internal::handler::movable_list_apply_delta::process_replacements::mov_0", + "loro::internal::handler::movable_list_apply_delta::process_replacements::mov_1", ]; for v in must_meet { let count = ensure_cov::get_cov_for(v); diff --git a/crates/loro-common/README.md b/crates/loro-common/README.md index f0ad75599..440531952 100644 --- a/crates/loro-common/README.md +++ b/crates/loro-common/README.md @@ -1,4 +1,4 @@ # loro-common This crate contains the common basic types for the Loro project. -It's shared by `loro-internal` and `loro-preload`. +It's shared by `loro` and `loro-preload`. diff --git a/crates/loro-internal/.gitignore b/crates/loro-internal/.gitignore deleted file mode 100644 index 1b5d04358..000000000 --- a/crates/loro-internal/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*dhat-heap.json diff --git a/crates/loro-internal/Cargo.toml b/crates/loro-internal/Cargo.toml deleted file mode 100644 index 198c12282..000000000 --- a/crates/loro-internal/Cargo.toml +++ /dev/null @@ -1,130 +0,0 @@ -[package] -name = "loro-internal" -version = "1.10.3" -edition = "2021" -license = "MIT" -description = "Loro internal library. Do not use it directly as it's not stable." -documentation = "https://docs.rs/loro/" -homepage = "https://loro.dev" -repository = "https://github.com/loro-dev/loro/" -authors = ["Zixuan Chen", "Liang Zhao"] -categories = [] -keywords = ["crdt", "local-first"] - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -generic-btree = { version = "^0.10.7" } -smallvec = { workspace = true } -loro-delta = { path = "../delta", version = "1.9.1", package = "loro-delta" } -rle = { path = "../rle", version = "1.6.0", package = "loro-rle" } -loro-common = { path = "../loro-common", version = "1.10.0" } -fractional_index = { path = "../fractional_index", features = [ - "serde", -], version = "1.6.0", package = "loro_fractional_index" } -loro-kv-store = { path = "../kv-store", version = "1.10.0" } -rustc-hash = { workspace = true } -serde = { workspace = true } -thiserror = { workspace = true } -enum-as-inner = { workspace = true } -serde_json = { workspace = true } -bytes = { workspace = true } -xxhash-rust = { workspace = true } -serde_columnar = { workspace = true } -itertools = { workspace = true } -enum_dispatch = { workspace = true } -once_cell = { workspace = true } -arbitrary = { version = "1", optional = true } -postcard = { version = "1", features = ["use-std"] } -append-only-bytes = { version = "0.1.12", features = ["u32_range"] } -im = { version = "15.1.0", features = ["serde"] } -tabled = { version = "0.10.0", optional = true } -wasm-bindgen = { version = "=0.2.100", optional = true } -js-sys = { version = "0.3.60", optional = true } -num = "0.4.0" -rand = { version = "0.8.5" } -getrandom = "0.2.15" -leb128 = "0.2.5" -num-traits = "0.2" -either = "1" -md5 = "0.7.0" -arref = "0.1.0" -tracing = { version = "0.1" } -nonmax = "0.5.5" -ensure-cov = { workspace = true } -pretty_assertions = "1.4.1" -thread_local = "1.1.8" -parking_lot = "0.12.5" -pest = "2.8.3" -pest_derive = "2.8.3" - -[target.'cfg(loom)'.dependencies] -loom = { version = "0.7", features = ["checkpoint"] } - -[lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(loom)'] } - -[target.'cfg(target_arch = "wasm32")'.dependencies.getrandom] -version = "0.2.15" -features = ["js"] - -[target.'cfg(all(target_arch = "wasm32", not(features = "wasm")))'.dependencies] -wasm-bindgen = "0.2.100" - -[dev-dependencies] -arbitrary = { version = "1" } -miniz_oxide = "0.7.1" -rand = { version = "0.8.5" } -tabled = "0.10.0" -ctor = "0.1.23" -bench-utils = { path = "../bench-utils" } -dev-utils = { path = "../dev-utils" } -zstd = "0.13.0" -criterion = { version = "0.7.0", features = ["html_reports"] } - -# See https://matklad.github.io/2021/02/27/delete-cargo-integration-tests.html -[lib] -doctest = false -bench = false - -[features] -# "wasm" will use utf-16 index by default when using text related stuff; But it'll use utf-8 encoding internally. -wasm = ["wasm-bindgen", "js-sys", "loro-common/wasm"] -# whether to use list slice instead of raw str in text container -test_utils = ["arbitrary", "tabled"] -# whether enable the counter container -counter = ["loro-common/counter"] -logging = ["loro-common/logging"] -jsonpath = [] - -[[bench]] -name = "text_r" -harness = false - -[[bench]] -name = "list" -harness = false - -[[bench]] -name = "encode" -harness = false - -[[bench]] -name = "pending" -harness = false - -[[bench]] -name = "event" -harness = false - -[[bench]] -name = "map" -harness = false - -[[bench]] -name = "tree" -harness = false - -[[bench]] -name = "jsonpath" -harness = false diff --git a/crates/loro-internal/Encoding.md b/crates/loro-internal/Encoding.md deleted file mode 100644 index 2815951a6..000000000 --- a/crates/loro-internal/Encoding.md +++ /dev/null @@ -1,25 +0,0 @@ -# Encoding Schema - -## Header - -The header has 22 bytes. - -- (0-4 bytes) Magic Bytes: The encoding starts with `loro` as magic bytes. -- (4-20 bytes) Checksum: MD5/xxhash checksum of the encoded data, including the header starting from 20th bytes. The checksum is encoded as a 16-byte array (for xxhash, the first 12 bytes are padded with 0). The `checksum` and `magic bytes` fields are trimmed when calculating the checksum. -- (20-21 bytes) Encoding Method (2 bytes, big endian): Multiple encoding methods are available for a specific encoding version. - -## Encode Mode: Updates - -In this approach, only ops, specifically their historical record, are encoded, while document states are excluded. - -Like Automerge's format, we employ columnar encoding for operations and changes. - -Previously, operations were ordered by their Operation ID (OpId) before columnar encoding. However, sorting operations based on their respective containers initially enhance compression potential. - -## Encode Mode: Snapshot - -This mode simultaneously captures document state and historical data. Upon importing a snapshot into a new document, initialization occurs directly from the snapshot, bypassing the need for CRDT-based recalculations. - -Unlike previous snapshot encoding methods, the current binary output in snapshot mode is compatible with the updates mode. This enhances the efficiency of importing snapshots into non-empty documents, where initialization via snapshot is infeasible. - -Additionally, when feasible, we leverage the sequence of operations to construct state snapshots. In CRDTs, deducing the specific ops constituting the current container state is feasible. These ops are tagged in relation to the container, facilitating direct state reconstruction from them. This approach, pioneered by Automerge, significantly improves compression efficiency. diff --git a/crates/loro-internal/README.md b/crates/loro-internal/README.md deleted file mode 100644 index d66d799e5..000000000 --- a/crates/loro-internal/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# loro-internal - -This is the internal implementation of Loro. -Its interface subject to change. You should not use it as dependency directly. -Consider use `loro` crate instead. diff --git a/crates/loro-internal/benches/encode.rs b/crates/loro-internal/benches/encode.rs deleted file mode 100644 index a2db865a3..000000000 --- a/crates/loro-internal/benches/encode.rs +++ /dev/null @@ -1,171 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion}; -#[cfg(feature = "test_utils")] -mod sync { - - use super::*; - use bench_utils::{get_automerge_actions, TextAction}; - use loro_internal::{cursor::PosType, encoding::ExportMode, LoroDoc}; - - pub fn b4(c: &mut Criterion) { - let actions = get_automerge_actions(); - let mut b = c.benchmark_group("encode_with_sync"); - b.sample_size(10); - b.bench_function("update", |b| { - b.iter(|| { - let c1 = LoroDoc::new(); - c1.set_peer_id(1).unwrap(); - let c2 = LoroDoc::new(); - c1.set_peer_id(2).unwrap(); - let t1 = c1.get_text("text"); - let t2 = c2.get_text("text"); - for (i, action) in actions.iter().enumerate() { - if i > 2000 { - break; - } - let TextAction { pos, ins, del } = action; - if i % 2 == 0 { - let mut txn = c1.txn().unwrap(); - t1.delete_with_txn(&mut txn, *pos, *del, PosType::Unicode) - .unwrap(); - t1.insert_with_txn(&mut txn, *pos, ins, PosType::Unicode) - .unwrap(); - txn.commit().unwrap(); - - let update = c1.export(ExportMode::updates(&c2.oplog_vv())).unwrap(); - c2.import(&update).unwrap(); - } else { - let mut txn = c2.txn().unwrap(); - t2.delete_with_txn(&mut txn, *pos, *del, PosType::Unicode) - .unwrap(); - t2.insert_with_txn(&mut txn, *pos, ins, PosType::Unicode) - .unwrap(); - txn.commit().unwrap(); - let update = c2.export(ExportMode::updates(&c1.oplog_vv())).unwrap(); - c1.import(&update).unwrap(); - } - } - }) - }); - } -} -#[cfg(feature = "test_utils")] -mod run { - use super::*; - use bench_utils::TextAction; - use loro_internal::{encoding::ExportMode, LoroDoc}; - - pub fn b4(c: &mut Criterion) { - let loro = LoroDoc::default(); - let mut ran = false; - let mut ensure_ran = || { - if !ran { - let actions = bench_utils::get_automerge_actions(); - let text = loro.get_text("text"); - for TextAction { pos, ins, del } in actions.iter() { - let mut txn = loro.txn().unwrap(); - text.delete_with_txn(&mut txn, *pos, *del).unwrap(); - text.insert_with_txn(&mut txn, *pos, ins).unwrap(); - } - ran = true; - } - }; - - let mut b = c.benchmark_group("encode"); - b.sample_size(10); - b.bench_function("B4_encode_updates", |b| { - ensure_ran(); - b.iter(|| { - let _ = loro.export(ExportMode::all_updates()).unwrap(); - }) - }); - b.bench_function("B4_decode_updates", |b| { - ensure_ran(); - let buf = loro.export(ExportMode::all_updates()).unwrap(); - - b.iter(|| { - let store2 = LoroDoc::default(); - store2.import(&buf).unwrap(); - }) - }); - b.bench_function("B4_decode_updates detached mode", |b| { - ensure_ran(); - let buf = loro.export(ExportMode::all_updates()).unwrap(); - - b.iter(|| { - let store2 = LoroDoc::default(); - store2.detach(); - store2.import(&buf).unwrap(); - }) - }); - b.bench_function("B4_encode_snapshot", |b| { - ensure_ran(); - b.iter(|| { - let _ = loro.export(ExportMode::Snapshot).unwrap(); - }) - }); - b.bench_function("B4_decode_snapshot", |b| { - ensure_ran(); - let buf = loro.export(ExportMode::Snapshot).unwrap(); - b.iter(|| { - let store2 = LoroDoc::default(); - store2.import(&buf).unwrap(); - }) - }); - - b.bench_function("B4_encode_json_update", |b| { - ensure_ran(); - b.iter(|| { - let _ = loro.export_json_updates(&Default::default(), &loro.oplog_vv(), true); - }) - }); - b.bench_function("B4_decode_json_update", |b| { - ensure_ran(); - let json = loro.export_json_updates(&Default::default(), &loro.oplog_vv(), true); - b.iter(|| { - let store2 = LoroDoc::default(); - store2.import_json_updates(json.clone()).unwrap(); - }) - }); - } -} - -mod import { - use criterion::Criterion; - use loro_internal::{cursor::PosType, encoding::ExportMode, LoroDoc}; - - #[allow(dead_code)] - pub fn causal_iter(c: &mut Criterion) { - let mut b = c.benchmark_group("causal_iter"); - b.sample_size(10); - b.bench_function("parallel_500", |b| { - b.iter(|| { - let c1 = LoroDoc::new(); - c1.set_peer_id(1).unwrap(); - let c2 = LoroDoc::new(); - c1.set_peer_id(2).unwrap(); - - let text1 = c1.get_text("text"); - let text2 = c2.get_text("text"); - for _ in 0..500 { - text1 - .insert_with_txn(&mut c1.txn().unwrap(), 0, "1", PosType::Unicode) - .unwrap(); - text2 - .insert_with_txn(&mut c2.txn().unwrap(), 0, "2", PosType::Unicode) - .unwrap(); - } - - let updates = c2.export(ExportMode::updates(&c1.oplog_vv())).unwrap(); - c1.import(&updates).unwrap() - }) - }); - } -} - -pub fn dumb(_c: &mut Criterion) {} - -#[cfg(feature = "test_utils")] -criterion_group!(benches, run::b4, sync::b4, import::causal_iter); -#[cfg(not(feature = "test_utils"))] -criterion_group!(benches, dumb); -criterion_main!(benches); diff --git a/crates/loro-internal/benches/event.rs b/crates/loro-internal/benches/event.rs deleted file mode 100644 index 892a191ca..000000000 --- a/crates/loro-internal/benches/event.rs +++ /dev/null @@ -1,48 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion}; -#[cfg(feature = "test_utils")] -mod event { - use super::*; - - use loro_internal::{ListHandler, LoroDoc}; - use std::sync::Arc; - - fn create_sub_container(handler: ListHandler, children_num: usize) -> Vec { - let mut ans = vec![]; - for idx in 0..children_num { - let child_handler = handler - .insert_container(idx, ListHandler::new_detached()) - .unwrap(); - ans.push(child_handler); - } - ans - } - - pub fn resolved_container(c: &mut Criterion) { - let mut b = c.benchmark_group("resolved"); - b.sample_size(10); - b.bench_function("subContainer in event", |b| { - let children_num = 80; - let deep = 3; - b.iter(|| { - let loro = LoroDoc::default(); - loro.start_auto_commit(); - let _g = loro.subscribe_root(Arc::new(|_e| {})); - let mut handlers = vec![loro.get_list("list")]; - for _ in 0..deep { - handlers = handlers - .into_iter() - .flat_map(|h| create_sub_container(h, children_num)) - .collect(); - } - }) - }); - } -} - -pub fn dumb(_c: &mut Criterion) {} - -#[cfg(feature = "test_utils")] -criterion_group!(benches, event::resolved_container); -#[cfg(not(feature = "test_utils"))] -criterion_group!(benches, dumb); -criterion_main!(benches); diff --git a/crates/loro-internal/benches/jsonpath.rs b/crates/loro-internal/benches/jsonpath.rs deleted file mode 100644 index 23696b066..000000000 --- a/crates/loro-internal/benches/jsonpath.rs +++ /dev/null @@ -1,317 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion}; - -#[cfg(feature = "test_utils")] -mod jsonpath { - use criterion::Criterion; - use loro_internal::{ListHandler, LoroDoc, MapHandler}; - use std::hint::black_box; - - // Sizes to test: small, medium, large - const SIZES: [usize; 3] = [100, 500, 2000]; - - /// Setup a large document with: - /// - books[0..size] with title, author, price, available - /// - '1984' by George Orwell every ~100 items - /// - Nested structure under $.catalog.fiction.books for recursive tests - fn setup_large_doc(size: usize) -> LoroDoc { - let doc = LoroDoc::new_auto_commit(); - let store = doc.get_map("store"); - let books = store - .insert_container("books", ListHandler::new_detached()) - .unwrap(); - - for i in 0..size { - let book = books - .insert_container(i, MapHandler::new_detached()) - .unwrap(); - let title = if i % 100 == 42 { - "1984" - } else { - &format!("Book {}", i) - }; - let author = if i % 100 == 42 { - "George Orwell" - } else { - &format!("Author {}", i % 10) - }; - let price = 5.0 + (i % 25) as f64; - let available = i % 4 != 0; - - book.insert("title", title).unwrap(); - book.insert("author", author).unwrap(); - book.insert("price", price).unwrap(); - book.insert("available", available).unwrap(); - } - - // Add nested structure for $..title and recursive filters - let catalog = doc.get_map("catalog"); - let fiction = catalog - .insert_container("fiction", MapHandler::new_detached()) - .unwrap(); - let nested_books = fiction - .insert_container("books", ListHandler::new_detached()) - .unwrap(); - for i in 0..10 { - let b = nested_books - .insert_container(i, MapHandler::new_detached()) - .unwrap(); - b.insert("title", format!("Nested {}", i)).unwrap(); - b.insert("price", 12.0 + i as f64).unwrap(); - } - - doc - } - - /// Benchmark a single JSONPath query across all sizes - fn bench_pattern(c: &mut Criterion, group_name: &str, query: &str, setup: F) - where - F: Fn(usize) -> LoroDoc, - { - let mut group = c.benchmark_group(group_name); - group.sample_size(if group_name.contains("large") { 20 } else { 50 }); - - for &size in &SIZES { - let doc = setup(size); - let name = format!("{} (size={})", query, size); - group.bench_function(&name, |b| { - b.iter(|| { - let result = doc.jsonpath(query).unwrap(); - black_box(result); - }) - }); - } - group.finish(); - } - - pub fn child_selector(c: &mut Criterion) { - bench_pattern( - c, - "Child Selector", - "$.store.books[0].title", - setup_large_doc, - ); - } - - pub fn wildcard(c: &mut Criterion) { - bench_pattern(c, "Wildcard", "$.store.books[*].title", setup_large_doc); - } - - pub fn recursive_descent(c: &mut Criterion) { - bench_pattern(c, "Recursive Descent", "$..title", setup_large_doc); - } - - pub fn quoted_keys(c: &mut Criterion) { - bench_pattern( - c, - "Quoted Keys", - "$.store['books'][0]['title']", - setup_large_doc, - ); - } - - pub fn string_filter(c: &mut Criterion) { - bench_pattern( - c, - "String Filter", - "$.store.books[?(@.title == '1984')].title", - setup_large_doc, - ); - } - - pub fn logical_operator(c: &mut Criterion) { - bench_pattern( - c, - "Logical Operator", - "$.store.books[?(@.author == 'George Orwell' && @.price < 10)].title", - setup_large_doc, - ); - } - - pub fn union_operation(c: &mut Criterion) { - bench_pattern( - c, - "Union Operation", - "$.store.books[0,2].title", - setup_large_doc, - ); - } - - pub fn slice_operation(c: &mut Criterion) { - let mut group = c.benchmark_group("Slice Operation"); - - for &size in &SIZES { - let doc = setup_large_doc(size); - - // Small slice - group.bench_function(format!("$.store.books[0:3].title (size={})", size), |b| { - b.iter(|| { - let result = doc.jsonpath("$.store.books[0:3].title").unwrap(); - black_box(result); - }) - }); - - // Large slice (half) - let half = size / 2; - group.bench_function( - format!("$.store.books[0:{}].title (size={})", half, size), - |b| { - b.iter(|| { - let result = doc - .jsonpath(&format!("$.store.books[0:{}].title", half)) - .unwrap(); - black_box(result); - }) - }, - ); - - // Negative slice - group.bench_function(format!("$.store.books[-10:].title (size={})", size), |b| { - b.iter(|| { - let result = doc.jsonpath("$.store.books[-10:].title").unwrap(); - black_box(result); - }) - }); - } - group.finish(); - } - - pub fn complex_filter(c: &mut Criterion) { - bench_pattern( - c, - "Complex Filter", - "$.store.books[?(@.price >= 10 && @.available == true && @.title contains '1984')].title", - setup_large_doc, - ); - } - - pub fn recursive_mapped_filter(c: &mut Criterion) { - bench_pattern( - c, - "Recursive Mapped Filter", - "$.store.books[?(@.price > 10)].title", - setup_large_doc, - ); - } - - pub fn recursive_filter(c: &mut Criterion) { - bench_pattern( - c, - "Recursive Filter", - "$..[?(@.price > 10)].title", - setup_large_doc, - ); - } - - // === Legacy / Extra: Keep your original ones (now size-scaled) === - - pub fn index_selector(c: &mut Criterion) { - let mut group = c.benchmark_group("Index Selector"); - group.sample_size(50); - - for &size in &SIZES { - let doc = setup_large_doc(size); - let idx = (size as i64 / 2).min(42); // Safe index - group.bench_function(format!("positive index {} (size={})", idx, size), |b| { - b.iter(|| { - let result = doc - .jsonpath(&format!("$.store.books[{}].title", idx)) - .unwrap(); - black_box(result); - }) - }); - - group.bench_function(format!("negative index -10 (size={})", size), |b| { - b.iter(|| { - let result = doc.jsonpath("$.store.books[-10].title").unwrap(); - black_box(result); - }) - }); - } - group.finish(); - } - - pub fn union_key_selector(c: &mut Criterion) { - let mut group = c.benchmark_group("Union Key Selector"); - group.sample_size(50); - - for &size in &SIZES { - let doc = setup_large_doc(size); - group.bench_function(format!("two keys single item (size={})", size), |b| { - b.iter(|| { - let result = doc.jsonpath("$.store.books[42]['title','author']").unwrap(); - black_box(result); - }) - }); - - group.bench_function(format!("three keys slice (size={})", size), |b| { - b.iter(|| { - let result = doc - .jsonpath("$.store.books[0:10]['title','author','price']") - .unwrap(); - black_box(result); - }) - }); - } - group.finish(); - } - - pub fn mixed_selectors(c: &mut Criterion) { - bench_pattern( - c, - "Mixed Selectors", - "$.store.books[0,5:15,20].title", - setup_large_doc, - ); - } - - pub fn real_world_patterns(c: &mut Criterion) { - let mut group = c.benchmark_group("Real World Patterns"); - group.sample_size(50); - - for &size in &SIZES { - let doc = setup_large_doc(size); - group.bench_function(format!("last 10 items (size={})", size), |b| { - b.iter(|| { - let result = doc.jsonpath("$.store.books[-10:].title").unwrap(); - black_box(result); - }) - }); - - group.bench_function(format!("pagination page 1 (size={})", size), |b| { - b.iter(|| { - let result = doc.jsonpath("$.store.books[0:20].title").unwrap(); - black_box(result); - }) - }); - } - group.finish(); - } - - // === Master Group === - pub fn all_benches(c: &mut Criterion) { - child_selector(c); - wildcard(c); - recursive_descent(c); - quoted_keys(c); - string_filter(c); - logical_operator(c); - union_operation(c); - slice_operation(c); - complex_filter(c); - recursive_mapped_filter(c); - recursive_filter(c); - index_selector(c); - union_key_selector(c); - mixed_selectors(c); - real_world_patterns(c); - } -} - -pub fn dumb(_c: &mut Criterion) {} - -#[cfg(feature = "test_utils")] -criterion_group!(benches, jsonpath::all_benches); -#[cfg(not(feature = "test_utils"))] -criterion_group!(benches, dumb); - -criterion_main!(benches); diff --git a/crates/loro-internal/benches/list.rs b/crates/loro-internal/benches/list.rs deleted file mode 100644 index fdb9c2ced..000000000 --- a/crates/loro-internal/benches/list.rs +++ /dev/null @@ -1,117 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion}; -#[cfg(feature = "test_utils")] -mod run { - use super::*; - use arbitrary::Arbitrary; - use arbitrary::Unstructured; - use loro_internal::loro::ExportMode; - use loro_internal::LoroDoc; - use loro_internal::LoroValue; - use rand::Rng; - use rand::SeedableRng; - - pub fn many_list_containers(c: &mut Criterion) { - #[derive(Arbitrary)] - struct Action { - container: u8, - actor: u8, - pos: u8, - value: u8, - sync: u8, - } - - let mut rgn = rand::rngs::StdRng::seed_from_u64(0); - let mut bytes = Vec::new(); - for _ in 0..10000 { - bytes.push(rgn.gen::()); - } - - let mut gen = Unstructured::new(&bytes); - let actions: [Action; 200] = gen.arbitrary().unwrap(); - let mut b = c.benchmark_group("10 list containers"); - b.sample_size(10); - b.bench_function("sync random inserts to 10 list containers", |b| { - b.iter(|| { - let mut actors: Vec<_> = (0..10).map(|_| LoroDoc::default()).collect(); - for action in actions.iter() { - let len = actors.len(); - let actor = &mut actors[action.actor as usize % len]; - let container = action.container % 10; - if container % 2 == 0 { - let text = actor.get_text(container.to_string().as_str()); - let mut txn = actor.txn().unwrap(); - text.insert_with_txn( - &mut txn, - (action.pos as usize) % text.len_unicode().max(1), - action.value.to_string().as_str(), - ) - .unwrap(); - } else { - let list = actor.get_list(container.to_string().as_str()); - let mut txn = actor.txn().unwrap(); - list.insert_with_txn( - &mut txn, - (action.pos as usize) % list.len().max(1), - action.value.to_string().as_str().into(), - ) - .unwrap(); - } - - let a = (action.actor as usize) % len; - let b = (action.sync as usize) % len; - if a != b { - let (a, b) = arref::array_mut_ref!(&mut actors, [a, b]); - a.import(&b.export(ExportMode::updates(&a.oplog_vv())).unwrap()) - .unwrap(); - } - } - - for i in 1..actors.len() { - let (a, b) = arref::array_mut_ref!(&mut actors, [0, i]); - a.import(&b.export(ExportMode::updates(&a.oplog_vv())).unwrap()) - .unwrap(); - } - for i in 1..actors.len() { - let (a, b) = arref::array_mut_ref!(&mut actors, [i, 0]); - a.import(&b.export(ExportMode::updates(&a.oplog_vv())).unwrap()) - .unwrap(); - } - }) - }); - } - - pub fn many_actors(c: &mut Criterion) { - let mut b = c.benchmark_group("many_actors"); - b.sample_size(10); - b.bench_function("100 actors", |b| { - b.iter(|| { - let mut actors: Vec<_> = (0..100).map(|_| LoroDoc::default()).collect(); - for (i, actor) in actors.iter_mut().enumerate() { - let list = actor.get_list("list"); - let value: LoroValue = i.to_string().into(); - let mut txn = actor.txn().unwrap(); - list.insert_with_txn(&mut txn, 0, value).unwrap(); - } - - for i in 1..actors.len() { - let (a, b) = arref::array_mut_ref!(&mut actors, [0, i]); - a.import(&b.export(ExportMode::updates(&a.oplog_vv())).unwrap()) - .unwrap(); - } - - for i in 1..actors.len() { - let (a, b) = arref::array_mut_ref!(&mut actors, [0, i]); - b.import(&a.export(ExportMode::updates(&b.oplog_vv())).unwrap()) - .unwrap(); - } - }) - }); - } -} -pub fn dumb(_c: &mut Criterion) {} - -#[cfg(feature = "test_utils")] -criterion_group!(benches, run::many_list_containers, run::many_actors); -#[cfg(not(feature = "test_utils"))] -criterion_group!(benches, dumb); -criterion_main!(benches); diff --git a/crates/loro-internal/benches/map.rs b/crates/loro-internal/benches/map.rs deleted file mode 100644 index 18daac9e8..000000000 --- a/crates/loro-internal/benches/map.rs +++ /dev/null @@ -1,85 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion}; -#[cfg(feature = "test_utils")] -mod map { - use super::*; - use loro_internal::{loro::ExportMode, LoroDoc}; - use rand::{rngs::StdRng, Rng}; - - pub fn tree_move(c: &mut Criterion) { - let mut b = c.benchmark_group("map crdt"); - b.sample_size(10); - b.bench_function("create 10^4 key", |b| { - let size = 10000; - b.iter(|| { - let loro = LoroDoc::new_auto_commit(); - let map = loro.get_map("map"); - for i in 0..size { - map.insert(&i.to_string(), i).unwrap(); - } - loro.commit_then_renew(); - }) - }); - - b.bench_function("map checkout 10^3", |b| { - let loro = LoroDoc::new_auto_commit(); - let map = loro.get_map("map"); - let mut versions = vec![]; - let size = 10000; - let mut rng: StdRng = rand::SeedableRng::seed_from_u64(0); - for i in 0..size { - versions.push(loro.oplog_frontiers()); - map.insert(&rng.gen::().to_string(), i).unwrap(); - loro.commit_then_renew(); - } - - b.iter(|| { - for _ in 0..1000 { - let i = rng.gen::() % 1000; - let f = &versions[i]; - loro.checkout(f).unwrap(); - } - }) - }); - - b.bench_function("realtime map set", |b| { - let doc_a = LoroDoc::default(); - let doc_b = LoroDoc::default(); - let map_a = doc_a.get_map("map"); - let map_b = doc_b.get_map("map"); - let n = 1000; - b.iter(|| { - for t in 0..n { - if t % 2 == 0 { - let mut txn = doc_a.txn().unwrap(); - map_a.insert_with_txn(&mut txn, "key", t.into()).unwrap(); - doc_b - .import( - &doc_a - .export(ExportMode::updates(&doc_b.oplog_vv())) - .unwrap(), - ) - .unwrap(); - } else { - let mut txn = doc_b.txn().unwrap(); - map_b.insert_with_txn(&mut txn, "key", t.into()).unwrap(); - doc_a - .import( - &doc_b - .export(ExportMode::updates(&doc_a.oplog_vv())) - .unwrap(), - ) - .unwrap(); - } - } - }) - }); - } -} - -pub fn dumb(_c: &mut Criterion) {} - -#[cfg(feature = "test_utils")] -criterion_group!(benches, map::tree_move); -#[cfg(not(feature = "test_utils"))] -criterion_group!(benches, dumb); -criterion_main!(benches); diff --git a/crates/loro-internal/benches/pending.rs b/crates/loro-internal/benches/pending.rs deleted file mode 100644 index 2feb57dc1..000000000 --- a/crates/loro-internal/benches/pending.rs +++ /dev/null @@ -1,47 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion}; -#[cfg(feature = "test_utils")] -mod pending { - use super::*; - use bench_utils::TextAction; - use loro_internal::{LoroDoc, VersionVector}; - - pub fn b4(c: &mut Criterion) { - let mut b = c.benchmark_group("B4 pending decode"); - b.sample_size(10); - b.bench_function("detached mode", |b| { - let loro = LoroDoc::default(); - let mut latest_vv = VersionVector::default(); - let mut updates = vec![]; - let actions = bench_utils::get_automerge_actions(); - let action_length = actions.len(); - let text = loro.get_text("text"); - for chunks in actions.chunks(action_length / 5) { - for TextAction { pos, ins, del } in chunks { - let mut txn = loro.txn().unwrap(); - text.delete_with_txn(&mut txn, *pos, *del).unwrap(); - text.insert_with_txn(&mut txn, *pos, ins).unwrap(); - updates - .push(loro.export(ExportMode::updates(&latest_vv))) - .unwrap(); - latest_vv = loro.oplog_vv(); - } - } - updates.reverse(); - b.iter(|| { - let store2 = LoroDoc::default(); - store2.detach(); - for update in updates.iter() { - store2.import(update).unwrap(); - } - }) - }); - } -} - -pub fn dumb(_c: &mut Criterion) {} - -#[cfg(feature = "test_utils")] -criterion_group!(benches, pending::b4); -#[cfg(not(feature = "test_utils"))] -criterion_group!(benches, dumb); -criterion_main!(benches); diff --git a/crates/loro-internal/benches/text_r.rs b/crates/loro-internal/benches/text_r.rs deleted file mode 100644 index 25705d895..000000000 --- a/crates/loro-internal/benches/text_r.rs +++ /dev/null @@ -1,392 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion}; - -#[cfg(feature = "test_utils")] -mod run { - use std::sync::Arc; - - use super::*; - use bench_utils::TextAction; - use criterion::black_box; - use loro_common::LoroValue; - use loro_internal::{loro::ExportMode, LoroDoc}; - - pub fn b4(c: &mut Criterion) { - let actions = bench_utils::get_automerge_actions(); - let mut b = c.benchmark_group("refactored direct_apply"); - b.sample_size(10); - b.bench_function("B4", |b| { - b.iter(|| { - let loro = LoroDoc::default(); - let text = loro.get_text("text"); - let mut txn = loro.txn().unwrap(); - - for TextAction { pos, ins, del } in actions.iter() { - text.delete_with_txn(&mut txn, *pos, *del).unwrap(); - text.insert_with_txn(&mut txn, *pos, ins).unwrap(); - } - }) - }); - - b.bench_function("B4 with 100K actors history", |b| { - let store = LoroDoc::default(); - for i in 0..100_000 { - store.set_peer_id(i).unwrap(); - let list = store.get_list("list"); - let value: LoroValue = i.to_string().into(); - let mut txn = store.txn().unwrap(); - list.insert_with_txn(&mut txn, 0, value).unwrap(); - txn.commit().unwrap(); - } - - let update = store.export(ExportMode::Snapshot).unwrap(); - drop(store); - b.iter_batched( - || { - let loro = LoroDoc::default(); - loro.import(&update).unwrap(); - loro - }, - |loro| { - let text = loro.get_text("text"); - let mut txn = loro.txn().unwrap(); - - for TextAction { pos, ins, del } in actions.iter() { - text.delete_with_txn(&mut txn, *pos, *del).unwrap(); - text.insert_with_txn(&mut txn, *pos, ins).unwrap(); - } - }, - criterion::BatchSize::SmallInput, - ) - }); - - b.bench_function("B4 Obs", |b| { - b.iter(|| { - let loro = LoroDoc::default(); - let text = loro.get_text("text"); - let _g = loro.subscribe_root(Arc::new(move |event| { - black_box(event); - })); - let mut txn = loro.txn().unwrap(); - for TextAction { pos, ins, del } in actions.iter() { - text.delete_with_txn(&mut txn, *pos, *del).unwrap(); - text.insert_with_txn(&mut txn, *pos, ins).unwrap(); - } - }) - }); - - b.bench_function("B4 encode snapshot", |b| { - let loro = LoroDoc::default(); - let text = loro.get_text("text"); - - let mut n = 0; - let mut txn = loro.txn().unwrap(); - for TextAction { pos, ins, del } in actions.iter() { - if n == 10 { - n = 0; - drop(txn); - txn = loro.txn().unwrap(); - } - n += 1; - text.delete_with_txn(&mut txn, *pos, *del).unwrap(); - text.insert_with_txn(&mut txn, *pos, ins).unwrap(); - } - txn.commit().unwrap(); - - b.iter(|| { - loro.export(ExportMode::Snapshot).unwrap(); - }); - }); - - b.bench_function("B4 encode updates", |b| { - let loro = LoroDoc::default(); - let text = loro.get_text("text"); - - let mut n = 0; - let mut txn = loro.txn().unwrap(); - for TextAction { pos, ins, del } in actions.iter() { - if n == 10 { - n = 0; - drop(txn); - txn = loro.txn().unwrap(); - } - n += 1; - text.delete_with_txn(&mut txn, *pos, *del).unwrap(); - text.insert_with_txn(&mut txn, *pos, ins).unwrap(); - } - txn.commit().unwrap(); - - b.iter(|| { - loro.export(ExportMode::all_updates()).unwrap(); - }); - }); - - b.bench_function("B4 decode snapshot", |b| { - let loro = LoroDoc::default(); - let text = loro.get_text("text"); - let mut n = 0; - let mut txn = loro.txn().unwrap(); - for TextAction { pos, ins, del } in actions.iter() { - if n == 10 { - n = 0; - drop(txn); - txn = loro.txn().unwrap(); - } - n += 1; - text.delete_with_txn(&mut txn, *pos, *del).unwrap(); - text.insert_with_txn(&mut txn, *pos, ins).unwrap(); - } - txn.commit().unwrap(); - - let data = loro.export(ExportMode::Snapshot).unwrap(); - b.iter(|| { - let l = LoroDoc::new(); - l.import(&data).unwrap(); - }); - }); - - b.bench_function("B4 import updates", |b| { - let loro = LoroDoc::default(); - let text = loro.get_text("text"); - - let mut n = 0; - let mut txn = loro.txn().unwrap(); - for TextAction { pos, ins, del } in actions.iter() { - if n == 10 { - n = 0; - drop(txn); - txn = loro.txn().unwrap(); - } - n += 1; - text.delete_with_txn(&mut txn, *pos, *del).unwrap(); - text.insert_with_txn(&mut txn, *pos, ins).unwrap(); - } - txn.commit().unwrap(); - - let data = loro.export(ExportMode::all_updates()).unwrap(); - b.iter(|| { - let l = LoroDoc::new(); - l.import(&data).unwrap(); - }); - }); - - // b.bench_function("B4 utf16", |b| { - // b.iter(|| { - // let loro = LoroDoc::new(); - // let text = loro.get_text("text"); - // let mut txn = loro.txn().unwrap(); - - // for TextAction { pos, ins, del } in actions.iter() { - // text.delete_utf16(&mut txn, *pos, *del).unwrap(); - // text.insert_utf16(&mut txn, *pos, ins).unwrap(); - // } - // }) - // }); - - b.bench_function("B4_Per100_Txn", |b| { - b.iter(|| { - let loro = LoroDoc::default(); - let text = loro.get_text("text"); - let mut n = 0; - let mut txn = loro.txn().unwrap(); - for TextAction { pos, ins, del } in actions.iter() { - if n == 100 { - n = 0; - drop(txn); - txn = loro.txn().unwrap(); - } - n += 1; - text.delete_with_txn(&mut txn, *pos, *del).unwrap(); - text.insert_with_txn(&mut txn, *pos, ins).unwrap(); - } - }) - }); - - b.bench_function("B4 One Op One Txn", |b| { - b.iter(|| { - let loro = LoroDoc::default(); - let text = loro.get_text("text"); - { - for TextAction { pos, ins, del } in actions.iter() { - let mut txn = loro.txn().unwrap(); - text.delete_with_txn(&mut txn, *pos, *del).unwrap(); - text.insert_with_txn(&mut txn, *pos, ins).unwrap(); - txn.commit().unwrap(); - } - } - }) - }); - - b.bench_function("B4 One Op One Txn Obs", |b| { - b.iter(|| { - let loro = LoroDoc::default(); - let text = loro.get_text("text"); - let _g = loro.subscribe_root(Arc::new(move |event| { - black_box(event); - })); - { - for TextAction { pos, ins, del } in actions.iter() { - let mut txn = loro.txn().unwrap(); - text.delete_with_txn(&mut txn, *pos, *del).unwrap(); - text.insert_with_txn(&mut txn, *pos, ins).unwrap(); - txn.commit().unwrap(); - } - } - }) - }); - - b.bench_function("B4DirectSync", |b| { - b.iter(|| { - let loro = LoroDoc::default(); - let loro_b = LoroDoc::default(); - let text = loro.get_text("text"); - for TextAction { pos, ins, del } in actions.iter() { - { - let mut txn = loro.txn().unwrap(); - text.delete_with_txn(&mut txn, *pos, *del).unwrap(); - text.insert_with_txn(&mut txn, *pos, ins).unwrap(); - } - - loro_b - .import( - &loro - .export(ExportMode::updates(&loro_b.oplog_vv())) - .unwrap(), - ) - .unwrap(); - } - }) - }); - - drop(b); - let mut b = c.benchmark_group("refactored-sync"); - b.bench_function("B4Parallel", |b| { - b.iter(|| { - let loro = LoroDoc::default(); - let loro_b = LoroDoc::default(); - let text = loro.get_text("text"); - let text2 = loro_b.get_text("text"); - let mut i = 0; - for TextAction { pos, ins, del } in actions.iter() { - let pos = *pos; - let del = *del; - i += 1; - if i > 1000 { - break; - } - - { - let mut txn = loro.txn().unwrap(); - text.delete_with_txn(&mut txn, pos, del).unwrap(); - text.insert_with_txn(&mut txn, pos, ins).unwrap(); - } - - { - let mut txn = loro_b.txn().unwrap(); - text2.delete_with_txn(&mut txn, pos, del).unwrap(); - text2.insert_with_txn(&mut txn, pos, ins).unwrap(); - } - loro_b - .import( - &loro - .export(ExportMode::updates(&loro_b.oplog_vv())) - .unwrap(), - ) - .unwrap(); - loro.import( - &loro_b - .export(ExportMode::updates(&loro.oplog_vv())) - .unwrap(), - ) - .unwrap(); - } - }) - }); - - let b = b.sample_size(10); - b.bench_function("DecodeUpdates B4Parallel", |b| { - let loro = LoroDoc::default(); - let loro_b = LoroDoc::default(); - let text = loro.get_text("text"); - let text2 = loro_b.get_text("text"); - for TextAction { pos, ins, del } in actions.iter() { - let pos = *pos; - let del = *del; - { - let mut txn = loro.txn().unwrap(); - text.delete_with_txn(&mut txn, pos, del).unwrap(); - text.insert_with_txn(&mut txn, pos, ins).unwrap(); - } - - { - let mut txn = loro_b.txn().unwrap(); - text2.delete_with_txn(&mut txn, pos, del).unwrap(); - text2.insert_with_txn(&mut txn, pos, ins).unwrap(); - } - loro_b - .import( - &loro - .export(ExportMode::updates(&loro_b.oplog_vv())) - .unwrap(), - ) - .unwrap(); - loro.import( - &loro_b - .export(ExportMode::updates(&loro.oplog_vv())) - .unwrap(), - ) - .unwrap(); - } - let data = loro.export(ExportMode::all_updates()).unwrap(); - b.iter(|| { - let loro = LoroDoc::default(); - loro.import(&data).unwrap(); - }) - }); - b.bench_function("DecodeSnapshot B4Parallel", |b| { - let loro = LoroDoc::default(); - let loro_b = LoroDoc::default(); - let text = loro.get_text("text"); - let text2 = loro_b.get_text("text"); - for TextAction { pos, ins, del } in actions.iter() { - let pos = *pos; - let del = *del; - { - let mut txn = loro.txn().unwrap(); - text.delete_with_txn(&mut txn, pos, del).unwrap(); - text.insert_with_txn(&mut txn, pos, ins).unwrap(); - } - - { - let mut txn = loro_b.txn().unwrap(); - text2.delete_with_txn(&mut txn, pos, del).unwrap(); - text2.insert_with_txn(&mut txn, pos, ins).unwrap(); - } - loro_b - .import( - &loro - .export(ExportMode::updates(&loro_b.oplog_vv())) - .unwrap(), - ) - .unwrap(); - loro.import( - &loro_b - .export(ExportMode::updates(&loro.oplog_vv())) - .unwrap(), - ) - .unwrap(); - } - let data = loro.export(ExportMode::Snapshot).unwrap(); - b.iter(|| { - let loro = LoroDoc::default(); - loro.import(&data).unwrap(); - }) - }); - } -} -pub fn dumb(_c: &mut Criterion) {} - -#[cfg(feature = "test_utils")] -criterion_group!(benches, run::b4); -#[cfg(not(feature = "test_utils"))] -criterion_group!(benches, dumb); -criterion_main!(benches); diff --git a/crates/loro-internal/benches/tree.rs b/crates/loro-internal/benches/tree.rs deleted file mode 100644 index a55f9768d..000000000 --- a/crates/loro-internal/benches/tree.rs +++ /dev/null @@ -1,166 +0,0 @@ -use criterion::{criterion_group, criterion_main, Criterion}; - -mod tree { - use super::*; - use criterion::{AxisScale, BenchmarkId, PlotConfiguration}; - use loro_internal::{encoding::ExportMode, LoroDoc, TreeParentId}; - use rand::{rngs::StdRng, Rng}; - - pub fn tree_move(c: &mut Criterion) { - let mut group = c.benchmark_group("movable tree"); - let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); - group.plot_config(plot_config); - group.sample_size(10); - - for i in 3..=6 { - let input = 10u64.pow(i); - group.bench_with_input( - BenchmarkId::new("create node append", input), - &input, - |b, i| { - b.iter(|| { - let loro = LoroDoc::new_auto_commit(); - let tree = loro.get_tree("tree"); - for idx in 0..*i { - tree.create_at(TreeParentId::Root, idx as usize).unwrap(); - } - }) - }, - ); - - group.bench_with_input( - BenchmarkId::new("move node append", input), - &input, - |b, i| { - let loro = LoroDoc::new_auto_commit(); - let tree = loro.get_tree("tree"); - const SIZE: usize = 1000; - let mut rng: StdRng = rand::SeedableRng::seed_from_u64(0); - let mut ids = vec![]; - for _ in 0..SIZE { - let pos = rng.gen::() % (ids.len() + 1); - ids.push(tree.create_at(TreeParentId::Root, pos).unwrap()); - } - - b.iter(|| { - for _ in 0..*i { - tree.create_at(TreeParentId::Root, 0).unwrap(); - let i = rng.gen::() % SIZE; - let j = rng.gen::() % SIZE; - tree.mov(ids[i], TreeParentId::Node(ids[j])) - .unwrap_or_default(); - } - }) - }, - ); - } - - group.bench_function("1000 node checkout 10^3", |b| { - let loro = LoroDoc::default(); - loro.start_auto_commit(); - let tree = loro.get_tree("tree"); - let mut ids = vec![]; - let mut versions = vec![]; - let size = 1000; - for _ in 0..size { - ids.push(tree.create(TreeParentId::Root).unwrap()) - } - let mut rng: StdRng = rand::SeedableRng::seed_from_u64(0); - let mut n = 1000; - while n > 0 { - let i = rng.gen::() % size; - let j = rng.gen::() % size; - if tree.mov(ids[i], TreeParentId::Node(ids[j])).is_ok() { - versions.push(loro.oplog_frontiers()); - n -= 1; - }; - } - b.iter(|| { - for _ in 0..1000 { - let i = rng.gen::() % 1000; - let f = &versions[i]; - loro.checkout(f).unwrap(); - } - }) - }); - - group.bench_function("300 deep node random checkout 10^3", |b| { - let depth = 300; - let loro = LoroDoc::default(); - loro.start_auto_commit(); - let tree = loro.get_tree("tree"); - let mut ids = vec![]; - let mut versions = vec![]; - let id1 = tree.create(TreeParentId::Root).unwrap(); - ids.push(id1); - versions.push(loro.oplog_frontiers()); - for _ in 1..depth { - let id = tree - .create(TreeParentId::Node(*ids.last().unwrap())) - .unwrap(); - ids.push(id); - versions.push(loro.oplog_frontiers()); - } - let mut rng: StdRng = rand::SeedableRng::seed_from_u64(0); - b.iter(|| { - for _ in 0..1000 { - let i = rng.gen::() % depth; - let f = &versions[i]; - loro.checkout(f).unwrap(); - } - }) - }); - - group.bench_function("realtime tree move", |b| { - let doc_a = LoroDoc::default(); - let doc_b = LoroDoc::default(); - doc_a.start_auto_commit(); - doc_b.start_auto_commit(); - let tree_a = doc_a.get_tree("tree"); - let tree_b = doc_b.get_tree("tree"); - let mut ids = vec![]; - let size = 1000; - for _ in 0..size { - ids.push(tree_a.create(TreeParentId::Root).unwrap()) - } - doc_b - .import(&doc_a.export(ExportMode::Snapshot).unwrap()) - .unwrap(); - let mut rng: StdRng = rand::SeedableRng::seed_from_u64(0); - let n = 1000; - b.iter(|| { - for t in 0..n { - let i = rng.gen::() % size; - let j = rng.gen::() % size; - if t % 2 == 0 { - tree_a - .mov(ids[i], TreeParentId::Node(ids[j])) - .unwrap_or_default(); - doc_b - .import( - &doc_a - .export(ExportMode::updates(&doc_b.oplog_vv())) - .unwrap(), - ) - .unwrap(); - } else { - tree_b - .mov(ids[i], TreeParentId::Node(ids[j])) - .unwrap_or_default(); - doc_a - .import( - &doc_b - .export(ExportMode::updates(&doc_a.oplog_vv())) - .unwrap(), - ) - .unwrap(); - } - } - }) - }); - group.finish(); - } -} - -criterion_group!(benches, tree::tree_move); -criterion_main!(benches); diff --git a/crates/loro-internal/deno.json b/crates/loro-internal/deno.json deleted file mode 100644 index 6edf0b37d..000000000 --- a/crates/loro-internal/deno.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "tasks": { - "test": "cargo nextest run --features test_utils", - "deny": "cargo deny check", - "fuzz": "cargo +nightly fuzz run", - "mem": "deno run -A ./scripts/run_mem.ts", - "flame": "CARGO_PROFILE_RELEASE_DEBUG=true cargo flamegraph --example encoding_refactored --root", - "bench": "cargo bench --features test_utils" - } -} diff --git a/crates/loro-internal/deno.lock b/crates/loro-internal/deno.lock deleted file mode 100644 index 5a95611b3..000000000 --- a/crates/loro-internal/deno.lock +++ /dev/null @@ -1,134 +0,0 @@ -{ - "version": "3", - "redirects": { - "https://deno.land/std/fmt/printf.ts": "https://deno.land/std@0.105.0/fmt/printf.ts", - "https://deno.land/std/path/mod.ts": "https://deno.land/std@0.105.0/path/mod.ts", - "https://deno.land/std/testing/asserts.ts": "https://deno.land/std@0.105.0/testing/asserts.ts", - "https://x.nest.land/std@0.73.0/path/mod.ts": "https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/path/mod.ts" - }, - "remote": { - "https://deno.land/std@0.105.0/_util/assert.ts": "2f868145a042a11d5ad0a3c748dcf580add8a0dbc0e876eaa0026303a5488f58", - "https://deno.land/std@0.105.0/_util/os.ts": "dfb186cc4e968c770ab6cc3288bd65f4871be03b93beecae57d657232ecffcac", - "https://deno.land/std@0.105.0/fmt/colors.ts": "d2f8355f00a74404668fc5a1e4a92983ce1a9b0a6ac1d40efbd681cb8f519586", - "https://deno.land/std@0.105.0/fmt/printf.ts": "7ec612e9b89958b8f7710129f74f502327aad285a9e48ee5297f5882fbc3a078", - "https://deno.land/std@0.105.0/path/_constants.ts": "1247fee4a79b70c89f23499691ef169b41b6ccf01887a0abd131009c5581b853", - "https://deno.land/std@0.105.0/path/_interface.ts": "1fa73b02aaa24867e481a48492b44f2598cd9dfa513c7b34001437007d3642e4", - "https://deno.land/std@0.105.0/path/_util.ts": "2e06a3b9e79beaf62687196bd4b60a4c391d862cfa007a20fc3a39f778ba073b", - "https://deno.land/std@0.105.0/path/common.ts": "eaf03d08b569e8a87e674e4e265e099f237472b6fd135b3cbeae5827035ea14a", - "https://deno.land/std@0.105.0/path/glob.ts": "3b84af55c53febacf6afe214c095624b22a56b6f57d7312157479cc783a0de65", - "https://deno.land/std@0.105.0/path/mod.ts": "4465dc494f271b02569edbb4a18d727063b5dbd6ed84283ff906260970a15d12", - "https://deno.land/std@0.105.0/path/posix.ts": "b81974c768d298f8dcd2c720229639b3803ca4a241fa9a355c762fa2bc5ef0c1", - "https://deno.land/std@0.105.0/path/separator.ts": "8fdcf289b1b76fd726a508f57d3370ca029ae6976fcde5044007f062e643ff1c", - "https://deno.land/std@0.105.0/path/win32.ts": "f4a3d4a3f2c9fe894da046d5eac48b5e789a0ebec5152b2c0985efe96a9f7ae1", - "https://deno.land/std@0.105.0/testing/_diff.ts": "5d3693155f561d1a5443ac751ac70aab9f5d67b4819a621d4b96b8a1a1c89620", - "https://deno.land/std@0.105.0/testing/asserts.ts": "e4311d45d956459d4423bc267208fe154b5294989da2ed93257b6a85cae0427e", - "https://deno.land/std@0.106.0/_util/assert.ts": "2f868145a042a11d5ad0a3c748dcf580add8a0dbc0e876eaa0026303a5488f58", - "https://deno.land/std@0.106.0/_util/os.ts": "dfb186cc4e968c770ab6cc3288bd65f4871be03b93beecae57d657232ecffcac", - "https://deno.land/std@0.106.0/fs/_util.ts": "f2ce811350236ea8c28450ed822a5f42a0892316515b1cd61321dec13569c56b", - "https://deno.land/std@0.106.0/fs/copy.ts": "631bbafbfe6cba282158abc8aeb7e8251cc69a7ec28ce12878ea1b75fec2add4", - "https://deno.land/std@0.106.0/fs/empty_dir.ts": "5f08b263dd064dc7917c4bbeb13de0f5505a664b9cdfe312fa86e7518cfaeb84", - "https://deno.land/std@0.106.0/fs/ensure_dir.ts": "b7c103dc41a3d1dbbb522bf183c519c37065fdc234831a4a0f7d671b1ed5fea7", - "https://deno.land/std@0.106.0/fs/ensure_file.ts": "c06031af24368e80c330897e4b8e9109efc8602ffabc8f3e2306be07529e1d13", - "https://deno.land/std@0.106.0/fs/ensure_link.ts": "26e54363508b822afd87a3f6e873bbbcd6b5993dd638f8170758c16262a75065", - "https://deno.land/std@0.106.0/fs/ensure_symlink.ts": "c07b6d19ef58b6f5c671ffa942e7f9be50315f4f78e2f9f511626fd2e13beccc", - "https://deno.land/std@0.106.0/fs/eol.ts": "afaebaaac36f48c423b920c836551997715672b80a0fee9aa7667c181a94f2df", - "https://deno.land/std@0.106.0/fs/exists.ts": "b0d2e31654819cc2a8d37df45d6b14686c0cc1d802e9ff09e902a63e98b85a00", - "https://deno.land/std@0.106.0/fs/expand_glob.ts": "73e7b13f01097b04ed782b3d63863379b718417417758ba622e282b1e5300b91", - "https://deno.land/std@0.106.0/fs/mod.ts": "26eee4b52a8c516e37d464094b080ff6822883e7f01ff0ba0a72b8dcd54b9927", - "https://deno.land/std@0.106.0/fs/move.ts": "4623058e39bbbeb3ad30aeff9c974c55d2d574ad7c480295c12b04c244686a99", - "https://deno.land/std@0.106.0/fs/walk.ts": "b91c655c60d048035f9cae0e6177991ab3245e786e3ab7d20a5b60012edf2126", - "https://deno.land/std@0.106.0/path/_constants.ts": "1247fee4a79b70c89f23499691ef169b41b6ccf01887a0abd131009c5581b853", - "https://deno.land/std@0.106.0/path/_interface.ts": "1fa73b02aaa24867e481a48492b44f2598cd9dfa513c7b34001437007d3642e4", - "https://deno.land/std@0.106.0/path/_util.ts": "2e06a3b9e79beaf62687196bd4b60a4c391d862cfa007a20fc3a39f778ba073b", - "https://deno.land/std@0.106.0/path/common.ts": "eaf03d08b569e8a87e674e4e265e099f237472b6fd135b3cbeae5827035ea14a", - "https://deno.land/std@0.106.0/path/glob.ts": "3b84af55c53febacf6afe214c095624b22a56b6f57d7312157479cc783a0de65", - "https://deno.land/std@0.106.0/path/mod.ts": "4465dc494f271b02569edbb4a18d727063b5dbd6ed84283ff906260970a15d12", - "https://deno.land/std@0.106.0/path/posix.ts": "b81974c768d298f8dcd2c720229639b3803ca4a241fa9a355c762fa2bc5ef0c1", - "https://deno.land/std@0.106.0/path/separator.ts": "8fdcf289b1b76fd726a508f57d3370ca029ae6976fcde5044007f062e643ff1c", - "https://deno.land/std@0.106.0/path/win32.ts": "f4a3d4a3f2c9fe894da046d5eac48b5e789a0ebec5152b2c0985efe96a9f7ae1", - "https://deno.land/std@0.198.0/_util/os.ts": "d932f56d41e4f6a6093d56044e29ce637f8dcc43c5a90af43504a889cf1775e3", - "https://deno.land/std@0.198.0/assert/assert.ts": "9a97dad6d98c238938e7540736b826440ad8c1c1e54430ca4c4e623e585607ee", - "https://deno.land/std@0.198.0/assert/assertion_error.ts": "4d0bde9b374dfbcbe8ac23f54f567b77024fb67dbb1906a852d67fe050d42f56", - "https://deno.land/std@0.198.0/path/_basename.ts": "057d420c9049821f983f784fd87fa73ac471901fb628920b67972b0f44319343", - "https://deno.land/std@0.198.0/path/_constants.ts": "e49961f6f4f48039c0dfed3c3f93e963ca3d92791c9d478ac5b43183413136e0", - "https://deno.land/std@0.198.0/path/_dirname.ts": "355e297236b2218600aee7a5301b937204c62e12da9db4b0b044993d9e658395", - "https://deno.land/std@0.198.0/path/_extname.ts": "eaaa5aae1acf1f03254d681bd6a8ce42a9cb5b7ff2213a9d4740e8ab31283664", - "https://deno.land/std@0.198.0/path/_format.ts": "4a99270d6810f082e614309164fad75d6f1a483b68eed97c830a506cc589f8b4", - "https://deno.land/std@0.198.0/path/_from_file_url.ts": "7e4e5626089785adddb061f1b9f4932d6b21c7df778e7449531a11e32048245c", - "https://deno.land/std@0.198.0/path/_interface.ts": "6471159dfbbc357e03882c2266d21ef9afdb1e4aa771b0545e90db58a0ba314b", - "https://deno.land/std@0.198.0/path/_is_absolute.ts": "05dac10b5e93c63198b92e3687baa2be178df5321c527dc555266c0f4f51558c", - "https://deno.land/std@0.198.0/path/_join.ts": "fd78555bc34d5f188918fc7018dfe8fe2df5bbad94a3b30a433666c03934d77f", - "https://deno.land/std@0.198.0/path/_normalize.ts": "a19ec8706b2707f9dd974662a5cd89fad438e62ab1857e08b314a8eb49a34d81", - "https://deno.land/std@0.198.0/path/_parse.ts": "0f9b0ff43682dd9964eb1c4398610c4e165d8db9d3ac9d594220217adf480cfa", - "https://deno.land/std@0.198.0/path/_relative.ts": "27bdeffb5311a47d85be26d37ad1969979359f7636c5cd9fcf05dcd0d5099dc5", - "https://deno.land/std@0.198.0/path/_resolve.ts": "3bf0287d62488cad08c3c219a9708c4a4c658c65d7b4400fd99afdc3ba10a64d", - "https://deno.land/std@0.198.0/path/_to_file_url.ts": "739bfda583598790b2e77ce227f2bb618f6ebdb939788cea47555b43970ec58c", - "https://deno.land/std@0.198.0/path/_to_namespaced_path.ts": "0d5f4caa2ed98ef7a8786286df6af804b50e38859ae897b5b5b4c8c5930a75c8", - "https://deno.land/std@0.198.0/path/_util.ts": "4e191b1bac6b3bf0c31aab42e5ca2e01a86ab5a0d2e08b75acf8585047a86221", - "https://deno.land/std@0.198.0/path/basename.ts": "6f08fbb90dbfcf320765b3abb01f995b1723f75e2534acfd5380e202c802a3aa", - "https://deno.land/std@0.198.0/path/common.ts": "ee7505ab01fd22de3963b64e46cff31f40de34f9f8de1fff6a1bd2fe79380000", - "https://deno.land/std@0.198.0/path/dirname.ts": "098996822a31b4c46e1eb52a19540d3c6f9f54b772fc8a197939eeabc29fca2f", - "https://deno.land/std@0.198.0/path/extname.ts": "9b83c62fd16505739541f7a3ab447d8972da39dbf668d47af2f93206c2480893", - "https://deno.land/std@0.198.0/path/format.ts": "cb22f95cc7853d590b87708cc9441785e760d711188facff3d225305a8213aca", - "https://deno.land/std@0.198.0/path/from_file_url.ts": "a6221cfc928928ec4d9786d767dfac98fa2ab746af0786446c9834a07b98817e", - "https://deno.land/std@0.198.0/path/glob.ts": "d479e0a695621c94d3fd7fe7abd4f9499caf32a8de13f25073451c6ef420a4e1", - "https://deno.land/std@0.198.0/path/is_absolute.ts": "6b3d36352eb7fa29edb53f9e7b09b1aeb022a3c5465764f6cc5b8c41f9736197", - "https://deno.land/std@0.198.0/path/join.ts": "4a2867ff2f3c81ffc9eb3d56dade16db6f8bd3854f269306d23dad4115089c84", - "https://deno.land/std@0.198.0/path/mod.ts": "7765507696cb321994cdacfc19ee3ba61e8e3ebf4bd98fa75a276cf5dc18ce2a", - "https://deno.land/std@0.198.0/path/normalize.ts": "7d992cd262b2deefa842d93a8ba2ed51f3949ba595b1d07f627ac2cddbc74808", - "https://deno.land/std@0.198.0/path/parse.ts": "031fe488b3497fb8312fc1dc3c3d6c2d80707edd9c661e18ee9fd20f95edf322", - "https://deno.land/std@0.198.0/path/posix.ts": "0a1c1952d132323a88736d03e92bd236f3ed5f9f079e5823fae07c8d978ee61b", - "https://deno.land/std@0.198.0/path/relative.ts": "7db80c5035016174267da16321a742d76e875215c317859a383b12f413c6f5d6", - "https://deno.land/std@0.198.0/path/resolve.ts": "103b62207726a27f28177f397008545804ecb20aaf00623af1f622b18cd80b9f", - "https://deno.land/std@0.198.0/path/separator.ts": "0fb679739d0d1d7bf45b68dacfb4ec7563597a902edbaf3c59b50d5bcadd93b1", - "https://deno.land/std@0.198.0/path/to_file_url.ts": "dd32f7a01bbf3b15b5df46796659984b372973d9b2d7d59bcf0eb990763a0cb5", - "https://deno.land/std@0.198.0/path/to_namespaced_path.ts": "4e643ab729bf49ccdc166ad48d2de262ff462938fcf2a44a4425588f4a0bd690", - "https://deno.land/std@0.198.0/path/win32.ts": "8b3f80ef7a462511d5e8020ff490edcaa0a0d118f1b1e9da50e2916bdd73f9dd", - "https://deno.land/x/cliui@v7.0.4-deno/build/lib/index.d.ts": "4f04923352ce24027ad6fe25c85249e0b0cc5c29fe18d62024d004c59d9e41ee", - "https://deno.land/x/cliui@v7.0.4-deno/build/lib/index.js": "fb6030c7b12602a4fca4d81de3ddafa301ba84fd9df73c53de6f3bdda7b482d5", - "https://deno.land/x/cliui@v7.0.4-deno/build/lib/string-utils.js": "b3eb9d2e054a43a3064af17332fb1839a7dadb205c5371af4789616afb1a117f", - "https://deno.land/x/cliui@v7.0.4-deno/deno.ts": "d07bc3338661f8011e3a5fd215061d17a52107a5383c29f40ce0c1ecb8bb8cc3", - "https://deno.land/x/dirname@1.1.2/types.ts": "c1ed1667545bc4b1d69bdb2fc26a5fa8edae3a56e3081209c16a408a322a2319", - "https://deno.land/x/escalade@v3.0.3/sync.ts": "493bc66563292c5c10c4a75a467a5933f24dad67d74b0f5a87e7b988fe97c104", - "https://deno.land/x/y18n@v5.0.0-deno/build/lib/index.d.ts": "11f40d97041eb271cc1a1c7b296c6e7a068d4843759575e7416f0d14ebf8239c", - "https://deno.land/x/y18n@v5.0.0-deno/build/lib/index.js": "92c4624714aa508d33c6d21c0b0ffa072369a8b306e5f8c7727662f570bbd026", - "https://deno.land/x/y18n@v5.0.0-deno/deno.ts": "80997f0709a0b43d29931e2b33946f2bbc32b13fd82f80a5409628455427e28d", - "https://deno.land/x/y18n@v5.0.0-deno/lib/platform-shims/deno.ts": "8fa2c96ac03734966260cfd2c5bc240e41725c913e5b64a0297aede09f52b39d", - "https://deno.land/x/yargs@v17.1.1-deno/build/lib/argsert.js": "eb085555452eac3ff300935994a42f35d16e04cf698cb775cb5ad4f5653c0627", - "https://deno.land/x/yargs@v17.1.1-deno/build/lib/command.js": "499c95cecd5e93f627e0b5ce66a193c9a595adc10fbafe0581a9725e38324dee", - "https://deno.land/x/yargs@v17.1.1-deno/build/lib/completion-templates.js": "f84823b1daa0ed0189e4f823f6a4fd29ad58de6a05771004918368fd62bb2b3f", - "https://deno.land/x/yargs@v17.1.1-deno/build/lib/completion.js": "c91772b89907ebf1a462804305d12d3b9deade75cd1b319c06831ac0bf5abd27", - "https://deno.land/x/yargs@v17.1.1-deno/build/lib/middleware.js": "cef3f017d5ff61c340c65b8422f5ab9600ba381aa656df634d1a3edf0f967527", - "https://deno.land/x/yargs@v17.1.1-deno/build/lib/parse-command.js": "327242c0afae207b7aefa13133439e3b321d7db4229febc5b7bd5285770ac7f7", - "https://deno.land/x/yargs@v17.1.1-deno/build/lib/typings/common-types.js": "9618b81a86acb88a61fd9988e9bc3ec21c5250d94fc2231ba7d898e71500789d", - "https://deno.land/x/yargs@v17.1.1-deno/build/lib/usage.js": "61071feb99ac220f1b27036406ae8e4f9ee606b373a5f3bcb60042c7bcfbd0d8", - "https://deno.land/x/yargs@v17.1.1-deno/build/lib/utils/apply-extends.js": "64640dce92669705abead3bdbe2c46c8318c8623843a55e4726fb3c55ff9dd1d", - "https://deno.land/x/yargs@v17.1.1-deno/build/lib/utils/is-promise.js": "be45baa3090c5106dd4e442cceef6b357a268783a2ee28ec10fe131a8cd8db72", - "https://deno.land/x/yargs@v17.1.1-deno/build/lib/utils/levenshtein.js": "d8638efc3376b5f794b1c8df6ef4f3d484b29d919127c7fdc242400e3cfded91", - "https://deno.land/x/yargs@v17.1.1-deno/build/lib/utils/maybe-async-result.js": "31cf4026279e14c87d16faa14ac758f35c8cc5795d29393c5ce07120f5a3caf6", - "https://deno.land/x/yargs@v17.1.1-deno/build/lib/utils/obj-filter.js": "5523fb2288d1e86ed48c460e176770b49587554df4ae2405b468c093786b040b", - "https://deno.land/x/yargs@v17.1.1-deno/build/lib/utils/set-blocking.js": "6fa8ffc3299f456e42902736bae35fbc1f2dc96b3905a02ba9629f5bd9f80af1", - "https://deno.land/x/yargs@v17.1.1-deno/build/lib/utils/which-module.js": "9267633b2c9f8990b2c699101b641e59ae59932e0dee5270613c0508bfa13c5d", - "https://deno.land/x/yargs@v17.1.1-deno/build/lib/validation.js": "3dc366de2eb23bc9457ed3e120b69db9d801251bef3dc19f93e4c0380ac0198c", - "https://deno.land/x/yargs@v17.1.1-deno/build/lib/yargs-factory.js": "a3e629d7d063b5ac007b18a0d8e9ad2ca72ca4d702c5c46822fbbdfdd6c512df", - "https://deno.land/x/yargs@v17.1.1-deno/build/lib/yerror.js": "1d9dead374fe06c8f13f2e4adafc002b8a15682b7185abf29638f1be96fd9dfc", - "https://deno.land/x/yargs@v17.1.1-deno/deno-types.ts": "62f5c61899c6da491890c8c84fd9580cfbfa2a83f5a70f6dc74727bbfb148623", - "https://deno.land/x/yargs@v17.1.1-deno/deno.ts": "f3df0bfd08ba367ec36dc59ef6cab1a391ace49ad44387ec5fe5d76289af08af", - "https://deno.land/x/yargs@v17.1.1-deno/lib/platform-shims/deno.ts": "b5a48b40d5c64fe66f5a77f87ebaf4413eea828ccd8159feeac370b3eef9a356", - "https://deno.land/x/yargs_parser@v20.2.4-deno/build/lib/string-utils.js": "12fc056b23703bc370aae5b179dc5abee53fca277abc30eaf76f78d2546d6413", - "https://deno.land/x/yargs_parser@v20.2.4-deno/build/lib/tokenize-arg-string.js": "7e0875b11795b8e217386e45f14b24a6e501ebbc62e15aa469aa8829d4d0ee61", - "https://deno.land/x/yargs_parser@v20.2.4-deno/build/lib/yargs-parser-types.d.ts": "434deb76c6632b3b6cbc4c6f153f8aca04e06055ae9c6b24b40218cbc42688d9", - "https://deno.land/x/yargs_parser@v20.2.4-deno/build/lib/yargs-parser.js": "453200a7dfbb002e605d8009b7dad30f2b1d93665e046ab89c073a4fe63dfd48", - "https://deno.land/x/yargs_parser@v20.2.4-deno/deno.ts": "ad53c0c82c3982c4fc5be9472384b259e0a32ce1f7ae0f68de7b2445df5642fc", - "https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/_util/assert.ts": "e1f76e77c5ccb5a8e0dbbbe6cce3a56d2556c8cb5a9a8802fc9565af72462149", - "https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/path/_constants.ts": "aba480c4a2c098b6374fdd5951fea13ecc8aaaf8b8aa4dae1871baa50243d676", - "https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/path/_interface.ts": "67b276380d297a7cedc3c17f7a0bf122edcfc96a3e1f69de06f379d85ba0e2c0", - "https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/path/_util.ts": "7820a788b35c26dfc27ff329df12507fc0553ae92727009597046f6cf856b4fa", - "https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/path/common.ts": "e4ec66a7416d56f60331b66e27a8a4f08c7b1cf48e350271cb69754a01cf5c04", - "https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/path/glob.ts": "54fea22f0f47dee07399d22e18a34a84eaf4b8a3771bbed96db43bbec71ef237", - "https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/path/mod.ts": "6de8885c2534757097818e302becd1cefcbc4c28ac022cc279e612ee04e8cfd1", - "https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/path/posix.ts": "7c2539b5d9e22b47f02ccc5b6ef11e3975a5c60f49d2241271eaa5936e6082a0", - "https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/path/separator.ts": "9dd15d46ff84a16e13554f56af7fee1f85f8d0f379efbbe60ac066a60561f036", - "https://lra6z45nakk5lnu3yjchp7tftsdnwwikwr65ocha5eojfnlgu4sa.arweave.net/XEHs860CldW2m8JEd_5lnIbbWQq0fdcI4OkckrVmpyQ/path/win32.ts": "47114c941681ecbabab4ec355cb41d525fb5a14175cc47a5c76fdc5eaee2685a" - } -} diff --git a/crates/loro-internal/docs/diff_calc.md b/crates/loro-internal/docs/diff_calc.md deleted file mode 100644 index 22e7d78b6..000000000 --- a/crates/loro-internal/docs/diff_calc.md +++ /dev/null @@ -1,23 +0,0 @@ -# Internal of Diff Calculation - -Diff calculation is the core of the `diff` command. It is responsible for calculating the difference between two versions of a container. - -# Three modes of diff calculation - -## 1. Checkout Mode - -This is the most general mode of diff calculation. It can be used whenever a user want to switch to a different version. -But it is also the slowest mode. It relies on the `ContainerHistoryCache`, which is expensive to build and maintain in memory. - -## 2. Import Mode - -This mode is used when the user imports new updates. It is faster than the checkout mode, but it is still slower than the linear mode. - -- The difference between the import mode and the checkout mode: in import mode, target version > current version. - So when calculating the `DiffCalculator` doesn't need to rely on `ContainerHistoryCache`, except for the Tree container. -- The difference between the import mode and the linear mode: in linear mode, all the imported updates are ordered, no concurrent update exists. - so there is no need to build CRDTs for the calculation - -## 3. Linear Mode - -This mode is used when we don't need to build CRDTs to calculate the difference. It is the fastest mode. diff --git a/crates/loro-internal/examples/automerge_x100.rs b/crates/loro-internal/examples/automerge_x100.rs deleted file mode 100644 index c8468f10f..000000000 --- a/crates/loro-internal/examples/automerge_x100.rs +++ /dev/null @@ -1,41 +0,0 @@ -use loro_internal::{cursor::PosType, loro::ExportMode, LoroDoc, VersionVector}; -use std::hint::black_box; - -fn main() { - use bench_utils::TextAction; - use std::time::Instant; - - let actions = bench_utils::get_automerge_actions(); - let loro = LoroDoc::default(); - loro.start_auto_commit(); - let start = Instant::now(); - // loro.subscribe_deep(Box::new(|_| ())); - let text = loro.get_text("text"); - let n = 100; - let mut v = VersionVector::new(); - for _ in 0..n { - for TextAction { del, ins, pos } in actions.iter() { - text.delete(*pos, *del, PosType::Unicode).unwrap(); - text.insert(*pos, ins, PosType::Unicode).unwrap(); - } - loro.commit_then_renew(); - black_box(loro.export(ExportMode::updates(&v))).unwrap(); - v = loro.oplog_vv(); - } - println!("Apply time {:?}", start.elapsed()); - loro.diagnose_size(); - drop(actions); - let start = Instant::now(); - let snapshot = loro.export(ExportMode::Snapshot).unwrap(); - println!("Snapshot encoding time {}", start.elapsed().as_millis()); - let compressed = zstd::encode_all(&mut snapshot.as_slice(), 0).unwrap(); - println!( - "Snapshot encoding time including compression {}", - start.elapsed().as_millis() - ); - println!("Snapshot size {}", snapshot.len()); - println!("Snapshot size after compression {}", compressed.len()); - let start = Instant::now(); - let _doc = LoroDoc::from_snapshot(&snapshot); - println!("Snapshot importing time {:?}", start.elapsed()); -} diff --git a/crates/loro-internal/examples/encoding.rs b/crates/loro-internal/examples/encoding.rs deleted file mode 100644 index 2ac5f309d..000000000 --- a/crates/loro-internal/examples/encoding.rs +++ /dev/null @@ -1,155 +0,0 @@ -use std::time::Instant; - -use bench_utils::TextAction; -use loro_internal::{cursor::PosType, loro::ExportMode, LoroDoc}; - -fn main() { - let actions = bench_utils::get_automerge_actions(); - - // let loro = LoroDoc::default(); - // let loro_b = LoroDoc::default(); - // let text = loro.get_text("text"); - // let mut i = 0; - // let start = Instant::now(); - // for TextAction { pos, ins, del } in actions.iter() { - // { - // let mut txn = loro.txn().unwrap(); - // text.delete(&mut txn, *pos, *del).unwrap(); - // text.insert(&mut txn, *pos, ins).unwrap(); - // } - - // loro_b - // .import(&loro.export(ExportMode::updates(&loro_b.oplog_vv())).unwrap()) - // .unwrap(); - // i += 1; - // if i == 30000 { - // break; - // } - // } - - // println!("{}ms", start.elapsed().as_millis()); - - let loro = LoroDoc::default(); - let text = loro.get_text("text"); - - for TextAction { pos, ins, del } in actions.iter() { - let mut txn = loro.txn().unwrap(); - text.delete_with_txn(&mut txn, *pos, *del, PosType::Unicode) - .unwrap(); - text.insert_with_txn(&mut txn, *pos, ins, PosType::Unicode) - .unwrap(); - txn.commit().unwrap(); - } - - let start = Instant::now(); - let snapshot = loro.export(ExportMode::Snapshot).unwrap(); - println!("Snapshot time {}ms", start.elapsed().as_millis()); - let output = miniz_oxide::deflate::compress_to_vec(&snapshot, 6); - println!( - "Snapshot+compression time {}ms", - start.elapsed().as_millis() - ); - - println!( - "snapshot size {} after compression {}", - snapshot.len(), - output.len(), - ); - - let start = Instant::now(); - let shallow_snapshot = loro - .export(ExportMode::shallow_snapshot(&loro.oplog_frontiers())) - .unwrap(); - println!("Shallow Snapshot time {}ms", start.elapsed().as_millis()); - let output = miniz_oxide::deflate::compress_to_vec(&shallow_snapshot, 6); - println!( - "Shallow Snapshot+compression time {}ms", - start.elapsed().as_millis() - ); - - println!( - "Shallow snapshot size {} after compression {}", - shallow_snapshot.len(), - output.len(), - ); - - let updates = loro.export(ExportMode::all_updates()).unwrap(); - let output = miniz_oxide::deflate::compress_to_vec(&updates, 6); - println!( - "updates size {} after compression {}", - updates.len(), - output.len(), - ); - - let json_updates = serde_json::to_string(&loro.export_json_updates( - &Default::default(), - &loro.oplog_vv(), - true, - )) - .unwrap(); - let output = miniz_oxide::deflate::compress_to_vec(json_updates.as_bytes(), 6); - println!( - "json updates size {} after compression {}", - json_updates.len(), - output.len(), - ); - - // { - // // Delta encoding - - { - // Delta encoding - - let start = Instant::now(); - for _ in 0..10 { - loro.export(ExportMode::all_updates()).unwrap(); - } - - println!("Avg encode {}ms", start.elapsed().as_millis() as f64 / 10.0); - - let data = loro.export(ExportMode::all_updates()).unwrap(); - let start = Instant::now(); - let n = 5; - for _ in 0..n { - let b = LoroDoc::default(); - b.detach(); - b.import(&data).unwrap(); - } - - println!( - "Avg normal decode {}ms (without applying)", - start.elapsed().as_millis() as f64 / (n as f64) - ); - println!("size len={}", data.len()); - let d = miniz_oxide::deflate::compress_to_vec(&data, 10); - println!("size after compress len={}", d.len()); - } - - // { - // // Snapshot encoding - // // println!("\n=======================\nSnapshot Encoding:"); - - // // let start = Instant::now(); - // // for _ in 0..10 { - // // loro.export(ExportMode::Snapshot); - // // } - - // // println!("Avg encode {}ms", start.elapsed().as_millis() as f64 / 10.0); - - // // let data = loro.export(ExportMode::Snapshot); - // // let start = Instant::now(); - // // let times = 300; - // // for _ in 0..times { - // // let b = LoroDoc::default(); - // // b.import(&data).unwrap(); - // // } - - // // println!( - // // "Avg decode {}ms", - // // start.elapsed().as_millis() as f64 / times as f64 - // // ); - // // println!("size len={}", data.len()); - // // let d = miniz_oxide::deflate::compress_to_vec(&data, 10); - // // println!("size after compress len={}", d.len()); - // } -} diff --git a/crates/loro-internal/examples/encoding_parallel.rs b/crates/loro-internal/examples/encoding_parallel.rs deleted file mode 100644 index 79224d91e..000000000 --- a/crates/loro-internal/examples/encoding_parallel.rs +++ /dev/null @@ -1,90 +0,0 @@ -use bench_utils::{get_automerge_actions, TextAction}; -use loro_internal::{cursor::PosType, encoding::ExportMode, LoroDoc}; - -// #[allow(dead_code)] -// fn parallel() { -// let mut rng: StdRng = SeedableRng::seed_from_u64(1); - -// let actions = get_automerge_actions(); -// let mut loro = LoroCore::new(Default::default(), Some(1)); -// let mut loro_b = LoroCore::new(Default::default(), Some(2)); -// let mut i = 0; -// for TextAction { pos, ins, del } in actions.iter() { -// i += 1; -// if i > 1000 { -// break; -// } -// let pos = *pos; -// let del = *del; -// let mut text = loro.get_text("text"); -// text.delete(&loro, pos, del).unwrap(); -// text.insert(&loro, pos, ins).unwrap(); -// let mut text = loro_b.get_text("text"); -// let r = rng.gen_range(1..11); -// for _ in 0..r { -// text.delete(&loro_b, pos, del).unwrap(); -// text.insert(&loro_b, pos, ins).unwrap(); -// } -// loro_b.import(loro.export(loro_b.vv_cloned())); -// loro.import(loro_b.export(loro.vv_cloned())); -// } -// let encoded = loro.encode_with_cfg(EncodeMode::RleUpdates(VersionVector::new())); -// println!("parallel doc size {} bytes", encoded.len()); -// let encoded = loro.encode_all(); -// println!("parallel doc size {} bytes", encoded.len()); -// } - -// #[allow(dead_code)] -// fn real_time() { -// let actions = get_automerge_actions(); -// let mut c1 = LoroCore::new(Default::default(), Some(0)); -// let mut c2 = LoroCore::new(Default::default(), Some(1)); -// let mut t1 = c1.get_text("text"); -// let mut t2 = c2.get_text("text"); -// for (i, action) in actions.iter().enumerate() { -// if i > 2000 { -// break; -// } -// let TextAction { pos, ins, del } = action; -// if i % 2 == 0 { -// t1.delete(&c1, *pos, *del).unwrap(); -// t1.insert(&c1, *pos, ins).unwrap(); -// let update = c1.encode_with_cfg(EncodeMode::Updates(c2.vv_cloned())); -// c2.decode(&update).unwrap(); -// } else { -// t2.delete(&c2, *pos, *del).unwrap(); -// t2.insert(&c2, *pos, ins).unwrap(); -// let update = c2.encode_with_cfg(EncodeMode::Updates(c1.vv_cloned())); -// c1.decode(&update).unwrap(); -// } -// } -// } - -fn main() { - let actions = get_automerge_actions(); - let loro = LoroDoc::default(); - let loro_b = LoroDoc::default(); - let text = loro.get_text("text"); - let mut count = 0; - for TextAction { pos, ins, del } in actions.iter() { - { - let mut txn = loro.txn().unwrap(); - text.delete_with_txn(&mut txn, *pos, *del, PosType::Unicode) - .unwrap(); - text.insert_with_txn(&mut txn, *pos, ins, PosType::Unicode) - .unwrap(); - } - - loro_b - .import( - &loro - .export(ExportMode::updates(&loro_b.oplog_vv())) - .unwrap(), - ) - .unwrap(); - count += 1; - if count % 1000 == 0 { - println!("{count}"); - } - } -} diff --git a/crates/loro-internal/examples/encoding_refactored.rs b/crates/loro-internal/examples/encoding_refactored.rs deleted file mode 100644 index 709c426c1..000000000 --- a/crates/loro-internal/examples/encoding_refactored.rs +++ /dev/null @@ -1,115 +0,0 @@ -use bench_utils::TextAction; -use loro_internal::{cursor::PosType, loro::ExportMode, LoroDoc}; -use std::hint::black_box; - -fn main() { - log_size(); - // bench_decode(); - // bench_decode_updates(); -} - -#[allow(unused)] -fn log_size() { - let actions = bench_utils::get_automerge_actions(); - { - let loro = LoroDoc::default(); - let text = loro.get_text("text"); - let mut txn = loro.txn().unwrap(); - - for TextAction { pos, ins, del } in actions.iter() { - text.delete_with_txn(&mut txn, *pos, *del, PosType::Unicode) - .unwrap(); - text.insert_with_txn(&mut txn, *pos, ins, PosType::Unicode) - .unwrap(); - } - txn.commit().unwrap(); - let snapshot = loro.export(ExportMode::Snapshot).unwrap(); - let updates = loro.export(ExportMode::all_updates()).unwrap(); - let json_updates = serde_json::to_string(&loro.export_json_updates( - &Default::default(), - &loro.oplog_vv(), - true, - )) - .unwrap(); - println!("\n"); - println!("Snapshot size={}", snapshot.len()); - println!("Updates size={}", updates.len()); - println!("Json Updates size={}", json_updates.len()); - println!("\n"); - loro.diagnose_size(); - } - println!("\n"); - println!("\n"); - println!("\n"); - { - println!("One Transaction Per Action"); - let loro = LoroDoc::default(); - let text = loro.get_text("text"); - - for TextAction { pos, ins, del } in actions.iter() { - let mut txn = loro.txn().unwrap(); - text.delete_with_txn(&mut txn, *pos, *del, PosType::Unicode) - .unwrap(); - text.insert_with_txn(&mut txn, *pos, ins, PosType::Unicode) - .unwrap(); - txn.commit().unwrap(); - } - let snapshot = loro.export(ExportMode::Snapshot).unwrap(); - let updates = loro.export(ExportMode::all_updates()).unwrap(); - println!("\n"); - println!("Snapshot size={}", snapshot.len()); - println!("Updates size={}", updates.len()); - println!("\n"); - loro.diagnose_size(); - } -} - -#[allow(unused)] -fn bench_decode() { - println!("Bench decode"); - let actions = bench_utils::get_automerge_actions(); - { - let mut loro = LoroDoc::default(); - let text = loro.get_text("text"); - loro.start_auto_commit(); - - for _ in 0..10 { - for TextAction { pos, ins, del } in actions.iter() { - text.delete(*pos, *del, PosType::Unicode).unwrap(); - text.insert(*pos, ins, PosType::Unicode).unwrap(); - } - } - let snapshot = loro.export(ExportMode::Snapshot).unwrap(); - // for _ in 0..100 { - // black_box(loro.export(ExportMode::Snapshot)); - // } - - for _ in 0..100 { - let loro = LoroDoc::new(); - loro.import(black_box(&snapshot)).unwrap(); - } - } -} - -#[allow(unused)] -fn bench_decode_updates() { - let actions = bench_utils::get_automerge_actions(); - let loro = LoroDoc::default(); - let text = loro.get_text("text"); - - #[allow(warnings)] - for TextAction { pos, ins, del } in actions.iter() { - let mut txn = loro.txn().unwrap(); - text.delete_with_txn(&mut txn, *pos, *del, PosType::Unicode) - .unwrap(); - text.insert_with_txn(&mut txn, *pos, ins, PosType::Unicode) - .unwrap(); - txn.commit().unwrap(); - } - - let updates = loro.export(ExportMode::all_updates()).unwrap(); - for _ in 0..10 { - let loro = LoroDoc::new(); - loro.import(black_box(&updates)).unwrap(); - } -} diff --git a/crates/loro-internal/examples/event.rs b/crates/loro-internal/examples/event.rs deleted file mode 100644 index b1fb85e46..000000000 --- a/crates/loro-internal/examples/event.rs +++ /dev/null @@ -1,66 +0,0 @@ -use std::sync::Arc; - -use loro_internal::{ - cursor::PosType, - event::Diff, - handler::{Handler, ValueOrHandler}, - ListHandler, LoroDoc, MapHandler, TextHandler, ToJson, TreeHandler, -}; - -fn main() { - let doc = LoroDoc::new(); - doc.start_auto_commit(); - let list = doc.get_list("list"); - let _g = doc.subscribe_root(Arc::new(|e| { - for container_diff in e.events { - match &container_diff.diff { - Diff::List(list) => { - for item in list.iter() { - if let loro_delta::DeltaItem::Replace { value, .. } = item { - for v in value.iter() { - match v { - ValueOrHandler::Handler(h) => { - // You can directly obtain the handler and perform some operations. - if matches!(h, Handler::Map(_)) { - let text = h - .as_map() - .unwrap() - .insert_container( - "text", - TextHandler::new_detached(), - ) - .unwrap(); - text.insert(0, "created from event", PosType::Unicode) - .unwrap(); - } - } - ValueOrHandler::Value(value) => { - println!("insert value {value:?}"); - } - } - } - } - } - } - Diff::Map(map) => { - println!("map container updates {:?}", map.updated); - } - _ => {} - } - } - })); - list.insert(0, "abc").unwrap(); - list.insert_container(1, ListHandler::new_detached()) - .unwrap(); - list.insert_container(2, MapHandler::new_detached()) - .unwrap(); - list.insert_container(3, TextHandler::new_detached()) - .unwrap(); - list.insert_container(4, TreeHandler::new_detached()) - .unwrap(); - doc.commit_then_renew(); - assert_eq!( - doc.get_deep_value().to_json(), - r#"{"list":["abc",[],{"text":"created from event"},"",[]]}"# - ); -} diff --git a/crates/loro-internal/examples/list.rs b/crates/loro-internal/examples/list.rs deleted file mode 100644 index b31373e4d..000000000 --- a/crates/loro-internal/examples/list.rs +++ /dev/null @@ -1,23 +0,0 @@ -use std::time::Instant; -// #[global_allocator] -// static ALLOC: dhat::Alloc = dhat::Alloc; - -use loro_internal::{encoding::ExportMode, LoroDoc}; - -fn main() { - // let p = dhat::Profiler::builder().trim_backtraces(None).build(); - let start = Instant::now(); - let actor = LoroDoc::default(); - let mut output = Vec::new(); - let list = actor.get_list("list"); - let mut last_vv = actor.oplog_vv(); - for i in 0..10000 { - let mut txn = actor.txn().unwrap(); - list.insert_with_txn(&mut txn, i, i.to_string().into()) - .unwrap(); - output.push(actor.export(ExportMode::updates(&last_vv.clone())).unwrap()); - last_vv = actor.oplog_vv(); - } - println!("{} ms", start.elapsed().as_millis()); - // drop(p) -} diff --git a/crates/loro-internal/examples/many_actors.rs b/crates/loro-internal/examples/many_actors.rs deleted file mode 100644 index fd36b1f74..000000000 --- a/crates/loro-internal/examples/many_actors.rs +++ /dev/null @@ -1,60 +0,0 @@ -use std::time::Instant; - -use loro_internal::{loro::ExportMode, LoroDoc, LoroValue}; -// #[global_allocator] -// static ALLOC: dhat::Alloc = dhat::Alloc; - -fn main() { - // with_100k_actors_then_action(); - import_with_many_actors(); -} - -#[allow(unused)] -fn import_with_many_actors() { - let store = LoroDoc::default(); - for i in 0..10000 { - store.set_peer_id(i); - let list = store.get_list("list"); - let value: LoroValue = i.to_string().into(); - let mut txn = store.txn().unwrap(); - list.insert_with_txn(&mut txn, 0, value).unwrap(); - txn.commit().unwrap(); - } - - { - let start = Instant::now(); - let bytes = store.export(ExportMode::Snapshot).unwrap(); - LoroDoc::default().import(&bytes).unwrap(); - println!("{} ms", start.elapsed().as_millis()); - } - - // let profiler = dhat::Profiler::builder().trim_backtraces(None).build(); - // let start = Instant::now(); - // let mut actor = LoroDoc::default(); - // actor.import_batch(&updates).unwrap(); - // println!("{} bytes", updates.iter().map(|x| x.len()).sum::()); - // // dbg!(actor.get_state_deep_value()); - // println!("{} ms", start.elapsed().as_millis()); - // drop(profiler); -} - -#[allow(unused)] -fn with_100k_actors_then_action() { - let store = LoroDoc::default(); - for i in 0..100_000 { - store.set_peer_id(i); - let list = store.get_list("list"); - let value: LoroValue = i.to_string().into(); - let mut txn = store.txn().unwrap(); - list.insert_with_txn(&mut txn, 0, value).unwrap(); - txn.commit().unwrap(); - } - - for i in 0..200_000 { - let list = store.get_list("list"); - let value: LoroValue = i.to_string().into(); - let mut txn = store.txn().unwrap(); - list.insert_with_txn(&mut txn, 0, value).unwrap(); - txn.commit().unwrap(); - } -} diff --git a/crates/loro-internal/examples/mem.rs b/crates/loro-internal/examples/mem.rs deleted file mode 100644 index b7bda998b..000000000 --- a/crates/loro-internal/examples/mem.rs +++ /dev/null @@ -1,110 +0,0 @@ -// #[global_allocator] -// static ALLOC: dhat::Alloc = dhat::Alloc; - -// use std::time::Instant; - -// use bench_utils::TextAction; -// use loro_internal::LoroDoc; - -// fn apply_automerge(times: usize) { -// let actions = bench_utils::get_automerge_actions(); -// let start = Instant::now(); -// let profiler = dhat::Profiler::builder().trim_backtraces(None).build(); -// let mut loro = LoroCore::default(); -// let mut text = loro.get_text("text"); -// println!("Apply Automerge Dataset 1X"); -// for _i in 0..times { -// for TextAction { pos, ins, del } in actions.iter() { -// text.delete(&loro, *pos, *del).unwrap(); -// text.insert(&loro, *pos, ins).unwrap(); -// } -// } -// drop(profiler); -// println!("Used: {} ms", start.elapsed().as_millis()); -// } - -// fn concurrent_actors(actor_num: usize) { -// let mut actors: Vec = Vec::new(); -// for _ in 0..actor_num { -// actors.push(LoroCore::default()); -// } - -// let mut updates = Vec::new(); -// for actor in actors.iter_mut() { -// let mut list = actor.get_list("list"); -// list.insert(actor, 0, 1).unwrap(); -// updates.push(actor.encode_all()); -// } - -// let mut a = actors.drain(0..1).next().unwrap(); -// drop(actors); -// let profiler = dhat::Profiler::builder().trim_backtraces(None).build(); -// for update in updates { -// a.decode(&update).unwrap(); -// } -// drop(profiler); -// } - -// fn realtime_sync(actor_num: usize, action_num: usize) { -// let actions = bench_utils::gen_realtime_actions(action_num, actor_num, 100); -// let profiler = dhat::Profiler::builder().trim_backtraces(None).build(); -// let mut actors = Vec::new(); -// for _ in 0..actor_num { -// actors.push(LoroDoc::default()); -// } - -// for action in actions { -// match action { -// bench_utils::Action::Text { client, action } => { -// let mut text = actors[client].get_text("text"); -// let bench_utils::TextAction { pos, ins, del } = action; -// let pos = pos % (text.len() + 1); -// let del = del.min(text.len() - pos); -// text.delete(&actors[client], pos, del).unwrap(); -// text.insert(&actors[client], pos, &ins).unwrap(); -// } -// bench_utils::Action::SyncAll => { -// let mut updates = Vec::new(); -// for i in 1..actor_num { -// let (a, b) = arref::array_mut_ref!(&mut actors, [0, i]); -// updates.push(b.encode_from(a.vv_cloned())); -// } -// for update in updates { -// // TODO: use import batch here -// actors[0].decode(&update).unwrap(); -// } -// for i in 1..actor_num { -// let (a, b) = arref::array_mut_ref!(&mut actors, [0, i]); -// b.decode(&a.encode_from(b.vv_cloned())).unwrap(); -// } -// } -// } -// } -// drop(profiler); -// } - -pub fn main() { - // let args: Vec<_> = std::env::args().collect(); - // if args.len() < 2 { - // apply_automerge(1); - // return; - // } - - // match args[1].as_str() { - // "automerge" => { - // apply_automerge(1); - // } - // "100_concurrent" => { - // concurrent_actors(100); - // } - // "200_concurrent" => { - // concurrent_actors(200); - // } - // "10_actor_sync_1000_actions" => realtime_sync(10, 1000), - // "20_actor_sync_1000_actions" => realtime_sync(20, 1000), - // "10_actor_sync_2000_actions" => realtime_sync(10, 2000), - // _ => { - // panic!("Unknown command `{}`", args.join(" ")); - // } - // } -} diff --git a/crates/loro-internal/examples/obs.rs b/crates/loro-internal/examples/obs.rs deleted file mode 100644 index fee6d7d1e..000000000 --- a/crates/loro-internal/examples/obs.rs +++ /dev/null @@ -1,26 +0,0 @@ -use bench_utils::TextAction; - -use loro_internal::{cursor::PosType, LoroDoc}; - -fn main() { - let actions = bench_utils::get_automerge_actions(); - let start = std::time::Instant::now(); - for _ in 0..10 { - let loro = LoroDoc::default(); - let text = loro.get_text("text"); - // loro.subscribe_deep(Arc::new(move |event| { - // black_box(event); - // })); - for TextAction { pos, ins, del } in actions.iter() { - let mut txn = loro.txn().unwrap(); - text.delete_with_txn(&mut txn, *pos, *del, PosType::Unicode) - .unwrap(); - text.insert_with_txn(&mut txn, *pos, ins, PosType::Unicode) - .unwrap(); - } - - text.diagnose(); - } - - println!("time: {:?}", start.elapsed()); -} diff --git a/crates/loro-internal/examples/pending.rs b/crates/loro-internal/examples/pending.rs deleted file mode 100644 index a2e5bae81..000000000 --- a/crates/loro-internal/examples/pending.rs +++ /dev/null @@ -1,33 +0,0 @@ -use bench_utils::TextAction; -use loro_internal::{cursor::PosType, encoding::ExportMode, LoroDoc, VersionVector}; - -pub fn main() { - let loro = LoroDoc::default(); - let mut latest_vv = VersionVector::default(); - let mut updates = vec![]; - let actions = bench_utils::get_automerge_actions(); - let action_length = actions.len(); - let text = loro.get_text("text"); - for chunks in actions.chunks(action_length / 10) { - for TextAction { pos, ins, del } in chunks { - let mut txn = loro.txn().unwrap(); - text.delete_with_txn(&mut txn, *pos, *del, PosType::Unicode) - .unwrap(); - text.insert_with_txn(&mut txn, *pos, ins, PosType::Unicode) - .unwrap(); - let update = loro.export(ExportMode::updates(&latest_vv)).unwrap(); - updates.push(update); - latest_vv = loro.oplog_vv(); - } - } - - println!("done encoding"); - updates.reverse(); - let start = std::time::Instant::now(); - let store2 = LoroDoc::default(); - store2.detach(); - for update in updates.iter() { - store2.import(update).unwrap(); - } - println!("Elapsed {}", start.elapsed().as_millis()); -} diff --git a/crates/loro-internal/examples/state_size.rs b/crates/loro-internal/examples/state_size.rs deleted file mode 100644 index 099025dee..000000000 --- a/crates/loro-internal/examples/state_size.rs +++ /dev/null @@ -1,127 +0,0 @@ -use loro_common::{LoroResult, LoroValue}; -use loro_internal::{loro::ExportMode, LoroDoc}; -use rand::{thread_rng, Rng}; - -#[derive(Debug, Clone, Copy)] -enum Kind { - Map, - List, - MovableList, - Text, - Tree, - Counter, -} - -fn empty_state() -> Vec { - let doc = LoroDoc::new_auto_commit(); - doc.export(ExportMode::StateOnly(None)).unwrap() -} - -fn create_elem_sequentially(n: usize, kind: Kind) -> LoroResult> { - let doc = LoroDoc::new_auto_commit(); - for i in 0..n { - match kind { - Kind::Map => { - doc.get_map("map").insert(&i.to_string(), i as u32)?; - } - Kind::List => { - doc.get_list("list").push(i as u32)?; - } - Kind::MovableList => { - doc.get_movable_list("movable_list") - .push(LoroValue::from(i as u32))?; - } - Kind::Text => { - let text = doc.get_text("text"); - text.insert_unicode(text.len_unicode(), &i.to_string())?; - } - Kind::Tree => { - doc.get_tree("tree").enable_fractional_index(0); - doc.get_tree("tree") - .create(loro_internal::TreeParentId::Root)?; - } - Kind::Counter => { - #[cfg(feature = "counter")] - { - doc.get_counter("counter").increment(i as f64)?; - } - } - } - } - let bytes = doc.export(ExportMode::StateOnly(None)).unwrap(); - Ok(bytes) -} - -fn create_elem_randomly(n: usize, kind: Kind) -> LoroResult> { - let doc = LoroDoc::new_auto_commit(); - let mut rng = thread_rng(); - for _ in 0..n / 5 { - for _ in 0..5 { - match kind { - Kind::Map => { - let i = rng.gen::() % 1000; - doc.get_map("map").insert(&i.to_string(), i as u32)?; - } - Kind::List => { - let list = doc.get_list("list"); - let i = rng.gen::() % (list.len() + 1); - list.insert(i, i as u32)?; - } - Kind::MovableList => { - let list = doc.get_movable_list("movable_list"); - let i = rng.gen::() % (list.len() + 1); - list.insert(i, i as u32)?; - } - Kind::Text => { - let text = doc.get_text("text"); - let i = rng.gen::() % (text.len_unicode() + 1); - text.insert_unicode(i, &i.to_string())?; - } - Kind::Tree => { - doc.get_tree("tree").enable_fractional_index(0); - doc.get_tree("tree") - .create(loro_internal::TreeParentId::Root)?; - } - Kind::Counter => { - #[cfg(feature = "counter")] - { - doc.get_counter("counter").increment(rng.gen::())?; - } - } - } - } - doc.set_peer_id(rng.gen::()).unwrap(); - } - let bytes = doc.export(ExportMode::StateOnly(None)).unwrap(); - Ok(bytes) -} - -fn main() -> LoroResult<()> { - for kind in [ - Kind::Map, - Kind::List, - Kind::MovableList, - Kind::Text, - #[allow(unused)] - Kind::Tree, - #[cfg(feature = "counter")] - Kind::Counter, - ] { - println!("============================="); - println!("{kind:?}"); - println!("============================="); - - for (title, bytes) in [ - ("empty", empty_state()), - ("10 items", create_elem_sequentially(10, kind)?), - ( - "1000 items sequentially", - create_elem_sequentially(1000, kind)?, - ), - ("1000 items randomly", create_elem_randomly(1000, kind)?), - ] { - println!("{}: {} bytes", title, bytes.len()) - } - } - Ok(()) -} diff --git a/crates/loro-internal/examples/tree.rs b/crates/loro-internal/examples/tree.rs deleted file mode 100644 index bc2c2d66f..000000000 --- a/crates/loro-internal/examples/tree.rs +++ /dev/null @@ -1,83 +0,0 @@ -use std::time::Instant; - -use loro_internal::{encoding::ExportMode, LoroDoc, TreeParentId}; -use rand::{rngs::StdRng, Rng}; - -#[allow(unused)] -fn checkout() { - let depth = 300; - let loro = LoroDoc::new_auto_commit(); - let tree = loro.get_tree("tree"); - let mut ids = vec![]; - let mut versions = vec![]; - let id1 = tree.create_at(TreeParentId::Root, 0).unwrap(); - ids.push(id1); - versions.push(loro.oplog_frontiers()); - for _ in 1..depth { - let id = tree - .create_at(TreeParentId::Node(*ids.last().unwrap()), 0) - .unwrap(); - ids.push(id); - versions.push(loro.oplog_frontiers()); - } - let mut rng: StdRng = rand::SeedableRng::seed_from_u64(0); - - for _ in 0..1000 { - let i = rng.gen::() % depth; - let f = &versions[i]; - loro.checkout(f).unwrap(); - } -} - -#[allow(unused)] -fn mov() { - let loro = LoroDoc::new_auto_commit(); - let tree = loro.get_tree("tree"); - let mut ids = vec![]; - let size = 10000; - for _ in 0..size { - ids.push(tree.create_at(TreeParentId::Root, 0).unwrap()) - } - let mut rng: StdRng = rand::SeedableRng::seed_from_u64(0); - let n = 100000; - - for _ in 0..n { - let i = rng.gen::() % size; - let j = rng.gen::() % size; - let children_num = tree.children_num(&TreeParentId::Node(ids[j])).unwrap_or(0); - tree.move_to(ids[i], TreeParentId::Node(ids[j]), children_num) - .unwrap_or_default(); - } - println!( - "encode snapshot size {:?}", - loro.export(ExportMode::Snapshot).unwrap().len() - ); - println!( - "encode updates size {:?}", - loro.export(ExportMode::all_updates()).unwrap().len() - ); -} - -#[allow(unused)] -fn create() { - let size = 100000; - let loro = LoroDoc::default(); - let tree = loro.get_tree("tree"); - for _ in 0..size { - tree.create_at(TreeParentId::Root, 0).unwrap(); - } - println!( - "encode snapshot size {:?}\n", - loro.export(ExportMode::Snapshot).unwrap().len() - ); - println!( - "encode updates size {:?}", - loro.export(ExportMode::all_updates()).unwrap().len() - ); -} - -fn main() { - let s = Instant::now(); - mov(); - println!("{} ms", s.elapsed().as_millis()); -} diff --git a/crates/loro-internal/fuzz/.gitignore b/crates/loro-internal/fuzz/.gitignore deleted file mode 100644 index 1a45eee77..000000000 --- a/crates/loro-internal/fuzz/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -target -corpus -artifacts -coverage diff --git a/crates/loro-internal/fuzz/Cargo.lock b/crates/loro-internal/fuzz/Cargo.lock deleted file mode 100644 index 648738abb..000000000 --- a/crates/loro-internal/fuzz/Cargo.lock +++ /dev/null @@ -1,1102 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "append-only-bytes" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac436601d6bdde674a0d7fb593e829ffe7b3387c351b356dd20e2d40f5bf3ee5" - -[[package]] -name = "arbitrary" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e" -dependencies = [ - "derive_arbitrary", -] - -[[package]] -name = "arrayvec" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" - -[[package]] -name = "arref" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ccd462b64c3c72f1be8305905a85d85403d768e8690c9b8bd3b9009a5761679" - -[[package]] -name = "atomic-polyfill" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28" -dependencies = [ - "critical-section", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "bitflags" -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 = "bitmaps" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d084b0137aaa901caf9f1e8b21daa6aa24d41cd806e111335541eff9683bd6" - -[[package]] -name = "bytecount" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c" - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" - -[[package]] -name = "cc" -version = "1.0.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4" -dependencies = [ - "jobserver", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cobs" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" - -[[package]] -name = "critical-section" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52" - -[[package]] -name = "darling" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.25", -] - -[[package]] -name = "darling_macro" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" -dependencies = [ - "darling_core", - "quote", - "syn 2.0.25", -] - -[[package]] -name = "derive_arbitrary" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e0efad4403bfc52dc201159c4b842a246a14b98c64b55dfd0f2d89729dfeb8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.25", -] - -[[package]] -name = "either" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" - -[[package]] -name = "embedded-io" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" - -[[package]] -name = "enum-as-inner" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 1.0.105", -] - -[[package]] -name = "enum-as-inner" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.25", -] - -[[package]] -name = "enum_dispatch" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11f36e95862220b211a6e2aa5eca09b4fa391b13cd52ceb8035a24bf65a79de2" -dependencies = [ - "once_cell", - "proc-macro2", - "quote", - "syn 1.0.105", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - -[[package]] -name = "generic-btree" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "210507e6dec78bb1304e52a174bd99efdd83894219bf20d656a066a0ce2fedc5" -dependencies = [ - "arref", - "fxhash", - "heapless 0.7.16", - "itertools 0.11.0", - "loro-thunderdome", - "proc-macro2", -] - -[[package]] -name = "getrandom" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "hash32" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" -dependencies = [ - "byteorder", -] - -[[package]] -name = "hash32" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" -dependencies = [ - "byteorder", -] - -[[package]] -name = "heapless" -version = "0.7.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743" -dependencies = [ - "atomic-polyfill", - "hash32 0.2.1", - "rustc_version", - "serde", - "spin", - "stable_deref_trait", -] - -[[package]] -name = "heapless" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" -dependencies = [ - "hash32 0.3.1", - "stable_deref_trait", -] - -[[package]] -name = "heck" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" - -[[package]] -name = "ident_case" -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 2.1.0", - "rand_core", - "rand_xoshiro", - "sized-chunks", - "typenum", - "version_check", -] - -[[package]] -name = "imbl" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc3be8d8cd36f33a46b1849f31f837c44d9fa87223baee3b4bd96b8f11df81eb" -dependencies = [ - "bitmaps 3.2.1", - "imbl-sized-chunks", - "rand_core", - "rand_xoshiro", - "version_check", -] - -[[package]] -name = "imbl-sized-chunks" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "144006fb58ed787dcae3f54575ff4349755b00ccc99f4b4873860b654be1ed63" -dependencies = [ - "bitmaps 3.2.1", -] - -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" - -[[package]] -name = "jobserver" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" -dependencies = [ - "libc", -] - -[[package]] -name = "leb128" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" - -[[package]] -name = "libc" -version = "0.2.147" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - -[[package]] -name = "libfuzzer-sys" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8fff891139ee62800da71b7fd5b508d570b9ad95e614a53c6f453ca08366038" -dependencies = [ - "arbitrary", - "cc", - "once_cell", -] - -[[package]] -name = "lock_api" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "loro-common" -version = "0.16.2" -dependencies = [ - "arbitrary", - "enum-as-inner 0.6.0", - "fxhash", - "leb128", - "loro-rle", - "nonmax", - "serde", - "serde_columnar", - "string_cache", - "thiserror", -] - -[[package]] -name = "loro-delta" -version = "0.16.2" -dependencies = [ - "arrayvec", - "enum-as-inner 0.5.1", - "generic-btree", - "heapless 0.8.0", - "tracing", -] - -[[package]] -name = "loro-internal" -version = "0.16.2" -dependencies = [ - "append-only-bytes", - "arbitrary", - "arref", - "bytes", - "either", - "enum-as-inner 0.5.1", - "enum_dispatch", - "fxhash", - "generic-btree", - "getrandom", - "im", - "itertools 0.12.1", - "leb128", - "loro-common", - "loro-delta", - "loro-rle", - "loro_fractional_index", - "md5", - "num", - "num-derive", - "num-traits", - "once_cell", - "postcard", - "rand", - "serde", - "serde_columnar", - "serde_json", - "smallvec", - "tabled", - "thiserror", - "tracing", -] - -[[package]] -name = "loro-internal-fuzz" -version = "0.0.0" -dependencies = [ - "libfuzzer-sys", - "loro-internal", -] - -[[package]] -name = "loro-rle" -version = "0.16.2" -dependencies = [ - "append-only-bytes", - "arref", - "enum-as-inner 0.6.0", - "fxhash", - "num", - "smallvec", -] - -[[package]] -name = "loro-thunderdome" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f3d053a135388e6b1df14e8af1212af5064746e9b87a06a345a7a779ee9695a" - -[[package]] -name = "loro_fractional_index" -version = "0.16.2" -dependencies = [ - "imbl", - "rand", - "serde", - "smallvec", -] - -[[package]] -name = "md5" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" - -[[package]] -name = "new_debug_unreachable" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" - -[[package]] -name = "nonmax" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51" - -[[package]] -name = "num" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-derive" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.105", -] - -[[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-bigint", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" -dependencies = [ - "autocfg", -] - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "papergrid" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1526bb6aa9f10ec339fb10360f22c57edf81d5678d0278e93bc12a47ffbe4b01" -dependencies = [ - "bytecount", - "fnv", - "unicode-width", -] - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-sys", -] - -[[package]] -name = "phf_shared" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" - -[[package]] -name = "postcard" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" -dependencies = [ - "cobs", - "embedded-io", - "heapless 0.7.16", - "serde", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "precomputed-hash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.105", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[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 = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags", -] - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] - -[[package]] -name = "ryu" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "semver" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" - -[[package]] -name = "serde" -version = "1.0.171" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_columnar" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3748cbf2b43a15ee9627881cabd7820d50508781cdebd3bb54cea49215d367a1" -dependencies = [ - "itertools 0.11.0", - "postcard", - "serde", - "serde_columnar_derive", - "thiserror", -] - -[[package]] -name = "serde_columnar_derive" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e5eaacabbc55a397ffbb1ee32523f40f86fdefea8a8d9db19630d8b7c00edd1" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.25", -] - -[[package]] -name = "serde_derive" -version = "1.0.171" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.25", -] - -[[package]] -name = "serde_json" -version = "1.0.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "siphasher" -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 2.1.0", - "typenum", -] - -[[package]] -name = "smallvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" -dependencies = [ - "serde", -] - -[[package]] -name = "spin" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09" -dependencies = [ - "lock_api", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "string_cache" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" -dependencies = [ - "new_debug_unreachable", - "once_cell", - "parking_lot", - "phf_shared", - "precomputed-hash", - "serde", -] - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "syn" -version = "1.0.105" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e3fc8c0c74267e2df136e5e5fb656a464158aa57624053375eb9c8c6e25ae2" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "tabled" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c3ee73732ffceaea7b8f6b719ce3bb17f253fa27461ffeaf568ebd0cdb4b85" -dependencies = [ - "papergrid", - "tabled_derive", - "unicode-width", -] - -[[package]] -name = "tabled_derive" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beca1b4eaceb4f2755df858b88d9b9315b7ccfd1ffd0d7a48a52602301f01a57" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.105", -] - -[[package]] -name = "thiserror" -version = "1.0.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.25", -] - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.25", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", -] - -[[package]] -name = "typenum" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" - -[[package]] -name = "unicode-ident" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" - -[[package]] -name = "unicode-width" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" diff --git a/crates/loro-internal/fuzz/Cargo.toml b/crates/loro-internal/fuzz/Cargo.toml deleted file mode 100644 index 264a9167b..000000000 --- a/crates/loro-internal/fuzz/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "loro-internal-fuzz" -version = "1.2.7" -authors = ["Automatically generated"] -publish = false -edition = "2018" - -[package.metadata] -cargo-fuzz = true - -[dependencies] -libfuzzer-sys = "0.4" - -[dependencies.loro-internal] -path = ".." -features = ["test_utils"] - -# Prevent this from interfering with workspaces -[workspace] -members = ["."] - -[[bin]] -name = "import" -path = "fuzz_targets/import.rs" -test = false -doc = false - -[[bin]] -name = "alloc_tree" -path = "fuzz_targets/alloc_tree.rs" -test = false -doc = false diff --git a/crates/loro-internal/fuzz/fuzz_targets/alloc_tree.rs b/crates/loro-internal/fuzz/fuzz_targets/alloc_tree.rs deleted file mode 100644 index 93f3932af..000000000 --- a/crates/loro-internal/fuzz/fuzz_targets/alloc_tree.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![no_main] - -use libfuzzer_sys::fuzz_target; -use loro_internal::dag::{fuzz_alloc_tree, Interaction}; - -fuzz_target!(|data: Vec| { - fuzz_alloc_tree(10, data.clone()); - fuzz_alloc_tree(5, data.clone()); - fuzz_alloc_tree(2, data); -}); diff --git a/crates/loro-internal/fuzz/fuzz_targets/import.rs b/crates/loro-internal/fuzz/fuzz_targets/import.rs deleted file mode 100644 index 6a416f87e..000000000 --- a/crates/loro-internal/fuzz/fuzz_targets/import.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![no_main] -use libfuzzer_sys::fuzz_target; -use loro_internal::LoroDoc; - -fuzz_target!(|data: Vec| { - let mut doc = LoroDoc::default(); - doc.import_snapshot_unchecked(&data); - doc.import_delta_updates_unchecked(&data); -}); diff --git a/crates/loro-internal/proptest-regressions/dag/test.txt b/crates/loro-internal/proptest-regressions/dag/test.txt deleted file mode 100644 index 54efd8605..000000000 --- a/crates/loro-internal/proptest-regressions/dag/test.txt +++ /dev/null @@ -1,10 +0,0 @@ -# Seeds for failure cases proptest has generated in the past. It is -# automatically read and these particular cases re-run before any -# novel cases are generated. -# -# It is recommended to check this file in to source control so that -# everyone who runs the test benefits from these saved cases. -cc 6fa5e507d2f2f20cb7f5d8a40762b5dfbe9832884ba1ec4fdd98afb3618a1495 # shrinks to before_merged_insertions = [], after_merged_insertions = [] -cc 33ec71c1f62792545519d525dcd8cdd8a4a666640aada85fc78bfe2d2b92591d # shrinks to mut interactions = [Interaction { dag_idx: 0, merge_with: None, len: 1 }, Interaction { dag_idx: 1, merge_with: None, len: 2 }, Interaction { dag_idx: 1, merge_with: Some(0), len: 1 }] -cc cbbf51fd3f0bad25aede701c73321a1ead8738e3052655595bd29aa378bc0655 # shrinks to interactions = [Interaction { dag_idx: 1, merge_with: None, len: 3 }, Interaction { dag_idx: 1, merge_with: None, len: 3 }, Interaction { dag_idx: 4, merge_with: Some(1), len: 1 }, Interaction { dag_idx: 0, merge_with: None, len: 1 }, Interaction { dag_idx: 2, merge_with: Some(0), len: 1 }, Interaction { dag_idx: 0, merge_with: None, len: 1 }, Interaction { dag_idx: 2, merge_with: Some(0), len: 1 }, Interaction { dag_idx: 3, merge_with: Some(0), len: 1 }] -cc eee5bb7b82641d1eab5da8ab36320aafb72768c9cafb531c0b16f37061d56527 # shrinks to before_merged_insertions = [Interaction { dag_idx: 0, merge_with: None, len: 1 }], after_merged_insertions = [Interaction { dag_idx: 0, merge_with: None, len: 1 }] diff --git a/crates/loro-internal/scripts/fuzz.ts b/crates/loro-internal/scripts/fuzz.ts deleted file mode 100644 index 86f7f1005..000000000 --- a/crates/loro-internal/scripts/fuzz.ts +++ /dev/null @@ -1,36 +0,0 @@ -import * as path from "https://deno.land/std@0.105.0/path/mod.ts"; -const __dirname = path.dirname(path.fromFileUrl(import.meta.url)); -import { resolve } from "https://deno.land/std@0.198.0/path/mod.ts"; - -const validTargets = Array.from( - Deno.readDirSync(resolve(__dirname, "../fuzz/fuzz_targets")), -).map((x) => x.name.replace(/.rs$/, "")); - -const targets = - Deno.args.length === 0 - ? validTargets - : Deno.args.filter((x) => validTargets.includes(x)); - -const promises = []; -for (const target of targets) { - const cmd = [ - "cargo", - "+nightly", - "fuzz", - "run", - target, - "--", - "-max_total_time=1", - ]; - console.log("🔨" + cmd.join(" ")); - promises.push( - Deno.run({ - cmd, - stdout: "inherit", - stderr: "inherit", - cwd: resolve(__dirname, ".."), - }).status(), - ); -} - -await Promise.allSettled(promises); diff --git a/crates/loro-internal/scripts/mem.ts b/crates/loro-internal/scripts/mem.ts deleted file mode 100644 index 384ba2b55..000000000 --- a/crates/loro-internal/scripts/mem.ts +++ /dev/null @@ -1,49 +0,0 @@ -import * as path from "https://deno.land/std@0.105.0/path/mod.ts"; -const __dirname = path.dirname(path.fromFileUrl(import.meta.url)); -import { resolve } from "https://deno.land/std@0.105.0/path/mod.ts"; - -export const Tasks = [ - "100_concurrent", - "200_concurrent", - "automerge", - "10_actor_sync_1000_actions", - "20_actor_sync_1000_actions", - "10_actor_sync_2000_actions", -]; - -export interface Result { - task: string; - maxBytes: number; - endBytes: number; -} - -// run `cargo run --example mem -r -- ${task}` -export async function run(task: string): Promise { - const cmd = `cargo run --example mem -r -- ${task}`; - const process = Deno.run({ - cmd: cmd.split(" "), - cwd: resolve(__dirname, ".."), - stdout: "piped", - stderr: "piped", - }); - - const output = new TextDecoder().decode(await process.stderrOutput()); - try { - // extract "2,555,555" from `dhat: At t-gmax: 2,555,555 bytes` - const maxBytes = parseInt( - output.match(/dhat: At t-gmax:\s+((\d+,?)+) bytes/)![1].replace(/,/g, ""), - ); - const endBytes = parseInt( - output.match(/dhat: At t-end:\s+((\d+,?)+) bytes/)![1].replace(/,/g, ""), - ); - return { - task, - maxBytes, - endBytes, - }; - } catch (e) { - console.error(e); - console.log(output); - throw e; - } -} diff --git a/crates/loro-internal/scripts/run_mem.ts b/crates/loro-internal/scripts/run_mem.ts deleted file mode 100644 index c1476b939..000000000 --- a/crates/loro-internal/scripts/run_mem.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { run, Tasks } from "./mem.ts"; - -const output = []; -for (const task of Tasks) { - const result = await run(task); - output.push(result); -} - -console.log(output); diff --git a/crates/loro-internal/tests/richtext.md b/crates/loro-internal/tests/richtext.md deleted file mode 100644 index 49b575d63..000000000 --- a/crates/loro-internal/tests/richtext.md +++ /dev/null @@ -1,98 +0,0 @@ -# Richtext Test Cases - -#### 0. Insert into bold span - -| Name | Text | -|:----------------|:-------------------------| -| Origin | `Hello World` | -| Concurrent A | `Hello World` | -| Concurrent B | `Hello New World` | -| Expected Result | `Hello New World` | - -#### 1. Merge Concurrent Styles - -| Name | Text | -|:----------------|:---------------------| -| Origin | Hello World | -| Concurrent A | `Hello World` | -| Concurrent B | `Hello World` | -| Expected Result | `Hello World` | - -#### 2. Concurrent insert text & remove style - -| Name | Text | -|:----------------|:-----------------------| -| Origin | `Hello World` | -| Concurrent A | `Hello World` | -| Concurrent B | `Hello a World` | -| Expected Result | `Hello a World` | - -#### 3. Concurrent insert text & style - -| Name | Text | -|:----------------|:-----------------------| -| Origin | `Hello World` | -| Concurrent A | `Hello World` | -| Concurrent B | `Hello a World` | -| Expected Result | `Hello a World` | - -#### 4. Concurrent text edit & style that shrink - -| Name | Text | -|:----------------|:---------------------------| -| Origin | `Hello World` | -| Concurrent A | `Hello World` | -| Concurrent B | `Hey World` | -| Expected Result | `Hey World` | - -#### 5. Local insertion expand rules - -> [**Hello**](https://www.google.com) World - -When insert a new character after "Hello", the new char should be bold but not link - -> [**Hello**](https://www.google.com)**t** World - - -| Name | Text | -|:----------------|:----------------------------------| -| Origin | `Hello World` | -| Expected Result | `Hellot World` | - - -#### 6. Concurrent unbold - -In Peritext paper 2.3.2 - -| Name | Text | -|:----------------|:---------------------------------------------| -| Origin | `The fox jumped over the dog.` | -| Concurrent A | `The fox jumped over the dog.` | -| Concurrent B | `The fox jumped over the dog.` | -| Expected Result | `The fox jumped over the dog.` | - -#### 7. Bold & Unbold - -In Peritext paper 2.3.3 - -| Name | Text | -|:----------------|:---------------------------------------------| -| Origin | `The fox jumped over the dog.` | -| Concurrent A | `The fox jumped over the dog.` | -| Concurrent B | `The fox jumped over the dog.` | -| Expected Result | `The fox jumped over the dog.` | - -#### 8. Overlapped formatting - -In Peritext paper 3.2, example 3 - -| Name | Text | -|:----------------|:-----------------------------| -| Origin | The fox jumped. | -| Concurrent A | **The fox** jumped. | -| Concurrent B | The *fox jumped*. | -| Expected Result | **The _fox_** jumped. | - -#### 9. Multiple instances of the same mark - -![](https://i.postimg.cc/MTNGq8cH/Clean-Shot-2023-10-09-at-12-16-29-2x.png) diff --git a/crates/loro-wasm/Cargo.toml b/crates/loro-wasm/Cargo.toml index f84dc7f2b..162f27462 100644 --- a/crates/loro-wasm/Cargo.toml +++ b/crates/loro-wasm/Cargo.toml @@ -13,7 +13,7 @@ release = false [dependencies] js-sys = "0.3.60" -loro-internal = { path = "../loro-internal", features = [ +loro = { path = "../loro", features = [ "wasm", "counter", "jsonpath", diff --git a/crates/loro-wasm/src/awareness.rs b/crates/loro-wasm/src/awareness.rs index 8e08a968e..ae6501b32 100644 --- a/crates/loro-wasm/src/awareness.rs +++ b/crates/loro-wasm/src/awareness.rs @@ -1,6 +1,6 @@ #![allow(deprecated)] use js_sys::{Array, Object, Reflect}; -use loro_internal::{ +use loro::internal::{ awareness::{ Awareness as InternalAwareness, EphemeralEventTrigger, EphemeralStore as InternalEphemeralStore, EphemeralStoreEvent, diff --git a/crates/loro-wasm/src/convert.rs b/crates/loro-wasm/src/convert.rs index 7090ae7ff..124208fa1 100644 --- a/crates/loro-wasm/src/convert.rs +++ b/crates/loro-wasm/src/convert.rs @@ -1,14 +1,14 @@ use js_sys::{Array, Map, Object, Reflect, Uint8Array}; use loro_common::{ContainerID, IdLp, LoroListValue, LoroMapValue, LoroValue}; use loro_delta::{array_vec, DeltaRopeBuilder}; -use loro_internal::delta::{ResolvedMapDelta, ResolvedMapValue}; -use loro_internal::encoding::{ImportBlobMetadata, ImportStatus}; -use loro_internal::event::{Diff, ListDeltaMeta, ListDiff, TextDiff, TextMeta}; -use loro_internal::handler::{Handler, TextDelta, ValueOrHandler}; -use loro_internal::json::JsonSchema; -use loro_internal::version::VersionRange; -use loro_internal::StringSlice; -use loro_internal::{Counter, CounterSpan, FxHashMap, IdSpan, ListDiffItem}; +use loro::internal::delta::{ResolvedMapDelta, ResolvedMapValue}; +use loro::internal::encoding::{ImportBlobMetadata, ImportStatus}; +use loro::internal::event::{Diff, ListDeltaMeta, ListDiff, TextDiff, TextMeta}; +use loro::internal::handler::{Handler, TextDelta, ValueOrHandler}; +use loro::internal::json::JsonSchema; +use loro::internal::version::VersionRange; +use loro::internal::StringSlice; +use loro::internal::{Counter, CounterSpan, FxHashMap, IdSpan, ListDiffItem}; use serde::Serialize; use wasm_bindgen::{JsCast, JsValue}; @@ -172,7 +172,7 @@ pub(crate) fn resolved_diff_to_js(value: &Diff, for_json: bool) -> JsResult { @@ -241,7 +241,7 @@ pub(crate) fn js_diff_to_inner_diff(js: JsValue) -> JsResult { fn delta_item_to_js(item: ListDiffItem, for_json: bool) -> JsResult<(JsValue, Option)> { match item { - loro_internal::loro_delta::DeltaItem::Retain { len, attr: _ } => { + loro::internal::loro_delta::DeltaItem::Retain { len, attr: _ } => { let obj = Object::new(); js_sys::Reflect::set( &obj, @@ -250,7 +250,7 @@ fn delta_item_to_js(item: ListDiffItem, for_json: bool) -> JsResult<(JsValue, Op )?; Ok((obj.into_js_result()?, None)) } - loro_internal::loro_delta::DeltaItem::Replace { + loro::internal::loro_delta::DeltaItem::Replace { value, attr: _, delete, diff --git a/crates/loro-wasm/src/counter.rs b/crates/loro-wasm/src/counter.rs index cbe8c6938..2b0085e48 100644 --- a/crates/loro-wasm/src/counter.rs +++ b/crates/loro-wasm/src/counter.rs @@ -1,5 +1,5 @@ use super::subscription_to_js_function_callback; -use loro_internal::{ +use loro::internal::{ handler::{counter::CounterHandler, Handler}, HandlerTrait, }; diff --git a/crates/loro-wasm/src/lib.rs b/crates/loro-wasm/src/lib.rs index c0421cc93..f92ef6f9a 100644 --- a/crates/loro-wasm/src/lib.rs +++ b/crates/loro-wasm/src/lib.rs @@ -11,7 +11,7 @@ use convert::{ js_value_to_loro_value, loro_json_schema_to_js_json_schema, resolved_diff_to_js, }; use js_sys::{Array, Object, Promise, Reflect, Uint8Array}; -use loro_internal::{ +use loro::internal::{ change::Lamport, configure::{StyleConfig, StyleConfigMap}, container::{richtext::ExpandType, ContainerID}, @@ -438,7 +438,7 @@ impl ChangeMeta { self.serialize(&s).unwrap() } - fn from_loro(meta: &loro_internal::ChangeMeta) -> Self { + fn from_loro(meta: &loro::internal::ChangeMeta) -> Self { Self { lamport: meta.lamport, length: meta.len as u32, @@ -2468,7 +2468,7 @@ fn diff_event_to_js_value(event: DiffEvent, for_json: bool) -> JsResult /// } /// fn container_diff_to_js_value( - event: &loro_internal::ContainerDiff, + event: &loro::internal::ContainerDiff, for_json: bool, ) -> JsResult { let obj = js_sys::Object::new(); @@ -5603,7 +5603,7 @@ fn subscription_to_js_function_callback(sub: Subscription) -> JsValue { } #[wasm_bindgen] -pub struct ChangeModifier(loro_internal::pre_commit::ChangeModifier); +pub struct ChangeModifier(loro::internal::pre_commit::ChangeModifier); #[wasm_bindgen] impl ChangeModifier { @@ -5681,7 +5681,7 @@ pub fn redact_json_updates( let mut loro_json = js_json_schema_to_loro_json_schema(json_updates)?; let version_range = js_value_to_version_range(version_range)?; - loro_internal::json::redact(&mut loro_json, version_range) + loro::internal::json::redact(&mut loro_json, version_range) .map_err(|e| JsValue::from_str(&format!("Failed to redact JSON: {e}")))?; loro_json_schema_to_js_json_schema(loro_json) diff --git a/crates/loro/Cargo.toml b/crates/loro/Cargo.toml index 42de337bf..b5d7963bd 100644 --- a/crates/loro/Cargo.toml +++ b/crates/loro/Cargo.toml @@ -14,33 +14,90 @@ keywords = ["crdt", "local-first"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -loro-internal = { path = "../loro-internal", version = "1.10.3" } loro-common = { path = "../loro-common", version = "1.10.0", features = [ "serde_json", ] } loro-kv-store = { path = "../kv-store", version = "1.10.0" } -delta = { path = "../delta", package = "loro-delta", version = "1.9.1" } +loro-delta = { path = "../delta", version = "1.9.1", package = "loro-delta" } +rle = { path = "../rle", version = "1.6.0", package = "loro-rle" } +fractional_index = { path = "../fractional_index", features = [ + "serde", +], version = "1.6.0", package = "loro_fractional_index" } generic-btree = { version = "^0.10.7" } +smallvec = { workspace = true } +serde = { workspace = true } +thiserror = { workspace = true } enum-as-inner = { workspace = true } tracing = { workspace = true } rustc-hash = { workspace = true } +serde_json = { workspace = true } +bytes = { workspace = true } +xxhash-rust = { workspace = true } +serde_columnar = { workspace = true } +itertools = { workspace = true } +enum_dispatch = { workspace = true } +once_cell = { workspace = true } +ensure-cov = { workspace = true } +either = { workspace = true } +arbitrary = { version = "1", optional = true } +postcard = { version = "1", features = ["use-std"] } +append-only-bytes = { version = "0.1.12", features = ["u32_range"] } +im = { version = "15.1.0", features = ["serde"] } +tabled = { version = "0.10.0", optional = true } +wasm-bindgen = { version = "=0.2.100", optional = true } +js-sys = { version = "0.3.60", optional = true } +num = "0.4.0" +rand = { version = "0.8.5" } +getrandom = "0.2.15" +leb128 = "0.2.5" +num-traits = "0.2" +md5 = "0.7.0" +arref = "0.1.0" +nonmax = "0.5.5" +pretty_assertions = "1.4.1" +thread_local = "1.1.8" +parking_lot = "0.12.5" +pest = "2.8.3" +pest_derive = "2.8.3" [dev-dependencies] serde_json = { version = "1.0.87", features = ["float_roundtrip"] } anyhow = "1.0.83" ctor = "0.2" dev-utils = { path = "../dev-utils" } +bench-utils = { path = "../bench-utils" } rand = "0.8.5" pretty_assertions = "1.4.0" loom = "0.7" base64 = "0.22.1" serial_test = "3" +criterion = { version = "0.7.0", features = ["html_reports"] } +arbitrary = { version = "1" } +tabled = "0.10.0" +miniz_oxide = "0.7.1" +zstd = "0.13.0" + +[target.'cfg(loom)'.dependencies] +loom = { version = "0.7", features = ["checkpoint"] } + +[target.'cfg(target_arch = "wasm32")'.dependencies.getrandom] +version = "0.2.15" +features = ["js"] + +[target.'cfg(all(target_arch = "wasm32", not(features = "wasm")))'.dependencies] +wasm-bindgen = "0.2.100" [features] default = ["counter"] -counter = ["loro-internal/counter"] -jsonpath = ["loro-internal/jsonpath"] -logging = ["loro-internal/logging"] +counter = ["loro-common/counter"] +jsonpath = [] +logging = ["loro-common/logging"] +test_utils = ["arbitrary", "tabled"] +wasm = ["wasm-bindgen", "js-sys", "loro-common/wasm"] + +[[bench]] +name = "merge_baseline" +harness = false [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(loom)'] } diff --git a/crates/loro-internal/VERSION b/crates/loro/VERSION similarity index 100% rename from crates/loro-internal/VERSION rename to crates/loro/VERSION diff --git a/crates/loro/benches/merge_baseline.rs b/crates/loro/benches/merge_baseline.rs new file mode 100644 index 000000000..f393f105d --- /dev/null +++ b/crates/loro/benches/merge_baseline.rs @@ -0,0 +1,235 @@ +use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; +use loro::internal::{ + LoroDoc as InternalLoroDoc, MapHandler, TextHandler, UndoItemMeta as InternalUndoItemMeta, + UndoManager as InternalUndoManager, +}; +use loro::{LoroDoc, LoroMap, LoroText, UndoItemMeta, UndoManager}; +use std::hint::black_box; +use std::sync::{ + atomic::{AtomicUsize, Ordering}, + Arc, +}; + +fn seed_heterogeneous_doc() -> LoroDoc { + let doc = LoroDoc::new(); + let root = doc.get_list("root_list"); + root.insert(0, 1).unwrap(); + root.insert(1, true).unwrap(); + let nested = root.insert_container(2, LoroMap::new()).unwrap(); + nested.insert("title", "loro").unwrap(); + nested.insert("count", 3).unwrap(); + let map = doc.get_map("root_map"); + map.insert("flag", true).unwrap(); + map.insert("count", 7).unwrap(); + let text = map.insert_container("text", LoroText::new()).unwrap(); + text.insert(0, "baseline").unwrap(); + let text = nested.insert_container("text", LoroText::new()).unwrap(); + text.insert(0, "baseline").unwrap(); + doc +} + +fn seed_internal_heterogeneous_doc() -> InternalLoroDoc { + let doc = InternalLoroDoc::new_auto_commit(); + let root = doc.get_list("root_list"); + root.insert(0, 1).unwrap(); + root.insert(1, true).unwrap(); + let nested = root + .insert_container(2, MapHandler::new_detached()) + .unwrap(); + nested.insert("title", "loro").unwrap(); + nested.insert("count", 3).unwrap(); + let map = doc.get_map("root_map"); + map.insert("flag", true).unwrap(); + map.insert("count", 7).unwrap(); + let text = map + .insert_container("text", TextHandler::new_detached()) + .unwrap(); + text.insert_unicode(0, "baseline").unwrap(); + let text = nested + .insert_container("text", TextHandler::new_detached()) + .unwrap(); + text.insert_unicode(0, "baseline").unwrap(); + doc +} + +fn bench_active_subscriptions(c: &mut Criterion) { + c.bench_function("merge baseline/public active subscriptions", |b| { + b.iter_batched( + || { + let doc = LoroDoc::new(); + let list = doc.get_list("list"); + let sub = doc.subscribe_root(Arc::new(|event| { + black_box(event.events.len()); + })); + (doc, list, sub) + }, + |(doc, list, sub)| { + black_box(&sub); + list.insert(0, 1).unwrap(); + list.insert(1, 2).unwrap(); + doc.commit(); + }, + BatchSize::SmallInput, + ); + }); +} + +fn bench_internal_active_subscriptions(c: &mut Criterion) { + c.bench_function("merge baseline/internal active subscriptions", |b| { + b.iter_batched( + || { + let doc = InternalLoroDoc::new_auto_commit(); + let list = doc.get_list("list"); + let sub = doc.subscribe_root(Arc::new(|event| { + black_box(event.events.len()); + })); + (doc, list, sub) + }, + |(doc, list, sub)| { + black_box(&sub); + list.insert(0, 1).unwrap(); + list.insert(1, 2).unwrap(); + doc.commit_then_renew(); + }, + BatchSize::SmallInput, + ); + }); +} + +fn bench_heterogeneous_reads(c: &mut Criterion) { + let doc = seed_heterogeneous_doc(); + let root = doc.get_list("root_list"); + let map = doc.get_map("root_map"); + c.bench_function("merge baseline/public heterogeneous reads", |b| { + b.iter(|| { + black_box(root.get(0)); + black_box(root.get(2)); + black_box(map.get("flag")); + black_box(map.get("text")); + black_box(doc.get_by_str_path("root_list/2/title")); + black_box(doc.get_by_str_path("root_list/2/text")); + black_box(doc.get_by_str_path("root_map/text")); + let mut list_values = Vec::new(); + root.for_each(|value| list_values.push(value)); + black_box(list_values); + let map_values: Vec<_> = map.values().collect(); + black_box(map_values); + }); + }); +} + +fn bench_internal_heterogeneous_reads(c: &mut Criterion) { + let doc = seed_internal_heterogeneous_doc(); + let root = doc.get_list("root_list"); + let map = doc.get_map("root_map"); + c.bench_function("merge baseline/internal heterogeneous reads", |b| { + b.iter(|| { + black_box(root.get_(0)); + black_box(root.get_(2)); + black_box(map.get_("flag")); + black_box(map.get_("text")); + black_box(doc.get_by_str_path("root_list/2/title")); + black_box(doc.get_by_str_path("root_list/2/text")); + black_box(doc.get_by_str_path("root_map/text")); + let mut list_values = Vec::new(); + root.for_each(|value| list_values.push(value)); + black_box(list_values); + let map_values: Vec<_> = map.values().collect(); + black_box(map_values); + }); + }); +} + +fn bench_diff_apply_diff(c: &mut Criterion) { + let doc = LoroDoc::new(); + let text = doc.get_text("text"); + text.insert(0, "hello").unwrap(); + doc.commit(); + let start = doc.state_frontiers(); + text.insert(5, " world").unwrap(); + doc.commit(); + let diff = doc.diff(&start, &doc.state_frontiers()).unwrap(); + + c.bench_function("merge baseline/public diff apply_diff", |b| { + b.iter_batched( + || (doc.fork_at(&start), diff.clone()), + |(fork, diff)| { + fork.apply_diff(diff).unwrap(); + black_box(fork.get_deep_value()); + }, + BatchSize::SmallInput, + ); + }); +} + +fn bench_undo_callbacks(c: &mut Criterion) { + c.bench_function("merge baseline/public undo callbacks", |b| { + b.iter_batched( + || { + let doc = LoroDoc::new(); + let text = doc.get_text("text"); + let callback_hits = Arc::new(AtomicUsize::new(0)); + let callback_hits_clone = callback_hits.clone(); + let mut undo = UndoManager::new(&doc); + undo.set_merge_interval(0); + undo.set_on_push(Some(Box::new(move |_, _, event| { + callback_hits_clone.fetch_add( + event.map(|event| event.events.len()).unwrap_or_default(), + Ordering::Relaxed, + ); + UndoItemMeta::new() + }))); + (doc, text, undo, callback_hits) + }, + |(doc, text, mut undo, callback_hits)| { + black_box(&mut undo); + text.insert(0, "hello").unwrap(); + doc.commit(); + black_box(callback_hits.load(Ordering::Relaxed)); + }, + BatchSize::SmallInput, + ); + }); +} + +fn bench_internal_undo_callbacks(c: &mut Criterion) { + c.bench_function("merge baseline/internal undo callbacks", |b| { + b.iter_batched( + || { + let doc = InternalLoroDoc::new_auto_commit(); + let text = doc.get_text("text"); + let callback_hits = Arc::new(AtomicUsize::new(0)); + let callback_hits_clone = callback_hits.clone(); + let undo = InternalUndoManager::new(&doc); + undo.set_merge_interval(0); + undo.set_on_push(Some(Box::new(move |_, _, event| { + callback_hits_clone.fetch_add( + event.map(|event| event.events.len()).unwrap_or_default(), + Ordering::Relaxed, + ); + InternalUndoItemMeta::new() + }))); + (doc, text, undo, callback_hits) + }, + |(doc, text, undo, callback_hits)| { + black_box(&undo); + text.insert_unicode(0, "hello").unwrap(); + doc.commit_then_renew(); + black_box(callback_hits.load(Ordering::Relaxed)); + }, + BatchSize::SmallInput, + ); + }); +} + +criterion_group!( + benches, + bench_active_subscriptions, + bench_internal_active_subscriptions, + bench_heterogeneous_reads, + bench_internal_heterogeneous_reads, + bench_diff_apply_diff, + bench_undo_callbacks, + bench_internal_undo_callbacks +); +criterion_main!(benches); diff --git a/crates/loro/src/counter.rs b/crates/loro/src/counter.rs index 85bc6e219..cb9f95f2d 100644 --- a/crates/loro/src/counter.rs +++ b/crates/loro/src/counter.rs @@ -1,4 +1,4 @@ -use loro_internal::{ +use crate::internal::{ container::ContainerID, handler::counter::CounterHandler, HandlerTrait, LoroResult, }; diff --git a/crates/loro/src/event.rs b/crates/loro/src/event.rs index eca51308c..8ad406fc5 100644 --- a/crates/loro/src/event.rs +++ b/crates/loro/src/event.rs @@ -1,19 +1,18 @@ //! Loro event handling. -use delta::array_vec::ArrayVec; -use delta::DeltaRope; use enum_as_inner::EnumAsInner; use loro_common::IdLp; -use loro_internal::container::ContainerID; -pub use loro_internal::delta::TreeDiff; -use loro_internal::delta::{ResolvedMapDelta, ResolvedMapValue}; -use loro_internal::event::{EventTriggerKind, ListDeltaMeta}; -use loro_internal::handler::{TextDelta, ValueOrHandler}; -use loro_internal::undo::DiffBatch as InnerDiffBatch; -use loro_internal::{ +use crate::internal::loro_delta::{self as loro_delta, array_vec::ArrayVec, DeltaRope}; +use crate::internal::container::ContainerID; +pub use crate::internal::delta::TreeDiff; +use crate::internal::delta::{ResolvedMapDelta, ResolvedMapValue}; +use crate::internal::event::{EventTriggerKind, ListDeltaMeta}; +use crate::internal::handler::{TextDelta, ValueOrHandler}; +use crate::internal::undo::DiffBatch as InnerDiffBatch; +use crate::internal::{ event::{Diff as DiffInner, Index}, ContainerDiff as ContainerDiffInner, DiffEvent as DiffEventInner, }; -use loro_internal::{FxHashMap, ListDiffInsertItem}; +use crate::internal::{FxHashMap, ListDiffInsertItem}; use std::borrow::Cow; use std::ops::Deref; use std::sync::Arc; @@ -140,10 +139,10 @@ impl<'a> From<&'a DiffInner> for Diff<'a> { let mut ans = Vec::new(); for item in l.iter() { match item { - delta::DeltaItem::Retain { len, .. } => { + loro_delta::DeltaItem::Retain { len, .. } => { ans.push(ListDiffItem::Retain { retain: *len }); } - delta::DeltaItem::Replace { + loro_delta::DeltaItem::Replace { value, delete, attr, @@ -193,10 +192,10 @@ impl From for Diff<'static> { let mut ans = Vec::new(); for item in l.iter() { match item { - delta::DeltaItem::Retain { len, .. } => { + loro_delta::DeltaItem::Retain { len, .. } => { ans.push(ListDiffItem::Retain { retain: *len }); } - delta::DeltaItem::Replace { + loro_delta::DeltaItem::Replace { value, delete, attr, diff --git a/crates/loro-internal/src/allocation/bfs.rs b/crates/loro/src/internal/allocation/bfs.rs similarity index 98% rename from crates/loro-internal/src/allocation/bfs.rs rename to crates/loro/src/internal/allocation/bfs.rs index 41a2ef5b4..4771d165c 100644 --- a/crates/loro-internal/src/allocation/bfs.rs +++ b/crates/loro/src/internal/allocation/bfs.rs @@ -1,5 +1,5 @@ #![allow(dead_code)] -use crate::{ +use crate::internal::{ dag::{Dag, DagNode}, id::ID, version::Frontiers, diff --git a/crates/loro-internal/src/allocation/dfs.rs b/crates/loro/src/internal/allocation/dfs.rs similarity index 99% rename from crates/loro-internal/src/allocation/dfs.rs rename to crates/loro/src/internal/allocation/dfs.rs index 552d34d11..d34d4ddcc 100644 --- a/crates/loro-internal/src/allocation/dfs.rs +++ b/crates/loro/src/internal/allocation/dfs.rs @@ -1,6 +1,6 @@ use std::collections::HashSet; -use crate::{ +use crate::internal::{ dag::{Dag, DagNode}, id::ID, version::Frontiers, diff --git a/crates/loro-internal/src/allocation/mod.rs b/crates/loro/src/internal/allocation/mod.rs similarity index 100% rename from crates/loro-internal/src/allocation/mod.rs rename to crates/loro/src/internal/allocation/mod.rs diff --git a/crates/loro-internal/src/arena.rs b/crates/loro/src/internal/arena.rs similarity index 95% rename from crates/loro-internal/src/arena.rs rename to crates/loro/src/internal/arena.rs index b7ab1bf22..e185ea7a1 100644 --- a/crates/loro-internal/src/arena.rs +++ b/crates/loro/src/internal/arena.rs @@ -1,7 +1,7 @@ mod str_arena; use self::str_arena::StrArena; -use crate::sync::{Mutex, MutexGuard}; -use crate::{ +use crate::internal::sync::{Mutex, MutexGuard}; +use crate::internal::{ change::Lamport, container::{ idx::ContainerIdx, @@ -427,19 +427,19 @@ impl SharedArena { container: ContainerIdx, ) -> Op { match content { - crate::op::RawOpContent::Map(MapSet { key, value }) => Op { + crate::internal::op::RawOpContent::Map(MapSet { key, value }) => Op { counter, container, - content: crate::op::InnerContent::Map(MapSet { key, value }), + content: crate::internal::op::InnerContent::Map(MapSet { key, value }), }, - crate::op::RawOpContent::List(list) => match list { + crate::internal::op::RawOpContent::List(list) => match list { ListOp::Insert { slice, pos } => match slice { ListSlice::RawData(values) => { let range = self.alloc_values(values.iter().cloned()); Op { counter, container, - content: crate::op::InnerContent::List(InnerListOp::Insert { + content: crate::internal::op::InnerContent::List(InnerListOp::Insert { slice: SliceRange::from(range.start as u32..range.end as u32), pos, }), @@ -450,7 +450,7 @@ impl SharedArena { Op { counter, container, - content: crate::op::InnerContent::List(InnerListOp::InsertText { + content: crate::internal::op::InnerContent::List(InnerListOp::InsertText { slice, unicode_start: info.start as u32, unicode_len: unicode_len as u32, @@ -462,7 +462,7 @@ impl SharedArena { ListOp::Delete(span) => Op { counter, container, - content: crate::op::InnerContent::List(InnerListOp::Delete(span)), + content: crate::internal::op::InnerContent::List(InnerListOp::Delete(span)), }, ListOp::StyleStart { start, @@ -505,21 +505,21 @@ impl SharedArena { content: InnerContent::List(InnerListOp::Set { elem_id, value }), }, }, - crate::op::RawOpContent::Tree(tree) => Op { + crate::internal::op::RawOpContent::Tree(tree) => Op { counter, container, - content: crate::op::InnerContent::Tree(tree.clone()), + content: crate::internal::op::InnerContent::Tree(tree.clone()), }, #[cfg(feature = "counter")] - crate::op::RawOpContent::Counter(c) => Op { + crate::internal::op::RawOpContent::Counter(c) => Op { counter, container, - content: crate::op::InnerContent::Future(crate::op::FutureInnerContent::Counter(c)), + content: crate::internal::op::InnerContent::Future(crate::internal::op::FutureInnerContent::Counter(c)), }, - crate::op::RawOpContent::Unknown { prop, value } => Op { + crate::internal::op::RawOpContent::Unknown { prop, value } => Op { counter, container, - content: crate::op::InnerContent::Future(crate::op::FutureInnerContent::Unknown { + content: crate::internal::op::InnerContent::Future(crate::internal::op::FutureInnerContent::Unknown { prop, value: Box::new(value), }), diff --git a/crates/loro-internal/src/arena/str_arena.rs b/crates/loro/src/internal/arena/str_arena.rs similarity index 98% rename from crates/loro-internal/src/arena/str_arena.rs rename to crates/loro/src/internal/arena/str_arena.rs index 78fd132b7..9da98aab7 100644 --- a/crates/loro-internal/src/arena/str_arena.rs +++ b/crates/loro/src/internal/arena/str_arena.rs @@ -2,7 +2,7 @@ use std::ops::{Bound, RangeBounds}; use append_only_bytes::{AppendOnlyBytes, BytesSlice}; -use crate::container::richtext::richtext_state::unicode_to_utf8_index; +use crate::internal::container::richtext::richtext_state::unicode_to_utf8_index; const INDEX_INTERVAL: u32 = 128; #[derive(Default, Debug, Clone)] diff --git a/crates/loro-internal/src/awareness.rs b/crates/loro/src/internal/awareness.rs similarity index 98% rename from crates/loro-internal/src/awareness.rs rename to crates/loro/src/internal/awareness.rs index f097b569d..b982eea3e 100644 --- a/crates/loro-internal/src/awareness.rs +++ b/crates/loro/src/internal/awareness.rs @@ -16,8 +16,8 @@ use loro_common::{LoroValue, PeerID}; use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; -use crate::change::{get_sys_timestamp, Timestamp}; -use crate::{SubscriberSetWithQueue, Subscription}; +use crate::internal::change::{get_sys_timestamp, Timestamp}; +use crate::internal::{SubscriberSetWithQueue, Subscription}; /// `Awareness` is a structure that tracks the ephemeral state of peers. /// @@ -211,7 +211,7 @@ pub type EphemeralSubscriber = Box bool + Send + /// # Example /// /// ```rust -/// use loro_internal::awareness::EphemeralStore; +/// use loro::internal::awareness::EphemeralStore; /// /// let mut store = EphemeralStore::new(1000); /// store.set("key", "value"); @@ -311,7 +311,7 @@ impl EphemeralStore { /// /// # Example /// ```rust - /// use loro_internal::awareness::EphemeralStore; + /// use loro::internal::awareness::EphemeralStore; /// use std::sync::{Arc, Mutex}; /// /// let store = EphemeralStore::new(30000); @@ -319,7 +319,7 @@ impl EphemeralStore { /// let count_clone = update_count.clone(); /// /// // Subscribe and collect first 3 updates, then auto-unsubscribe - /// let sub = store.subscribe_local_updates(Box::new(move |bytes| { + /// let sub = store.subscribe_local_updates(Box::new(move |bytes: &Vec| { /// println!("Received {} bytes of ephemeral data", bytes.len()); /// let mut count = count_clone.lock().unwrap(); /// *count += 1; diff --git a/crates/loro-internal/src/change.rs b/crates/loro/src/internal/change.rs similarity index 99% rename from crates/loro-internal/src/change.rs rename to crates/loro/src/internal/change.rs index 4543f47d0..ffa603964 100644 --- a/crates/loro-internal/src/change.rs +++ b/crates/loro/src/internal/change.rs @@ -4,7 +4,7 @@ //! //! Note: `dep` can only point to the end of the other [Change]. This is the invariant of [Change]s. -use crate::{ +use crate::internal::{ dag::DagNode, estimated_size::EstimatedSize, id::{Counter, ID}, diff --git a/crates/loro-internal/src/change_meta.rs b/crates/loro/src/internal/change_meta.rs similarity index 96% rename from crates/loro-internal/src/change_meta.rs rename to crates/loro/src/internal/change_meta.rs index 93e9cbd9e..aea379319 100644 --- a/crates/loro-internal/src/change_meta.rs +++ b/crates/loro/src/internal/change_meta.rs @@ -3,7 +3,7 @@ use std::{cmp::Ordering, sync::Arc}; use loro_common::HasLamport; use rle::HasLength; -use crate::{ +use crate::internal::{ change::{Change, Lamport, Timestamp}, id::ID, version::Frontiers, @@ -92,7 +92,7 @@ impl ChangeMeta { } /// Get the commit timestamp in seconds since Unix epoch. - pub fn timestamp(&self) -> crate::change::Timestamp { + pub fn timestamp(&self) -> crate::internal::change::Timestamp { self.timestamp } } diff --git a/crates/loro-internal/src/configure.rs b/crates/loro/src/internal/configure.rs similarity index 97% rename from crates/loro-internal/src/configure.rs rename to crates/loro/src/internal/configure.rs index 148e32139..418f40919 100644 --- a/crates/loro-internal/src/configure.rs +++ b/crates/loro/src/internal/configure.rs @@ -1,8 +1,8 @@ use loro_common::ContainerID; use rustc_hash::FxHashSet; -pub use crate::container::richtext::config::{StyleConfig, StyleConfigMap}; -use crate::LoroDoc; +pub use crate::internal::container::richtext::config::{StyleConfig, StyleConfigMap}; +use crate::internal::LoroDoc; use std::sync::atomic::{AtomicBool, AtomicI64}; use std::sync::RwLock; use std::sync::{Arc, Mutex}; diff --git a/crates/loro-internal/src/container.rs b/crates/loro/src/internal/container.rs similarity index 98% rename from crates/loro-internal/src/container.rs rename to crates/loro/src/internal/container.rs index a25e61abe..8683ee1a7 100644 --- a/crates/loro-internal/src/container.rs +++ b/crates/loro/src/internal/container.rs @@ -2,9 +2,9 @@ //! Each [Op] has an associated container. It's the [Container]'s responsibility to //! calculate the state from the [Op]s. //! -//! Every [Container] can take a [Snapshot], which contains [crate::LoroValue] that describes the state. +//! Every [Container] can take a [Snapshot], which contains [crate::internal::LoroValue] that describes the state. //! -use crate::{arena::SharedArena, InternalString, ID}; +use crate::internal::{arena::SharedArena, InternalString, ID}; pub mod list; pub mod map; diff --git a/crates/loro-internal/src/container/list/list_op.rs b/crates/loro/src/internal/container/list/list_op.rs similarity index 98% rename from crates/loro-internal/src/container/list/list_op.rs rename to crates/loro/src/internal/container/list/list_op.rs index d8c07f00e..bea4e5ab8 100644 --- a/crates/loro-internal/src/container/list/list_op.rs +++ b/crates/loro/src/internal/container/list/list_op.rs @@ -6,7 +6,7 @@ use loro_common::{ContainerType, HasId, HasIdSpan, IdLp, LoroValue, ID}; use rle::{HasLength, Mergable, Sliceable}; use serde::{Deserialize, Serialize}; -use crate::{ +use crate::internal::{ container::richtext::TextStyleInfoFlag, container::richtext::richtext_state::unicode_to_utf8_index, op::{ListSlice, SliceRange}, @@ -278,7 +278,7 @@ impl Sliceable for DeleteSpanWithId { } /// `len` can be negative so that we can merge text deletions efficiently. -/// It looks like [crate::span::CounterSpan], but how should they merge ([Mergable] impl) and slice ([Sliceable] impl) are very different +/// It looks like [crate::internal::span::CounterSpan], but how should they merge ([Mergable] impl) and slice ([Sliceable] impl) are very different /// /// len cannot be zero; /// @@ -664,7 +664,7 @@ mod test { use rle::{HasLength as _, Mergable, Sliceable}; use std::time::Instant; - use crate::{container::list::list_op::DeleteSpanWithId, op::ListSlice}; + use crate::internal::{container::list::list_op::DeleteSpanWithId, op::ListSlice}; use super::{DeleteSpan, InnerListOp, ListOp}; @@ -771,7 +771,7 @@ mod test { #[ignore] fn perf_insert_text_slice_split_suffix() { // Run with: - // cargo test -p loro-internal perf_insert_text_slice_split_suffix -- --ignored --nocapture + // cargo test -p loro perf_insert_text_slice_split_suffix -- --ignored --nocapture const TEXT_LEN: usize = 2 * 1024 * 1024; const CHUNK_UNICODE_LEN: usize = 4096; diff --git a/crates/loro-internal/src/container/list/mod.rs b/crates/loro/src/internal/container/list/mod.rs similarity index 100% rename from crates/loro-internal/src/container/list/mod.rs rename to crates/loro/src/internal/container/list/mod.rs diff --git a/crates/loro-internal/src/container/map/map_content.rs b/crates/loro/src/internal/container/map/map_content.rs similarity index 95% rename from crates/loro-internal/src/container/map/map_content.rs rename to crates/loro/src/internal/container/map/map_content.rs index 993718ad5..9d27a1c5e 100644 --- a/crates/loro-internal/src/container/map/map_content.rs +++ b/crates/loro/src/internal/container/map/map_content.rs @@ -1,7 +1,7 @@ use rle::{HasLength, Mergable, Sliceable}; use serde::{Deserialize, Serialize}; -use crate::{InternalString, LoroValue}; +use crate::internal::{InternalString, LoroValue}; // Note: It will be encoded into binary format, so the order of its fields should not be changed. #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] diff --git a/crates/loro-internal/src/container/map/mod.rs b/crates/loro/src/internal/container/map/mod.rs similarity index 100% rename from crates/loro-internal/src/container/map/mod.rs rename to crates/loro/src/internal/container/map/mod.rs diff --git a/crates/loro-internal/src/container/richtext.rs b/crates/loro/src/internal/container/richtext.rs similarity index 97% rename from crates/loro-internal/src/container/richtext.rs rename to crates/loro/src/internal/container/richtext.rs index 4526f574d..7eb055b0d 100644 --- a/crates/loro-internal/src/container/richtext.rs +++ b/crates/loro/src/internal/container/richtext.rs @@ -6,7 +6,7 @@ //! - Entity index: unicode index + style anchor index. Each unicode code point or style anchor is an entity. //! - Utf16 index //! -//! In [crate::op::Op], we always use entity index to persist richtext ops. +//! In [crate::internal::op::Op], we always use entity index to persist richtext ops. //! //! The users of this type can only operate on unicode index or utf16 index, but calculated entity index will be provided. @@ -17,7 +17,7 @@ pub(crate) mod str_slice; mod style_range_map; mod tracker; -use crate::{change::Lamport, delta::StyleMeta, utils::string_slice::StringSlice, InternalString}; +use crate::internal::{change::Lamport, delta::StyleMeta, utils::string_slice::StringSlice, InternalString}; use fugue_span::*; use loro_common::{Counter, IdFull, IdLp, LoroValue, PeerID, ID}; use serde::{Deserialize, Serialize}; diff --git a/crates/loro-internal/src/container/richtext/config.rs b/crates/loro/src/internal/container/richtext/config.rs similarity index 100% rename from crates/loro-internal/src/container/richtext/config.rs rename to crates/loro/src/internal/container/richtext/config.rs diff --git a/crates/loro-internal/src/container/richtext/fugue_span.rs b/crates/loro/src/internal/container/richtext/fugue_span.rs similarity index 100% rename from crates/loro-internal/src/container/richtext/fugue_span.rs rename to crates/loro/src/internal/container/richtext/fugue_span.rs diff --git a/crates/loro-internal/src/container/richtext/richtext_state.rs b/crates/loro/src/internal/container/richtext/richtext_state.rs similarity index 99% rename from crates/loro-internal/src/container/richtext/richtext_state.rs rename to crates/loro/src/internal/container/richtext/richtext_state.rs index d0e198df3..a61c868a6 100644 --- a/crates/loro-internal/src/container/richtext/richtext_state.rs +++ b/crates/loro/src/internal/container/richtext/richtext_state.rs @@ -18,7 +18,7 @@ use std::{ }; use tracing::instrument; -use crate::{ +use crate::internal::{ container::richtext::style_range_map::EMPTY_STYLES, delta::{DeltaValue, StyleMeta}, utils::query_by_len::{EntityIndexQueryWithEventIndex, IndexQueryWithEntityIndex, QueryByLen}, @@ -34,7 +34,7 @@ use super::{ AnchorType, RichtextSpan, StyleKey, StyleOp, }; -pub(crate) use crate::cursor::PosType; +pub(crate) use crate::internal::cursor::PosType; #[derive(Clone, Debug, Default)] pub(crate) struct RichtextState { @@ -1141,7 +1141,7 @@ impl BTreeTrait for RichtextTreeTrait { // This query implementation will prefer right element when both left element and right element are valid. mod query { - use crate::utils::query_by_len::{IndexQuery, QueryByLen}; + use crate::internal::utils::query_by_len::{IndexQuery, QueryByLen}; use super::*; @@ -2909,7 +2909,7 @@ mod test { use append_only_bytes::AppendOnlyBytes; use serde_json::json; - use crate::{container::richtext::TextStyleInfoFlag, ToJson}; + use crate::internal::{container::richtext::TextStyleInfoFlag, ToJson}; use super::*; diff --git a/crates/loro-internal/src/container/richtext/str_slice.rs b/crates/loro/src/internal/container/richtext/str_slice.rs similarity index 100% rename from crates/loro-internal/src/container/richtext/str_slice.rs rename to crates/loro/src/internal/container/richtext/str_slice.rs diff --git a/crates/loro-internal/src/container/richtext/style_range_map.rs b/crates/loro/src/internal/container/richtext/style_range_map.rs similarity index 99% rename from crates/loro-internal/src/container/richtext/style_range_map.rs rename to crates/loro/src/internal/container/richtext/style_range_map.rs index f7487d4db..b79845b00 100644 --- a/crates/loro-internal/src/container/richtext/style_range_map.rs +++ b/crates/loro/src/internal/container/richtext/style_range_map.rs @@ -15,7 +15,7 @@ use rustc_hash::FxHashMap; use once_cell::sync::Lazy; -use crate::delta::StyleMeta; +use crate::internal::delta::StyleMeta; use super::{AnchorType, StyleKey, StyleOp}; @@ -571,7 +571,7 @@ impl BTreeTrait for RangeNumMapTrait { mod test { use loro_common::PeerID; - use crate::{change::Lamport, container::richtext::TextStyleInfoFlag}; + use crate::internal::{change::Lamport, container::richtext::TextStyleInfoFlag}; use super::*; diff --git a/crates/loro-internal/src/container/richtext/tinyvec.rs b/crates/loro/src/internal/container/richtext/tinyvec.rs similarity index 100% rename from crates/loro-internal/src/container/richtext/tinyvec.rs rename to crates/loro/src/internal/container/richtext/tinyvec.rs diff --git a/crates/loro-internal/src/container/richtext/tracker.rs b/crates/loro/src/internal/container/richtext/tracker.rs similarity index 98% rename from crates/loro-internal/src/container/richtext/tracker.rs rename to crates/loro/src/internal/container/richtext/tracker.rs index 18eac0106..6ef5f7c69 100644 --- a/crates/loro-internal/src/container/richtext/tracker.rs +++ b/crates/loro/src/internal/container/richtext/tracker.rs @@ -8,7 +8,7 @@ use loro_common::{Counter, HasId, HasIdSpan, IdFull, IdSpan, Lamport, PeerID, ID use rle::HasLength as _; use tracing::instrument; -use crate::{cursor::AbsolutePosition, VersionVector}; +use crate::internal::{cursor::AbsolutePosition, VersionVector}; use self::{crdt_rope::CrdtRope, id_to_cursor::IdToCursor}; @@ -603,9 +603,9 @@ impl Tracker { return Some(AbsolutePosition { pos: index, side: if is_activated { - crate::cursor::Side::Middle + crate::internal::cursor::Side::Middle } else { - crate::cursor::Side::Left + crate::internal::cursor::Side::Left }, }); } @@ -636,7 +636,7 @@ impl Tracker { #[cfg(test)] mod test { - use crate::{container::richtext::RichtextChunk, vv}; + use crate::internal::{container::richtext::RichtextChunk, vv}; use generic_btree::rle::HasLength; use super::*; @@ -689,7 +689,7 @@ mod test { #[ignore] fn perf_update_insert_by_split_quadratic() { // Run with: - // cargo test -p loro-internal perf_update_insert_by_split_quadratic -- --ignored --nocapture + // cargo test -p loro perf_update_insert_by_split_quadratic -- --ignored --nocapture const CHUNK_LEN: usize = 256; let fragments: usize = std::env::var("LORO_PERF_FRAGMENTS") .ok() @@ -737,7 +737,7 @@ mod test { #[ignore] fn perf_update_insert_by_split_quadratic_unknown() { // Run with: - // LORO_PERF_FRAGMENTS=8192 cargo test -p loro-internal perf_update_insert_by_split_quadratic_unknown -- --ignored --nocapture + // LORO_PERF_FRAGMENTS=8192 cargo test -p loro perf_update_insert_by_split_quadratic_unknown -- --ignored --nocapture const CHUNK_LEN: usize = 256; let fragments: usize = std::env::var("LORO_PERF_FRAGMENTS") .ok() diff --git a/crates/loro-internal/src/container/richtext/tracker/crdt_rope.rs b/crates/loro/src/internal/container/richtext/tracker/crdt_rope.rs similarity index 99% rename from crates/loro-internal/src/container/richtext/tracker/crdt_rope.rs rename to crates/loro/src/internal/container/richtext/tracker/crdt_rope.rs index 6c3c901c5..bc7744695 100644 --- a/crates/loro-internal/src/container/richtext/tracker/crdt_rope.rs +++ b/crates/loro/src/internal/container/richtext/tracker/crdt_rope.rs @@ -8,7 +8,7 @@ use itertools::Itertools; use loro_common::{Counter, HasCounter, HasCounterSpan, HasIdSpan, IdSpan, Lamport, ID}; use smallvec::{smallvec, SmallVec}; -use crate::container::richtext::{fugue_span::DiffStatus, FugueSpan, RichtextChunk, Status}; +use crate::internal::container::richtext::{fugue_span::DiffStatus, FugueSpan, RichtextChunk, Status}; use super::UNKNOWN_PEER_ID; @@ -678,7 +678,7 @@ mod test { use loro_common::{CompactId, Counter, IdFull, PeerID, ID}; - use crate::container::richtext::RichtextChunk; + use crate::internal::container::richtext::RichtextChunk; use super::*; diff --git a/crates/loro-internal/src/container/richtext/tracker/id_to_cursor.rs b/crates/loro/src/internal/container/richtext/tracker/id_to_cursor.rs similarity index 100% rename from crates/loro-internal/src/container/richtext/tracker/id_to_cursor.rs rename to crates/loro/src/internal/container/richtext/tracker/id_to_cursor.rs diff --git a/crates/loro-internal/src/container/tree/bool_rle_vec.rs b/crates/loro/src/internal/container/tree/bool_rle_vec.rs similarity index 100% rename from crates/loro-internal/src/container/tree/bool_rle_vec.rs rename to crates/loro/src/internal/container/tree/bool_rle_vec.rs diff --git a/crates/loro-internal/src/container/tree/mod.rs b/crates/loro/src/internal/container/tree/mod.rs similarity index 100% rename from crates/loro-internal/src/container/tree/mod.rs rename to crates/loro/src/internal/container/tree/mod.rs diff --git a/crates/loro-internal/src/container/tree/tree_ds.rs b/crates/loro/src/internal/container/tree/tree_ds.rs similarity index 98% rename from crates/loro-internal/src/container/tree/tree_ds.rs rename to crates/loro/src/internal/container/tree/tree_ds.rs index 01912995e..c03f7623f 100644 --- a/crates/loro-internal/src/container/tree/tree_ds.rs +++ b/crates/loro/src/internal/container/tree/tree_ds.rs @@ -3,7 +3,7 @@ use loro_common::{IdFull, IdLp, TreeID}; use rustc_hash::FxHashMap; -use crate::VersionVector; +use crate::internal::VersionVector; use super::bool_rle_vec::BoolRleVec; diff --git a/crates/loro-internal/src/container/tree/tree_op.rs b/crates/loro/src/internal/container/tree/tree_op.rs similarity index 98% rename from crates/loro-internal/src/container/tree/tree_op.rs rename to crates/loro/src/internal/container/tree/tree_op.rs index 5f7fe3c20..06f79e1a6 100644 --- a/crates/loro-internal/src/container/tree/tree_op.rs +++ b/crates/loro/src/internal/container/tree/tree_op.rs @@ -3,7 +3,7 @@ use loro_common::TreeID; use rle::{HasLength, Mergable}; use serde::{Deserialize, Serialize}; -use crate::state::TreeParentId; +use crate::internal::state::TreeParentId; /// The operation of movable tree. /// diff --git a/crates/loro-internal/src/cursor.rs b/crates/loro/src/internal/cursor.rs similarity index 100% rename from crates/loro-internal/src/cursor.rs rename to crates/loro/src/internal/cursor.rs diff --git a/crates/loro-internal/src/dag.rs b/crates/loro/src/internal/dag.rs similarity index 99% rename from crates/loro-internal/src/dag.rs rename to crates/loro/src/internal/dag.rs index 321b0fac6..1c187e515 100644 --- a/crates/loro-internal/src/dag.rs +++ b/crates/loro/src/internal/dag.rs @@ -23,7 +23,7 @@ mod test; #[cfg(feature = "test_utils")] pub use test::{fuzz_alloc_tree, Interaction}; -use crate::{ +use crate::internal::{ change::Lamport, diff_calc::DiffMode, id::{Counter, PeerID, ID}, diff --git a/crates/loro-internal/src/dag/iter.rs b/crates/loro/src/internal/dag/iter.rs similarity index 99% rename from crates/loro-internal/src/dag/iter.rs rename to crates/loro/src/internal/dag/iter.rs index 2f1322175..e8682c796 100644 --- a/crates/loro-internal/src/dag/iter.rs +++ b/crates/loro/src/internal/dag/iter.rs @@ -1,4 +1,4 @@ -use crate::version::Frontiers; +use crate::internal::version::Frontiers; use num::Zero; use std::{collections::BTreeMap, ops::Range}; diff --git a/crates/loro-internal/src/dag/mermaid.rs b/crates/loro/src/internal/dag/mermaid.rs similarity index 100% rename from crates/loro-internal/src/dag/mermaid.rs rename to crates/loro/src/internal/dag/mermaid.rs diff --git a/crates/loro-internal/src/dag/test.excalidraw b/crates/loro/src/internal/dag/test.excalidraw similarity index 100% rename from crates/loro-internal/src/dag/test.excalidraw rename to crates/loro/src/internal/dag/test.excalidraw diff --git a/crates/loro-internal/src/dag/test.rs b/crates/loro/src/internal/dag/test.rs similarity index 98% rename from crates/loro-internal/src/dag/test.rs rename to crates/loro/src/internal/dag/test.rs index dc3afba8e..88231775c 100644 --- a/crates/loro-internal/src/dag/test.rs +++ b/crates/loro/src/internal/dag/test.rs @@ -5,7 +5,7 @@ use loro_common::HasCounter; use std::{cmp::Ordering, sync::Arc}; use super::*; -use crate::{ +use crate::internal::{ array_mut_ref, change::Lamport, id::{Counter, PeerID, ID}, @@ -384,7 +384,7 @@ mod dfs { #[allow(unused)] #[allow(dead_code)] use super::*; - use crate::{allocation::calc_critical_version_dfs, delta::DeltaValue}; + use crate::internal::{allocation::calc_critical_version_dfs, delta::DeltaValue}; use rand::{rngs::StdRng, SeedableRng}; #[test] @@ -456,7 +456,7 @@ mod bfs { use loro_common::ID; use rand::{rngs::StdRng, SeedableRng}; - use crate::{ + use crate::internal::{ allocation::calc_critical_version, dag::{ test::{TestDag, TestNode}, @@ -619,13 +619,13 @@ fn test_alloc() { } let a = &dags[0]; let start = a.frontier(); - let end = crate::allocation::get_end_list(a, start); + let end = crate::internal::allocation::get_end_list(a, start); let critical_version_actual: HashSet = - crate::allocation::calc_critical_version(a, start) + crate::internal::allocation::calc_critical_version(a, start) .into_iter() .collect(); let critical_version: HashSet = - crate::allocation::calc_critical_version_dfs(a, start, &end) + crate::internal::allocation::calc_critical_version_dfs(a, start, &end) .into_iter() .collect(); assert!(critical_version_actual.eq(&critical_version)); @@ -646,11 +646,11 @@ pub fn fuzz_alloc_tree(num: usize, mut actions: Vec) { let a = &dags[0]; let start = a.frontier(); - let end = crate::allocation::get_end_list(a, start); - let actual: HashSet = crate::allocation::calc_critical_version(a, start) + let end = crate::internal::allocation::get_end_list(a, start); + let actual: HashSet = crate::internal::allocation::calc_critical_version(a, start) .into_iter() .collect(); - let expected: HashSet = crate::allocation::calc_critical_version_dfs(a, start, &end) + let expected: HashSet = crate::internal::allocation::calc_critical_version_dfs(a, start, &end) .into_iter() .collect(); assert!(actual.eq(&expected)); @@ -670,7 +670,7 @@ fn failed_fuzz() { // #[cfg(test)] // mod find_path { -// use crate::{fx_map, span::CounterSpan}; +// use crate::internal::{fx_map, span::CounterSpan}; // use super::*; @@ -1012,7 +1012,7 @@ fn failed_fuzz() { // mod find_common_ancestors_proptest { -// use crate::{ +// use crate::internal::{ // array_mut_ref, // span::HasIdSpan, // tests::{PROPTEST_FACTOR_1, PROPTEST_FACTOR_10}, @@ -1328,7 +1328,7 @@ fn failed_fuzz() { // mod dag_partial_iter { // use loro_common::HasCounterSpan; -// use crate::{dag::iter::IterReturn, tests::PROPTEST_FACTOR_10}; +// use crate::internal::{dag::iter::IterReturn, tests::PROPTEST_FACTOR_10}; // use super::*; diff --git a/crates/loro-internal/src/delta.rs b/crates/loro/src/internal/delta.rs similarity index 100% rename from crates/loro-internal/src/delta.rs rename to crates/loro/src/internal/delta.rs diff --git a/crates/loro-internal/src/delta/map.rs b/crates/loro/src/internal/delta/map.rs similarity index 98% rename from crates/loro-internal/src/delta/map.rs rename to crates/loro/src/internal/delta/map.rs index f77f37f31..c73f64794 100644 --- a/crates/loro-internal/src/delta/map.rs +++ b/crates/loro/src/internal/delta/map.rs @@ -2,7 +2,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; use serde::Serialize; use std::fmt::Debug; -use crate::{InternalString, LoroValue}; +use crate::internal::{InternalString, LoroValue}; #[derive(Clone, Debug, Serialize)] pub struct ValuePair { diff --git a/crates/loro-internal/src/delta/map_delta.rs b/crates/loro/src/internal/delta/map_delta.rs similarity index 99% rename from crates/loro-internal/src/delta/map_delta.rs rename to crates/loro/src/internal/delta/map_delta.rs index e07ac5c91..37c926920 100644 --- a/crates/loro-internal/src/delta/map_delta.rs +++ b/crates/loro/src/internal/delta/map_delta.rs @@ -4,7 +4,7 @@ use loro_common::IdLp; use rustc_hash::FxHashMap; use serde::{ser::SerializeStruct, Serialize}; -use crate::{ +use crate::internal::{ change::Lamport, handler::ValueOrHandler, id::PeerID, span::HasLamport, InternalString, LoroDocInner, LoroValue, }; diff --git a/crates/loro-internal/src/delta/movable_list.rs b/crates/loro/src/internal/delta/movable_list.rs similarity index 100% rename from crates/loro-internal/src/delta/movable_list.rs rename to crates/loro/src/internal/delta/movable_list.rs diff --git a/crates/loro-internal/src/delta/seq.rs b/crates/loro/src/internal/delta/seq.rs similarity index 100% rename from crates/loro-internal/src/delta/seq.rs rename to crates/loro/src/internal/delta/seq.rs diff --git a/crates/loro-internal/src/delta/text.rs b/crates/loro/src/internal/delta/text.rs similarity index 96% rename from crates/loro-internal/src/delta/text.rs rename to crates/loro/src/internal/delta/text.rs index b375de2f2..4b590824f 100644 --- a/crates/loro-internal/src/delta/text.rs +++ b/crates/loro/src/internal/delta/text.rs @@ -2,10 +2,10 @@ use loro_common::{InternalString, LoroValue, PeerID}; use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; -use crate::change::Lamport; -use crate::container::richtext::{Style, Styles}; -use crate::event::TextMeta; -use crate::ToJson; +use crate::internal::change::Lamport; +use crate::internal::container::richtext::{Style, Styles}; +use crate::internal::event::TextMeta; +use crate::internal::ToJson; use super::Meta; diff --git a/crates/loro-internal/src/delta/tree.rs b/crates/loro/src/internal/delta/tree.rs similarity index 97% rename from crates/loro-internal/src/delta/tree.rs rename to crates/loro/src/internal/delta/tree.rs index 8f368e590..ce134bd0d 100644 --- a/crates/loro-internal/src/delta/tree.rs +++ b/crates/loro/src/internal/delta/tree.rs @@ -5,7 +5,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; use std::fmt::Debug; use std::ops::{Deref, DerefMut}; -use crate::state::TreeParentId; +use crate::internal::state::TreeParentId; #[derive(Debug, Clone, Default)] pub struct TreeDiff { @@ -111,7 +111,7 @@ pub struct TreeDeltaItem { pub last_effective_move_op_id: IdFull, } -/// The action of [`TreeDiff`]. It's the same as [`crate::container::tree::tree_op::TreeOp`], but semantic. +/// The action of [`TreeDiff`]. It's the same as [`crate::internal::container::tree::tree_op::TreeOp`], but semantic. #[derive(Debug, Clone)] pub enum TreeInternalDiff { /// First create the node, have not seen it before diff --git a/crates/loro-internal/src/diff/LICENSE b/crates/loro/src/internal/diff/LICENSE similarity index 100% rename from crates/loro-internal/src/diff/LICENSE rename to crates/loro/src/internal/diff/LICENSE diff --git a/crates/loro-internal/src/diff/diff_impl.rs b/crates/loro/src/internal/diff/diff_impl.rs similarity index 99% rename from crates/loro-internal/src/diff/diff_impl.rs rename to crates/loro/src/internal/diff/diff_impl.rs index aef44cd5b..9f97976c8 100644 --- a/crates/loro-internal/src/diff/diff_impl.rs +++ b/crates/loro/src/internal/diff/diff_impl.rs @@ -14,7 +14,7 @@ //! //! The implementation of this algorithm is based on the implementation by //! Brandon Williams. -use crate::change::get_sys_timestamp; +use crate::internal::change::get_sys_timestamp; use rustc_hash::FxHashMap; use std::cmp::Ordering; use std::collections::BinaryHeap; diff --git a/crates/loro-internal/src/diff/mod.rs b/crates/loro/src/internal/diff/mod.rs similarity index 100% rename from crates/loro-internal/src/diff/mod.rs rename to crates/loro/src/internal/diff/mod.rs diff --git a/crates/loro-internal/src/diff_calc.rs b/crates/loro/src/internal/diff_calc.rs similarity index 96% rename from crates/loro-internal/src/diff_calc.rs rename to crates/loro/src/internal/diff_calc.rs index 107661c8d..b96217954 100644 --- a/crates/loro-internal/src/diff_calc.rs +++ b/crates/loro/src/internal/diff_calc.rs @@ -19,7 +19,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; use smallvec::SmallVec; use tracing::{info_span, instrument}; -use crate::{ +use crate::internal::{ change::Lamport, container::{ idx::ContainerIdx, @@ -140,9 +140,9 @@ impl DiffCalculator { pub(crate) fn calc_diff_internal( &mut self, oplog: &super::oplog::OpLog, - before: &crate::VersionVector, + before: &crate::internal::VersionVector, before_frontiers: &Frontiers, - after: &crate::VersionVector, + after: &crate::internal::VersionVector, after_frontiers: &Frontiers, container_filter: Option<&dyn Fn(ContainerIdx) -> bool>, ) -> (Vec, DiffMode) { @@ -346,32 +346,32 @@ impl DiffCalculator { self.calculators .entry(idx) .or_insert_with(|| match idx.get_type() { - crate::ContainerType::Text => ( + crate::internal::ContainerType::Text => ( depth, ContainerDiffCalculator::Richtext(RichtextDiffCalculator::new()), ), - crate::ContainerType::Map => ( + crate::internal::ContainerType::Map => ( depth, ContainerDiffCalculator::Map(MapDiffCalculator::new(idx)), ), - crate::ContainerType::List => ( + crate::internal::ContainerType::List => ( depth, ContainerDiffCalculator::List(ListDiffCalculator::default()), ), - crate::ContainerType::Tree => ( + crate::internal::ContainerType::Tree => ( depth, ContainerDiffCalculator::Tree(TreeDiffCalculator::new(idx)), ), - crate::ContainerType::Unknown(_) => ( + crate::internal::ContainerType::Unknown(_) => ( depth, ContainerDiffCalculator::Unknown(unknown::UnknownDiffCalculator), ), - crate::ContainerType::MovableList => ( + crate::internal::ContainerType::MovableList => ( depth, ContainerDiffCalculator::MovableList(MovableListDiffCalculator::new(idx)), ), #[cfg(feature = "counter")] - crate::ContainerType::Counter => ( + crate::internal::ContainerType::Counter => ( depth, ContainerDiffCalculator::Counter(CounterDiffCalculator::new(idx)), ), @@ -388,12 +388,12 @@ impl DiffCalculator { /// #[enum_dispatch] pub(crate) trait DiffCalculatorTrait { - fn start_tracking(&mut self, oplog: &OpLog, vv: &crate::VersionVector, mode: DiffMode); + fn start_tracking(&mut self, oplog: &OpLog, vv: &crate::internal::VersionVector, mode: DiffMode); fn apply_change( &mut self, oplog: &OpLog, - op: crate::op::RichOp, - vv: Option<&crate::VersionVector>, + op: crate::internal::op::RichOp, + vv: Option<&crate::internal::VersionVector>, ); fn calculate_diff( &mut self, @@ -439,8 +439,8 @@ impl MapDiffCalculator { impl DiffCalculatorTrait for MapDiffCalculator { fn start_tracking( &mut self, - _oplog: &crate::OpLog, - _vv: &crate::VersionVector, + _oplog: &crate::internal::OpLog, + _vv: &crate::internal::VersionVector, mode: DiffMode, ) { self.changed.clear(); @@ -449,9 +449,9 @@ impl DiffCalculatorTrait for MapDiffCalculator { fn apply_change( &mut self, - _oplog: &crate::OpLog, - op: crate::op::RichOp, - _vv: Option<&crate::VersionVector>, + _oplog: &crate::internal::OpLog, + op: crate::internal::op::RichOp, + _vv: Option<&crate::internal::VersionVector>, ) { if matches!(self.current_mode, DiffMode::Checkout) { // We need to use history cache anyway @@ -559,13 +559,13 @@ pub(crate) struct ListDiffCalculator { } impl ListDiffCalculator { - pub(crate) fn get_id_latest_pos(&self, id: ID) -> Option { + pub(crate) fn get_id_latest_pos(&self, id: ID) -> Option { self.tracker.get_target_id_latest_index_at_new_version(id) } } impl MovableListDiffCalculator { - pub(crate) fn get_id_latest_pos(&self, id: ID) -> Option { + pub(crate) fn get_id_latest_pos(&self, id: ID) -> Option { self.list .tracker .get_target_id_latest_index_at_new_version(id) @@ -581,7 +581,7 @@ impl std::fmt::Debug for ListDiffCalculator { } impl DiffCalculatorTrait for ListDiffCalculator { - fn start_tracking(&mut self, _oplog: &OpLog, vv: &crate::VersionVector, _mode: DiffMode) { + fn start_tracking(&mut self, _oplog: &OpLog, vv: &crate::internal::VersionVector, _mode: DiffMode) { if !vv.includes_vv(&self.start_vv) || !self.tracker.all_vv().includes_vv(vv) { self.tracker = Box::new(RichtextTracker::new_with_unknown()); self.start_vv = vv.clone(); @@ -593,15 +593,15 @@ impl DiffCalculatorTrait for ListDiffCalculator { fn apply_change( &mut self, _oplog: &OpLog, - op: crate::op::RichOp, - vv: Option<&crate::VersionVector>, + op: crate::internal::op::RichOp, + vv: Option<&crate::internal::VersionVector>, ) { if let Some(vv) = vv { self.tracker.checkout(vv); } match &op.op().content { - crate::op::InnerContent::List(l) => match l { + crate::internal::op::InnerContent::List(l) => match l { InnerListOp::Insert { slice, pos } => { self.tracker.insert( op.id_full(), @@ -799,7 +799,7 @@ impl DiffCalculatorTrait for RichtextDiffCalculator { fn start_tracking( &mut self, _oplog: &super::oplog::OpLog, - vv: &crate::VersionVector, + vv: &crate::internal::VersionVector, mode: DiffMode, ) { match mode { @@ -837,15 +837,15 @@ impl DiffCalculatorTrait for RichtextDiffCalculator { fn apply_change( &mut self, oplog: &super::oplog::OpLog, - op: crate::op::RichOp, - vv: Option<&crate::VersionVector>, + op: crate::internal::op::RichOp, + vv: Option<&crate::internal::VersionVector>, ) { match &mut *self.mode { RichtextCalcMode::Linear { diff, last_style_start, } => match &op.raw_op().content { - crate::op::InnerContent::List(l) => match l { + crate::internal::op::InnerContent::List(l) => match l { InnerListOp::Insert { .. } | InnerListOp::Move { .. } | InnerListOp::Set { .. } => { @@ -944,7 +944,7 @@ impl DiffCalculatorTrait for RichtextDiffCalculator { tracker.checkout(vv); } match &op.raw_op().content { - crate::op::InnerContent::List(l) => match l { + crate::internal::op::InnerContent::List(l) => match l { InnerListOp::Insert { .. } | InnerListOp::Move { .. } | InnerListOp::Set { .. } => { @@ -1201,7 +1201,7 @@ struct MovableListInner { } impl DiffCalculatorTrait for MovableListDiffCalculator { - fn start_tracking(&mut self, _oplog: &OpLog, vv: &crate::VersionVector, mode: DiffMode) { + fn start_tracking(&mut self, _oplog: &OpLog, vv: &crate::internal::VersionVector, mode: DiffMode) { if !vv.includes_vv(&self.list.start_vv) || !self.list.tracker.all_vv().includes_vv(vv) { self.list.tracker = Box::new(RichtextTracker::new_with_unknown()); self.list.start_vv = vv.clone(); @@ -1214,8 +1214,8 @@ impl DiffCalculatorTrait for MovableListDiffCalculator { fn apply_change( &mut self, oplog: &OpLog, - op: crate::op::RichOp, - vv: Option<&crate::VersionVector>, + op: crate::internal::op::RichOp, + vv: Option<&crate::internal::VersionVector>, ) { let InnerContent::List(l) = &op.raw_op().content else { unreachable!() @@ -1306,7 +1306,7 @@ impl DiffCalculatorTrait for MovableListDiffCalculator { let real_op = op.op(); match &real_op.content { - crate::op::InnerContent::List(l) => match l { + crate::internal::op::InnerContent::List(l) => match l { InnerListOp::Insert { slice, pos } => { this.tracker.insert( op.id_full(), diff --git a/crates/loro-internal/src/diff_calc/counter.rs b/crates/loro/src/internal/diff_calc/counter.rs similarity index 83% rename from crates/loro-internal/src/diff_calc/counter.rs rename to crates/loro/src/internal/diff_calc/counter.rs index bf0663b54..7c3effef2 100644 --- a/crates/loro-internal/src/diff_calc/counter.rs +++ b/crates/loro/src/internal/diff_calc/counter.rs @@ -2,7 +2,7 @@ use std::collections::BTreeMap; use loro_common::{ContainerID, ID}; -use crate::{container::idx::ContainerIdx, event::InternalDiff, OpLog}; +use crate::internal::{container::idx::ContainerIdx, event::InternalDiff, OpLog}; use super::{DiffCalcVersionInfo, DiffCalculatorTrait, DiffMode}; @@ -20,13 +20,13 @@ impl CounterDiffCalculator { } impl DiffCalculatorTrait for CounterDiffCalculator { - fn start_tracking(&mut self, _oplog: &OpLog, _vv: &crate::VersionVector, _mode: DiffMode) {} + fn start_tracking(&mut self, _oplog: &OpLog, _vv: &crate::internal::VersionVector, _mode: DiffMode) {} fn apply_change( &mut self, _oplog: &OpLog, - op: crate::op::RichOp, - _vv: Option<&crate::VersionVector>, + op: crate::internal::op::RichOp, + _vv: Option<&crate::internal::VersionVector>, ) { let id = op.id(); self.ops.insert( diff --git a/crates/loro-internal/src/diff_calc/tree.rs b/crates/loro/src/internal/diff_calc/tree.rs similarity index 97% rename from crates/loro-internal/src/diff_calc/tree.rs rename to crates/loro/src/internal/diff_calc/tree.rs index 6a71bda39..fb17c8bee 100644 --- a/crates/loro-internal/src/diff_calc/tree.rs +++ b/crates/loro/src/internal/diff_calc/tree.rs @@ -5,7 +5,7 @@ use itertools::Itertools; use loro_common::{ContainerID, IdFull, IdLp, Lamport, PeerID, TreeID, ID}; use rustc_hash::FxHashMap; -use crate::{ +use crate::internal::{ container::{idx::ContainerIdx, tree::tree_op::TreeOp}, dag::DagUtils, delta::{TreeDelta, TreeDeltaItem, TreeInternalDiff}, @@ -31,7 +31,7 @@ enum TreeDiffCalculatorMode { } impl DiffCalculatorTrait for TreeDiffCalculator { - fn start_tracking(&mut self, _oplog: &OpLog, _vv: &crate::VersionVector, mode: DiffMode) { + fn start_tracking(&mut self, _oplog: &OpLog, _vv: &crate::internal::VersionVector, mode: DiffMode) { match mode { DiffMode::Checkout => { self.mode = TreeDiffCalculatorMode::Crdt; @@ -51,8 +51,8 @@ impl DiffCalculatorTrait for TreeDiffCalculator { fn apply_change( &mut self, _oplog: &OpLog, - op: crate::op::RichOp, - _vv: Option<&crate::VersionVector>, + op: crate::internal::op::RichOp, + _vv: Option<&crate::internal::VersionVector>, ) { match &mut self.mode { TreeDiffCalculatorMode::Crdt => {} @@ -63,7 +63,7 @@ impl DiffCalculatorTrait for TreeDiffCalculator { let content = op.content.as_tree().unwrap(); let item: TreeDeltaItem = match &**content { - crate::container::tree::tree_op::TreeOp::Create { + crate::internal::container::tree::tree_op::TreeOp::Create { target, parent, position, @@ -75,7 +75,7 @@ impl DiffCalculatorTrait for TreeDiffCalculator { }, last_effective_move_op_id: id_full, }, - crate::container::tree::tree_op::TreeOp::Move { + crate::internal::container::tree::tree_op::TreeOp::Move { target, parent, position, @@ -87,7 +87,7 @@ impl DiffCalculatorTrait for TreeDiffCalculator { }, last_effective_move_op_id: id_full, }, - crate::container::tree::tree_op::TreeOp::Delete { target } => TreeDeltaItem { + crate::internal::container::tree::tree_op::TreeOp::Delete { target } => TreeDeltaItem { target: *target, action: TreeInternalDiff::Delete { parent: TreeParentId::Deleted, diff --git a/crates/loro-internal/src/diff_calc/unknown.rs b/crates/loro/src/internal/diff_calc/unknown.rs similarity index 68% rename from crates/loro-internal/src/diff_calc/unknown.rs rename to crates/loro/src/internal/diff_calc/unknown.rs index 25a6fbff3..0ef59fcdb 100644 --- a/crates/loro-internal/src/diff_calc/unknown.rs +++ b/crates/loro/src/internal/diff_calc/unknown.rs @@ -1,6 +1,6 @@ use loro_common::ContainerID; -use crate::{container::idx::ContainerIdx, event::InternalDiff, OpLog}; +use crate::internal::{container::idx::ContainerIdx, event::InternalDiff, OpLog}; use super::{DiffCalcVersionInfo, DiffCalculatorTrait, DiffMode}; @@ -8,13 +8,13 @@ use super::{DiffCalcVersionInfo, DiffCalculatorTrait, DiffMode}; pub struct UnknownDiffCalculator; impl DiffCalculatorTrait for UnknownDiffCalculator { - fn start_tracking(&mut self, _oplog: &OpLog, _vv: &crate::VersionVector, _mode: DiffMode) {} + fn start_tracking(&mut self, _oplog: &OpLog, _vv: &crate::internal::VersionVector, _mode: DiffMode) {} fn apply_change( &mut self, _oplog: &OpLog, - _op: crate::op::RichOp, - _vv: Option<&crate::VersionVector>, + _op: crate::internal::op::RichOp, + _vv: Option<&crate::internal::VersionVector>, ) { } diff --git a/crates/loro-internal/src/encoding.rs b/crates/loro/src/internal/encoding.rs similarity index 99% rename from crates/loro-internal/src/encoding.rs rename to crates/loro/src/internal/encoding.rs index 5b881fa3b..604be3e34 100644 --- a/crates/loro-internal/src/encoding.rs +++ b/crates/loro/src/internal/encoding.rs @@ -11,9 +11,9 @@ pub(crate) use outdated_encode_reordered::{ use outdated_encode_reordered::{import_changes_to_oplog, ImportChangesResult}; pub(crate) use value::OwnedValue; -use crate::version::{Frontiers, VersionRange}; -use crate::LoroDoc; -use crate::{oplog::OpLog, LoroError, VersionVector}; +use crate::internal::version::{Frontiers, VersionRange}; +use crate::internal::LoroDoc; +use crate::internal::{oplog::OpLog, LoroError, VersionVector}; use loro_common::{HasIdSpan, IdSpan, InternalString, LoroEncodeError, LoroResult, ID}; use num_traits::{FromPrimitive, ToPrimitive}; use std::borrow::Cow; diff --git a/crates/loro-internal/src/encoding/arena.rs b/crates/loro/src/internal/encoding/arena.rs similarity index 98% rename from crates/loro-internal/src/encoding/arena.rs rename to crates/loro/src/internal/encoding/arena.rs index b47670d7c..c33548b01 100644 --- a/crates/loro-internal/src/encoding/arena.rs +++ b/crates/loro/src/internal/encoding/arena.rs @@ -1,6 +1,6 @@ use std::{borrow::Cow, ops::Deref}; -use crate::InternalString; +use crate::internal::InternalString; use loro_common::{ContainerID, ContainerType, Counter, LoroError, LoroResult, PeerID}; use rustc_hash::FxHashSet; use serde_columnar::columnar; @@ -30,7 +30,7 @@ impl ValueEncodeRegister for EncodedRegisters<'_> { fn encode_tree_op( &mut self, - op: &crate::container::tree::tree_op::TreeOp, + op: &crate::internal::container::tree::tree_op::TreeOp, ) -> super::value::Value<'static> { Value::TreeMove(super::value::EncodedTreeMove::from_tree_op(op, self)) } diff --git a/crates/loro-internal/src/encoding/fast_snapshot.rs b/crates/loro/src/internal/encoding/fast_snapshot.rs similarity index 97% rename from crates/loro-internal/src/encoding/fast_snapshot.rs rename to crates/loro/src/internal/encoding/fast_snapshot.rs index 6e1b0ac60..940077861 100644 --- a/crates/loro-internal/src/encoding/fast_snapshot.rs +++ b/crates/loro/src/internal/encoding/fast_snapshot.rs @@ -15,7 +15,7 @@ //! use std::io::{Read, Write}; -use crate::{ +use crate::internal::{ change::Change, encoding::shallow_snapshot, oplog::ChangeStore, version::Frontiers, LoroDoc, OpLog, VersionVector, }; @@ -107,7 +107,7 @@ pub(crate) fn decode_snapshot_inner( state_bytes, shallow_root_state_bytes, } = snapshot; - ensure_cov::notify_cov("loro_internal::import::fast_snapshot::decode_snapshot"); + ensure_cov::notify_cov("loro::internal::import::fast_snapshot::decode_snapshot"); let mut oplog = doc.oplog().lock().map_err(|_| { LoroError::DecodeError( "decode_snapshot: failed to lock oplog" @@ -135,13 +135,13 @@ pub(crate) fn decode_snapshot_inner( let need_calc = state_bytes.is_none(); let state_frontiers; if shallow_root_state_bytes.is_empty() { - ensure_cov::notify_cov("loro_internal::import::snapshot::normal"); + ensure_cov::notify_cov("loro::internal::import::snapshot::normal"); if let Some(bytes) = state_bytes { state.store.decode(bytes)?; } state_frontiers = oplog.frontiers().clone(); } else { - ensure_cov::notify_cov("loro_internal::import::snapshot::gc"); + ensure_cov::notify_cov("loro::internal::import::snapshot::gc"); let shallow_root_state_frontiers = state.store.decode_gc( shallow_root_state_bytes.clone(), oplog.dag().shallow_since_frontiers().clone(), diff --git a/crates/loro-internal/src/encoding/json_schema.rs b/crates/loro/src/internal/encoding/json_schema.rs similarity index 99% rename from crates/loro-internal/src/encoding/json_schema.rs rename to crates/loro/src/internal/encoding/json_schema.rs index 28559b5a9..43405af84 100644 --- a/crates/loro-internal/src/encoding/json_schema.rs +++ b/crates/loro/src/internal/encoding/json_schema.rs @@ -2,7 +2,7 @@ use super::{ outdated_encode_reordered::{import_changes_to_oplog, ImportChangesResult, ValueRegister}, ImportStatus, }; -use crate::{ +use crate::internal::{ arena::SharedArena, change::{Change, ChangeRef}, container::{ @@ -769,7 +769,7 @@ fn decode_op(op: json::JsonOp, arena: &SharedArena, peers: &Option>) let JsonOpContent::Future(json::FutureOpWrapper { prop: _, value }) = content else { unreachable!() }; - use crate::encoding::OwnedValue; + use crate::internal::encoding::OwnedValue; match value { json::FutureOp::Counter(OwnedValue::F64(c)) | json::FutureOp::Unknown(OwnedValue::F64(c)) => { @@ -815,7 +815,7 @@ impl TryFrom for JsonSchema { } pub mod json { - use crate::{ + use crate::internal::{ encoding::OwnedValue, version::{Frontiers, VersionRange}, }; @@ -1039,7 +1039,7 @@ pub mod json { }; #[allow(unused_imports)] - use crate::encoding::OwnedValue; + use crate::internal::encoding::OwnedValue; impl Serialize for super::JsonOp { fn serialize(&self, serializer: S) -> Result @@ -1158,7 +1158,7 @@ pub mod json { use loro_common::ID; use serde::{ser::SerializeMap, Deserializer, Serializer}; - use crate::version::Frontiers; + use crate::internal::version::Frontiers; pub fn serialize(f: &Frontiers, s: S) -> Result where @@ -1495,7 +1495,7 @@ fn redact_value(v: &mut LoroValue) { #[cfg(test)] mod tests { - use crate::{LoroDoc, VersionVector}; + use crate::internal::{LoroDoc, VersionVector}; #[test] fn json_range_version() { diff --git a/crates/loro-internal/src/encoding/outdated_encode_reordered.rs b/crates/loro/src/internal/encoding/outdated_encode_reordered.rs similarity index 78% rename from crates/loro-internal/src/encoding/outdated_encode_reordered.rs rename to crates/loro/src/internal/encoding/outdated_encode_reordered.rs index 0c59f9c87..122469c7c 100644 --- a/crates/loro-internal/src/encoding/outdated_encode_reordered.rs +++ b/crates/loro/src/internal/encoding/outdated_encode_reordered.rs @@ -7,8 +7,8 @@ use loro_common::{ use serde_columnar::{columnar, ColumnarError}; use std::sync::Arc; -use crate::version::VersionRange; -use crate::{ +use crate::internal::version::VersionRange; +use crate::internal::{ arena::SharedArena, change::{Change, Lamport}, container::{ @@ -20,7 +20,7 @@ use crate::{ use super::value::{Value, ValueDecodedArenasTrait}; -pub(crate) use crate::encoding::value_register::ValueRegister; +pub(crate) use crate::internal::encoding::value_register::ValueRegister; #[allow(unused_imports)] use super::value::FutureValue; @@ -85,7 +85,7 @@ pub(crate) fn import_changes_to_oplog( mod encode { use loro_common::ContainerType; - use crate::{ + use crate::internal::{ arena::SharedArena, encoding::value::{MarkStart, Value, ValueEncodeRegister, ValueKind, ValueWriter}, op::{FutureInnerContent, Op}, @@ -103,23 +103,23 @@ mod encode { pub(crate) fn get_op_prop(op: &Op, registers: &mut dyn ValueEncodeRegister) -> i32 { match &op.content { - crate::op::InnerContent::List(list) => match list { - crate::container::list::list_op::InnerListOp::Move { to, .. } => *to as i32, - crate::container::list::list_op::InnerListOp::Set { .. } => 0, - crate::container::list::list_op::InnerListOp::Insert { pos, .. } => *pos as i32, - crate::container::list::list_op::InnerListOp::InsertText { pos, .. } => *pos as i32, - crate::container::list::list_op::InnerListOp::Delete(span) => span.span.pos as i32, - crate::container::list::list_op::InnerListOp::StyleStart { start, .. } => { + crate::internal::op::InnerContent::List(list) => match list { + crate::internal::container::list::list_op::InnerListOp::Move { to, .. } => *to as i32, + crate::internal::container::list::list_op::InnerListOp::Set { .. } => 0, + crate::internal::container::list::list_op::InnerListOp::Insert { pos, .. } => *pos as i32, + crate::internal::container::list::list_op::InnerListOp::InsertText { pos, .. } => *pos as i32, + crate::internal::container::list::list_op::InnerListOp::Delete(span) => span.span.pos as i32, + crate::internal::container::list::list_op::InnerListOp::StyleStart { start, .. } => { *start as i32 } - crate::container::list::list_op::InnerListOp::StyleEnd => 0, + crate::internal::container::list::list_op::InnerListOp::StyleEnd => 0, }, - crate::op::InnerContent::Map(map) => { + crate::internal::op::InnerContent::Map(map) => { let key = registers.key_mut().register(&map.key); key as i32 } - crate::op::InnerContent::Tree(_) => 0, - crate::op::InnerContent::Future(f) => get_future_op_prop(f), + crate::internal::op::InnerContent::Tree(_) => 0, + crate::internal::op::InnerContent::Future(f) => get_future_op_prop(f), } } @@ -132,8 +132,8 @@ mod encode { registers: &mut dyn ValueEncodeRegister, ) -> ValueKind { let value = match &op.content { - crate::op::InnerContent::List(list) => match list { - crate::container::list::list_op::InnerListOp::Insert { slice, .. } => { + crate::internal::op::InnerContent::List(list) => match list { + crate::internal::container::list::list_op::InnerListOp::Insert { slice, .. } => { assert!(matches!( op.container.get_type(), ContainerType::List | ContainerType::MovableList @@ -141,10 +141,10 @@ mod encode { let value = arena.get_values(slice.0.start as usize..slice.0.end as usize); Value::LoroValue(value.into()) } - crate::container::list::list_op::InnerListOp::InsertText { slice, .. } => { + crate::internal::container::list::list_op::InnerListOp::InsertText { slice, .. } => { Value::Str(std::str::from_utf8(slice.as_bytes()).unwrap()) } - crate::container::list::list_op::InnerListOp::Delete(span) => { + crate::internal::container::list::list_op::InnerListOp::Delete(span) => { delete_start.push(EncodedDeleteStartId { peer_idx: registers.peer_mut().register(&span.id_start.peer), counter: span.id_start.counter, @@ -152,7 +152,7 @@ mod encode { }); Value::DeleteSeq } - crate::container::list::list_op::InnerListOp::StyleStart { + crate::internal::container::list::list_op::InnerListOp::StyleStart { start, end, key, @@ -164,15 +164,15 @@ mod encode { value: value.clone(), info: info.to_byte(), }), - crate::container::list::list_op::InnerListOp::Set { elem_id, value } => { + crate::internal::container::list::list_op::InnerListOp::Set { elem_id, value } => { Value::ListSet { peer_idx: registers.peer_mut().register(&elem_id.peer), lamport: elem_id.lamport, value: value.clone(), } } - crate::container::list::list_op::InnerListOp::StyleEnd => Value::Null, - crate::container::list::list_op::InnerListOp::Move { + crate::internal::container::list::list_op::InnerListOp::StyleEnd => Value::Null, + crate::internal::container::list::list_op::InnerListOp::Move { from, elem_id: from_id, to: _, @@ -182,18 +182,18 @@ mod encode { lamport: from_id.lamport as usize, }, }, - crate::op::InnerContent::Map(map) => { + crate::internal::op::InnerContent::Map(map) => { assert_eq!(op.container.get_type(), ContainerType::Map); match &map.value { Some(v) => Value::LoroValue(v.clone()), None => Value::DeleteOnce, } } - crate::op::InnerContent::Tree(t) => { + crate::internal::op::InnerContent::Tree(t) => { assert_eq!(op.container.get_type(), ContainerType::Tree); registers.encode_tree_op(t) } - crate::op::InnerContent::Future(f) => match f { + crate::internal::op::InnerContent::Future(f) => match f { #[cfg(feature = "counter")] FutureInnerContent::Counter(c) => { let c_abs = c.abs(); @@ -221,13 +221,13 @@ pub(crate) fn decode_op( positions: &[Vec], prop: i32, op_id: ID, -) -> LoroResult { +) -> LoroResult { let content = match cid.container_type() { ContainerType::Text => match value { Value::Str(s) => { let (slice, result) = shared_arena.alloc_str_with_slice(s); - crate::op::InnerContent::List( - crate::container::list::list_op::InnerListOp::InsertText { + crate::internal::op::InnerContent::List( + crate::internal::container::list::list_op::InnerListOp::InsertText { slice, unicode_start: result.start as u32, unicode_len: (result.end - result.start) as u32, @@ -240,7 +240,7 @@ pub(crate) fn decode_op( let peer_idx = del_start.peer_idx; let cnt = del_start.counter; let len = del_start.len; - crate::op::InnerContent::List(crate::container::list::list_op::InnerListOp::Delete( + crate::internal::op::InnerContent::List(crate::internal::container::list::list_op::InnerListOp::Delete( DeleteSpanWithId::new( ID::new(arenas.peers()[peer_idx], cnt as Counter), prop as isize, @@ -248,8 +248,8 @@ pub(crate) fn decode_op( ), )) } - Value::MarkStart(mark) => crate::op::InnerContent::List( - crate::container::list::list_op::InnerListOp::StyleStart { + Value::MarkStart(mark) => crate::internal::op::InnerContent::List( + crate::internal::container::list::list_op::InnerListOp::StyleStart { start: prop as u32, end: prop as u32 + mark.len, key: mark.key, @@ -257,8 +257,8 @@ pub(crate) fn decode_op( info: TextStyleInfoFlag::from_byte(mark.info), }, ), - Value::Null => crate::op::InnerContent::List( - crate::container::list::list_op::InnerListOp::StyleEnd, + Value::Null => crate::internal::op::InnerContent::List( + crate::internal::container::list::list_op::InnerListOp::StyleEnd, ), _ => unreachable!(), }, @@ -270,10 +270,10 @@ pub(crate) fn decode_op( .clone(); match value { Value::DeleteOnce => { - crate::op::InnerContent::Map(crate::container::map::MapSet { key, value: None }) + crate::internal::op::InnerContent::Map(crate::internal::container::map::MapSet { key, value: None }) } Value::LoroValue(v) => { - crate::op::InnerContent::Map(crate::container::map::MapSet { + crate::internal::op::InnerContent::Map(crate::internal::container::map::MapSet { key, value: Some(v.clone()), }) @@ -286,8 +286,8 @@ pub(crate) fn decode_op( match value { Value::LoroValue(arr) => { let range = shared_arena.alloc_values(arr.into_list().unwrap().iter().cloned()); - crate::op::InnerContent::List( - crate::container::list::list_op::InnerListOp::Insert { + crate::internal::op::InnerContent::List( + crate::internal::container::list::list_op::InnerListOp::Insert { slice: SliceRange::new(range.start as u32..range.end as u32), pos, }, @@ -298,8 +298,8 @@ pub(crate) fn decode_op( let peer_idx = del_start.peer_idx; let cnt = del_start.counter; let len = del_start.len; - crate::op::InnerContent::List( - crate::container::list::list_op::InnerListOp::Delete( + crate::internal::op::InnerContent::List( + crate::internal::container::list::list_op::InnerListOp::Delete( DeleteSpanWithId::new( ID::new(arenas.peers()[peer_idx], cnt as Counter), pos as isize, @@ -312,7 +312,7 @@ pub(crate) fn decode_op( } } ContainerType::Tree => match value { - Value::TreeMove(op) => crate::op::InnerContent::Tree(Arc::new( + Value::TreeMove(op) => crate::internal::op::InnerContent::Tree(Arc::new( arenas.decode_tree_op(positions, op, op_id)?, )), Value::RawTreeMove(op) => { @@ -326,7 +326,7 @@ pub(crate) fn decode_op( let parent_id = TreeID::new(arenas.peers()[op.parent_peer_idx], op.parent_cnt as Counter); if parent_id.is_deleted_root() { - return Ok(crate::op::InnerContent::Tree(Arc::new(TreeOp::Delete { + return Ok(crate::internal::op::InnerContent::Tree(Arc::new(TreeOp::Delete { target: subject, }))); } @@ -349,7 +349,7 @@ pub(crate) fn decode_op( position: fi, } }; - crate::op::InnerContent::Tree(Arc::new(ans)) + crate::internal::op::InnerContent::Tree(Arc::new(ans)) } _ => { unreachable!() @@ -360,8 +360,8 @@ pub(crate) fn decode_op( match value { Value::LoroValue(arr) => { let range = shared_arena.alloc_values(arr.into_list().unwrap().iter().cloned()); - crate::op::InnerContent::List( - crate::container::list::list_op::InnerListOp::Insert { + crate::internal::op::InnerContent::List( + crate::internal::container::list::list_op::InnerListOp::Insert { slice: SliceRange::new(range.start as u32..range.end as u32), pos, }, @@ -372,8 +372,8 @@ pub(crate) fn decode_op( let peer_idx = del_start.peer_idx; let cnt = del_start.counter; let len = del_start.len; - crate::op::InnerContent::List( - crate::container::list::list_op::InnerListOp::Delete( + crate::internal::op::InnerContent::List( + crate::internal::container::list::list_op::InnerListOp::Delete( DeleteSpanWithId::new( ID::new(arenas.peers()[peer_idx], cnt as Counter), pos as isize, @@ -386,8 +386,8 @@ pub(crate) fn decode_op( from, from_idx, lamport, - } => crate::op::InnerContent::List( - crate::container::list::list_op::InnerListOp::Move { + } => crate::internal::op::InnerContent::List( + crate::internal::container::list::list_op::InnerListOp::Move { from: from as u32, elem_id: IdLp::new(arenas.peers()[from_idx], lamport as Lamport), to: prop as u32, @@ -397,8 +397,8 @@ pub(crate) fn decode_op( peer_idx, lamport, value, - } => crate::op::InnerContent::List( - crate::container::list::list_op::InnerListOp::Set { + } => crate::internal::op::InnerContent::List( + crate::internal::container::list::list_op::InnerListOp::Set { elem_id: IdLp::new(arenas.peers()[peer_idx], lamport as Lamport), value, }, @@ -408,12 +408,12 @@ pub(crate) fn decode_op( } #[cfg(feature = "counter")] ContainerType::Counter => match value { - Value::F64(c) => crate::op::InnerContent::Future(FutureInnerContent::Counter(c)), - Value::I64(c) => crate::op::InnerContent::Future(FutureInnerContent::Counter(c as f64)), + Value::F64(c) => crate::internal::op::InnerContent::Future(FutureInnerContent::Counter(c)), + Value::I64(c) => crate::internal::op::InnerContent::Future(FutureInnerContent::Counter(c as f64)), _ => unreachable!(), }, // NOTE: The future container type need also try to parse the unknown type - ContainerType::Unknown(_) => crate::op::InnerContent::Future(FutureInnerContent::Unknown { + ContainerType::Unknown(_) => crate::internal::op::InnerContent::Future(FutureInnerContent::Unknown { prop, value: Box::new(value.into_owned()), }), @@ -441,7 +441,7 @@ mod test { use loro_common::LoroValue; use rustc_hash::FxHashSet; - use crate::{ + use crate::internal::{ encoding::{ arena::EncodedRegisters, value::{ValueReader, ValueWriter}, diff --git a/crates/loro-internal/src/encoding/shallow_snapshot.rs b/crates/loro/src/internal/encoding/shallow_snapshot.rs similarity index 97% rename from crates/loro-internal/src/encoding/shallow_snapshot.rs rename to crates/loro/src/internal/encoding/shallow_snapshot.rs index bb9a6cf52..ecc6cf53a 100644 --- a/crates/loro-internal/src/encoding/shallow_snapshot.rs +++ b/crates/loro/src/internal/encoding/shallow_snapshot.rs @@ -4,7 +4,7 @@ use std::collections::BTreeSet; use loro_common::{ContainerID, ContainerType, LoroEncodeError, ID}; -use crate::{ +use crate::internal::{ container::list::list_op::InnerListOp, dag::DagUtils, encoding::fast_snapshot::{Snapshot, _encode_snapshot}, @@ -43,7 +43,7 @@ pub(crate) fn export_shallow_snapshot_inner( #[cfg(debug_assertions)] { - use crate::dag::Dag; + use crate::internal::dag::Dag; if !start_from.is_empty() { assert!(start_from.len() == 1); let id = start_from.as_single().unwrap(); @@ -212,7 +212,7 @@ fn cids_to_bytes( /// /// It should be the LCA of the user given version and the latest version. /// Otherwise, users cannot replay the history from the initial version till the latest version. -fn calc_shallow_doc_start(oplog: &crate::OpLog, frontiers: &Frontiers) -> Frontiers { +fn calc_shallow_doc_start(oplog: &crate::internal::OpLog, frontiers: &Frontiers) -> Frontiers { // start is the real start frontiers let (mut start, _) = oplog .dag() @@ -228,7 +228,7 @@ fn calc_shallow_doc_start(oplog: &crate::OpLog, frontiers: &Frontiers) -> Fronti for id in start.iter() { let mut processed = false; if let Some(op) = oplog.get_op_that_includes(id) { - if let crate::op::InnerContent::List(InnerListOp::StyleStart { .. }) = &op.content { + if let crate::internal::op::InnerContent::List(InnerListOp::StyleStart { .. }) = &op.content { // StyleStart and StyleEnd operations must be kept together in the GC snapshot. // Splitting them could lead to an weird document state that cannot be // properly encoded. To ensure they stay together, we advance the frontier by diff --git a/crates/loro-internal/src/encoding/value.rs b/crates/loro/src/internal/encoding/value.rs similarity index 99% rename from crates/loro-internal/src/encoding/value.rs rename to crates/loro/src/internal/encoding/value.rs index 05c21dff3..cf7c1baeb 100644 --- a/crates/loro-internal/src/encoding/value.rs +++ b/crates/loro/src/internal/encoding/value.rs @@ -8,7 +8,7 @@ use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; use std::sync::Arc; -use crate::{ +use crate::internal::{ change::Lamport, container::tree::tree_op::TreeOp, encoding::outdated_encode_reordered::MAX_COLLECTION_SIZE, }; @@ -26,7 +26,7 @@ pub trait ValueDecodedArenasTrait { positions: &[Vec], op: super::value::EncodedTreeMove, id: ID, - ) -> LoroResult; + ) -> LoroResult; } pub trait ValueEncodeRegister { diff --git a/crates/loro-internal/src/encoding/value_register.rs b/crates/loro/src/internal/encoding/value_register.rs similarity index 100% rename from crates/loro-internal/src/encoding/value_register.rs rename to crates/loro/src/internal/encoding/value_register.rs diff --git a/crates/loro-internal/src/error.rs b/crates/loro/src/internal/error.rs similarity index 100% rename from crates/loro-internal/src/error.rs rename to crates/loro/src/internal/error.rs diff --git a/crates/loro-internal/src/estimated_size.rs b/crates/loro/src/internal/estimated_size.rs similarity index 100% rename from crates/loro-internal/src/estimated_size.rs rename to crates/loro/src/internal/estimated_size.rs diff --git a/crates/loro-internal/src/event.rs b/crates/loro/src/internal/event.rs similarity index 97% rename from crates/loro-internal/src/event.rs rename to crates/loro/src/internal/event.rs index 9430c3f52..78ff07222 100644 --- a/crates/loro-internal/src/event.rs +++ b/crates/loro/src/internal/event.rs @@ -5,7 +5,7 @@ use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; use smallvec::SmallVec; -use crate::{ +use crate::internal::{ container::richtext::richtext_state::RichtextStateChunk, delta::{Delta, MapDelta, Meta, MovableListInnerDelta, ResolvedMapDelta, TreeDelta, TreeDiff}, diff_calc::DiffMode, @@ -19,7 +19,7 @@ use std::{borrow::Cow, hash::Hash}; use loro_common::{ContainerID, LoroValue, TreeID}; -use crate::{container::idx::ContainerIdx, version::Frontiers}; +use crate::internal::{container::idx::ContainerIdx, version::Frontiers}; #[derive(Debug, Clone)] pub struct ContainerDiff { @@ -258,11 +258,11 @@ impl Meta for ListDeltaMeta { fn compose( &mut self, other: &Self, - type_pair: (crate::delta::DeltaType, crate::delta::DeltaType), + type_pair: (crate::internal::delta::DeltaType, crate::internal::delta::DeltaType), ) { // We can't have two Some because we don't have `move_from` for Retain. // And this function is only called when composing a insert/retain with a retain. - if let (crate::delta::DeltaType::Insert, crate::delta::DeltaType::Insert) = type_pair { + if let (crate::internal::delta::DeltaType::Insert, crate::internal::delta::DeltaType::Insert) = type_pair { unreachable!() } @@ -501,7 +501,7 @@ mod test { use itertools::Itertools; use loro_common::LoroValue; - use crate::{cursor::PosType, ApplyDiff, LoroDoc}; + use crate::internal::{cursor::PosType, ApplyDiff, LoroDoc}; #[test] fn test_text_event() { diff --git a/crates/loro-internal/src/fork.rs b/crates/loro/src/internal/fork.rs similarity index 94% rename from crates/loro-internal/src/fork.rs rename to crates/loro/src/internal/fork.rs index 15b10ac0f..bf76ad6b6 100644 --- a/crates/loro-internal/src/fork.rs +++ b/crates/loro/src/internal/fork.rs @@ -30,13 +30,13 @@ //! use std::borrow::Cow; -use crate::{version::Frontiers, LoroDoc}; +use crate::internal::{version::Frontiers, LoroDoc}; impl LoroDoc { /// Creates a new LoroDoc at a specified version (Frontiers) pub fn fork_at(&self, frontiers: &Frontiers) -> Self { let bytes = self - .export(crate::loro::ExportMode::SnapshotAt { + .export(crate::internal::loro::ExportMode::SnapshotAt { version: Cow::Borrowed(frontiers), }) .unwrap(); diff --git a/crates/loro-internal/src/fuzz.rs b/crates/loro/src/internal/fuzz.rs similarity index 100% rename from crates/loro-internal/src/fuzz.rs rename to crates/loro/src/internal/fuzz.rs diff --git a/crates/loro-internal/src/handler.rs b/crates/loro/src/internal/handler.rs similarity index 98% rename from crates/loro-internal/src/handler.rs rename to crates/loro/src/internal/handler.rs index 3b43329c9..cb5b9442f 100644 --- a/crates/loro-internal/src/handler.rs +++ b/crates/loro/src/internal/handler.rs @@ -1,6 +1,6 @@ use super::{state::DocState, txn::Transaction}; -use crate::sync::Mutex; -use crate::{ +use crate::internal::sync::Mutex; +use crate::internal::{ container::{ idx::ContainerIdx, list::list_op::{DeleteSpan, DeleteSpanWithId, ListOp}, @@ -28,7 +28,7 @@ use serde::{Deserialize, Serialize}; use std::{borrow::Cow, cmp::Reverse, collections::BinaryHeap, fmt::Debug, ops::Deref, sync::Arc}; use tracing::{error, instrument}; -pub use crate::diff::diff_impl::UpdateOptions; +pub use crate::internal::diff::diff_impl::UpdateOptions; pub use tree::TreeHandler; mod movable_list_apply_delta; mod tree; @@ -440,15 +440,15 @@ impl TextDelta { impl From<&DeltaItem> for TextDelta { fn from(value: &DeltaItem) -> Self { match value { - crate::delta::DeltaItem::Retain { retain, attributes } => TextDelta::Retain { + crate::internal::delta::DeltaItem::Retain { retain, attributes } => TextDelta::Retain { retain: *retain, attributes: attributes.to_option_map(), }, - crate::delta::DeltaItem::Insert { insert, attributes } => TextDelta::Insert { + crate::internal::delta::DeltaItem::Insert { insert, attributes } => TextDelta::Insert { insert: insert.to_string(), attributes: attributes.to_option_map(), }, - crate::delta::DeltaItem::Delete { + crate::internal::delta::DeltaItem::Delete { delete, attributes: _, } => TextDelta::Delete { delete: *delete }, @@ -1864,7 +1864,7 @@ impl TextHandler { txn.apply_local_op( inner.container_idx, - crate::op::RawOpContent::List(crate::container::list::list_op::ListOp::Insert { + crate::internal::op::RawOpContent::List(crate::internal::container::list::list_op::ListOp::Insert { slice: ListSlice::RawStr { str: Cow::Borrowed(s), unicode_len, @@ -1936,7 +1936,7 @@ impl TextHandler { let event_start = event_end - range.event_len as isize; txn.apply_local_op( inner.container_idx, - crate::op::RawOpContent::List(ListOp::Delete(DeleteSpanWithId::new( + crate::internal::op::RawOpContent::List(ListOp::Delete(DeleteSpanWithId::new( range.id_start, range.entity_start as isize, range.entity_len() as isize, @@ -2140,7 +2140,7 @@ impl TextHandler { drop(doc_state); txn.apply_local_op( inner.container_idx, - crate::op::RawOpContent::List(ListOp::StyleStart { + crate::internal::op::RawOpContent::List(ListOp::StyleStart { start: entity_start as u32, end: entity_end as u32, key: key.clone(), @@ -2150,14 +2150,14 @@ impl TextHandler { EventHint::Mark { start: event_start as u32, end: event_end as u32, - style: crate::container::richtext::Style { key, data: value }, + style: crate::internal::container::richtext::Style { key, data: value }, }, &inner.doc, )?; txn.apply_local_op( inner.container_idx, - crate::op::RawOpContent::List(ListOp::StyleEnd), + crate::internal::op::RawOpContent::List(ListOp::StyleEnd), EventHint::MarkEnd, &inner.doc, )?; @@ -2635,7 +2635,7 @@ impl ListHandler { txn.apply_local_op( inner.container_idx, - crate::op::RawOpContent::List(crate::container::list::list_op::ListOp::Insert { + crate::internal::op::RawOpContent::List(crate::internal::container::list::list_op::ListOp::Insert { slice: ListSlice::RawData(Cow::Owned(vec![v.clone()])), pos, }), @@ -2719,7 +2719,7 @@ impl ListHandler { let v = LoroValue::Container(container_id.clone()); txn.apply_local_op( inner.container_idx, - crate::op::RawOpContent::List(crate::container::list::list_op::ListOp::Insert { + crate::internal::op::RawOpContent::List(crate::internal::container::list::list_op::ListOp::Insert { slice: ListSlice::RawData(Cow::Owned(vec![v.clone()])), pos, }), @@ -2765,7 +2765,7 @@ impl ListHandler { for id in ids.into_iter() { txn.apply_local_op( inner.container_idx, - crate::op::RawOpContent::List(ListOp::Delete(DeleteSpanWithId::new( + crate::internal::op::RawOpContent::List(ListOp::Delete(DeleteSpanWithId::new( id.id(), pos as isize, 1, @@ -2955,7 +2955,7 @@ impl ListHandler { &self, delta: loro_delta::DeltaRope< loro_delta::array_vec::ArrayVec, - crate::event::ListDeltaMeta, + crate::internal::event::ListDeltaMeta, >, on_container_remap: &mut dyn FnMut(ContainerID, ContainerID), ) -> LoroResult<()> { @@ -3098,7 +3098,7 @@ impl MovableListHandler { let inner = self.inner.try_attached_state()?; txn.apply_local_op( inner.container_idx, - crate::op::RawOpContent::List(crate::container::list::list_op::ListOp::Insert { + crate::internal::op::RawOpContent::List(crate::internal::container::list::list_op::ListOp::Insert { slice: ListSlice::RawData(Cow::Owned(vec![v.clone()])), pos: op_index, }), @@ -3175,7 +3175,7 @@ impl MovableListHandler { let inner = self.inner.try_attached_state()?; txn.apply_local_op( inner.container_idx, - crate::op::RawOpContent::List(crate::container::list::list_op::ListOp::Move { + crate::internal::op::RawOpContent::List(crate::internal::container::list::list_op::ListOp::Move { from: op_from as u32, to: op_to as u32, elem_id: elem_id.to_id(), @@ -3293,7 +3293,7 @@ impl MovableListHandler { let inner = self.inner.try_attached_state()?; txn.apply_local_op( inner.container_idx, - crate::op::RawOpContent::List(crate::container::list::list_op::ListOp::Insert { + crate::internal::op::RawOpContent::List(crate::internal::container::list::list_op::ListOp::Insert { slice: ListSlice::RawData(Cow::Owned(vec![v.clone()])), pos: op_index, }), @@ -3346,7 +3346,7 @@ impl MovableListHandler { unreachable!() }; - let op = crate::op::RawOpContent::List(crate::container::list::list_op::ListOp::Set { + let op = crate::internal::op::RawOpContent::List(crate::internal::container::list::list_op::ListOp::Set { elem_id: elem_id.to_id(), value: value.clone(), }); @@ -3396,7 +3396,7 @@ impl MovableListHandler { let inner = self.inner.try_attached_state()?; txn.apply_local_op( inner.container_idx, - crate::op::RawOpContent::List(crate::container::list::list_op::ListOp::Set { + crate::internal::op::RawOpContent::List(crate::internal::container::list::list_op::ListOp::Set { elem_id: elem_id.to_id(), value: v.clone(), }), @@ -3459,7 +3459,7 @@ impl MovableListHandler { for (id, op_pos) in ids.into_iter().zip(new_poses.into_iter()) { txn.apply_local_op( inner.container_idx, - crate::op::RawOpContent::List(ListOp::Delete(DeleteSpanWithId::new( + crate::internal::op::RawOpContent::List(ListOp::Delete(DeleteSpanWithId::new( id, op_pos as isize, 1, @@ -3797,7 +3797,7 @@ impl MapHandler { let inner = this.inner.try_attached_state()?; txn.apply_local_op( inner.container_idx, - crate::op::RawOpContent::Map(crate::container::map::MapSet { + crate::internal::op::RawOpContent::Map(crate::internal::container::map::MapSet { key: key.into(), value: Some(value.clone()), }), @@ -3833,7 +3833,7 @@ impl MapHandler { let inner = self.inner.try_attached_state()?; txn.apply_local_op( inner.container_idx, - crate::op::RawOpContent::Map(crate::container::map::MapSet { + crate::internal::op::RawOpContent::Map(crate::internal::container::map::MapSet { key: key.into(), value: Some(value.clone()), }), @@ -3871,7 +3871,7 @@ impl MapHandler { let container_id = ContainerID::new_normal(id, child.kind()); txn.apply_local_op( inner.container_idx, - crate::op::RawOpContent::Map(crate::container::map::MapSet { + crate::internal::op::RawOpContent::Map(crate::internal::container::map::MapSet { key: key.into(), value: Some(LoroValue::Container(container_id.clone())), }), @@ -3900,7 +3900,7 @@ impl MapHandler { let inner = self.inner.try_attached_state()?; txn.apply_local_op( inner.container_idx, - crate::op::RawOpContent::Map(crate::container::map::MapSet { + crate::internal::op::RawOpContent::Map(crate::internal::container::map::MapSet { key: key.into(), value: None, }), @@ -4178,7 +4178,7 @@ pub mod counter { use loro_common::LoroResult; - use crate::{ + use crate::internal::{ txn::{EventHint, Transaction}, HandlerTrait, }; @@ -4223,7 +4223,7 @@ pub mod counter { let inner = self.inner.try_attached_state()?; txn.apply_local_op( inner.container_idx, - crate::op::RawOpContent::Counter(n), + crate::internal::op::RawOpContent::Counter(n), EventHint::Counter(n), &inner.doc, ) @@ -4255,7 +4255,7 @@ pub mod counter { matches!(&self.inner, MaybeDetached::Attached(..)) } - fn attached_handler(&self) -> Option<&crate::BasicHandler> { + fn attached_handler(&self) -> Option<&crate::internal::BasicHandler> { self.inner.attached_handler() } @@ -4290,8 +4290,8 @@ pub mod counter { fn attach( &self, - txn: &mut crate::txn::Transaction, - parent: &crate::BasicHandler, + txn: &mut crate::internal::txn::Transaction, + parent: &crate::internal::BasicHandler, self_id: loro_common::ContainerID, ) -> loro_common::LoroResult { match &self.inner { @@ -4324,7 +4324,7 @@ pub mod counter { } } - fn doc(&self) -> Option { + fn doc(&self) -> Option { match &self.inner { MaybeDetached::Detached(_) => None, MaybeDetached::Attached(a) => Some(a.doc()), @@ -4337,12 +4337,12 @@ pub mod counter { mod test { use super::{HandlerTrait, TextDelta}; - use crate::cursor::PosType; - use crate::loro::ExportMode; - use crate::state::TreeParentId; - use crate::version::Frontiers; - use crate::LoroDoc; - use crate::{fx_map, ToJson}; + use crate::internal::cursor::PosType; + use crate::internal::loro::ExportMode; + use crate::internal::state::TreeParentId; + use crate::internal::version::Frontiers; + use crate::internal::LoroDoc; + use crate::internal::{fx_map, ToJson}; use loro_common::{LoroValue, ID}; use serde_json::json; diff --git a/crates/loro-internal/src/handler/movable_list_apply_delta.rs b/crates/loro/src/internal/handler/movable_list_apply_delta.rs similarity index 96% rename from crates/loro-internal/src/handler/movable_list_apply_delta.rs rename to crates/loro/src/internal/handler/movable_list_apply_delta.rs index dc948de75..cf47e1fa8 100644 --- a/crates/loro-internal/src/handler/movable_list_apply_delta.rs +++ b/crates/loro/src/internal/handler/movable_list_apply_delta.rs @@ -31,7 +31,7 @@ impl MovableListHandler { &self, delta: loro_delta::DeltaRope< loro_delta::array_vec::ArrayVec, - crate::event::ListDeltaMeta, + crate::internal::event::ListDeltaMeta, >, container_remap: &mut FxHashMap, ) -> LoroResult<()> { @@ -141,7 +141,7 @@ impl MovableListHandler { &self, delta: &loro_delta::DeltaRope< loro_delta::array_vec::ArrayVec, - crate::event::ListDeltaMeta, + crate::internal::event::ListDeltaMeta, >, ) -> FxHashMap { let mut index = 0; @@ -212,7 +212,7 @@ impl MovableListHandler { fn process_replacements( &self, values: &loro_delta::array_vec::ArrayVec, - attr: &crate::event::ListDeltaMeta, + attr: &crate::internal::event::ListDeltaMeta, context: &mut ReplacementContext, ) -> LoroResult<()> { for v in values.iter() { @@ -238,7 +238,7 @@ impl MovableListHandler { fn apply_insertion( &self, - attr: &crate::event::ListDeltaMeta, + attr: &crate::internal::event::ListDeltaMeta, context: &mut ReplacementContext<'_>, mut old_id: ContainerID, ) -> Result<(), LoroError> { @@ -253,7 +253,7 @@ impl MovableListHandler { if let Some(old_index) = context.to_delete.remove(&old_id) { if old_index > *context.index { ensure_cov::notify_cov( - "loro_internal::handler::movable_list_apply_delta::process_replacements::mov_0", + "loro::internal::handler::movable_list_apply_delta::process_replacements::mov_0", ); self.mov(old_index, *context.index)?; context.next_deleted.push(Reverse(old_index)); @@ -261,7 +261,7 @@ impl MovableListHandler { *context.index_shift += 1; } else { ensure_cov::notify_cov( - "loro_internal::handler::movable_list_apply_delta::process_replacements::mov_1", + "loro::internal::handler::movable_list_apply_delta::process_replacements::mov_1", ); self.mov(old_index, *context.index - 1)?; } diff --git a/crates/loro-internal/src/handler/text_update.rs b/crates/loro/src/internal/handler/text_update.rs similarity index 99% rename from crates/loro-internal/src/handler/text_update.rs rename to crates/loro/src/internal/handler/text_update.rs index 6202262d4..1ef549b4b 100644 --- a/crates/loro-internal/src/handler/text_update.rs +++ b/crates/loro/src/internal/handler/text_update.rs @@ -3,7 +3,7 @@ use std::{char, sync::Arc}; use itertools::Itertools; use rustc_hash::FxHashMap; -use crate::diff::DiffHandler; +use crate::internal::diff::DiffHandler; use super::TextHandler; diff --git a/crates/loro-internal/src/handler/tree.rs b/crates/loro/src/internal/handler/tree.rs similarity index 98% rename from crates/loro-internal/src/handler/tree.rs rename to crates/loro/src/internal/handler/tree.rs index 36e5829e2..79decef7b 100644 --- a/crates/loro-internal/src/handler/tree.rs +++ b/crates/loro/src/internal/handler/tree.rs @@ -8,7 +8,7 @@ use loro_common::{ use rustc_hash::FxHashMap; use smallvec::smallvec; -use crate::{ +use crate::internal::{ container::tree::tree_op::TreeOp, delta::{TreeDiffItem, TreeExternalDiff}, state::{ @@ -260,7 +260,7 @@ impl HandlerTrait for TreeHandler { } } - fn doc(&self) -> Option { + fn doc(&self) -> Option { match &self.inner { MaybeDetached::Detached(_) => None, MaybeDetached::Attached(a) => Some(a.doc()), @@ -310,7 +310,7 @@ impl TreeHandler { }; txn.apply_local_op( inner.container_idx, - crate::op::RawOpContent::Tree(Arc::new(TreeOp::Delete { target })), + crate::internal::op::RawOpContent::Tree(Arc::new(TreeOp::Delete { target })), EventHint::Tree(smallvec![TreeDiffItem { target, action: TreeExternalDiff::Delete { @@ -410,7 +410,7 @@ impl TreeHandler { txn.apply_local_op( inner.container_idx, - crate::op::RawOpContent::Tree(Arc::new(TreeOp::Create { + crate::internal::op::RawOpContent::Tree(Arc::new(TreeOp::Create { target, parent: parent.tree_id(), position: position.clone(), @@ -493,7 +493,7 @@ impl TreeHandler { let inner = self.inner.try_attached_state()?; txn.apply_local_op( inner.container_idx, - crate::op::RawOpContent::Tree(Arc::new(TreeOp::Move { + crate::internal::op::RawOpContent::Tree(Arc::new(TreeOp::Move { target, parent: parent.tree_id(), position: position.clone(), @@ -672,7 +672,7 @@ impl TreeHandler { ) -> LoroResult { txn.apply_local_op( inner.container_idx, - crate::op::RawOpContent::Tree(Arc::new(TreeOp::Create { + crate::internal::op::RawOpContent::Tree(Arc::new(TreeOp::Create { target: tree_id, parent: parent.tree_id(), position: position.clone(), @@ -703,7 +703,7 @@ impl TreeHandler { ) -> LoroResult<()> { txn.apply_local_op( inner.container_idx, - crate::op::RawOpContent::Tree(Arc::new(TreeOp::Move { + crate::internal::op::RawOpContent::Tree(Arc::new(TreeOp::Move { target, parent: parent.tree_id(), position: position.clone(), diff --git a/crates/loro-internal/src/history_cache.rs b/crates/loro/src/internal/history_cache.rs similarity index 97% rename from crates/loro-internal/src/history_cache.rs rename to crates/loro/src/internal/history_cache.rs index 490f8a9d8..e066189fd 100644 --- a/crates/loro-internal/src/history_cache.rs +++ b/crates/loro/src/internal/history_cache.rs @@ -5,7 +5,7 @@ use std::{ sync::Arc, }; -use crate::sync::Mutex; +use crate::internal::sync::Mutex; use either::Either; use enum_as_inner::EnumAsInner; use enum_dispatch::enum_dispatch; @@ -16,7 +16,7 @@ use loro_common::{ use rle::HasLength; use rustc_hash::FxHashMap; -use crate::{ +use crate::internal::{ change::{Change, Lamport}, container::{ idx::ContainerIdx, list::list_op::InnerListOp, @@ -199,7 +199,7 @@ impl ContainerHistoryCache { if let Some(state) = self.shallow_root_state.as_ref() { ensure_cov::notify_cov( - "loro_internal::history_cache::init_cache_by_visit_all_change_slow::visit_gc", + "loro::internal::history_cache::init_cache_by_visit_all_change_slow::visit_gc", ); let mut store = state.store.lock().unwrap(); for (idx, c) in store.iter_all_containers_mut() { @@ -217,7 +217,7 @@ impl ContainerHistoryCache { let state = c.get_state_mut(*idx, default_ctx); match state { - crate::state::State::MapState(m) => { + crate::internal::state::State::MapState(m) => { if for_checkout { let c = self.for_checkout.as_mut().unwrap(); for (k, v) in m.iter() { @@ -225,7 +225,7 @@ impl ContainerHistoryCache { } } } - crate::state::State::MovableListState(l) => { + crate::internal::state::State::MovableListState(l) => { for (idlp, elem) in l.elements() { if for_checkout { let c = self.for_checkout.as_mut().unwrap(); @@ -239,7 +239,7 @@ impl ContainerHistoryCache { } } } - crate::state::State::TreeState(t) => { + crate::internal::state::State::TreeState(t) => { if for_importing { let c = self.for_importing.as_mut().unwrap(); let tree = c.entry(*idx).or_insert_with(|| { @@ -306,7 +306,7 @@ impl ContainerHistoryCache { idx: ContainerIdx, target_span: loro_common::IdSpan, ) -> Vec { - ensure_cov::notify_cov("loro_internal::history_cache::find_text_chunks_in"); + ensure_cov::notify_cov("loro::internal::history_cache::find_text_chunks_in"); let Some(state) = self.shallow_root_state.as_ref() else { return Vec::new(); }; @@ -346,7 +346,7 @@ impl ContainerHistoryCache { idx: ContainerIdx, target_span: loro_common::IdSpan, ) -> Vec { - ensure_cov::notify_cov("loro_internal::history_cache::find_list_chunks_in"); + ensure_cov::notify_cov("loro::internal::history_cache::find_list_chunks_in"); let Some(state) = self.shallow_root_state.as_ref() else { return Vec::new(); }; @@ -366,7 +366,7 @@ impl ContainerHistoryCache { let mut ans = Vec::with_capacity(target_span.atom_len()); match list_state { - crate::state::State::ListState(list) => { + crate::internal::state::State::ListState(list) => { for v in list.iter_with_id() { if target_span.contains(v.id.id()) { ans.push(SliceWithId { @@ -377,7 +377,7 @@ impl ContainerHistoryCache { } } } - crate::state::State::MovableListState(list) => { + crate::internal::state::State::MovableListState(list) => { for (move_id, elem_id, v) in list.iter_with_last_move_id_and_elem_id() { if target_span.contains(move_id.id()) { ans.push(SliceWithId { @@ -708,7 +708,7 @@ impl HistoryCacheTrait for MovableListHistoryCache { let cur_id = op.id_full(); match &op.op().content { InnerContent::List(l) => match l { - crate::container::list::list_op::InnerListOp::Move { elem_id, .. } => { + crate::internal::container::list::list_op::InnerListOp::Move { elem_id, .. } => { self.move_set.insert(MovableListInnerDeltaEntry { element_lamport: elem_id.lamport, element_peer: elem_id.peer, @@ -717,7 +717,7 @@ impl HistoryCacheTrait for MovableListHistoryCache { counter: cur_id.counter, }); } - crate::container::list::list_op::InnerListOp::Set { elem_id, .. } => { + crate::internal::container::list::list_op::InnerListOp::Set { elem_id, .. } => { self.set_set.insert(MovableListSetDeltaEntry { element_lamport: elem_id.lamport, element_peer: elem_id.peer, diff --git a/crates/loro-internal/src/id.rs b/crates/loro/src/internal/id.rs similarity index 100% rename from crates/loro-internal/src/id.rs rename to crates/loro/src/internal/id.rs diff --git a/crates/loro-internal/src/jsonpath/ast.rs b/crates/loro/src/internal/jsonpath/ast.rs similarity index 98% rename from crates/loro-internal/src/jsonpath/ast.rs rename to crates/loro/src/internal/jsonpath/ast.rs index f484755d2..6b2320f30 100644 --- a/crates/loro-internal/src/jsonpath/ast.rs +++ b/crates/loro/src/internal/jsonpath/ast.rs @@ -1,5 +1,5 @@ -use crate::jsonpath::errors::JSONPathError; -use crate::jsonpath::JSONPathParser; +use crate::internal::jsonpath::errors::JSONPathError; +use crate::internal::jsonpath::JSONPathParser; use std::fmt::{self, Write}; #[derive(Debug, Clone)] diff --git a/crates/loro-internal/src/jsonpath/errors.rs b/crates/loro/src/internal/jsonpath/errors.rs similarity index 100% rename from crates/loro-internal/src/jsonpath/errors.rs rename to crates/loro/src/internal/jsonpath/errors.rs diff --git a/crates/loro-internal/src/jsonpath/jsonpath.pest b/crates/loro/src/internal/jsonpath/jsonpath.pest similarity index 100% rename from crates/loro-internal/src/jsonpath/jsonpath.pest rename to crates/loro/src/internal/jsonpath/jsonpath.pest diff --git a/crates/loro-internal/src/jsonpath/jsonpath_impl.rs b/crates/loro/src/internal/jsonpath/jsonpath_impl.rs similarity index 99% rename from crates/loro-internal/src/jsonpath/jsonpath_impl.rs rename to crates/loro/src/internal/jsonpath/jsonpath_impl.rs index 4c2c30082..943448881 100644 --- a/crates/loro-internal/src/jsonpath/jsonpath_impl.rs +++ b/crates/loro/src/internal/jsonpath/jsonpath_impl.rs @@ -1,11 +1,11 @@ -use crate::handler::{ +use crate::internal::handler::{ Handler, ListHandler, MapHandler, MovableListHandler, TextHandler, TreeHandler, ValueOrHandler, }; -use crate::jsonpath::ast::{ +use crate::internal::jsonpath::ast::{ ComparisonOperator, FilterExpression, LogicalOperator, Segment, Selector, }; -use crate::jsonpath::JSONPathParser; -use crate::{HandlerTrait, LoroDoc}; +use crate::internal::jsonpath::JSONPathParser; +use crate::internal::{HandlerTrait, LoroDoc}; use loro_common::{ContainerID, LoroValue}; use std::ops::ControlFlow; use thiserror::Error; @@ -843,7 +843,7 @@ impl PathValue for LoroValue { #[cfg(test)] mod tests { use super::*; - use crate::{ListHandler, LoroDoc, LoroValue, MapHandler}; + use crate::internal::{ListHandler, LoroDoc, LoroValue, MapHandler}; fn setup_test_doc() -> LoroDoc { let doc = LoroDoc::new(); diff --git a/crates/loro-internal/src/jsonpath/mod.rs b/crates/loro/src/internal/jsonpath/mod.rs similarity index 100% rename from crates/loro-internal/src/jsonpath/mod.rs rename to crates/loro/src/internal/jsonpath/mod.rs diff --git a/crates/loro-internal/src/jsonpath/parser.rs b/crates/loro/src/internal/jsonpath/parser.rs similarity index 99% rename from crates/loro-internal/src/jsonpath/parser.rs rename to crates/loro/src/internal/jsonpath/parser.rs index 60425fe49..67f787f22 100644 --- a/crates/loro-internal/src/jsonpath/parser.rs +++ b/crates/loro/src/internal/jsonpath/parser.rs @@ -10,14 +10,14 @@ use std::{collections::HashMap, ops::RangeInclusive}; use pest::{iterators::Pair, Parser}; use pest_derive::Parser; -use crate::jsonpath::ast::{ +use crate::internal::jsonpath::ast::{ ComparisonOperator, FilterExpression, LogicalOperator, Segment, Selector, }; -use crate::jsonpath::errors::JSONPathError; -use crate::jsonpath::Query; +use crate::internal::jsonpath::errors::JSONPathError; +use crate::internal::jsonpath::Query; #[derive(Parser)] -#[grammar = "jsonpath/jsonpath.pest"] +#[grammar = "internal/jsonpath/jsonpath.pest"] struct JSONPath; #[derive(Debug)] diff --git a/crates/loro-internal/src/jsonpath/subscription.rs b/crates/loro/src/internal/jsonpath/subscription.rs similarity index 99% rename from crates/loro-internal/src/jsonpath/subscription.rs rename to crates/loro/src/internal/jsonpath/subscription.rs index 599bc18a1..50eddb98a 100644 --- a/crates/loro-internal/src/jsonpath/subscription.rs +++ b/crates/loro/src/internal/jsonpath/subscription.rs @@ -29,7 +29,7 @@ use std::sync::Arc; use loro_common::TreeID; use smallvec::SmallVec; -use crate::{ +use crate::internal::{ event::{Diff, Index}, jsonpath::{ ast::{Query, Segment, Selector}, @@ -356,7 +356,7 @@ impl LoroDoc { #[cfg(test)] mod tests { use super::*; - use crate::{LoroDoc, MapHandler}; + use crate::internal::{LoroDoc, MapHandler}; use std::sync::atomic::{AtomicUsize, Ordering}; fn make_book( diff --git a/crates/loro-internal/src/kv_store.rs b/crates/loro/src/internal/kv_store.rs similarity index 99% rename from crates/loro-internal/src/kv_store.rs rename to crates/loro/src/internal/kv_store.rs index 9cd773a2c..08dac687e 100644 --- a/crates/loro-internal/src/kv_store.rs +++ b/crates/loro/src/internal/kv_store.rs @@ -1,4 +1,4 @@ -use crate::sync::Mutex; +use crate::internal::sync::Mutex; use bytes::Bytes; pub use loro_kv_store::compress::CompressionType; pub use loro_kv_store::MemKvStore; diff --git a/crates/loro-internal/src/lock.rs b/crates/loro/src/internal/lock.rs similarity index 97% rename from crates/loro-internal/src/lock.rs rename to crates/loro/src/internal/lock.rs index aedd5962a..6b103f9ed 100644 --- a/crates/loro-internal/src/lock.rs +++ b/crates/loro/src/internal/lock.rs @@ -12,11 +12,11 @@ //! - Violations are detected and reported with helpful panics that include the //! callsite (via `#[track_caller]`) and a backtrace on release-order errors. //! -//! The actual locking is backed by [`crate::sync::Mutex`], which resolves to +//! The actual locking is backed by [`crate::internal::sync::Mutex`], which resolves to //! `std::sync::Mutex` in normal builds and `loom::sync::Mutex` under loom. This //! keeps the code testable with loom while maintaining the same API. -use crate::sync::ThreadLocal; -use crate::sync::{Mutex, MutexGuard}; +use crate::internal::sync::ThreadLocal; +use crate::internal::sync::{Mutex, MutexGuard}; use std::backtrace::Backtrace; use std::fmt::{Debug, Display}; use std::ops::{Deref, DerefMut}; @@ -31,7 +31,7 @@ use std::sync::Arc; /// is greater than or equal to this lock’s kind. Release order is also checked; /// dropping the guard out of LIFO order results in a panic. /// -/// This type wraps [`crate::sync::Mutex`], so it remains compatible with loom-based +/// This type wraps [`crate::internal::sync::Mutex`], so it remains compatible with loom-based /// concurrency testing. #[derive(Debug)] pub struct LoroMutex { diff --git a/crates/loro-internal/src/loro.rs b/crates/loro/src/internal/loro.rs similarity index 97% rename from crates/loro-internal/src/loro.rs rename to crates/loro/src/internal/loro.rs index db696acd0..f4966e72d 100644 --- a/crates/loro-internal/src/loro.rs +++ b/crates/loro/src/internal/loro.rs @@ -1,10 +1,10 @@ -use crate::encoding::json_schema::{encode_change, export_json_in_id_span}; -pub use crate::encoding::ExportMode; -use crate::pre_commit::{FirstCommitFromPeerCallback, FirstCommitFromPeerPayload}; -pub use crate::state::analyzer::{ContainerAnalysisInfo, DocAnalysis}; -use crate::sync::AtomicBool; -pub(crate) use crate::LoroDocInner; -use crate::{ +use crate::internal::encoding::json_schema::{encode_change, export_json_in_id_span}; +pub use crate::internal::encoding::ExportMode; +use crate::internal::pre_commit::{FirstCommitFromPeerCallback, FirstCommitFromPeerPayload}; +pub use crate::internal::state::analyzer::{ContainerAnalysisInfo, DocAnalysis}; +use crate::internal::sync::AtomicBool; +pub(crate) use crate::internal::LoroDocInner; +use crate::internal::{ arena::SharedArena, change::Timestamp, configure::{Configure, DefaultRandom, SecureRandomGenerator, StyleConfig}, @@ -36,9 +36,9 @@ use crate::{ ChangeMeta, DocDiff, HandlerTrait, InternalString, ListHandler, LoroDoc, LoroError, MapHandler, VersionVector, }; -use crate::{change::ChangeRef, lock::LockKind}; -use crate::{lock::LoroMutexGuard, pre_commit::PreCommitCallback}; -use crate::{ +use crate::internal::{change::ChangeRef, lock::LockKind}; +use crate::internal::{lock::LoroMutexGuard, pre_commit::PreCommitCallback}; +use crate::internal::{ lock::{LoroLockGroup, LoroMutex}, txn::Transaction, }; @@ -580,7 +580,7 @@ impl LoroDoc { bytes: &[u8], origin: InternalString, ) -> Result { - ensure_cov::notify_cov("loro_internal::import"); + ensure_cov::notify_cov("loro::internal::import"); let parsed = parse_header_and_body(bytes, true)?; loro_common::info!("Importing with mode={:?}", &parsed.mode); let result = match parsed.mode { @@ -613,7 +613,7 @@ impl LoroDoc { } EncodeMode::FastSnapshot => { if self.can_reset_with_snapshot() { - ensure_cov::notify_cov("loro_internal::import::snapshot"); + ensure_cov::notify_cov("loro::internal::import::snapshot"); loro_common::info!("Init by fast snapshot {}", self.peer_id()); decode_snapshot(self, parsed.mode, parsed.body, origin) } else { @@ -704,7 +704,7 @@ impl LoroDoc { let json = json.try_into().map_err(|_| LoroError::InvalidJsonSchema)?; self.with_barrier(|| { let result = self.update_oplog_and_apply_delta_to_state_if_needed( - |oplog| crate::encoding::json_schema::import_json(oplog, json), + |oplog| crate::internal::encoding::json_schema::import_json(oplog, json), Default::default(), ); self.emit_events(); @@ -741,7 +741,7 @@ impl LoroDoc { } } - crate::encoding::json_schema::export_json( + crate::internal::encoding::json_schema::export_json( &oplog, start_vv, end_vv, @@ -877,7 +877,7 @@ impl LoroDoc { pub fn get_counter( &self, id: I, - ) -> crate::handler::counter::CounterHandler { + ) -> crate::internal::handler::counter::CounterHandler { let id = id.into_container_id(&self.arena, ContainerType::Counter); assert!(self.has_container(&id)); Handler::new_attached(id, self.clone()) @@ -940,7 +940,7 @@ impl LoroDoc { }; let spans = self.oplog.lock().unwrap().split_span_based_on_deps(id_span); - let diff = crate::undo::undo( + let diff = crate::internal::undo::undo( spans, match post_transform_base { Some(d) => Either::Right(d), @@ -1633,7 +1633,7 @@ impl LoroDoc { let depth = self.arena.get_depth(idx); let (_, diff_calc) = &mut diff_calc.get_or_create_calc(idx, depth); match diff_calc { - crate::diff_calc::ContainerDiffCalculator::Richtext(text) => { + crate::internal::diff_calc::ContainerDiffCalculator::Richtext(text) => { let c = text.get_id_latest_pos(id).unwrap(); let new_pos = c.pos; let handler = self.get_text(&pos.container); @@ -1646,7 +1646,7 @@ impl LoroDoc { }, }) } - crate::diff_calc::ContainerDiffCalculator::List(list) => { + crate::internal::diff_calc::ContainerDiffCalculator::List(list) => { let c = list.get_id_latest_pos(id).unwrap(); let new_pos = c.pos; let handler = self.get_list(&pos.container); @@ -1658,7 +1658,7 @@ impl LoroDoc { }, }) } - crate::diff_calc::ContainerDiffCalculator::MovableList(list) => { + crate::internal::diff_calc::ContainerDiffCalculator::MovableList(list) => { let c = list.get_id_latest_pos(id).unwrap(); let new_pos = c.pos; let handler = self.get_movable_list(&pos.container); @@ -1671,11 +1671,11 @@ impl LoroDoc { }, }) } - crate::diff_calc::ContainerDiffCalculator::Tree(_) => unreachable!(), - crate::diff_calc::ContainerDiffCalculator::Map(_) => unreachable!(), + crate::internal::diff_calc::ContainerDiffCalculator::Tree(_) => unreachable!(), + crate::internal::diff_calc::ContainerDiffCalculator::Map(_) => unreachable!(), #[cfg(feature = "counter")] - crate::diff_calc::ContainerDiffCalculator::Counter(_) => unreachable!(), - crate::diff_calc::ContainerDiffCalculator::Unknown(_) => unreachable!(), + crate::internal::diff_calc::ContainerDiffCalculator::Counter(_) => unreachable!(), + crate::internal::diff_calc::ContainerDiffCalculator::Unknown(_) => unreachable!(), } } else { match pos.container.container_type() { @@ -2115,7 +2115,7 @@ impl Default for CommitOptions { #[cfg(test)] mod test { - use crate::{cursor::PosType, loro::ExportMode, version::Frontiers, LoroDoc, ToJson}; + use crate::internal::{cursor::PosType, loro::ExportMode, version::Frontiers, LoroDoc, ToJson}; use loro_common::ID; #[test] diff --git a/crates/loro-internal/src/macros.rs b/crates/loro/src/internal/macros.rs similarity index 95% rename from crates/loro-internal/src/macros.rs rename to crates/loro/src/internal/macros.rs index 1fbd90af1..6ede682e9 100644 --- a/crates/loro-internal/src/macros.rs +++ b/crates/loro/src/internal/macros.rs @@ -1,6 +1,6 @@ /// ```no_run /// use rustc_hash::FxHashMap; -/// use loro_internal::fx_map; +/// use loro::fx_map; /// /// let mut expected = FxHashMap::default(); /// expected.insert("test".to_string(), "test".to_string()); @@ -22,7 +22,7 @@ macro_rules! fx_map { } /// ```no_run -/// use loro_internal::vv; +/// use loro::vv; /// /// let v = vv!(1 => 2, 2 => 3); /// assert_eq!(v.get(&1), Some(&2)); @@ -32,7 +32,7 @@ macro_rules! fx_map { macro_rules! vv { ($($key:expr => $value:expr),*) => { { - let mut m = $crate::version::VersionVector::default(); + let mut m = $crate::internal::version::VersionVector::default(); $( m.insert($key, $value); )* diff --git a/crates/loro-internal/src/lib.rs b/crates/loro/src/internal/mod.rs similarity index 78% rename from crates/loro-internal/src/lib.rs rename to crates/loro/src/internal/mod.rs index 295ac5665..014b08c17 100644 --- a/crates/loro-internal/src/lib.rs +++ b/crates/loro/src/internal/mod.rs @@ -1,8 +1,13 @@ -//! loro-internal is a CRDT framework. -//! -//! +//! Canonical engine surface for the merged `loro` crate. //! +//! `loro::internal` now owns the implementation modules that previously lived in +//! the hidden engine crate. First-party crates should treat the handler, value, event, +//! diff, and undo types re-exported here as the canonical low-level surface. //! +//! The public `loro::Loro*` and `loro::event::*` APIs remain compatibility +//! facades. They preserve stable semantics, while first-party performance- +//! sensitive paths can stay on the canonical internal surface without rebuilding +//! handler/value/event wrappers on hot paths. #![deny(clippy::undocumented_unsafe_blocks)] #![allow(clippy::uninlined_format_args)] #![warn(rustdoc::broken_intra_doc_links)] @@ -13,7 +18,7 @@ pub mod diff; pub mod diff_calc; pub mod handler; pub mod sync; -use crate::sync::AtomicBool; +use crate::internal::sync::AtomicBool; use std::sync::Arc; mod change_meta; pub(crate) mod lock; @@ -23,10 +28,15 @@ use diff_calc::DiffCalculator; use lock::LoroMutex; pub use change_meta::ChangeMeta; -pub use event::{ContainerDiff, DiffEvent, DocDiff, ListDiff, ListDiffInsertItem, ListDiffItem}; +pub use event::{ + ContainerDiff, Diff, DiffEvent, DocDiff, EventTriggerKind, Index, ListDeltaMeta, ListDiff, + ListDiffInsertItem, ListDiffItem, TextDiff, TextDiffItem, TextMeta, +}; +#[cfg(feature = "counter")] +pub use handler::counter::CounterHandler; pub use handler::{ - BasicHandler, HandlerTrait, ListHandler, MapHandler, MovableListHandler, TextHandler, - TreeHandler, UnknownHandler, + BasicHandler, Handler, HandlerTrait, ListHandler, MapHandler, MovableListHandler, TextDelta, + TextHandler, TreeHandler, UnknownHandler, ValueOrHandler, }; pub use loro_common; pub use oplog::OpLog; @@ -37,9 +47,10 @@ use pre_commit::{ pub use rustc_hash::FxHashMap; pub use state::DocState; pub use state::{TreeNode, TreeNodeWithChildren, TreeParentId}; +pub use subscription::Subscriber; use subscription::{LocalUpdateCallback, Observer, PeerIdUpdateCallback}; use txn::Transaction; -pub use undo::UndoManager; +pub use undo::{DiffBatch, UndoItemMeta, UndoManager, UndoOrRedo}; pub use utils::subscription::SubscriberSetWithQueue; pub use utils::subscription::Subscription; pub mod allocation; @@ -83,6 +94,7 @@ pub(crate) mod macros; pub(crate) mod state; pub mod undo; pub(crate) mod value; +pub use crate::{array_mut_ref, fx_map, version_range, vv}; // TODO: rename as Key? pub(crate) use loro_common::InternalString; @@ -121,7 +133,7 @@ pub use version::VersionVector; #[derive(Debug, Clone)] #[repr(transparent)] pub struct LoroDoc { - inner: Arc, + pub(crate) inner: Arc, } impl LoroDoc { @@ -170,7 +182,7 @@ pub struct LoroDocInner { } /// The version of the loro crate -pub const LORO_VERSION: &str = include_str!("../VERSION"); +pub const LORO_VERSION: &str = include_str!("../../VERSION"); impl Drop for LoroDoc { fn drop(&mut self) { diff --git a/crates/loro-internal/src/op.rs b/crates/loro/src/internal/op.rs similarity index 98% rename from crates/loro-internal/src/op.rs rename to crates/loro/src/internal/op.rs index 155f64cb8..1fadbf465 100644 --- a/crates/loro-internal/src/op.rs +++ b/crates/loro/src/internal/op.rs @@ -1,4 +1,4 @@ -use crate::{ +use crate::internal::{ change::{Change, Lamport, Timestamp}, container::{idx::ContainerIdx, ContainerID}, estimated_size::EstimatedSize, @@ -6,7 +6,7 @@ use crate::{ oplog::BlockChangeRef, span::{HasCounter, HasId, HasLamport}, }; -use crate::{delta::DeltaValue, LoroValue}; +use crate::internal::{delta::DeltaValue, LoroValue}; use either::Either; use enum_as_inner::EnumAsInner; use loro_common::{CompactIdLp, ContainerType, CounterSpan, IdFull, IdLp, IdSpan}; @@ -112,14 +112,14 @@ impl Op { match &self.content { InnerContent::List(l) => match l { - crate::container::list::list_op::InnerListOp::Insert { .. } => { + crate::internal::container::list::list_op::InnerListOp::Insert { .. } => { if matches!(self.container.get_type(), ContainerType::Text) { Some(size.min(self.atom_len())) } else { Some((size / 4).min(self.atom_len())) } } - crate::container::list::list_op::InnerListOp::InsertText { .. } => { + crate::internal::container::list::list_op::InnerListOp::InsertText { .. } => { Some(size.min(self.atom_len())) } _ => unreachable!(), @@ -595,7 +595,7 @@ impl DeltaValue for SliceWithId { #[cfg(test)] mod test { - use crate::LoroValue; + use crate::internal::LoroValue; use super::ListSlice; diff --git a/crates/loro-internal/src/op/content.rs b/crates/loro/src/internal/op/content.rs similarity index 95% rename from crates/loro-internal/src/op/content.rs rename to crates/loro/src/internal/op/content.rs index d98fb1c77..4c6912f74 100644 --- a/crates/loro-internal/src/op/content.rs +++ b/crates/loro/src/internal/op/content.rs @@ -6,7 +6,7 @@ use rle::{HasLength, Mergable, Sliceable}; #[cfg(feature = "wasm")] use serde::{Deserialize, Serialize}; -use crate::{ +use crate::internal::{ arena::SharedArena, container::{ list::list_op::{InnerListOp, ListOp}, @@ -48,19 +48,19 @@ impl InnerContent { InnerListOp::StyleStart { .. } => {} InnerListOp::StyleEnd => {} }, - crate::op::InnerContent::Map(m) => { + crate::internal::op::InnerContent::Map(m) => { if let Some(LoroValue::Container(c)) = &m.value { f(c); } } - crate::op::InnerContent::Tree(t) => { + crate::internal::op::InnerContent::Tree(t) => { let id = t.target().associated_meta_container(); f(&id); } - crate::op::InnerContent::Future(f) => match &f { + crate::internal::op::InnerContent::Future(f) => match &f { #[cfg(feature = "counter")] - crate::op::FutureInnerContent::Counter(_) => {} - crate::op::FutureInnerContent::Unknown { .. } => {} + crate::internal::op::FutureInnerContent::Counter(_) => {} + crate::internal::op::FutureInnerContent::Unknown { .. } => {} }, } } diff --git a/crates/loro-internal/src/oplog.rs b/crates/loro/src/internal/oplog.rs similarity index 94% rename from crates/loro-internal/src/oplog.rs rename to crates/loro/src/internal/oplog.rs index a85a67e18..12f858911 100644 --- a/crates/loro-internal/src/oplog.rs +++ b/crates/loro/src/internal/oplog.rs @@ -2,7 +2,7 @@ mod change_store; pub(crate) mod loro_dag; mod pending_changes; -use crate::sync::Mutex; +use crate::internal::sync::Mutex; use bytes::Bytes; use std::borrow::Cow; use std::cell::RefCell; @@ -13,19 +13,19 @@ use tracing::trace_span; use self::change_store::iter::MergedChangeIter; use self::pending_changes::PendingChanges; use super::arena::SharedArena; -use crate::change::{get_sys_timestamp, Change, Lamport, Timestamp}; -use crate::configure::Configure; -use crate::container::list::list_op; -use crate::dag::{Dag, DagUtils}; -use crate::diff_calc::DiffMode; -use crate::encoding::decode_oplog; -use crate::encoding::{ImportStatus, ParsedHeaderAndBody}; -use crate::history_cache::ContainerHistoryCache; -use crate::id::{Counter, PeerID, ID}; -use crate::op::{FutureInnerContent, ListSlice, RawOpContent, RemoteOp, RichOp}; -use crate::span::{HasCounterSpan, HasLamportSpan}; -use crate::version::{Frontiers, ImVersionVector, VersionVector}; -use crate::LoroError; +use crate::internal::change::{get_sys_timestamp, Change, Lamport, Timestamp}; +use crate::internal::configure::Configure; +use crate::internal::container::list::list_op; +use crate::internal::dag::{Dag, DagUtils}; +use crate::internal::diff_calc::DiffMode; +use crate::internal::encoding::decode_oplog; +use crate::internal::encoding::{ImportStatus, ParsedHeaderAndBody}; +use crate::internal::history_cache::ContainerHistoryCache; +use crate::internal::id::{Counter, PeerID, ID}; +use crate::internal::op::{FutureInnerContent, ListSlice, RawOpContent, RemoteOp, RichOp}; +use crate::internal::span::{HasCounterSpan, HasLamportSpan}; +use crate::internal::version::{Frontiers, ImVersionVector, VersionVector}; +use crate::internal::LoroError; use change_store::BlockOpRef; use loro_common::{HasIdSpan, IdLp, IdSpan}; use rle::{HasLength, RleVec, Sliceable}; @@ -654,12 +654,12 @@ pub(crate) fn convert_change_to_remote( pub(crate) fn local_op_to_remote( arena: &SharedArena, - op: &crate::op::Op, + op: &crate::internal::op::Op, ) -> SmallVec<[RemoteOp<'static>; 1]> { let container = arena.get_container_id(op.container).unwrap(); let mut contents: SmallVec<[_; 1]> = SmallVec::new(); match &op.content { - crate::op::InnerContent::List(list) => match list { + crate::internal::op::InnerContent::List(list) => match list { list_op::InnerListOp::Insert { slice, pos } => match container.container_type() { loro_common::ContainerType::Text => { let str = arena @@ -734,19 +734,19 @@ pub(crate) fn local_op_to_remote( })) } }, - crate::op::InnerContent::Map(map) => { + crate::internal::op::InnerContent::Map(map) => { let value = map.value.clone(); - contents.push(RawOpContent::Map(crate::container::map::MapSet { + contents.push(RawOpContent::Map(crate::internal::container::map::MapSet { key: map.key.clone(), value, })) } - crate::op::InnerContent::Tree(tree) => contents.push(RawOpContent::Tree(tree.clone())), - crate::op::InnerContent::Future(f) => match f { + crate::internal::op::InnerContent::Tree(tree) => contents.push(RawOpContent::Tree(tree.clone())), + crate::internal::op::InnerContent::Future(f) => match f { #[cfg(feature = "counter")] - crate::op::FutureInnerContent::Counter(c) => contents.push(RawOpContent::Counter(*c)), + crate::internal::op::FutureInnerContent::Counter(c) => contents.push(RawOpContent::Counter(*c)), FutureInnerContent::Unknown { prop, value } => { - contents.push(crate::op::RawOpContent::Unknown { + contents.push(crate::internal::op::RawOpContent::Unknown { prop: *prop, value: (**value).clone(), }) diff --git a/crates/loro-internal/src/oplog/change_store.rs b/crates/loro/src/internal/oplog/change_store.rs similarity index 99% rename from crates/loro-internal/src/oplog/change_store.rs rename to crates/loro/src/internal/oplog/change_store.rs index b79fe6550..4d12dcbb3 100644 --- a/crates/loro-internal/src/oplog/change_store.rs +++ b/crates/loro/src/internal/oplog/change_store.rs @@ -1,7 +1,7 @@ use self::block_encode::{decode_block, decode_header, encode_block, ChangesBlockHeader}; use super::{loro_dag::AppDagNodeInner, AppDagNode}; -use crate::sync::Mutex; -use crate::{ +use crate::internal::sync::Mutex; +use crate::internal::{ arena::SharedArena, change::Change, estimated_size::EstimatedSize, @@ -1550,8 +1550,8 @@ impl ChangesBlockBytes { #[cfg(test)] mod test { - use crate::cursor::PosType; - use crate::{ + use crate::internal::cursor::PosType; + use crate::internal::{ loro::ExportMode, oplog::convert_change_to_remote, state::TreeParentId, ListHandler, LoroDoc, MovableListHandler, TextHandler, TreeHandler, }; diff --git a/crates/loro-internal/src/oplog/change_store/block_encode.rs b/crates/loro/src/internal/oplog/change_store/block_encode.rs similarity index 97% rename from crates/loro-internal/src/oplog/change_store/block_encode.rs rename to crates/loro/src/internal/oplog/change_store/block_encode.rs index 48fec3793..0dd7b5fc8 100644 --- a/crates/loro-internal/src/oplog/change_store/block_encode.rs +++ b/crates/loro/src/internal/oplog/change_store/block_encode.rs @@ -81,15 +81,15 @@ use serde_columnar::{columnar, AnyRleDecoder, DeltaOfDeltaDecoder, Itertools}; use tracing::info; use super::block_meta_encode::decode_changes_header; -use crate::arena::SharedArena; -use crate::change::{Change, Timestamp}; -use crate::container::tree::tree_op; -use crate::encoding::arena::{ContainerArena, PositionArena}; -use crate::encoding::value_register::ValueRegister; -use crate::encoding::{ +use crate::internal::arena::SharedArena; +use crate::internal::change::{Change, Timestamp}; +use crate::internal::container::tree::tree_op; +use crate::internal::encoding::arena::{ContainerArena, PositionArena}; +use crate::internal::encoding::value_register::ValueRegister; +use crate::internal::encoding::{ self, decode_op, encode_op, get_op_prop, EncodedDeleteStartId, IterableEncodedDeleteStartId, }; -use crate::op::Op; +use crate::internal::op::Op; #[derive(Debug, Serialize, Deserialize)] struct EncodedBlock<'a> { @@ -158,7 +158,7 @@ pub fn encode_block(block: &[Change], arena: &SharedArena) -> Vec { let mut position_set = BTreeSet::default(); for c in block { for op in c.ops().iter() { - if let crate::op::InnerContent::Tree(tree_op) = &op.content { + if let crate::internal::op::InnerContent::Tree(tree_op) = &op.content { match &**tree_op { tree_op::TreeOp::Create { position, .. } => { position_set.insert(position.clone()); @@ -306,12 +306,12 @@ struct Registers { position_register: ValueRegister, } -use crate::encoding::value::{ +use crate::internal::encoding::value::{ RawTreeMove, Value, ValueDecodedArenasTrait, ValueEncodeRegister, ValueKind, ValueReader, ValueWriter, }; -use crate::oplog::change_store::block_meta_encode::encode_changes; -use crate::version::Frontiers; +use crate::internal::oplog::change_store::block_meta_encode::encode_changes; +use crate::internal::version::Frontiers; impl ValueEncodeRegister for Registers { fn key_mut(&mut self) -> &mut ValueRegister { &mut self.key_register @@ -660,7 +660,7 @@ pub fn decode_block( #[cfg(test)] mod test { - use crate::{cursor::PosType, delta::DeltaValue, loro::ExportMode, LoroDoc}; + use crate::internal::{cursor::PosType, delta::DeltaValue, loro::ExportMode, LoroDoc}; #[test] pub fn encode_single_text_edit() { diff --git a/crates/loro-internal/src/oplog/change_store/block_meta_encode.rs b/crates/loro/src/internal/oplog/change_store/block_meta_encode.rs similarity index 98% rename from crates/loro-internal/src/oplog/change_store/block_meta_encode.rs rename to crates/loro/src/internal/oplog/change_store/block_meta_encode.rs index a62d8546c..44aa55d52 100644 --- a/crates/loro-internal/src/oplog/change_store/block_meta_encode.rs +++ b/crates/loro/src/internal/oplog/change_store/block_meta_encode.rs @@ -6,7 +6,7 @@ use serde_columnar::{ DeltaOfDeltaEncoder, }; -use crate::{change::Change, encoding::value_register::ValueRegister, version::Frontiers}; +use crate::internal::{change::Change, encoding::value_register::ValueRegister, version::Frontiers}; use super::block_encode::ChangesBlockHeader; diff --git a/crates/loro-internal/src/oplog/change_store/iter.rs b/crates/loro/src/internal/oplog/change_store/iter.rs similarity index 98% rename from crates/loro-internal/src/oplog/change_store/iter.rs rename to crates/loro/src/internal/oplog/change_store/iter.rs index 27bba4113..7b678db4e 100644 --- a/crates/loro-internal/src/oplog/change_store/iter.rs +++ b/crates/loro/src/internal/oplog/change_store/iter.rs @@ -5,7 +5,7 @@ use std::{ use loro_common::{CounterSpan, HasIdSpan}; -use crate::{OpLog, VersionVector}; +use crate::internal::{OpLog, VersionVector}; use super::{BlockChangeRef, ChangesBlock}; diff --git a/crates/loro-internal/src/oplog/loro_dag.rs b/crates/loro/src/internal/oplog/loro_dag.rs similarity index 99% rename from crates/loro-internal/src/oplog/loro_dag.rs rename to crates/loro/src/internal/oplog/loro_dag.rs index 0b5595678..e9527268a 100644 --- a/crates/loro-internal/src/oplog/loro_dag.rs +++ b/crates/loro/src/internal/oplog/loro_dag.rs @@ -1,9 +1,9 @@ -use crate::change::{Change, Lamport}; -use crate::dag::{Dag, DagNode}; -use crate::id::{Counter, ID}; -use crate::span::{HasId, HasLamport}; -use crate::sync::Mutex; -use crate::version::{shrink_frontiers, Frontiers, ImVersionVector, VersionVector}; +use crate::internal::change::{Change, Lamport}; +use crate::internal::dag::{Dag, DagNode}; +use crate::internal::id::{Counter, ID}; +use crate::internal::span::{HasId, HasLamport}; +use crate::internal::sync::Mutex; +use crate::internal::version::{shrink_frontiers, Frontiers, ImVersionVector, VersionVector}; use loro_common::{HasCounter, HasCounterSpan, HasIdSpan, HasLamportSpan, PeerID}; use once_cell::sync::OnceCell; use rle::{HasIndex, HasLength, Mergable, Sliceable}; diff --git a/crates/loro-internal/src/oplog/pending_changes.rs b/crates/loro/src/internal/oplog/pending_changes.rs similarity index 99% rename from crates/loro-internal/src/oplog/pending_changes.rs rename to crates/loro/src/internal/oplog/pending_changes.rs index 9501742cd..beb5ba625 100644 --- a/crates/loro-internal/src/oplog/pending_changes.rs +++ b/crates/loro/src/internal/oplog/pending_changes.rs @@ -1,6 +1,6 @@ use std::{collections::BTreeMap, ops::Deref}; -use crate::{ +use crate::internal::{ change::Change, version::{ImVersionVector, VersionRange}, OpLog, VersionVector, @@ -177,7 +177,7 @@ fn remote_change_apply_state( #[cfg(test)] mod test { - use crate::{cursor::PosType, loro::ExportMode, LoroDoc, ToJson, VersionVector}; + use crate::internal::{cursor::PosType, loro::ExportMode, LoroDoc, ToJson, VersionVector}; #[test] fn import_pending() { diff --git a/crates/loro-internal/src/parent.rs b/crates/loro/src/internal/parent.rs similarity index 99% rename from crates/loro-internal/src/parent.rs rename to crates/loro/src/internal/parent.rs index 371950f32..536778cf8 100644 --- a/crates/loro-internal/src/parent.rs +++ b/crates/loro/src/internal/parent.rs @@ -6,7 +6,7 @@ use loro_common::LoroValue; -use crate::{ +use crate::internal::{ arena::SharedArena, change::Change, container::{list::list_op::ListOp, map::MapSet}, diff --git a/crates/loro-internal/src/pre_commit.rs b/crates/loro/src/internal/pre_commit.rs similarity index 98% rename from crates/loro-internal/src/pre_commit.rs rename to crates/loro/src/internal/pre_commit.rs index eb6f3fbe5..dbad277ec 100644 --- a/crates/loro-internal/src/pre_commit.rs +++ b/crates/loro/src/internal/pre_commit.rs @@ -1,6 +1,6 @@ use std::sync::{Arc, Mutex}; -use crate::{ +use crate::internal::{ change::{Change, Timestamp}, oplog::get_timestamp_now_txn, ChangeMeta, diff --git a/crates/loro-internal/src/span.rs b/crates/loro/src/internal/span.rs similarity index 100% rename from crates/loro-internal/src/span.rs rename to crates/loro/src/internal/span.rs diff --git a/crates/loro-internal/src/state.rs b/crates/loro/src/internal/state.rs similarity index 99% rename from crates/loro-internal/src/state.rs rename to crates/loro/src/internal/state.rs index 1b9bacf0b..a9ab69b95 100644 --- a/crates/loro-internal/src/state.rs +++ b/crates/loro/src/internal/state.rs @@ -1,4 +1,4 @@ -use crate::sync::{AtomicU64, Mutex}; +use crate::internal::sync::{AtomicU64, Mutex}; use std::sync::RwLock; use std::sync::{Arc, Weak}; use std::{borrow::Cow, io::Write, sync::atomic::Ordering}; @@ -13,7 +13,7 @@ use loro_delta::DeltaItem; use rustc_hash::{FxHashMap, FxHashSet}; use tracing::{info_span, instrument, warn}; -use crate::{ +use crate::internal::{ configure::{Configure, DefaultRandom, SecureRandomGenerator}, container::{idx::ContainerIdx, richtext::config::StyleConfigMap}, cursor::Cursor, @@ -342,7 +342,7 @@ impl DocState { event_recorder: Default::default(), dead_containers_cache: Default::default(), }, - crate::lock::LockKind::DocState, + crate::internal::lock::LockKind::DocState, )) } @@ -566,7 +566,7 @@ impl DocState { let idx = diff.idx; let internal_diff = std::mem::take(&mut diff.diff); match &internal_diff { - crate::event::DiffVariant::None => { + crate::internal::event::DiffVariant::None => { if is_recording { let state = self.store.get_or_create_mut(diff.idx); let extern_diff = state.to_diff(&self.doc); @@ -580,7 +580,7 @@ impl DocState { diff.diff = extern_diff.into(); } } - crate::event::DiffVariant::Internal(_) => { + crate::internal::event::DiffVariant::Internal(_) => { let cid = self.arena.idx_to_id(idx).unwrap(); info_span!("apply diff on", container_id = ?cid).in_scope(|| { if self.in_txn { @@ -627,7 +627,7 @@ impl DocState { } }); } - crate::event::DiffVariant::External(_) => unreachable!(), + crate::internal::event::DiffVariant::External(_) => unreachable!(), } to_revive_in_this_layer.remove(&idx); @@ -1413,7 +1413,7 @@ impl DocState { State::CounterState(_) => unreachable!(), } } else { - if matches!(pos.side, crate::cursor::Side::Left) { + if matches!(pos.side, crate::internal::cursor::Side::Left) { return Some(0); } diff --git a/crates/loro-internal/src/state/analyzer.rs b/crates/loro/src/internal/state/analyzer.rs similarity index 98% rename from crates/loro-internal/src/state/analyzer.rs rename to crates/loro/src/internal/state/analyzer.rs index dae04c9d3..3b9514baa 100644 --- a/crates/loro-internal/src/state/analyzer.rs +++ b/crates/loro/src/internal/state/analyzer.rs @@ -1,4 +1,4 @@ -use crate::{change::Timestamp, LoroDoc}; +use crate::internal::{change::Timestamp, LoroDoc}; use loro_common::ContainerID; use rle::HasLength; use rustc_hash::FxHashMap; diff --git a/crates/loro-internal/src/state/container_store.rs b/crates/loro/src/internal/state/container_store.rs similarity index 98% rename from crates/loro-internal/src/state/container_store.rs rename to crates/loro/src/internal/state/container_store.rs index f37b09694..151909eb1 100644 --- a/crates/loro-internal/src/state/container_store.rs +++ b/crates/loro/src/internal/state/container_store.rs @@ -1,7 +1,7 @@ use super::{ContainerCreationContext, State}; -use crate::arena::LoadAllFlag; -use crate::sync::{AtomicU64, Mutex}; -use crate::{ +use crate::internal::arena::LoadAllFlag; +use crate::internal::sync::{AtomicU64, Mutex}; +use crate::internal::{ arena::SharedArena, configure::Configure, container::idx::ContainerIdx, utils::kv_wrapper::KvWrapper, version::Frontiers, }; @@ -288,7 +288,7 @@ impl ContainerStore { #[cfg(test)] mod test { use super::*; - use crate::{ + use crate::internal::{ cursor::PosType, state::TreeParentId, ListHandler, LoroDoc, MapHandler, MovableListHandler, }; diff --git a/crates/loro-internal/src/state/container_store/container_wrapper.rs b/crates/loro/src/internal/state/container_store/container_wrapper.rs similarity index 99% rename from crates/loro-internal/src/state/container_store/container_wrapper.rs rename to crates/loro/src/internal/state/container_store/container_wrapper.rs index f486195e4..e3e8d3829 100644 --- a/crates/loro-internal/src/state/container_store/container_wrapper.rs +++ b/crates/loro/src/internal/state/container_store/container_wrapper.rs @@ -3,8 +3,8 @@ use loro_common::{ContainerID, ContainerType, LoroResult, LoroValue}; use tracing::trace; #[cfg(feature = "counter")] -use crate::state::counter_state::CounterState; -use crate::{ +use crate::internal::state::counter_state::CounterState; +use crate::internal::{ arena::SharedArena, container::idx::ContainerIdx, state::{ diff --git a/crates/loro-internal/src/state/container_store/inner_store.rs b/crates/loro/src/internal/state/container_store/inner_store.rs similarity index 99% rename from crates/loro-internal/src/state/container_store/inner_store.rs rename to crates/loro/src/internal/state/container_store/inner_store.rs index 7fe01c665..38ca2b171 100644 --- a/crates/loro-internal/src/state/container_store/inner_store.rs +++ b/crates/loro/src/internal/state/container_store/inner_store.rs @@ -1,4 +1,4 @@ -use crate::{ +use crate::internal::{ arena::SharedArena, configure::Configure, container::idx::ContainerIdx, state::container_store::FRONTIERS_KEY, utils::kv_wrapper::KvWrapper, version::Frontiers, }; diff --git a/crates/loro-internal/src/state/counter_state.rs b/crates/loro/src/internal/state/counter_state.rs similarity index 95% rename from crates/loro-internal/src/state/counter_state.rs rename to crates/loro/src/internal/state/counter_state.rs index a7e8379d7..97e7f8e59 100644 --- a/crates/loro-internal/src/state/counter_state.rs +++ b/crates/loro/src/internal/state/counter_state.rs @@ -2,7 +2,7 @@ use std::sync::Weak; use loro_common::{ContainerID, LoroResult, LoroValue}; -use crate::{ +use crate::internal::{ configure::Configure, container::idx::ContainerIdx, event::{Diff, Index, InternalDiff}, @@ -85,7 +85,7 @@ impl ContainerState for CounterState { } mod snapshot { - use crate::state::FastStateSnapshot; + use crate::internal::state::FastStateSnapshot; use super::*; @@ -105,7 +105,7 @@ mod snapshot { fn decode_snapshot_fast( idx: ContainerIdx, v: (LoroValue, &[u8]), - _ctx: crate::state::ContainerCreationContext, + _ctx: crate::internal::state::ContainerCreationContext, ) -> LoroResult where Self: Sized, diff --git a/crates/loro-internal/src/state/dead_containers_cache.rs b/crates/loro/src/internal/state/dead_containers_cache.rs similarity index 97% rename from crates/loro-internal/src/state/dead_containers_cache.rs rename to crates/loro/src/internal/state/dead_containers_cache.rs index c40dbf06e..856ae8bf0 100644 --- a/crates/loro-internal/src/state/dead_containers_cache.rs +++ b/crates/loro/src/internal/state/dead_containers_cache.rs @@ -1,5 +1,5 @@ use super::{ContainerState, DocState}; -use crate::container::idx::ContainerIdx; +use crate::internal::container::idx::ContainerIdx; use rustc_hash::FxHashMap; #[derive(Default, Debug, Clone)] diff --git a/crates/loro-internal/src/state/list_state.rs b/crates/loro/src/internal/state/list_state.rs similarity index 96% rename from crates/loro-internal/src/state/list_state.rs rename to crates/loro/src/internal/state/list_state.rs index e16986e60..3f91f7904 100644 --- a/crates/loro-internal/src/state/list_state.rs +++ b/crates/loro/src/internal/state/list_state.rs @@ -1,7 +1,7 @@ use std::{io::Write, ops::RangeBounds, sync::Weak}; use super::{ApplyLocalOpReturn, ContainerState, DiffApplyContext, FastStateSnapshot}; -use crate::{ +use crate::internal::{ configure::Configure, container::{idx::ContainerIdx, list::list_op::ListOp, ContainerID}, event::{Diff, Index, InternalDiff, ListDiff}, @@ -373,11 +373,11 @@ impl ContainerState for ListState { let doc = &doc.upgrade().unwrap(); for span in delta.iter() { match span { - crate::delta::DeltaItem::Retain { retain: len, .. } => { + crate::internal::delta::DeltaItem::Retain { retain: len, .. } => { index += len; ans.push_retain(*len, Default::default()); } - crate::delta::DeltaItem::Insert { insert: value, .. } => { + crate::internal::delta::DeltaItem::Insert { insert: value, .. } => { let mut arr = Vec::new(); match &value.values { either::Either::Left(range) => { @@ -398,7 +398,7 @@ impl ContainerState for ListState { self.insert_batch(index, arr, value.id); index += len; } - crate::delta::DeltaItem::Delete { delete: len, .. } => { + crate::internal::delta::DeltaItem::Delete { delete: len, .. } => { self.delete_range(index..index + len, None); ans.push_delete(*len); } @@ -415,10 +415,10 @@ impl ContainerState for ListState { let mut index = 0; for span in delta.iter() { match span { - crate::delta::DeltaItem::Retain { retain: len, .. } => { + crate::internal::delta::DeltaItem::Retain { retain: len, .. } => { index += len; } - crate::delta::DeltaItem::Insert { insert: value, .. } => { + crate::internal::delta::DeltaItem::Insert { insert: value, .. } => { let mut arr = Vec::new(); match &value.values { either::Either::Left(range) => { @@ -434,7 +434,7 @@ impl ContainerState for ListState { self.insert_batch(index, arr, value.id); index += len; } - crate::delta::DeltaItem::Delete { delete: len, .. } => { + crate::internal::delta::DeltaItem::Delete { delete: len, .. } => { self.delete_range(index..index + len, None); } } @@ -521,7 +521,7 @@ mod snapshot { use loro_common::{Counter, Lamport, PeerID}; use serde_columnar::columnar; - use crate::{encoding::value_register::ValueRegister, state::ContainerCreationContext}; + use crate::internal::{encoding::value_register::ValueRegister, state::ContainerCreationContext}; use super::*; #[columnar(vec, ser, de, iterable)] @@ -625,7 +625,7 @@ mod test { use itertools::Itertools; use loro_common::{Counter, Lamport}; - use crate::state::ContainerCreationContext; + use crate::internal::state::ContainerCreationContext; use super::*; @@ -636,7 +636,7 @@ mod test { loro_common::ContainerType::List, )); fn id(name: &str) -> ContainerID { - ContainerID::new_root(name, crate::ContainerType::List) + ContainerID::new_root(name, crate::internal::ContainerType::List) } list.insert(0, LoroValue::Container(id("abc")), IdFull::new(0, 0, 0)); list.insert(0, LoroValue::Container(id("x")), IdFull::new(0, 0, 0)); diff --git a/crates/loro-internal/src/state/map_state.rs b/crates/loro/src/internal/state/map_state.rs similarity index 98% rename from crates/loro-internal/src/state/map_state.rs rename to crates/loro/src/internal/state/map_state.rs index 770bc1840..03ad757d8 100644 --- a/crates/loro-internal/src/state/map_state.rs +++ b/crates/loro/src/internal/state/map_state.rs @@ -3,7 +3,7 @@ use std::{collections::BTreeMap, sync::Weak}; use loro_common::{ContainerID, IdLp, LoroResult, PeerID}; use rustc_hash::FxHashMap; -use crate::{ +use crate::internal::{ configure::Configure, container::{idx::ContainerIdx, map::MapSet}, delta::{MapValue, ResolvedMapDelta, ResolvedMapValue}, @@ -248,7 +248,7 @@ mod snapshot { use rustc_hash::{FxHashMap, FxHashSet}; use serde_columnar::Itertools; - use crate::{ + use crate::internal::{ delta::MapValue, encoding::value_register::ValueRegister, state::{ContainerCreationContext, ContainerState, FastStateSnapshot}, @@ -302,7 +302,7 @@ mod snapshot { } fn decode_snapshot_fast( - idx: crate::container::idx::ContainerIdx, + idx: crate::internal::container::idx::ContainerIdx, (value, bytes): (loro_common::LoroValue, &[u8]), _ctx: ContainerCreationContext, ) -> loro_common::LoroResult @@ -371,7 +371,7 @@ mod snapshot { mod map_snapshot_test { use loro_common::LoroValue; - use crate::container::idx::ContainerIdx; + use crate::internal::container::idx::ContainerIdx; use super::*; diff --git a/crates/loro-internal/src/state/movable_list_state.rs b/crates/loro/src/internal/state/movable_list_state.rs similarity index 99% rename from crates/loro-internal/src/state/movable_list_state.rs rename to crates/loro/src/internal/state/movable_list_state.rs index 708f38d4e..8c46c41ec 100644 --- a/crates/loro-internal/src/state/movable_list_state.rs +++ b/crates/loro/src/internal/state/movable_list_state.rs @@ -8,7 +8,7 @@ use generic_btree::BTree; use loro_common::{CompactIdLp, ContainerID, IdFull, IdLp, LoroResult, LoroValue, PeerID, ID}; use rustc_hash::FxHashMap; -use crate::{ +use crate::internal::{ configure::Configure, container::{idx::ContainerIdx, list::list_op::ListOp}, delta::DeltaItem, @@ -70,7 +70,7 @@ mod list_item_tree { BTreeTrait, }; - use crate::utils::query_by_len::{IndexQuery, QueryByLen}; + use crate::internal::utils::query_by_len::{IndexQuery, QueryByLen}; use super::ListItem; @@ -1121,7 +1121,7 @@ impl ContainerState for MovableListState { // It doesn't need to worry about the deletion of the list item, because it's handled by the list diff. for (elem_id, delta_item) in diff.elements.into_iter() { - let crate::delta::ElementDelta { + let crate::internal::delta::ElementDelta { pos, value, value_updated, @@ -1435,7 +1435,7 @@ mod snapshot { use loro_common::{IdFull, IdLp, LoroValue, PeerID}; - use crate::{ + use crate::internal::{ encoding::value_register::ValueRegister, state::{ContainerCreationContext, ContainerState, FastStateSnapshot}, }; @@ -1542,7 +1542,7 @@ mod snapshot { } fn decode_snapshot_fast( - idx: crate::container::idx::ContainerIdx, + idx: crate::internal::container::idx::ContainerIdx, (list_value, mut bytes): (loro_common::LoroValue, &[u8]), _ctx: ContainerCreationContext, ) -> loro_common::LoroResult @@ -1642,7 +1642,7 @@ mod snapshot { use loro_common::{CompactIdLp, ContainerID, LoroValue, ID}; - use crate::container::idx::ContainerIdx; + use crate::internal::container::idx::ContainerIdx; use super::*; @@ -1776,7 +1776,7 @@ mod snapshot { #[cfg(test)] mod test { - use crate::{loro::ExportMode, HandlerTrait, LoroDoc, ToJson}; + use crate::internal::{loro::ExportMode, HandlerTrait, LoroDoc, ToJson}; use serde_json::json; #[test] diff --git a/crates/loro-internal/src/state/richtext_state.rs b/crates/loro/src/internal/state/richtext_state.rs similarity index 99% rename from crates/loro-internal/src/state/richtext_state.rs rename to crates/loro/src/internal/state/richtext_state.rs index 8b8bce4b7..50c792f54 100644 --- a/crates/loro-internal/src/state/richtext_state.rs +++ b/crates/loro/src/internal/state/richtext_state.rs @@ -6,7 +6,7 @@ use std::ops::Range; use std::sync::RwLock; use std::sync::{Arc, Weak}; -use crate::{ +use crate::internal::{ container::{ idx::ContainerIdx, list::list_op, @@ -285,7 +285,7 @@ impl RichtextState { #[cfg(test)] mod tests { - use crate::{container::richtext::StyleKey, cursor::PosType, handler::HandlerTrait, LoroDoc}; + use crate::internal::{container::richtext::StyleKey, cursor::PosType, handler::HandlerTrait, LoroDoc}; #[test] fn has_style_key_in_entity_range_basic() { @@ -800,7 +800,7 @@ impl ContainerState for RichtextState { fn apply_local_op(&mut self, r_op: &RawOp, op: &Op) -> LoroResult { self.update_version(); match &op.content { - crate::op::InnerContent::List(l) => match l { + crate::internal::op::InnerContent::List(l) => match l { list_op::InnerListOp::Insert { slice: _, pos: _ } => { unreachable!() } @@ -894,7 +894,7 @@ impl ContainerState for RichtextState { false } - fn fork(&self, config: &crate::configure::Configure) -> Self { + fn fork(&self, config: &crate::internal::configure::Configure) -> Self { Self { idx: self.idx, config: config.text_style_config.clone(), @@ -1113,7 +1113,7 @@ mod snapshot { use serde_columnar::columnar; use std::{io::Read, sync::Arc}; - use crate::{ + use crate::internal::{ container::richtext::{ self, richtext_state::RichtextStateChunk, str_slice::StrSlice, StyleOp, TextStyleInfoFlag, @@ -1261,7 +1261,7 @@ mod snapshot { } fn decode_snapshot_fast( - idx: crate::container::idx::ContainerIdx, + idx: crate::internal::container::idx::ContainerIdx, (string, mut bytes): (loro_common::LoroValue, &[u8]), ctx: ContainerCreationContext, ) -> loro_common::LoroResult diff --git a/crates/loro-internal/src/state/tree_state.rs b/crates/loro/src/internal/state/tree_state.rs similarity index 98% rename from crates/loro-internal/src/state/tree_state.rs rename to crates/loro/src/internal/state/tree_state.rs index 9f32f30be..80d32f3cf 100644 --- a/crates/loro-internal/src/state/tree_state.rs +++ b/crates/loro/src/internal/state/tree_state.rs @@ -15,19 +15,19 @@ use std::ops::{Deref, DerefMut}; use std::sync::Weak; use super::{ApplyLocalOpReturn, ContainerState, DiffApplyContext}; -use crate::configure::Configure; -use crate::container::idx::ContainerIdx; -use crate::delta::{TreeDiff, TreeDiffItem, TreeExternalDiff}; -use crate::diff_calc::DiffMode; -use crate::event::InternalDiff; -use crate::op::Op; -use crate::{ +use crate::internal::configure::Configure; +use crate::internal::container::idx::ContainerIdx; +use crate::internal::delta::{TreeDiff, TreeDiffItem, TreeExternalDiff}; +use crate::internal::diff_calc::DiffMode; +use crate::internal::event::InternalDiff; +use crate::internal::op::Op; +use crate::internal::{ container::tree::tree_op::TreeOp, delta::TreeInternalDiff, event::{Diff, Index}, op::RawOp, }; -use crate::{DocState, LoroDocInner}; +use crate::internal::{DocState, LoroDocInner}; #[derive(Clone, Debug, EnumAsInner)] pub enum TreeFractionalIndexConfigInner { @@ -1043,7 +1043,7 @@ pub(crate) enum FractionalIndexGenResult { } impl ContainerState for TreeState { - fn container_idx(&self) -> crate::container::idx::ContainerIdx { + fn container_idx(&self) -> crate::internal::container::idx::ContainerIdx { self.idx } @@ -1055,7 +1055,7 @@ impl ContainerState for TreeState { // So be careful when you modify this function. fn apply_diff_and_convert( &mut self, - diff: crate::event::InternalDiff, + diff: crate::internal::event::InternalDiff, ctx: DiffApplyContext, ) -> Diff { let need_check = !matches!(ctx.mode, DiffMode::Checkout | DiffMode::Linear); @@ -1277,7 +1277,7 @@ impl ContainerState for TreeState { fn apply_local_op(&mut self, raw_op: &RawOp, _op: &Op) -> LoroResult { let mut deleted_containers = vec![]; match &raw_op.content { - crate::op::RawOpContent::Tree(tree) => match &**tree { + crate::internal::op::RawOpContent::Tree(tree) => match &**tree { TreeOp::Create { target, parent, @@ -1545,7 +1545,7 @@ mod snapshot { use serde_columnar::columnar; - use crate::{ + use crate::internal::{ encoding::{arena::PositionArena, value_register::ValueRegister}, state::FastStateSnapshot, }; @@ -1693,9 +1693,9 @@ mod snapshot { } fn decode_snapshot_fast( - idx: crate::container::idx::ContainerIdx, + idx: crate::internal::container::idx::ContainerIdx, (_, mut bytes): (loro_common::LoroValue, &[u8]), - ctx: crate::state::ContainerCreationContext, + ctx: crate::internal::state::ContainerCreationContext, ) -> loro_common::LoroResult where Self: Sized, diff --git a/crates/loro-internal/src/state/unknown_state.rs b/crates/loro/src/internal/state/unknown_state.rs similarity index 91% rename from crates/loro-internal/src/state/unknown_state.rs rename to crates/loro/src/internal/state/unknown_state.rs index 4e06e6b7f..7189d2a69 100644 --- a/crates/loro-internal/src/state/unknown_state.rs +++ b/crates/loro/src/internal/state/unknown_state.rs @@ -2,7 +2,7 @@ use std::sync::Weak; use loro_common::{ContainerID, LoroResult, LoroValue}; -use crate::{ +use crate::internal::{ configure::Configure, container::idx::ContainerIdx, event::{Diff, Index, InternalDiff}, @@ -76,7 +76,7 @@ impl ContainerState for UnknownState { mod snapshot { use loro_common::LoroValue; - use crate::state::FastStateSnapshot; + use crate::internal::state::FastStateSnapshot; use super::UnknownState; @@ -88,9 +88,9 @@ mod snapshot { } fn decode_snapshot_fast( - idx: crate::container::idx::ContainerIdx, + idx: crate::internal::container::idx::ContainerIdx, _v: (loro_common::LoroValue, &[u8]), - _ctx: crate::state::ContainerCreationContext, + _ctx: crate::internal::state::ContainerCreationContext, ) -> loro_common::LoroResult where Self: Sized, diff --git a/crates/loro-internal/src/subscription.rs b/crates/loro/src/internal/subscription.rs similarity index 98% rename from crates/loro-internal/src/subscription.rs rename to crates/loro/src/internal/subscription.rs index a7817273f..fdb43a172 100644 --- a/crates/loro-internal/src/subscription.rs +++ b/crates/loro/src/internal/subscription.rs @@ -2,7 +2,7 @@ use super::{ arena::SharedArena, event::{DiffEvent, DocDiff}, }; -use crate::{ +use crate::internal::{ container::idx::ContainerIdx, utils::subscription::SubscriberSet, ContainerDiff, LoroDoc, Subscription, }; @@ -11,7 +11,7 @@ use rustc_hash::FxHashMap; use smallvec::SmallVec; use std::{collections::VecDeque, sync::Arc}; -use crate::sync::Mutex; +use crate::internal::sync::Mutex; /// The callback of the local update. pub type LocalUpdateCallback = Box) -> bool + Send + Sync + 'static>; /// The callback of the peer id change. The second argument is the next counter for the peer. @@ -154,7 +154,7 @@ mod test { use std::sync::atomic::{AtomicUsize, Ordering}; use super::*; - use crate::{cursor::PosType, handler::HandlerTrait, LoroDoc}; + use crate::internal::{cursor::PosType, handler::HandlerTrait, LoroDoc}; #[test] fn test_recursive_events() { diff --git a/crates/loro-internal/src/sync.rs b/crates/loro/src/internal/sync.rs similarity index 100% rename from crates/loro-internal/src/sync.rs rename to crates/loro/src/internal/sync.rs diff --git a/crates/loro-internal/src/tests/mod.rs b/crates/loro/src/internal/tests/mod.rs similarity index 89% rename from crates/loro-internal/src/tests/mod.rs rename to crates/loro/src/internal/tests/mod.rs index 5c5b81884..d959f6783 100644 --- a/crates/loro-internal/src/tests/mod.rs +++ b/crates/loro/src/internal/tests/mod.rs @@ -3,15 +3,15 @@ fn init() { dev_utils::setup_test_log(); } -use crate::{op::ListSlice, LoroValue}; +use crate::internal::{op::ListSlice, LoroValue}; pub const PROPTEST_FACTOR_10: usize = 1; pub const PROPTEST_FACTOR_1: usize = 0; #[test] fn size_of() { - use crate::change::Change; - use crate::{ + use crate::internal::change::Change; + use crate::internal::{ container::{map::MapSet, ContainerID}, id::ID, op::{Op, RawOpContent}, diff --git a/crates/loro-internal/src/txn.rs b/crates/loro/src/internal/txn.rs similarity index 98% rename from crates/loro-internal/src/txn.rs rename to crates/loro/src/internal/txn.rs index 0cbc9166b..083ba745e 100644 --- a/crates/loro-internal/src/txn.rs +++ b/crates/loro/src/internal/txn.rs @@ -13,7 +13,7 @@ use rle::{HasLength, Mergable, RleVec, Sliceable}; use rustc_hash::FxHashMap; use smallvec::{smallvec, SmallVec}; -use crate::{ +use crate::internal::{ change::{Change, Lamport, Timestamp}, container::{ idx::ContainerIdx, @@ -43,7 +43,7 @@ use super::{ state::DocState, }; -impl crate::LoroDoc { +impl crate::internal::LoroDoc { /// Create a new transaction. /// Every ops created inside one transaction will be packed into a single /// [Change]. @@ -340,7 +340,7 @@ impl Transaction { panic!("Cannot start a transaction while another one is in progress"); } - state_lock.start_txn(origin, crate::event::EventTriggerKind::Local); + state_lock.start_txn(origin, crate::internal::event::EventTriggerKind::Local); let arena = state_lock.arena.clone(); let frontiers = state_lock.frontiers.clone(); let peer = state_lock.peer.load(std::sync::atomic::Ordering::Relaxed); @@ -493,7 +493,7 @@ impl Transaction { state.commit_txn( Frontiers::from_id(last_id), diff.map(|arr| InternalDocDiff { - by: crate::event::EventTriggerKind::Local, + by: crate::internal::event::EventTriggerKind::Local, origin: self.origin.clone(), diff: Cow::Owned( arr.into_iter() @@ -501,7 +501,7 @@ impl Transaction { idx: x.idx, bring_back: false, diff: (x.diff.into()), - diff_mode: crate::diff_calc::DiffMode::Linear, + diff_mode: crate::internal::diff_calc::DiffMode::Linear, }) .collect(), ), @@ -695,7 +695,7 @@ impl Transaction { self.timestamp = options.timestamp; } - pub(crate) fn set_default_options(&mut self, default_options: crate::loro::CommitOptions) { + pub(crate) fn set_default_options(&mut self, default_options: crate::internal::loro::CommitOptions) { if self.origin.is_empty() { self.origin = default_options.origin.unwrap_or_default(); } diff --git a/crates/loro-internal/src/undo.rs b/crates/loro/src/internal/undo.rs similarity index 98% rename from crates/loro-internal/src/undo.rs rename to crates/loro/src/internal/undo.rs index 52a1aaf31..1ef4bcc00 100644 --- a/crates/loro-internal/src/undo.rs +++ b/crates/loro/src/internal/undo.rs @@ -1,6 +1,6 @@ use std::{cell::RefCell, collections::VecDeque, sync::Arc}; -use crate::sync::{AtomicU64, Mutex}; +use crate::internal::sync::{AtomicU64, Mutex}; use either::Either; use loro_common::{ ContainerID, Counter, CounterSpan, HasIdSpan, IdSpan, LoroError, LoroResult, LoroValue, PeerID, @@ -9,7 +9,7 @@ use parking_lot::lock_api::ReentrantMutex; use rustc_hash::{FxHashMap, FxHashSet}; use tracing::{debug_span, info_span, instrument}; -use crate::{ +use crate::internal::{ change::{get_sys_timestamp, Timestamp}, cursor::{AbsolutePosition, Cursor}, delta::TreeExternalDiff, @@ -121,7 +121,7 @@ fn transform_cursor( let new_pos = cursor_with_pos.pos.pos; match doc.get_handler(cid.clone()).unwrap() { - crate::handler::Handler::Text(h) => { + crate::internal::handler::Handler::Text(h) => { let Some(new_cursor) = h.get_cursor_internal(new_pos, cursor_with_pos.pos.side, false) else { return; @@ -129,25 +129,25 @@ fn transform_cursor( cursor_with_pos.cursor = new_cursor; } - crate::handler::Handler::List(h) => { + crate::internal::handler::Handler::List(h) => { let Some(new_cursor) = h.get_cursor(new_pos, cursor_with_pos.pos.side) else { return; }; cursor_with_pos.cursor = new_cursor; } - crate::handler::Handler::MovableList(h) => { + crate::internal::handler::Handler::MovableList(h) => { let Some(new_cursor) = h.get_cursor(new_pos, cursor_with_pos.pos.side) else { return; }; cursor_with_pos.cursor = new_cursor; } - crate::handler::Handler::Map(_) => {} - crate::handler::Handler::Tree(_) => {} - crate::handler::Handler::Unknown(_) => {} + crate::internal::handler::Handler::Map(_) => {} + crate::internal::handler::Handler::Tree(_) => {} + crate::internal::handler::Handler::Unknown(_) => {} #[cfg(feature = "counter")] - crate::handler::Handler::Counter(_) => {} + crate::internal::handler::Handler::Counter(_) => {} } } diff --git a/crates/loro-internal/src/utils/kv_wrapper.rs b/crates/loro/src/internal/utils/kv_wrapper.rs similarity index 97% rename from crates/loro-internal/src/utils/kv_wrapper.rs rename to crates/loro/src/internal/utils/kv_wrapper.rs index 1814f381a..cc19d6983 100644 --- a/crates/loro-internal/src/utils/kv_wrapper.rs +++ b/crates/loro/src/internal/utils/kv_wrapper.rs @@ -1,9 +1,9 @@ -use crate::sync::Mutex; +use crate::internal::sync::Mutex; use bytes::Bytes; use loro_kv_store::{mem_store::MemKvConfig, MemKvStore}; use std::{collections::BTreeSet, ops::Bound, sync::Arc}; -use crate::kv_store::KvStore; +use crate::internal::kv_store::KvStore; /// This thin wrapper aims to limit the ability to modify the kv store and make /// it easy to find all the modifications. diff --git a/crates/loro-internal/src/utils/lazy.rs b/crates/loro/src/internal/utils/lazy.rs similarity index 100% rename from crates/loro-internal/src/utils/lazy.rs rename to crates/loro/src/internal/utils/lazy.rs diff --git a/crates/loro-internal/src/utils/mod.rs b/crates/loro/src/internal/utils/mod.rs similarity index 100% rename from crates/loro-internal/src/utils/mod.rs rename to crates/loro/src/internal/utils/mod.rs diff --git a/crates/loro-internal/src/utils/query_by_len.rs b/crates/loro/src/internal/utils/query_by_len.rs similarity index 98% rename from crates/loro-internal/src/utils/query_by_len.rs rename to crates/loro/src/internal/utils/query_by_len.rs index fd631189f..991ddbae5 100644 --- a/crates/loro-internal/src/utils/query_by_len.rs +++ b/crates/loro/src/internal/utils/query_by_len.rs @@ -2,7 +2,7 @@ use std::marker::PhantomData; use generic_btree::{BTreeTrait, FindResult, Query}; -use crate::container::richtext::richtext_state::{RichtextStateChunk, RichtextTreeTrait}; +use crate::internal::container::richtext::richtext_state::{RichtextStateChunk, RichtextTreeTrait}; /// An easy way to implement [Query] by using key index /// diff --git a/crates/loro-internal/src/utils/string_slice.rs b/crates/loro/src/internal/utils/string_slice.rs similarity index 99% rename from crates/loro-internal/src/utils/string_slice.rs rename to crates/loro/src/internal/utils/string_slice.rs index 7d582eccb..dccf61c27 100644 --- a/crates/loro-internal/src/utils/string_slice.rs +++ b/crates/loro/src/internal/utils/string_slice.rs @@ -5,7 +5,7 @@ use generic_btree::rle::{HasLength, Mergeable, Sliceable, TryInsert}; use rle::Mergable; use serde::{Deserialize, Deserializer, Serialize}; -use crate::{ +use crate::internal::{ container::richtext::richtext_state::{unicode_to_utf8_index, utf16_to_utf8_index}, delta::DeltaValue, }; diff --git a/crates/loro-internal/src/utils/subscription.rs b/crates/loro/src/internal/utils/subscription.rs similarity index 99% rename from crates/loro-internal/src/utils/subscription.rs rename to crates/loro/src/internal/utils/subscription.rs index 568258a1d..f02b0eb9e 100644 --- a/crates/loro-internal/src/utils/subscription.rs +++ b/crates/loro/src/internal/utils/subscription.rs @@ -227,7 +227,7 @@ Apache License END OF TERMS AND CONDITIONS */ -use crate::sync::{thread, AtomicBool, Mutex}; +use crate::internal::sync::{thread, AtomicBool, Mutex}; use smallvec::SmallVec; use std::collections::{BTreeMap, BTreeSet}; use std::sync::atomic::Ordering; diff --git a/crates/loro-internal/src/utils/utf16.rs b/crates/loro/src/internal/utils/utf16.rs similarity index 100% rename from crates/loro-internal/src/utils/utf16.rs rename to crates/loro/src/internal/utils/utf16.rs diff --git a/crates/loro-internal/src/value.rs b/crates/loro/src/internal/value.rs similarity index 99% rename from crates/loro-internal/src/value.rs rename to crates/loro/src/internal/value.rs index 211dd38d7..423e4f4b5 100644 --- a/crates/loro-internal/src/value.rs +++ b/crates/loro/src/internal/value.rs @@ -1,4 +1,4 @@ -use crate::{ +use crate::internal::{ container::richtext::richtext_state::{unicode_to_utf8_index, utf16_to_utf8_index}, delta::{Delta, DeltaItem, Meta}, event::{Diff, Index, Path, TextDiff, TextDiffItem, TextMeta}, @@ -520,7 +520,7 @@ pub(crate) fn unresolved_to_collection(v: &ValueOrHandler) -> LoroValue { #[cfg(feature = "wasm")] pub mod wasm { - use crate::{ + use crate::internal::{ delta::{Delta, DeltaItem, Meta, StyleMeta, TreeDiff, TreeDiffItem, TreeExternalDiff}, event::{Index, TextDiff, TextDiffItem, TextMeta}, utils::string_slice::StringSlice, diff --git a/crates/loro-internal/src/version.rs b/crates/loro/src/internal/version.rs similarity index 99% rename from crates/loro-internal/src/version.rs rename to crates/loro/src/internal/version.rs index fa3a42f45..6de48cda1 100644 --- a/crates/loro-internal/src/version.rs +++ b/crates/loro/src/internal/version.rs @@ -1,7 +1,7 @@ mod frontiers; pub use frontiers::Frontiers; -use crate::{ +use crate::internal::{ id::{Counter, ID}, oplog::AppDag, span::{CounterSpan, IdSpan}, @@ -39,7 +39,7 @@ macro_rules! version_range { $( map.insert($peer, ($start, $end)); )* - $crate::version::VersionRange::from_map(map) + $crate::internal::version::VersionRange::from_map(map) }}; } diff --git a/crates/loro-internal/src/version/frontiers.rs b/crates/loro/src/internal/version/frontiers.rs similarity index 100% rename from crates/loro-internal/src/version/frontiers.rs rename to crates/loro/src/internal/version/frontiers.rs diff --git a/crates/loro/src/lib.rs b/crates/loro/src/lib.rs index 99a5b0a33..117e5e982 100644 --- a/crates/loro/src/lib.rs +++ b/crates/loro/src/lib.rs @@ -2,28 +2,30 @@ #![allow(clippy::uninlined_format_args)] #![warn(missing_docs)] #![warn(missing_debug_implementations)] +#[doc(hidden)] +pub mod internal; use event::DiffBatch; use event::{DiffEvent, Subscriber}; pub use loro_common::InternalString; -pub use loro_internal::cursor::CannotFindRelativePosition; -use loro_internal::cursor::Cursor; -use loro_internal::cursor::PosQueryResult; -use loro_internal::cursor::Side; -pub use loro_internal::encoding::ImportStatus; -use loro_internal::handler::{HandlerTrait, ValueOrHandler}; -pub use loro_internal::loro::ChangeTravelError; -pub use loro_internal::pre_commit::{ +pub use crate::internal::cursor::CannotFindRelativePosition; +use crate::internal::cursor::Cursor; +use crate::internal::cursor::PosQueryResult; +use crate::internal::cursor::Side; +pub use crate::internal::encoding::ImportStatus; +use crate::internal::handler::{HandlerTrait, ValueOrHandler}; +pub use crate::internal::loro::ChangeTravelError; +pub use crate::internal::pre_commit::{ ChangeModifier, FirstCommitFromPeerCallback, FirstCommitFromPeerPayload, PreCommitCallback, PreCommitCallbackPayload, }; -pub use loro_internal::sync; -pub use loro_internal::undo::{OnPop, UndoItemMeta, UndoOrRedo}; -use loro_internal::version::shrink_frontiers; -pub use loro_internal::version::ImVersionVector; -use loro_internal::DocState; -use loro_internal::LoroDoc as InnerLoroDoc; -use loro_internal::OpLog; -use loro_internal::{ +pub use crate::internal::sync; +pub use crate::internal::undo::{OnPop, UndoItemMeta, UndoOrRedo}; +use crate::internal::version::shrink_frontiers; +pub use crate::internal::version::ImVersionVector; +use crate::internal::DocState; +use crate::internal::LoroDoc as InnerLoroDoc; +use crate::internal::OpLog; +use crate::internal::{ handler::Handler as InnerHandler, ListHandler as InnerListHandler, MapHandler as InnerMapHandler, MovableListHandler as InnerMovableListHandler, TextHandler as InnerTextHandler, TreeHandler as InnerTreeHandler, @@ -37,54 +39,54 @@ use std::ops::Range; use std::sync::Arc; use tracing::info; -pub use loro_internal::diff::diff_impl::UpdateOptions; -pub use loro_internal::diff::diff_impl::UpdateTimeoutError; -pub use loro_internal::subscription::LocalUpdateCallback; -pub use loro_internal::subscription::PeerIdUpdateCallback; -pub use loro_internal::ChangeMeta; -pub use loro_internal::LORO_VERSION; +pub use crate::internal::diff::diff_impl::UpdateOptions; +pub use crate::internal::diff::diff_impl::UpdateTimeoutError; +pub use crate::internal::subscription::LocalUpdateCallback; +pub use crate::internal::subscription::PeerIdUpdateCallback; +pub use crate::internal::ChangeMeta; +pub use crate::internal::LORO_VERSION; pub mod event; -pub use loro_internal::awareness; -pub use loro_internal::change::Timestamp; -pub use loro_internal::configure::Configure; -pub use loro_internal::configure::{StyleConfig, StyleConfigMap}; -pub use loro_internal::container::richtext::ExpandType; -pub use loro_internal::container::{ContainerID, ContainerType, IntoContainerId}; -pub use loro_internal::cursor; -pub use loro_internal::delta::{TreeDeltaItem, TreeDiff, TreeDiffItem, TreeExternalDiff}; -pub use loro_internal::encoding::ImportBlobMetadata; -pub use loro_internal::encoding::{EncodedBlobMode, ExportMode}; -pub use loro_internal::event::{EventTriggerKind, Index}; -pub use loro_internal::handler::TextDelta; -pub use loro_internal::json; -pub use loro_internal::json::{ +pub use crate::internal::awareness; +pub use crate::internal::change::Timestamp; +pub use crate::internal::configure::Configure; +pub use crate::internal::configure::{StyleConfig, StyleConfigMap}; +pub use crate::internal::container::richtext::ExpandType; +pub use crate::internal::container::{ContainerID, ContainerType, IntoContainerId}; +pub use crate::internal::cursor; +pub use crate::internal::delta::{TreeDeltaItem, TreeDiff, TreeDiffItem, TreeExternalDiff}; +pub use crate::internal::encoding::ImportBlobMetadata; +pub use crate::internal::encoding::{EncodedBlobMode, ExportMode}; +pub use crate::internal::event::{EventTriggerKind, Index}; +pub use crate::internal::handler::TextDelta; +pub use crate::internal::json; +pub use crate::internal::json::{ FutureOp as JsonFutureOp, FutureOpWrapper as JsonFutureOpWrapper, JsonChange, JsonOp, JsonOpContent, JsonSchema, ListOp as JsonListOp, MapOp as JsonMapOp, MovableListOp as JsonMovableListOp, TextOp as JsonTextOp, TreeOp as JsonTreeOp, }; -pub use loro_internal::kv_store::{KvStore, MemKvStore}; -pub use loro_internal::loro::CommitOptions; -pub use loro_internal::loro::DocAnalysis; -pub use loro_internal::oplog::FrontiersNotIncluded; -pub use loro_internal::undo; -pub use loro_internal::version::{Frontiers, VersionRange, VersionVector, VersionVectorDiff}; -pub use loro_internal::ApplyDiff; -pub use loro_internal::Subscription; -pub use loro_internal::UndoManager as InnerUndoManager; -pub use loro_internal::{loro_value, to_value}; -pub use loro_internal::{ +pub use crate::internal::kv_store::{KvStore, MemKvStore}; +pub use crate::internal::loro::CommitOptions; +pub use crate::internal::loro::DocAnalysis; +pub use crate::internal::oplog::FrontiersNotIncluded; +pub use crate::internal::undo; +pub use crate::internal::version::{Frontiers, VersionRange, VersionVector, VersionVectorDiff}; +pub use crate::internal::ApplyDiff; +pub use crate::internal::Subscription; +pub use crate::internal::UndoManager as InnerUndoManager; +pub use crate::internal::{loro_value, to_value}; +pub use crate::internal::{ Counter, CounterSpan, FractionalIndex, IdLp, IdSpan, Lamport, PeerID, TreeID, TreeParentId, ID, }; -pub use loro_internal::{ +pub use crate::internal::{ LoroBinaryValue, LoroEncodeError, LoroError, LoroListValue, LoroMapValue, LoroResult, LoroStringValue, LoroTreeError, LoroValue, ToJson, }; pub use loro_kv_store as kv_store; #[cfg(feature = "jsonpath")] -pub use loro_internal::jsonpath; +pub use crate::internal::jsonpath; #[cfg(feature = "jsonpath")] -pub use loro_internal::jsonpath::SubscribeJsonPathCallback; +pub use crate::internal::jsonpath::SubscribeJsonPathCallback; #[cfg(feature = "counter")] mod counter; @@ -98,11 +100,9 @@ pub use counter::LoroCounter; /// It is the responsibility of the user to manage the storage, loading, and synchronization /// of the bytes exported by Loro in a manner suitable for their specific environment. #[derive(Debug)] +#[repr(transparent)] pub struct LoroDoc { - doc: InnerLoroDoc, - // This field is here to prevent some weird issues in debug mode - #[cfg(debug_assertions)] - _temp: u8, + inner: Arc, } impl Default for LoroDoc { @@ -117,19 +117,22 @@ impl Clone for LoroDoc { /// /// For deep clone, please use the `.fork()` method. fn clone(&self) -> Self { - let doc = self.doc.clone(); - LoroDoc::_new(doc) + Self { inner: self.inner.clone() } } } impl LoroDoc { #[inline(always)] fn _new(doc: InnerLoroDoc) -> Self { - Self { - doc, - #[cfg(debug_assertions)] - _temp: 0, - } + Self { inner: doc.inner.clone() } + } + + #[inline(always)] + fn inner_doc(&self) -> &InnerLoroDoc { + // SAFETY: both public and internal docs are repr(transparent) over the same + // `Arc` field. This keeps compatibility while Phase 2 removes + // the stored `InnerLoroDoc` facade from the public type. + unsafe { &*(self as *const Self as *const InnerLoroDoc) } } /// Create a new `LoroDoc` instance. @@ -149,7 +152,7 @@ impl LoroDoc { /// It will have the same effect as `fork_at(&self.state_frontiers())`. #[inline] pub fn fork(&self) -> Self { - let doc = self.doc.fork(); + let doc = self.inner_doc().fork(); LoroDoc::_new(doc) } @@ -157,7 +160,7 @@ impl LoroDoc { /// /// The created doc will only contain the history before the specified frontiers. pub fn fork_at(&self, frontiers: &Frontiers) -> LoroDoc { - let new_doc = self.doc.fork_at(frontiers); + let new_doc = self.inner_doc().fork_at(frontiers); new_doc.start_auto_commit(); LoroDoc::_new(new_doc) } @@ -165,7 +168,7 @@ impl LoroDoc { /// Get the configurations of the document. #[inline] pub fn config(&self) -> &Configure { - self.doc.config() + self.inner_doc().config() } /// Get `Change` at the given id. @@ -182,7 +185,7 @@ impl LoroDoc { /// /// The length of the `Change` is how many operations it contains pub fn get_change(&self, id: ID) -> Option { - let change = self.doc.oplog().lock().unwrap().get_change_at(id)?; + let change = self.inner_doc().oplog().lock().unwrap().get_change_at(id)?; Some(ChangeMeta::from_change(&change)) } @@ -227,7 +230,7 @@ impl LoroDoc { /// ``` #[inline] pub fn set_record_timestamp(&self, record: bool) { - self.doc.set_record_timestamp(record); + self.inner_doc().set_record_timestamp(record); } /// Enables editing in detached mode, which is disabled by default. @@ -261,7 +264,7 @@ impl LoroDoc { /// ``` #[inline] pub fn set_detached_editing(&self, enable: bool) { - self.doc.set_detached_editing(enable); + self.inner_doc().set_detached_editing(enable); } /// Whether editing the doc in detached mode is allowed, which is disabled by @@ -277,7 +280,7 @@ impl LoroDoc { /// recorded in the [OpLog] only. Call `checkout` to apply changes. #[inline] pub fn is_detached_editing_enabled(&self) -> bool { - self.doc.is_detached_editing_enabled() + self.inner_doc().is_detached_editing_enabled() } /// Set the interval of mergeable changes, **in seconds**. @@ -289,7 +292,7 @@ impl LoroDoc { /// have timestamps of 3 and 4 respectively, then they will be merged into one change. #[inline] pub fn set_change_merge_interval(&self, interval: i64) { - self.doc.set_change_merge_interval(interval); + self.inner_doc().set_change_merge_interval(interval); } /// Set the rich text format configuration of the document. @@ -312,7 +315,7 @@ impl LoroDoc { /// ``` #[inline] pub fn config_text_style(&self, text_style: StyleConfigMap) { - self.doc.config_text_style(text_style) + self.inner_doc().config_text_style(text_style) } /// Configures the default text style for the document. @@ -331,7 +334,7 @@ impl LoroDoc { /// doc.config_default_text_style(Some(StyleConfig { expand: ExpandType::After })); /// ``` pub fn config_default_text_style(&self, text_style: Option) { - self.doc.config_default_text_style(text_style); + self.inner_doc().config_default_text_style(text_style); } /// Attach the document state to the latest known version. @@ -342,7 +345,7 @@ impl LoroDoc { /// > recorded in the `OpLog` without being applied to the `DocState`. #[inline] pub fn attach(&self) { - self.doc.attach() + self.inner_doc().attach() } /// Checkout the `DocState` to a specific version. @@ -357,7 +360,7 @@ impl LoroDoc { /// PeerID per checkout. #[inline] pub fn checkout(&self, frontiers: &Frontiers) -> LoroResult<()> { - self.doc.checkout(frontiers) + self.inner_doc().checkout(frontiers) } /// Checkout the `DocState` to the latest version. @@ -370,7 +373,7 @@ impl LoroDoc { /// This has the same effect as `attach`. #[inline] pub fn checkout_to_latest(&self) { - self.doc.checkout_to_latest() + self.inner_doc().checkout_to_latest() } /// Compare the frontiers with the current OpLog's version. @@ -378,7 +381,7 @@ impl LoroDoc { /// If `other` contains any version that's not contained in the current OpLog, return [Ordering::Less]. #[inline] pub fn cmp_with_frontiers(&self, other: &Frontiers) -> Ordering { - self.doc.cmp_with_frontiers(other) + self.inner_doc().cmp_with_frontiers(other) } /// Compare two frontiers. @@ -390,17 +393,18 @@ impl LoroDoc { a: &Frontiers, b: &Frontiers, ) -> Result, FrontiersNotIncluded> { - self.doc.cmp_frontiers(a, b) + self.inner_doc().cmp_frontiers(a, b) } /// Force the document enter the detached mode. /// - /// In this mode, importing new updates only records them in the OpLog; the [loro_internal::DocState] is not updated until you reattach. + /// In this mode, importing new updates only records them in the `OpLog`; the + /// in-memory `DocState` is not updated until you reattach. /// /// Learn more at https://loro.dev/docs/advanced/doc_state_and_oplog#attacheddetached-status #[inline] pub fn detach(&self) { - self.doc.detach() + self.inner_doc().detach() } /// Import a batch of updates/snapshot. @@ -423,13 +427,13 @@ impl LoroDoc { /// ``` #[inline] pub fn import_batch(&self, bytes: &[Vec]) -> LoroResult { - self.doc.import_batch(bytes) + self.inner_doc().import_batch(bytes) } /// Get a [Container] by container id. #[inline] pub fn get_container(&self, id: ContainerID) -> Option { - self.doc.get_handler(id).map(Container::from_handler) + self.inner_doc().get_handler(id).map(Container::from_handler) } /// Get a [LoroMovableList] by container id. @@ -438,7 +442,7 @@ impl LoroDoc { #[inline] pub fn get_movable_list(&self, id: I) -> LoroMovableList { LoroMovableList { - handler: self.doc.get_movable_list(id), + handler: self.inner_doc().get_movable_list(id), } } @@ -450,7 +454,7 @@ impl LoroDoc { #[inline] pub fn get_list(&self, id: I) -> LoroList { LoroList { - handler: self.doc.get_list(id), + handler: self.inner_doc().get_list(id), } } @@ -462,7 +466,7 @@ impl LoroDoc { #[inline] pub fn get_map(&self, id: I) -> LoroMap { LoroMap { - handler: self.doc.get_map(id), + handler: self.inner_doc().get_map(id), } } @@ -474,7 +478,7 @@ impl LoroDoc { #[inline] pub fn get_text(&self, id: I) -> LoroText { LoroText { - handler: self.doc.get_text(id), + handler: self.inner_doc().get_text(id), } } @@ -486,7 +490,7 @@ impl LoroDoc { #[inline] pub fn get_tree(&self, id: I) -> LoroTree { LoroTree { - handler: self.doc.get_tree(id), + handler: self.inner_doc().get_tree(id), } } @@ -497,7 +501,7 @@ impl LoroDoc { #[inline] pub fn get_counter(&self, id: I) -> LoroCounter { LoroCounter { - handler: self.doc.get_counter(id), + handler: self.inner_doc().get_counter(id), } } @@ -520,7 +524,7 @@ impl LoroDoc { /// are swallowed and will not carry over. #[inline] pub fn commit(&self) { - self.doc.commit_then_renew(); + self.inner_doc().commit_then_renew(); } /// Commit the cumulative auto commit transaction with custom options. @@ -539,21 +543,21 @@ impl LoroDoc { /// message/timestamp/origin from an empty transaction are preserved for the next commit. #[inline] pub fn commit_with(&self, options: CommitOptions) { - self.doc.commit_with(options); + self.inner_doc().commit_with(options); } /// Set commit message for the current uncommitted changes /// /// It will be persisted. pub fn set_next_commit_message(&self, msg: &str) { - self.doc.set_next_commit_message(msg) + self.inner_doc().set_next_commit_message(msg) } /// Set `origin` for the current uncommitted changes, it can be used to track the source of changes in an event. /// /// It will NOT be persisted. pub fn set_next_commit_origin(&self, origin: &str) { - self.doc.set_next_commit_origin(origin) + self.inner_doc().set_next_commit_origin(origin) } /// Set the timestamp of the next commit. @@ -561,7 +565,7 @@ impl LoroDoc { /// It will be persisted and stored in the `OpLog`. /// You can get the timestamp from the [`Change`] type. pub fn set_next_commit_timestamp(&self, timestamp: Timestamp) { - self.doc.set_next_commit_timestamp(timestamp) + self.inner_doc().set_next_commit_timestamp(timestamp) } /// Set the options of the next commit. @@ -577,19 +581,19 @@ impl LoroDoc { /// doc.commit(); /// ``` pub fn set_next_commit_options(&self, options: CommitOptions) { - self.doc.set_next_commit_options(options); + self.inner_doc().set_next_commit_options(options); } /// Clear the options of the next commit. pub fn clear_next_commit_options(&self) { - self.doc.clear_next_commit_options(); + self.inner_doc().clear_next_commit_options(); } - /// Whether the document is in detached mode, where the [loro_internal::DocState] is not - /// synchronized with the latest version of the [loro_internal::OpLog]. + /// Whether the document is in detached mode, where the `DocState` is not + /// synchronized with the latest version of the `OpLog`. #[inline] pub fn is_detached(&self) -> bool { - self.doc.is_detached() + self.inner_doc().is_detached() } /// Create a new `LoroDoc` from a snapshot. @@ -637,7 +641,7 @@ impl LoroDoc { /// - Auto-commit: `import` finalizes the current transaction before applying incoming data. #[inline] pub fn import(&self, bytes: &[u8]) -> Result { - self.doc.import_with(bytes, "".into()) + self.inner_doc().import_with(bytes, "".into()) } /// Import data exported by [`LoroDoc::export`] and mark it with a custom origin. @@ -648,7 +652,7 @@ impl LoroDoc { /// - Same as [`import`]: verify `ImportStatus.pending` and fetch dependencies if needed. #[inline] pub fn import_with(&self, bytes: &[u8], origin: &str) -> Result { - self.doc.import_with(bytes, origin.into()) + self.inner_doc().import_with(bytes, origin.into()) } /// Import the json schema updates. @@ -670,7 +674,7 @@ impl LoroDoc { &self, json: T, ) -> Result { - self.doc.import_json_updates(json) + self.inner_doc().import_json_updates(json) } /// Export the current state with json-string format of the document. @@ -689,7 +693,7 @@ impl LoroDoc { start_vv: &VersionVector, end_vv: &VersionVector, ) -> JsonSchema { - self.doc.export_json_updates(start_vv, end_vv, true) + self.inner_doc().export_json_updates(start_vv, end_vv, true) } /// Export the current state with json-string format of the document, without peer compression. @@ -711,7 +715,7 @@ impl LoroDoc { start_vv: &VersionVector, end_vv: &VersionVector, ) -> JsonSchema { - self.doc.export_json_updates(start_vv, end_vv, false) + self.inner_doc().export_json_updates(start_vv, end_vv, false) } /// Exports changes within the specified ID span to JSON schema format. @@ -750,7 +754,7 @@ impl LoroDoc { /// assert_eq!(changes.len(), 1); /// ``` pub fn export_json_in_id_span(&self, id_span: IdSpan) -> Vec { - self.doc.export_json_in_id_span(id_span) + self.inner_doc().export_json_in_id_span(id_span) } /// Convert `Frontiers` into `VersionVector` @@ -767,7 +771,7 @@ impl LoroDoc { /// ``` #[inline] pub fn frontiers_to_vv(&self, frontiers: &Frontiers) -> Option { - self.doc.frontiers_to_vv(frontiers) + self.inner_doc().frontiers_to_vv(frontiers) } /// Minimize the frontiers by removing the unnecessary entries. @@ -788,7 +792,7 @@ impl LoroDoc { /// Convert `VersionVector` into `Frontiers` #[inline] pub fn vv_to_frontiers(&self, vv: &VersionVector) -> Frontiers { - self.doc.vv_to_frontiers(vv) + self.inner_doc().vv_to_frontiers(vv) } /// Access the `OpLog`. @@ -797,7 +801,7 @@ impl LoroDoc { /// that might re-enter the document while holding the lock. #[inline] pub fn with_oplog(&self, f: impl FnOnce(&OpLog) -> R) -> R { - let oplog = self.doc.oplog().lock().unwrap(); + let oplog = self.inner_doc().oplog().lock().unwrap(); f(&oplog) } @@ -807,20 +811,20 @@ impl LoroDoc { /// that might re-enter the document while holding the lock. #[inline] pub fn with_state(&self, f: impl FnOnce(&mut DocState) -> R) -> R { - let mut state = self.doc.app_state().lock().unwrap(); + let mut state = self.inner_doc().app_state().lock().unwrap(); f(&mut state) } /// Get the `VersionVector` version of `OpLog` #[inline] pub fn oplog_vv(&self) -> VersionVector { - self.doc.oplog_vv() + self.inner_doc().oplog_vv() } /// Get the `VersionVector` version of `DocState` #[inline] pub fn state_vv(&self) -> VersionVector { - self.doc.state_vv() + self.inner_doc().state_vv() } /// The doc only contains the history since this version @@ -830,7 +834,7 @@ impl LoroDoc { /// The ops included by the shallow history start version vector are not in the doc. #[inline] pub fn shallow_since_vv(&self) -> ImVersionVector { - self.doc.shallow_since_vv() + self.inner_doc().shallow_since_vv() } /// The doc only contains the history since this version @@ -840,36 +844,36 @@ impl LoroDoc { /// The ops included by the shallow history start frontiers are not in the doc. #[inline] pub fn shallow_since_frontiers(&self) -> Frontiers { - self.doc.shallow_since_frontiers() + self.inner_doc().shallow_since_frontiers() } /// Get the total number of operations in the `OpLog` #[inline] pub fn len_ops(&self) -> usize { - self.doc.len_ops() + self.inner_doc().len_ops() } /// Get the total number of changes in the `OpLog` #[inline] pub fn len_changes(&self) -> usize { - self.doc.len_changes() + self.inner_doc().len_changes() } /// Get the shallow value of the document. #[inline] pub fn get_value(&self) -> LoroValue { - self.doc.get_value() + self.inner_doc().get_value() } /// Get the entire state of the current DocState #[inline] pub fn get_deep_value(&self) -> LoroValue { - self.doc.get_deep_value() + self.inner_doc().get_deep_value() } /// Get the entire state of the current DocState with container id pub fn get_deep_value_with_id(&self) -> LoroValue { - self.doc + self.inner_doc() .app_state() .lock() .unwrap() @@ -879,7 +883,7 @@ impl LoroDoc { /// Get the `Frontiers` version of `OpLog`. #[inline] pub fn oplog_frontiers(&self) -> Frontiers { - self.doc.oplog_frontiers() + self.inner_doc().oplog_frontiers() } /// Get the `Frontiers` version of `DocState`. @@ -898,13 +902,13 @@ impl LoroDoc { /// ``` #[inline] pub fn state_frontiers(&self) -> Frontiers { - self.doc.state_frontiers() + self.inner_doc().state_frontiers() } /// Get the PeerID #[inline] pub fn peer_id(&self) -> PeerID { - self.doc.peer_id() + self.inner_doc().peer_id() } /// Change the PeerID @@ -916,7 +920,7 @@ impl LoroDoc { /// Prefer the default random PeerID per process/session. #[inline] pub fn set_peer_id(&self, peer: PeerID) -> LoroResult<()> { - self.doc.set_peer_id(peer) + self.inner_doc().set_peer_id(peer) } /// Subscribe the events of a container. @@ -966,7 +970,7 @@ impl LoroDoc { /// ``` #[inline] pub fn subscribe(&self, container_id: &ContainerID, callback: Subscriber) -> Subscription { - self.doc.subscribe( + self.inner_doc().subscribe( container_id, Arc::new(move |e| { callback(DiffEvent::from(e)); @@ -976,7 +980,7 @@ impl LoroDoc { /// Subscribe all the events. /// - /// The callback will be invoked when any part of the [loro_internal::DocState] is changed. + /// The callback will be invoked when any part of the document state is changed. /// Returns a subscription that can be used to unsubscribe. /// /// The events will be emitted after a transaction is committed. A transaction is committed when: @@ -987,8 +991,8 @@ impl LoroDoc { /// - `doc.checkout(version)` is called. #[inline] pub fn subscribe_root(&self, callback: Subscriber) -> Subscription { - // self.doc.subscribe_root(callback) - self.doc.subscribe_root(Arc::new(move |e| { + // self.inner_doc().subscribe_root(callback) + self.inner_doc().subscribe_root(Arc::new(move |e| { callback(DiffEvent::from(e)); })) } @@ -1030,7 +1034,7 @@ impl LoroDoc { /// doc.commit(); /// ``` pub fn subscribe_local_update(&self, callback: LocalUpdateCallback) -> Subscription { - self.doc.subscribe_local_update(callback) + self.inner_doc().subscribe_local_update(callback) } /// Subscribe to peer ID changes in the document. @@ -1065,20 +1069,20 @@ impl LoroDoc { /// doc.set_peer_id(100).unwrap(); /// ``` pub fn subscribe_peer_id_change(&self, callback: PeerIdUpdateCallback) -> Subscription { - self.doc.subscribe_peer_id_change(callback) + self.inner_doc().subscribe_peer_id_change(callback) } /// Check the correctness of the document state by comparing it with the state /// calculated by applying all the history. #[inline] pub fn check_state_correctness_slow(&self) { - self.doc.check_state_diff_calc_consistency_slow() + self.inner_doc().check_state_diff_calc_consistency_slow() } /// Get the handler by the path. #[inline] pub fn get_by_path(&self, path: &[Index]) -> Option { - self.doc.get_by_path(path).map(ValueOrContainer::from) + self.inner_doc().get_by_path(path).map(ValueOrContainer::from) } /// Get the handler by the string path. @@ -1136,7 +1140,7 @@ impl LoroDoc { /// ``` #[inline] pub fn get_by_str_path(&self, path: &str) -> Option { - self.doc.get_by_str_path(path).map(ValueOrContainer::from) + self.inner_doc().get_by_str_path(path).map(ValueOrContainer::from) } /// Get the absolute position of the given cursor. @@ -1162,19 +1166,19 @@ impl LoroDoc { &self, cursor: &Cursor, ) -> Result { - self.doc.query_pos(cursor) + self.inner_doc().query_pos(cursor) } /// Get the inner LoroDoc ref. #[inline] pub fn inner(&self) -> &InnerLoroDoc { - &self.doc + self.inner_doc() } /// Whether the history cache is built. #[inline] pub fn has_history_cache(&self) -> bool { - self.doc.has_history_cache() + self.inner_doc().has_history_cache() } /// Free the history cache that is used for making checkout faster. @@ -1183,13 +1187,13 @@ impl LoroDoc { /// You can free it by calling this method. #[inline] pub fn free_history_cache(&self) { - self.doc.free_history_cache() + self.inner_doc().free_history_cache() } /// Free the cached diff calculator that is used for checkout. #[inline] pub fn free_diff_calculator(&self) { - self.doc.free_diff_calculator() + self.inner_doc().free_diff_calculator() } /// Encoded all ops and history cache to bytes and store them in the kv store. @@ -1197,7 +1201,7 @@ impl LoroDoc { /// This will free up the memory that used by parsed ops #[inline] pub fn compact_change_store(&self) { - self.doc.compact_change_store() + self.inner_doc().compact_change_store() } /// Export the document in the given mode. @@ -1233,19 +1237,19 @@ impl LoroDoc { /// assert!(!delta.is_empty()); /// ``` pub fn export(&self, mode: ExportMode) -> Result, LoroEncodeError> { - self.doc.export(mode) + self.inner_doc().export(mode) } /// Analyze the container info of the doc /// /// This is used for development and debugging. It can be slow. pub fn analyze(&self) -> DocAnalysis { - self.doc.analyze() + self.inner_doc().analyze() } /// Get the path from the root to the container pub fn get_path_to_container(&self, id: &ContainerID) -> Option> { - self.doc.get_path_to_container(id) + self.inner_doc().get_path_to_container(id) } /// Evaluate a JSONPath expression on the document and return matching values or handlers. @@ -1281,7 +1285,7 @@ impl LoroDoc { #[inline] #[cfg(feature = "jsonpath")] pub fn jsonpath(&self, path: &str) -> Result, JsonPathError> { - self.doc + self.inner_doc() .jsonpath(path) .map(|vec| vec.into_iter().map(ValueOrContainer::from).collect()) } @@ -1299,7 +1303,7 @@ impl LoroDoc { jsonpath: &str, callback: SubscribeJsonPathCallback, ) -> LoroResult { - self.doc.subscribe_jsonpath(jsonpath, callback) + self.inner_doc().subscribe_jsonpath(jsonpath, callback) } /// Get the number of operations in the pending transaction. @@ -1307,7 +1311,7 @@ impl LoroDoc { /// The pending transaction is the one that is not committed yet. It will be committed /// after calling `doc.commit()`, `doc.export(mode)` or `doc.checkout(version)`. pub fn get_pending_txn_len(&self) -> usize { - self.doc.get_pending_txn_len() + self.inner_doc().get_pending_txn_len() } /// Traverses the ancestors of the Change containing the given ID, including itself. @@ -1324,12 +1328,12 @@ impl LoroDoc { ids: &[ID], f: &mut dyn FnMut(ChangeMeta) -> ControlFlow<()>, ) -> Result<(), ChangeTravelError> { - self.doc.travel_change_ancestors(ids, f) + self.inner_doc().travel_change_ancestors(ids, f) } /// Check if the doc contains the full history. pub fn is_shallow(&self) -> bool { - self.doc.is_shallow() + self.inner_doc().is_shallow() } /// Gets container IDs modified in the given ID range. @@ -1345,7 +1349,7 @@ impl LoroDoc { /// * `id` - The starting ID of the change range /// * `len` - The length of the change range to check pub fn get_changed_containers_in(&self, id: ID, len: usize) -> FxHashSet { - self.doc.get_changed_containers_in(id, len) + self.inner_doc().get_changed_containers_in(id, len) } /// Find the operation id spans that between the `from` version and the `to` version. @@ -1365,7 +1369,7 @@ impl LoroDoc { /// ``` #[inline] pub fn find_id_spans_between(&self, from: &Frontiers, to: &Frontiers) -> VersionVectorDiff { - self.doc.find_id_spans_between(from, to) + self.inner_doc().find_id_spans_between(from, to) } /// Revert the current document state back to the target version @@ -1392,7 +1396,7 @@ impl LoroDoc { /// ``` #[inline] pub fn revert_to(&self, version: &Frontiers) -> LoroResult<()> { - self.doc.revert_to(version) + self.inner_doc().revert_to(version) } /// Apply a diff to the current document state. @@ -1400,7 +1404,7 @@ impl LoroDoc { /// Internally, it will apply the diff to the current state. #[inline] pub fn apply_diff(&self, diff: DiffBatch) -> LoroResult<()> { - self.doc.apply_diff(diff.into()) + self.inner_doc().apply_diff(diff.into()) } /// Calculate the diff between two versions. @@ -1418,7 +1422,7 @@ impl LoroDoc { /// ``` #[inline] pub fn diff(&self, a: &Frontiers, b: &Frontiers) -> LoroResult { - self.doc.diff(a, b).map(|x| x.into()) + self.inner_doc().diff(a, b).map(|x| x.into()) } /// Check if the doc contains the target container. @@ -1452,7 +1456,7 @@ impl LoroDoc { /// assert!(doc2.has_container(&"cid:1@1:List".try_into().unwrap())); /// ``` pub fn has_container(&self, container_id: &ContainerID) -> bool { - self.doc.has_container(container_id) + self.inner_doc().has_container(container_id) } /// Subscribe to the first commit from a peer. Operations performed on the `LoroDoc` within this callback @@ -1510,7 +1514,7 @@ impl LoroDoc { &self, callback: FirstCommitFromPeerCallback, ) -> Subscription { - self.doc.subscribe_first_commit_from_peer(callback) + self.inner_doc().subscribe_first_commit_from_peer(callback) } /// Subscribe to pre-commit events. @@ -1565,7 +1569,7 @@ impl LoroDoc { /// doc.commit(); /// ``` pub fn subscribe_pre_commit(&self, callback: PreCommitCallback) -> Subscription { - self.doc.subscribe_pre_commit(callback) + self.inner_doc().subscribe_pre_commit(callback) } /// Delete all content from a root container and hide it from the document. @@ -1576,7 +1580,7 @@ impl LoroDoc { /// /// Only works on root containers (containers without parents). pub fn delete_root_container(&self, cid: ContainerID) { - self.doc.delete_root_container(cid); + self.inner_doc().delete_root_container(cid); } /// Set whether to hide empty root containers. @@ -1592,7 +1596,7 @@ impl LoroDoc { /// dbg!(doc.get_deep_value()); // {} /// ``` pub fn set_hide_empty_root_containers(&self, hide: bool) { - self.doc.set_hide_empty_root_containers(hide); + self.inner_doc().set_hide_empty_root_containers(hide); } } @@ -1852,7 +1856,7 @@ impl LoroList { /// /// ``` /// use loro::LoroDoc; - /// use loro_internal::cursor::Side; + /// use loro::cursor::Side; /// /// let doc = LoroDoc::new(); /// let list = doc.get_list("list"); @@ -3273,7 +3277,7 @@ impl LoroMovableList { /// /// ``` /// use loro::LoroDoc; - /// use loro_internal::cursor::Side; + /// use loro::cursor::Side; /// /// let doc = LoroDoc::new(); /// let list = doc.get_movable_list("list"); @@ -3421,7 +3425,7 @@ impl ContainerTrait for LoroUnknown { use enum_as_inner::EnumAsInner; #[cfg(feature = "jsonpath")] -use loro_internal::jsonpath::jsonpath_impl::JsonPathError; +use crate::internal::jsonpath::jsonpath_impl::JsonPathError; /// All the CRDT containers supported by Loro. #[derive(Clone, Debug, EnumAsInner)] @@ -3445,7 +3449,7 @@ pub enum Container { impl SealedTrait for Container {} impl ContainerTrait for Container { - type Handler = loro_internal::handler::Handler; + type Handler = crate::internal::handler::Handler; fn id(&self) -> ContainerID { match self { @@ -3648,7 +3652,7 @@ pub struct UndoManager(InnerUndoManager); impl UndoManager { /// Create a new UndoManager. pub fn new(doc: &LoroDoc) -> Self { - let inner = InnerUndoManager::new(&doc.doc); + let inner = InnerUndoManager::new(doc.inner_doc()); inner.set_max_undo_steps(100); Self(inner) } diff --git a/crates/loro/tests/integration_test/detached_editing_test.rs b/crates/loro/tests/integration_test/detached_editing_test.rs index 65ecb96c5..0e4b0437d 100644 --- a/crates/loro/tests/integration_test/detached_editing_test.rs +++ b/crates/loro/tests/integration_test/detached_editing_test.rs @@ -2,7 +2,7 @@ use pretty_assertions::assert_eq; use std::sync::{Arc, Mutex}; use loro::{Frontiers, LoroDoc, LoroError, UndoManager, ID}; -use loro_internal::vv; +use loro::vv; #[test] fn disallow_editing_on_detached_mode_by_default() { diff --git a/crates/loro/tests/integration_test/redact_test.rs b/crates/loro/tests/integration_test/redact_test.rs index 95239af8c..556eb33a5 100644 --- a/crates/loro/tests/integration_test/redact_test.rs +++ b/crates/loro/tests/integration_test/redact_test.rs @@ -1,6 +1,5 @@ use loro::json::redact; -use loro::{LoroDoc, LoroList, LoroMovableList, LoroTree, LoroValue}; -use loro_internal::version::VersionRange; +use loro::{LoroDoc, LoroList, LoroMovableList, LoroTree, LoroValue, VersionRange}; #[test] fn redact_text_doc() { diff --git a/crates/loro/tests/integration_test/undo_test.rs b/crates/loro/tests/integration_test/undo_test.rs index c26900497..1d6544bd9 100644 --- a/crates/loro/tests/integration_test/undo_test.rs +++ b/crates/loro/tests/integration_test/undo_test.rs @@ -5,9 +5,9 @@ use std::sync::{ use loro::{ undo::UndoItemMeta, ContainerTrait as _, ExportMode, LoroDoc, LoroError, LoroList, LoroMap, - LoroResult, LoroText, LoroValue, StyleConfigMap, ToJson, UndoManager, + LoroResult, LoroText, LoroValue, StyleConfig, StyleConfigMap, ToJson, UndoManager, + CommitOptions, ID, }; -use loro_internal::{configure::StyleConfig, id::ID, loro::CommitOptions}; use serde_json::json; use tracing::{debug_span, info_span}; diff --git a/crates/loro/tests/internal_autocommit.rs b/crates/loro/tests/internal_autocommit.rs new file mode 100644 index 000000000..1e90e9586 --- /dev/null +++ b/crates/loro/tests/internal_autocommit.rs @@ -0,0 +1,3 @@ +mod compat { + include!("internal_compat_src/autocommit.rs"); +} diff --git a/crates/loro/tests/internal_canonical_surface.rs b/crates/loro/tests/internal_canonical_surface.rs new file mode 100644 index 000000000..58517cce1 --- /dev/null +++ b/crates/loro/tests/internal_canonical_surface.rs @@ -0,0 +1,75 @@ +use loro::internal::{ + Diff, Handler, LoroDoc, MapHandler, TextHandler, UndoItemMeta, UndoManager, ValueOrHandler, +}; +use std::sync::{ + atomic::{AtomicUsize, Ordering}, + Arc, +}; + +#[test] +fn canonical_internal_handler_surface_covers_read_paths() { + let doc = LoroDoc::new_auto_commit(); + let list = doc.get_list("list"); + let nested = list + .insert_container(0, MapHandler::new_detached()) + .unwrap(); + nested.insert("flag", true).unwrap(); + let text = nested + .insert_container("text", TextHandler::new_detached()) + .unwrap(); + text.insert_unicode(0, "hello").unwrap(); + + assert!(matches!( + list.get_(0), + Some(ValueOrHandler::Handler(Handler::Map(_))) + )); + assert!(matches!( + nested.get_("text"), + Some(ValueOrHandler::Handler(Handler::Text(_))) + )); + assert!(matches!( + doc.get_by_str_path("list/0/text"), + Some(ValueOrHandler::Handler(Handler::Text(_))) + )); + + let mut iterated = Vec::new(); + nested.for_each(|_, value| iterated.push(value)); + assert!(iterated + .iter() + .any(|value| matches!(value, ValueOrHandler::Handler(Handler::Text(_))))); + + let values: Vec<_> = nested.values().collect(); + assert!(values + .iter() + .any(|value| matches!(value, ValueOrHandler::Handler(Handler::Text(_))))); +} + +#[test] +fn canonical_internal_event_surface_drives_subscriptions_and_undo() { + let doc = LoroDoc::new_auto_commit(); + let text = doc.get_text("text"); + + let root_events = Arc::new(AtomicUsize::new(0)); + let root_events_clone = root_events.clone(); + let _sub = doc.subscribe_root(Arc::new(move |event| { + assert!(matches!(&event.events[0].diff, Diff::Text(_))); + root_events_clone.fetch_add(event.events.len(), Ordering::Relaxed); + })); + + let undo_events = Arc::new(AtomicUsize::new(0)); + let undo_events_clone = undo_events.clone(); + let undo = UndoManager::new(&doc); + undo.set_merge_interval(0); + undo.set_on_push(Some(Box::new(move |_, _, event| { + let event = event.expect("undo push should carry the canonical diff event"); + assert!(matches!(&event.events[0].diff, Diff::Text(_))); + undo_events_clone.fetch_add(event.events.len(), Ordering::Relaxed); + UndoItemMeta::new() + }))); + + text.insert_unicode(0, "hello").unwrap(); + doc.commit_then_renew(); + + assert_eq!(root_events.load(Ordering::Relaxed), 1); + assert_eq!(undo_events.load(Ordering::Relaxed), 1); +} diff --git a/crates/loro-internal/tests/autocommit.rs b/crates/loro/tests/internal_compat_src/autocommit.rs similarity index 99% rename from crates/loro-internal/tests/autocommit.rs rename to crates/loro/tests/internal_compat_src/autocommit.rs index 524ed2fb2..9aabcf9a5 100644 --- a/crates/loro-internal/tests/autocommit.rs +++ b/crates/loro/tests/internal_compat_src/autocommit.rs @@ -1,5 +1,5 @@ use loro_common::ID; -use loro_internal::{ +use loro::internal::{ cursor::PosType, loro::ExportMode, version::Frontiers, HandlerTrait, LoroDoc, TextHandler, ToJson, }; diff --git a/crates/loro-internal/tests/ephemeral_store.rs b/crates/loro/tests/internal_compat_src/ephemeral_store.rs similarity index 94% rename from crates/loro-internal/tests/ephemeral_store.rs rename to crates/loro/tests/internal_compat_src/ephemeral_store.rs index 7160b51ed..bc34c9b49 100644 --- a/crates/loro-internal/tests/ephemeral_store.rs +++ b/crates/loro/tests/internal_compat_src/ephemeral_store.rs @@ -1,5 +1,5 @@ -use loro_internal::awareness::EphemeralStore; -use loro_internal::LoroValue; +use loro::internal::awareness::EphemeralStore; +use loro::internal::LoroValue; use serde::Serialize; use std::time::{Duration, SystemTime, UNIX_EPOCH}; diff --git a/crates/loro-internal/tests/fugue.rs b/crates/loro/tests/internal_compat_src/fugue.rs similarity index 98% rename from crates/loro-internal/tests/fugue.rs rename to crates/loro/tests/internal_compat_src/fugue.rs index 661a74496..1b1c6a487 100644 --- a/crates/loro-internal/tests/fugue.rs +++ b/crates/loro/tests/internal_compat_src/fugue.rs @@ -1,5 +1,5 @@ use loro_common::LoroResult; -use loro_internal::{LoroDoc, ToJson}; +use loro::internal::{LoroDoc, ToJson}; use serde_json::json; #[test] diff --git a/crates/loro-internal/tests/richtext.rs b/crates/loro/tests/internal_compat_src/richtext.rs similarity index 98% rename from crates/loro-internal/tests/richtext.rs rename to crates/loro/tests/internal_compat_src/richtext.rs index 553c8e594..c63e984f7 100644 --- a/crates/loro-internal/tests/richtext.rs +++ b/crates/loro/tests/internal_compat_src/richtext.rs @@ -1,9 +1,9 @@ -//! All the tests in this file are based on [richtext.md] +/// All the tests in this file are based on [richtext.md] use std::ops::Range; use loro_common::LoroValue; -use loro_internal::{cursor::PosType, loro::ExportMode, LoroDoc, ToJson}; +use loro::internal::{cursor::PosType, loro::ExportMode, LoroDoc, ToJson}; use serde_json::json; fn init(s: &str) -> LoroDoc { diff --git a/crates/loro-internal/tests/test.rs b/crates/loro/tests/internal_compat_src/test.rs similarity index 99% rename from crates/loro-internal/tests/test.rs rename to crates/loro/tests/internal_compat_src/test.rs index 949e768db..0dadd807a 100644 --- a/crates/loro-internal/tests/test.rs +++ b/crates/loro/tests/internal_compat_src/test.rs @@ -1,9 +1,9 @@ use loro_common::{ loro_value, ContainerID, ContainerType, IdSpan, LoroError, LoroResult, LoroValue, PeerID, ID, }; -use loro_internal::awareness::EphemeralStore; -use loro_internal::sync::{AtomicBool, Mutex}; -use loro_internal::{ +use loro::internal::awareness::EphemeralStore; +use loro::internal::sync::{AtomicBool, Mutex}; +use loro::internal::{ cursor::PosType, delta::ResolvedMapValue, encoding::ImportStatus, @@ -370,7 +370,7 @@ fn import_after_init_handlers() { Arc::new(|event| { assert!(matches!( event.events[0].diff, - loro_internal::event::Diff::Text(_) + loro::internal::event::Diff::Text(_) )) }), ); @@ -379,7 +379,7 @@ fn import_after_init_handlers() { Arc::new(|event| { assert!(matches!( event.events[0].diff, - loro_internal::event::Diff::Map(_) + loro::internal::event::Diff::Map(_) )) }), ); @@ -388,7 +388,7 @@ fn import_after_init_handlers() { Arc::new(|event| { assert!(matches!( event.events[0].diff, - loro_internal::event::Diff::List(_) + loro::internal::event::Diff::List(_) )) }), ); diff --git a/crates/loro-internal/tests/tree.rs b/crates/loro/tests/internal_compat_src/tree.rs similarity index 96% rename from crates/loro-internal/tests/tree.rs rename to crates/loro/tests/internal_compat_src/tree.rs index 8cdae51f8..59ceeb041 100644 --- a/crates/loro-internal/tests/tree.rs +++ b/crates/loro/tests/internal_compat_src/tree.rs @@ -1,4 +1,4 @@ -use loro_internal::{LoroDoc, TreeParentId}; +use loro::internal::{LoroDoc, TreeParentId}; #[test] fn tree_index() { diff --git a/crates/loro-internal/tests/undo.rs b/crates/loro/tests/internal_compat_src/undo.rs similarity index 99% rename from crates/loro-internal/tests/undo.rs rename to crates/loro/tests/internal_compat_src/undo.rs index 0641e5993..7c56fade8 100644 --- a/crates/loro-internal/tests/undo.rs +++ b/crates/loro/tests/internal_compat_src/undo.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; -use loro_internal::{ +use loro::internal::{ cursor::PosType, handler::UpdateOptions, loro::ExportMode, LoroDoc, UndoManager, }; diff --git a/crates/loro/tests/internal_ephemeral_store.rs b/crates/loro/tests/internal_ephemeral_store.rs new file mode 100644 index 000000000..59e20797c --- /dev/null +++ b/crates/loro/tests/internal_ephemeral_store.rs @@ -0,0 +1,3 @@ +mod compat { + include!("internal_compat_src/ephemeral_store.rs"); +} diff --git a/crates/loro/tests/internal_fugue.rs b/crates/loro/tests/internal_fugue.rs new file mode 100644 index 000000000..329d74a78 --- /dev/null +++ b/crates/loro/tests/internal_fugue.rs @@ -0,0 +1,3 @@ +mod compat { + include!("internal_compat_src/fugue.rs"); +} diff --git a/crates/loro/tests/internal_richtext.rs b/crates/loro/tests/internal_richtext.rs new file mode 100644 index 000000000..927ad65a1 --- /dev/null +++ b/crates/loro/tests/internal_richtext.rs @@ -0,0 +1,3 @@ +mod compat { + include!("internal_compat_src/richtext.rs"); +} diff --git a/crates/loro/tests/internal_shim_test.rs b/crates/loro/tests/internal_shim_test.rs new file mode 100644 index 000000000..5b83b4dc0 --- /dev/null +++ b/crates/loro/tests/internal_shim_test.rs @@ -0,0 +1,3 @@ +mod compat { + include!("internal_compat_src/test.rs"); +} diff --git a/crates/loro/tests/internal_tree.rs b/crates/loro/tests/internal_tree.rs new file mode 100644 index 000000000..0e4a91172 --- /dev/null +++ b/crates/loro/tests/internal_tree.rs @@ -0,0 +1,3 @@ +mod compat { + include!("internal_compat_src/tree.rs"); +} diff --git a/crates/loro/tests/internal_undo.rs b/crates/loro/tests/internal_undo.rs new file mode 100644 index 000000000..fe50fd9ad --- /dev/null +++ b/crates/loro/tests/internal_undo.rs @@ -0,0 +1,3 @@ +mod compat { + include!("internal_compat_src/undo.rs"); +} diff --git a/crates/loro/tests/loro_rust_test.rs b/crates/loro/tests/loro_rust_test.rs index 6d27cfc57..9c333381c 100644 --- a/crates/loro/tests/loro_rust_test.rs +++ b/crates/loro/tests/loro_rust_test.rs @@ -18,10 +18,8 @@ use loro::{ event::{Diff, DiffBatch, ListDiffItem}, loro_value, CommitOptions, ContainerID, ContainerTrait, ContainerType, ExportMode, Frontiers, FrontiersNotIncluded, IdSpan, Index, LoroDoc, LoroError, LoroList, LoroMap, LoroMapValue, - LoroStringValue, LoroText, LoroValue, ToJson, TreeParentId, -}; -use loro_internal::{ - encoding::EncodedBlobMode, fx_map, handler::TextDelta, id::ID, version_range, vv, LoroResult, + LoroResult, LoroStringValue, LoroText, LoroValue, ToJson, TreeParentId, EncodedBlobMode, + TextDelta, ID, fx_map, version_range, vv, }; use rand::{Rng, SeedableRng}; use serde_json::json; @@ -528,7 +526,7 @@ fn subscribe() { Arc::new(move |event| { assert!(matches!( event.triggered_by, - loro_internal::event::EventTriggerKind::Local + loro::EventTriggerKind::Local )); for event in event.events { let delta = event.diff.as_text().unwrap(); @@ -906,11 +904,11 @@ fn get_out_of_bound_cursor() { let a = LoroDoc::new(); let text = a.get_text("text"); text.insert(0, "123").unwrap(); - text.get_cursor(5, loro_internal::cursor::Side::Right); + text.get_cursor(5, loro::cursor::Side::Right); let list = a.get_list("list"); - list.get_cursor(5, loro_internal::cursor::Side::Right); + list.get_cursor(5, loro::cursor::Side::Right); let m_list = a.get_movable_list("list"); - m_list.get_cursor(5, loro_internal::cursor::Side::Right); + m_list.get_cursor(5, loro::cursor::Side::Right); } #[test] diff --git a/crates/loro/tests/merge_semantics_baseline.rs b/crates/loro/tests/merge_semantics_baseline.rs new file mode 100644 index 000000000..c755f9868 --- /dev/null +++ b/crates/loro/tests/merge_semantics_baseline.rs @@ -0,0 +1,72 @@ +use anyhow::Result; +use loro::{ContainerTrait, ExportMode, LoroDoc, LoroText}; + +#[test] +fn new_keeps_public_auto_commit_behavior() -> Result<()> { + let doc = LoroDoc::new(); + let text = doc.get_text("text"); + text.insert(0, "hello")?; + + assert_eq!(text.to_string(), "hello"); + assert!(!doc.export(ExportMode::all_updates())?.is_empty()); + + Ok(()) +} + +#[test] +fn from_snapshot_keeps_public_auto_commit_behavior() -> Result<()> { + let doc = LoroDoc::new(); + doc.get_text("text").insert(0, "hello")?; + let snapshot = doc.export(ExportMode::Snapshot)?; + + let restored = LoroDoc::from_snapshot(&snapshot)?; + restored.get_text("text").insert(5, "!")?; + + assert_eq!(restored.get_text("text").to_string(), "hello!"); + + let roundtrip = LoroDoc::from_snapshot(&restored.export(ExportMode::Snapshot)?)?; + assert_eq!(roundtrip.get_deep_value(), restored.get_deep_value()); + + Ok(()) +} + +#[test] +fn fork_at_keeps_public_auto_commit_behavior() -> Result<()> { + let doc = LoroDoc::new(); + let text = doc.get_text("text"); + text.insert(0, "hello")?; + doc.commit(); + let first_frontiers = doc.state_frontiers(); + + text.insert(5, " world")?; + doc.commit(); + + let forked = doc.fork_at(&first_frontiers); + forked.get_text("text").insert(5, "!")?; + + assert_eq!(forked.get_text("text").to_string(), "hello!"); + + let roundtrip = LoroDoc::from_snapshot(&forked.export(ExportMode::Snapshot)?)?; + assert_eq!(roundtrip.get_deep_value(), forked.get_deep_value()); + + Ok(()) +} + +#[test] +fn attached_container_doc_keeps_public_auto_commit_behavior() -> Result<()> { + let doc = LoroDoc::new(); + let map = doc.get_map("map"); + let text = map.insert_container("text", LoroText::new())?; + text.insert(0, "hello")?; + + let attached_doc = text.doc().expect("attached containers should expose their doc"); + attached_doc.get_text("other").insert(0, "world")?; + + assert_eq!(attached_doc.get_deep_value(), doc.get_deep_value()); + assert_eq!(doc.get_text("other").to_string(), "world"); + + let roundtrip = LoroDoc::from_snapshot(&attached_doc.export(ExportMode::Snapshot)?)?; + assert_eq!(roundtrip.get_deep_value(), attached_doc.get_deep_value()); + + Ok(()) +} diff --git a/crates/loro/tests/readme.rs b/crates/loro/tests/readme.rs index 099729205..745717403 100644 --- a/crates/loro/tests/readme.rs +++ b/crates/loro/tests/readme.rs @@ -49,7 +49,7 @@ fn readme_basic() { #[test] fn get_list_cursor_example() { use loro::LoroDoc; - use loro_internal::cursor::Side; + use loro::cursor::Side; let doc = LoroDoc::new(); let list = doc.get_list("list"); diff --git a/docs/encoding-container-states.md b/docs/encoding-container-states.md index 0fad593a0..75962422a 100644 --- a/docs/encoding-container-states.md +++ b/docs/encoding-container-states.md @@ -38,7 +38,7 @@ Each container state is wrapped in a `ContainerWrapper` before being stored in t > > When decoding `Option` via postcard, use the postcard serde column. -**Source**: `crates/loro-internal/src/state/container_store/container_wrapper.rs:100-120` +**Source**: `crates/loro/src/internal/state/container_store/container_wrapper.rs:100-120` **Source**: `crates/loro-common/src/lib.rs:378-401` (historical mapping) --- @@ -155,7 +155,7 @@ function decodeMapState(bytes) { } ``` -**Source**: `crates/loro-internal/src/state/map_state.rs:260-365` +**Source**: `crates/loro/src/internal/state/map_state.rs:260-365` --- @@ -198,7 +198,7 @@ List container stores ordered elements with element IDs. Row count is inferred from the column data during decoding. ``` -**Source**: `crates/loro-internal/src/state/list_state.rs:529-619` +**Source**: `crates/loro/src/internal/state/list_state.rs:529-619` --- @@ -336,7 +336,7 @@ function decodeRichtextState(bytes) { > Implementers should use proper Unicode scalar iteration (e.g., `[...str]` spread > or `Intl.Segmenter` for grapheme-aware handling). -**Source**: `crates/loro-internal/src/state/richtext_state.rs:1130-1339` +**Source**: `crates/loro/src/internal/state/richtext_state.rs:1130-1339` --- @@ -425,7 +425,7 @@ To decode position[i]: position = position[i-1][0..common_prefix_length] + rest ``` -**Source**: `crates/loro-internal/src/state/tree_state.rs:1556-1746` +**Source**: `crates/loro/src/internal/state/tree_state.rs:1556-1746` --- @@ -493,7 +493,7 @@ The first item in `items` is a sentinel. For each item record: **previous** visible item's `invisible_list_item` counter (see line 1509). This means each record's `invisible_list_item` represents invisible items that **follow** the visible item. -**Source**: `crates/loro-internal/src/state/movable_list_state.rs:1392-1637` +**Source**: `crates/loro/src/internal/state/movable_list_state.rs:1392-1637` --- @@ -509,7 +509,7 @@ When the `counter` feature is enabled: └─────────────────┴──────────────────────────────────────────────────────────┘ ``` -**Source**: `crates/loro-internal/src/state/counter_state.rs` +**Source**: `crates/loro/src/internal/state/counter_state.rs` --- @@ -580,11 +580,11 @@ function decodeContainerState(bytes) { | Container | Source File | |-----------|-------------| -| MapState | `crates/loro-internal/src/state/map_state.rs` | -| ListState | `crates/loro-internal/src/state/list_state.rs` | -| RichtextState | `crates/loro-internal/src/state/richtext_state.rs` | -| TreeState | `crates/loro-internal/src/state/tree_state.rs` | -| MovableListState | `crates/loro-internal/src/state/movable_list_state.rs` | -| CounterState | `crates/loro-internal/src/state/counter_state.rs` | -| ContainerWrapper | `crates/loro-internal/src/state/container_store/container_wrapper.rs` | -| PositionArena | `crates/loro-internal/src/encoding/arena.rs` | +| MapState | `crates/loro/src/internal/state/map_state.rs` | +| ListState | `crates/loro/src/internal/state/list_state.rs` | +| RichtextState | `crates/loro/src/internal/state/richtext_state.rs` | +| TreeState | `crates/loro/src/internal/state/tree_state.rs` | +| MovableListState | `crates/loro/src/internal/state/movable_list_state.rs` | +| CounterState | `crates/loro/src/internal/state/counter_state.rs` | +| ContainerWrapper | `crates/loro/src/internal/state/container_store/container_wrapper.rs` | +| PositionArena | `crates/loro/src/internal/encoding/arena.rs` | diff --git a/docs/encoding-xxhash32.md b/docs/encoding-xxhash32.md index b0b89d3ec..1345db1af 100644 --- a/docs/encoding-xxhash32.md +++ b/docs/encoding-xxhash32.md @@ -205,4 +205,4 @@ function verifyBlock(blockBytes) { --- -**Source**: Based on xxHash specification and Loro's usage at `crates/kv-store/src/sstable.rs` and `crates/loro-internal/src/encoding.rs` +**Source**: Based on xxHash specification and Loro's usage at `crates/kv-store/src/sstable.rs` and `crates/loro/src/internal/encoding.rs` diff --git a/docs/encoding.md b/docs/encoding.md index 37212a279..17833c9b9 100644 --- a/docs/encoding.md +++ b/docs/encoding.md @@ -37,7 +37,7 @@ Loro supports multiple export modes to meet different synchronization requiremen | `StateOnly` | `FastSnapshot (3)` | State-only snapshot with minimal history (depth=1) | | `SnapshotAt` | `FastSnapshot (3)` | Full history till target version + state at that version | -**Source**: `crates/loro-internal/src/encoding.rs:52-70` +**Source**: `crates/loro/src/internal/encoding.rs:52-70` --- @@ -86,7 +86,7 @@ The checksum is stored in bytes [16..20] of the header as a little-endian u32. > **See Also**: [xxHash32 Algorithm Specification](./encoding-xxhash32.md) for complete implementation details and JavaScript code. -**Source**: `crates/loro-internal/src/encoding.rs:275-295, 397-416` +**Source**: `crates/loro/src/internal/encoding.rs:275-295, 397-416` --- @@ -119,7 +119,7 @@ The FastSnapshot body contains three sections: └───────────────┴─────────────────────────────────────────────────┘ ``` -**Source**: `crates/loro-internal/src/encoding/fast_snapshot.rs:1-46` +**Source**: `crates/loro/src/internal/encoding/fast_snapshot.rs:1-46` ### Encoding Pseudocode @@ -168,7 +168,7 @@ The FastUpdates body contains a sequence of LEB128-length-prefixed change blocks └───────────────┴─────────────────────────────────────────────────┘ ``` -**Source**: `crates/loro-internal/src/encoding/fast_snapshot.rs:257-288` +**Source**: `crates/loro/src/internal/encoding/fast_snapshot.rs:257-288` --- @@ -315,7 +315,7 @@ The OpLog is stored as a KV Store with the following key-value schema: | `b"sf"` (2 bytes) | Shallow start Frontiers | | 12 bytes: PeerID (8) + Counter (4) | Encoded Change Block | -**Source**: `crates/loro-internal/src/oplog/change_store.rs:47-59, 110-113` +**Source**: `crates/loro/src/internal/oplog/change_store.rs:47-59, 110-113` ### Block Key Format @@ -355,7 +355,7 @@ VersionVector is encoded using **postcard** format (a compact binary serializati The VersionVector is a HashMap serialized with postcard. -**Source**: `crates/loro-internal/src/version.rs:843-850` +**Source**: `crates/loro/src/internal/version.rs:843-850` ### Frontiers Encoding @@ -378,7 +378,7 @@ Frontiers is encoded as a Vec using **postcard** format. └───────────────┴─────────────────────────────────────────────────┘ ``` -**Source**: `crates/loro-internal/src/version/frontiers.rs:219-231` +**Source**: `crates/loro/src/internal/version/frontiers.rs:219-231` --- @@ -395,7 +395,7 @@ The document state is stored as a KV Store where each container's state is a sep | `ContainerID.to_bytes()` | ContainerWrapper encoded bytes | | `FRONTIERS_KEY` (`b"fr"`) | Frontiers encoding (for shallow snapshots) | -**Source**: `crates/loro-internal/src/state/container_store.rs:48` (FRONTIERS_KEY) +**Source**: `crates/loro/src/internal/state/container_store.rs:48` (FRONTIERS_KEY) ### ContainerID Encoding @@ -460,7 +460,7 @@ Each container's state is wrapped in a ContainerWrapper: └───────────────┴─────────────────────────────────────────────────┘ ``` -**Source**: `crates/loro-internal/src/state/container_store/container_wrapper.rs:100-120` +**Source**: `crates/loro/src/internal/state/container_store/container_wrapper.rs:100-120` --- @@ -468,7 +468,7 @@ Each container's state is wrapped in a ContainerWrapper: Each Change Block contains multiple consecutive Changes from the same peer. Blocks are approximately 4KB after compression. -**Source**: `crates/loro-internal/src/oplog/change_store/block_encode.rs:1-65` +**Source**: `crates/loro/src/internal/oplog/change_store/block_encode.rs:1-65` ### Block Structure Overview @@ -535,7 +535,7 @@ The `header` field contains change metadata: └───────────────┴──────────────────────────────────────────────────┘ ``` -**Source**: `crates/loro-internal/src/oplog/change_store/block_meta_encode.rs` +**Source**: `crates/loro/src/internal/oplog/change_store/block_meta_encode.rs` ### Operations Section (serde_columnar) @@ -586,8 +586,8 @@ The `prop` field meaning varies by container type and operation: **Note**: For Map operations, the actual key string is stored in the `keys` section of the change block, and `prop` is the index into that arena. -**Source**: `crates/loro-internal/src/encoding/outdated_encode_reordered.rs:104-124` (get_op_prop) -**Source**: `crates/loro-internal/src/oplog/change_store/block_encode.rs:414-428` (EncodedOp struct) +**Source**: `crates/loro/src/internal/encoding/outdated_encode_reordered.rs:104-124` (get_op_prop) +**Source**: `crates/loro/src/internal/oplog/change_store/block_encode.rs:414-428` (EncodedOp struct) ### Container Arena Encoding (postcard Vec) @@ -623,7 +623,7 @@ For non-root containers (is_root = false): > Columnar encoding only applies when serializing via a ColumnarVec wrapper, so > the strategies are NOT applied here - it's plain postcard row-wise encoding. -**Source**: `crates/loro-internal/src/encoding/arena.rs:39-50, 94-96` +**Source**: `crates/loro/src/internal/encoding/arena.rs:39-50, 94-96` ### Position Arena Encoding (serde_columnar) @@ -643,7 +643,7 @@ Decoding: For each position, take common_prefix bytes from previous position and append rest bytes. ``` -**Source**: `crates/loro-internal/src/encoding/arena.rs:159-232` +**Source**: `crates/loro/src/internal/encoding/arena.rs:159-232` ### Key Strings Section @@ -657,7 +657,7 @@ position and append rest bytes. └───────────────┴──────────────────────────────────────────────────┘ ``` -**Source**: `crates/loro-internal/src/encoding/value.rs:860-867` (read_str/write_str pattern) +**Source**: `crates/loro/src/internal/encoding/value.rs:860-867` (read_str/write_str pattern) ### Delete Start IDs Section (serde_columnar) @@ -673,7 +673,7 @@ position and append rest bytes. └───────────────┴──────────────────────────────────────────────────┘ ``` -**Source**: `crates/loro-internal/src/encoding/outdated_encode_reordered.rs:427-436` (EncodedDeleteStartId) +**Source**: `crates/loro/src/internal/encoding/outdated_encode_reordered.rs:427-436` (EncodedDeleteStartId) --- @@ -704,7 +704,7 @@ Loro uses a tagged value encoding system where each value is prefixed with a typ | 16 | RawTreeMove | Raw tree move (internal) | | 0x80 \| kind | Future | Unknown/future value types | -**Source**: `crates/loro-internal/src/encoding/value.rs:39-161` +**Source**: `crates/loro/src/internal/encoding/value.rs:39-161` **Notes (Future)**: - The encoding uses the high bit (`0x80`) as a marker and stores the future kind in the low 7 bits. @@ -726,8 +726,8 @@ Binary: LEB128(len) + raw bytes DeltaInt: LEB128 signed encoding (i32) ``` -**Source**: `crates/loro-internal/src/encoding/value.rs:858-882` (read_i64, read_f64) -**Source**: `crates/loro-internal/src/encoding/value.rs:1045-1073` (write_i64, write_f64) +**Source**: `crates/loro/src/internal/encoding/value.rs:858-882` (read_i64, read_f64) +**Source**: `crates/loro/src/internal/encoding/value.rs:1045-1073` (write_i64, write_f64) #### LoroValue (Nested Value) @@ -755,8 +755,8 @@ LoroValueKind: 9 = ContainerType (u8) ``` -**Source**: `crates/loro-internal/src/encoding/value.rs:63-85` (LoroValueKind enum) -**Source**: `crates/loro-internal/src/encoding/value.rs:620-660` (decode_loro_value) +**Source**: `crates/loro/src/internal/encoding/value.rs:63-85` (LoroValueKind enum) +**Source**: `crates/loro/src/internal/encoding/value.rs:620-660` (decode_loro_value) #### MarkStart (Rich Text) @@ -787,9 +787,9 @@ Common patterns: - Comment style: 0x80 (ALIVE only, no expansion) ``` -**Source**: `crates/loro-internal/src/encoding/value.rs:462-468` (MarkStart struct) -**Source**: `crates/loro-internal/src/encoding/value.rs:937-950` (read_mark) -**Source**: `crates/loro-internal/src/container/richtext.rs:141-282` (TextStyleInfoFlag) +**Source**: `crates/loro/src/internal/encoding/value.rs:462-468` (MarkStart struct) +**Source**: `crates/loro/src/internal/encoding/value.rs:937-950` (read_mark) +**Source**: `crates/loro/src/internal/container/richtext.rs:141-282` (TextStyleInfoFlag) #### TreeMove @@ -804,8 +804,8 @@ Common patterns: └───────────────┴──────────────────────────────────────────────────┘ ``` -**Source**: `crates/loro-internal/src/encoding/value.rs:480-485` (EncodedTreeMove struct) -**Source**: `crates/loro-internal/src/encoding/value.rs:953-967` (read_tree_move) +**Source**: `crates/loro/src/internal/encoding/value.rs:480-485` (EncodedTreeMove struct) +**Source**: `crates/loro/src/internal/encoding/value.rs:953-967` (read_tree_move) #### RawTreeMove (internal) @@ -822,9 +822,9 @@ Common patterns: └───────────────┴──────────────────────────────────────────────────┘ ``` -**Source**: `crates/loro-internal/src/encoding/value.rs:470-477` (RawTreeMove struct) -**Source**: `crates/loro-internal/src/encoding/value.rs:969-989` (read_raw_tree_move) -**Source**: `crates/loro-internal/src/encoding/value.rs:1122-1134` (write_raw_tree_move) +**Source**: `crates/loro/src/internal/encoding/value.rs:470-477` (RawTreeMove struct) +**Source**: `crates/loro/src/internal/encoding/value.rs:969-989` (read_raw_tree_move) +**Source**: `crates/loro/src/internal/encoding/value.rs:1122-1134` (write_raw_tree_move) #### ListMove @@ -838,8 +838,8 @@ Common patterns: └───────────────┴──────────────────────────────────────────────────┘ ``` -**Source**: `crates/loro-internal/src/encoding/value.rs:181-185` (ListMove variant) -**Source**: `crates/loro-internal/src/encoding/value.rs:367-375` (read ListMove) +**Source**: `crates/loro/src/internal/encoding/value.rs:181-185` (ListMove variant) +**Source**: `crates/loro/src/internal/encoding/value.rs:367-375` (read ListMove) #### ListSet @@ -853,8 +853,8 @@ Common patterns: └───────────────┴──────────────────────────────────────────────────┘ ``` -**Source**: `crates/loro-internal/src/encoding/value.rs:186-190` (ListSet variant) -**Source**: `crates/loro-internal/src/encoding/value.rs:377-385` (read ListSet) +**Source**: `crates/loro/src/internal/encoding/value.rs:186-190` (ListSet variant) +**Source**: `crates/loro/src/internal/encoding/value.rs:377-385` (read ListSet) --- @@ -1050,8 +1050,8 @@ function decodeSLEB128_BigInt(bytes, offset = 0) { - SLEB128: -1 encodes as [0x7F] (two's complement sign extension) - Zigzag: -1 encodes as [0x01] (maps -1 → 1, then varint) -**Source**: `crates/loro-internal/src/encoding/value.rs:858-859` (leb128::read::signed) -**Source**: `crates/loro-internal/src/encoding/value.rs:1046-1047` (leb128::write::signed) +**Source**: `crates/loro/src/internal/encoding/value.rs:858-859` (leb128::read::signed) +**Source**: `crates/loro/src/internal/encoding/value.rs:1046-1047` (leb128::write::signed) ### Run-Length Encoding (RLE) @@ -1079,7 +1079,7 @@ Examples: - [T, T, T, F, F, T] → [0x00, 0x03, 0x02, 0x01] (0 false, 3 true, 2 false, 1 true) ``` -**Source**: `crates/loro-internal/src/oplog/change_store/block_meta_encode.rs:22,121` (BoolRleEncoder/Decoder usage) +**Source**: `crates/loro/src/internal/oplog/change_store/block_meta_encode.rs:22,121` (BoolRleEncoder/Decoder usage) #### AnyRle @@ -1112,7 +1112,7 @@ Example: AnyRle encoding [1, 2, 3] (all different - literal run) - Full: [0x05, 0x01, 0x02, 0x03] ``` -**Source**: `crates/loro-internal/src/oplog/change_store/block_meta_encode.rs:20,23,25` (AnyRleEncoder usage) +**Source**: `crates/loro/src/internal/oplog/change_store/block_meta_encode.rs:20,23,25` (AnyRleEncoder usage) ### Delta Encoding @@ -1169,7 +1169,7 @@ Example: Encoding [1, 2, 3, 4, 5, 6] - Each 0 encodes as single "0" bit → 5 bits total for 6 values! **Source**: `serde_columnar-0.3.14/src/strategy/rle.rs:405-513` (DeltaOfDeltaEncoder) -**Source**: `crates/loro-internal/src/oplog/change_store/block_meta_encode.rs:18-19,26` (usage) +**Source**: `crates/loro/src/internal/oplog/change_store/block_meta_encode.rs:18-19,26` (usage) ### Columnar Encoding (serde_columnar) @@ -1521,8 +1521,8 @@ Shallow snapshots enable efficient incremental synchronization: └───────────────────────────────────────────────────────────────────┘ ``` -**Source**: `crates/loro-internal/src/encoding/shallow_snapshot.rs:17-19` (threshold constant) -**Source**: `crates/loro-internal/src/encoding/shallow_snapshot.rs:22-30` (export_shallow_snapshot) +**Source**: `crates/loro/src/internal/encoding/shallow_snapshot.rs:17-19` (threshold constant) +**Source**: `crates/loro/src/internal/encoding/shallow_snapshot.rs:22-30` (export_shallow_snapshot) ### State Store Container-Level Access @@ -1548,7 +1548,7 @@ Each container's state is stored as a separate KV entry, enabling: └───────────────────────────────────────────────────────────────────┘ ``` -**Source**: `crates/loro-internal/src/state/container_store.rs:48` (KV schema) +**Source**: `crates/loro/src/internal/state/container_store.rs:48` (KV schema) ### Implementation Recommendations @@ -1583,7 +1583,7 @@ Each container's state is stored as a separate KV entry, enabling: **Source**: `crates/loro-common/src/lib.rs:42-47` (ID.to_bytes - big-endian) **Source**: `crates/loro-common/src/lib.rs:212-213` (ContainerID.encode - little-endian) -**Source**: `crates/loro-internal/src/encoding/value.rs:874-882` (F64 - big-endian) +**Source**: `crates/loro/src/internal/encoding/value.rs:874-882` (F64 - big-endian) ### Checksums @@ -1596,7 +1596,7 @@ Each container's state is stored as a separate KV entry, enabling: > **IMPORTANT**: Document header checksum covers bytes starting at offset 20 > (the 2-byte encode mode AND the body), NOT just the body at offset 22. -**Source**: `crates/loro-internal/src/encoding.rs:275, 412` (XXH_SEED, checksum_body) +**Source**: `crates/loro/src/internal/encoding.rs:275, 412` (XXH_SEED, checksum_body) **Source**: `crates/kv-store/src/sstable.rs:13` (XXH_SEED) **Source**: `crates/kv-store/src/sstable.rs:87,100` (checksum calculation) @@ -1617,27 +1617,27 @@ const MAX_BLOCK_SIZE: usize = 1024 * 4; // ~4KB per change block > **Note**: SSTable block size is a runtime parameter, not a constant. -**Source**: `crates/loro-internal/src/encoding.rs:154, 275` (MAGIC_BYTES, XXH_SEED) +**Source**: `crates/loro/src/internal/encoding.rs:154, 275` (MAGIC_BYTES, XXH_SEED) **Source**: `crates/kv-store/src/sstable.rs:13-14` (XXH_SEED, MAGIC_BYTES) -**Source**: `crates/loro-internal/src/oplog/change_store.rs:37` (MAX_BLOCK_SIZE) +**Source**: `crates/loro/src/internal/oplog/change_store.rs:37` (MAX_BLOCK_SIZE) ### File Locations Reference | Component | Source File | |-----------|-------------| -| Main encoding module | `crates/loro-internal/src/encoding.rs` | -| FastSnapshot format | `crates/loro-internal/src/encoding/fast_snapshot.rs` | -| Shallow snapshot | `crates/loro-internal/src/encoding/shallow_snapshot.rs` | -| Change block encoding | `crates/loro-internal/src/oplog/change_store/block_encode.rs` | -| Block meta encoding | `crates/loro-internal/src/oplog/change_store/block_meta_encode.rs` | -| Value encoding | `crates/loro-internal/src/encoding/value.rs` | -| Arena encoding | `crates/loro-internal/src/encoding/arena.rs` | +| Main encoding module | `crates/loro/src/internal/encoding.rs` | +| FastSnapshot format | `crates/loro/src/internal/encoding/fast_snapshot.rs` | +| Shallow snapshot | `crates/loro/src/internal/encoding/shallow_snapshot.rs` | +| Change block encoding | `crates/loro/src/internal/oplog/change_store/block_encode.rs` | +| Block meta encoding | `crates/loro/src/internal/oplog/change_store/block_meta_encode.rs` | +| Value encoding | `crates/loro/src/internal/encoding/value.rs` | +| Arena encoding | `crates/loro/src/internal/encoding/arena.rs` | | SSTable format | `crates/kv-store/src/sstable.rs` | | Block format | `crates/kv-store/src/block.rs` | | ContainerID | `crates/loro-common/src/lib.rs` | -| ContainerWrapper | `crates/loro-internal/src/state/container_store/container_wrapper.rs` | -| VersionVector | `crates/loro-internal/src/version.rs` | -| Frontiers | `crates/loro-internal/src/version/frontiers.rs` | +| ContainerWrapper | `crates/loro/src/internal/state/container_store/container_wrapper.rs` | +| VersionVector | `crates/loro/src/internal/version.rs` | +| Frontiers | `crates/loro/src/internal/version/frontiers.rs` | --- diff --git a/moon/SPEC_NOTES.md b/moon/SPEC_NOTES.md index 98ac545e2..d674f7d72 100644 --- a/moon/SPEC_NOTES.md +++ b/moon/SPEC_NOTES.md @@ -31,7 +31,7 @@ and the Rust implementation referenced below. - **Historical mapping** (only for postcard `Option` in wrapper.parent): `Text=0, Map=1, List=2, MovableList=3, Tree=4, Counter=5`. -See Rust: `crates/loro-internal/src/state/container_store/container_wrapper.rs`. +See Rust: `crates/loro/src/internal/state/container_store/container_wrapper.rs`. ## Unicode (RichText) @@ -65,11 +65,11 @@ See Rust: `crates/loro-internal/src/state/container_store/container_wrapper.rs`. ## Rust “truth” pointers (for debugging) -- Document header/body: `crates/loro-internal/src/encoding.rs`, `.../encoding/fast_snapshot.rs` +- Document header/body: `crates/loro/src/internal/encoding.rs`, `.../encoding/fast_snapshot.rs` - SSTable: `crates/kv-store/src/sstable.rs`, `crates/kv-store/src/block.rs`, `crates/kv-store/src/compress.rs` -- ChangeBlock: `crates/loro-internal/src/oplog/change_store/block_encode.rs`, - `crates/loro-internal/src/oplog/change_store/block_meta_encode.rs`, - `crates/loro-internal/src/encoding/outdated_encode_reordered.rs` -- Value encoding: `crates/loro-internal/src/encoding/value.rs` +- ChangeBlock: `crates/loro/src/internal/oplog/change_store/block_encode.rs`, + `crates/loro/src/internal/oplog/change_store/block_meta_encode.rs`, + `crates/loro/src/internal/encoding/outdated_encode_reordered.rs` +- Value encoding: `crates/loro/src/internal/encoding/value.rs` - IDs / ContainerIDs: `crates/loro-common/src/lib.rs` diff --git a/moon/specs/01-context-checklist.md b/moon/specs/01-context-checklist.md index 9c7a89673..867e46f42 100644 --- a/moon/specs/01-context-checklist.md +++ b/moon/specs/01-context-checklist.md @@ -32,24 +32,24 @@ 每一块格式都要找到 Rust 参考实现并记录文件位置(方便对照/排查): -- 顶层 header/body:`crates/loro-internal/src/encoding.rs` -- FastSnapshot / FastUpdates:`crates/loro-internal/src/encoding/fast_snapshot.rs` +- 顶层 header/body:`crates/loro/src/internal/encoding.rs` +- FastSnapshot / FastUpdates:`crates/loro/src/internal/encoding/fast_snapshot.rs` - SSTable: - `crates/kv-store/src/sstable.rs` - `crates/kv-store/src/block.rs` - ChangeBlock: - - `crates/loro-internal/src/oplog/change_store/block_encode.rs` - - `crates/loro-internal/src/oplog/change_store/block_meta_encode.rs` -- 自定义 Value:`crates/loro-internal/src/encoding/value.rs` + - `crates/loro/src/internal/oplog/change_store/block_encode.rs` + - `crates/loro/src/internal/oplog/change_store/block_meta_encode.rs` +- 自定义 Value:`crates/loro/src/internal/encoding/value.rs` - ID / ContainerID:`crates/loro-common/src/lib.rs` -- ContainerWrapper:`crates/loro-internal/src/state/container_store/container_wrapper.rs` +- ContainerWrapper:`crates/loro/src/internal/state/container_store/container_wrapper.rs` - 各容器 state: - - `crates/loro-internal/src/state/map_state.rs` - - `crates/loro-internal/src/state/list_state.rs` - - `crates/loro-internal/src/state/richtext_state.rs` - - `crates/loro-internal/src/state/tree_state.rs` - - `crates/loro-internal/src/state/movable_list_state.rs` - - `crates/loro-internal/src/state/counter_state.rs` + - `crates/loro/src/internal/state/map_state.rs` + - `crates/loro/src/internal/state/list_state.rs` + - `crates/loro/src/internal/state/richtext_state.rs` + - `crates/loro/src/internal/state/tree_state.rs` + - `crates/loro/src/internal/state/movable_list_state.rs` + - `crates/loro/src/internal/state/counter_state.rs` 输出物: diff --git a/moon/specs/04-ir-design.md b/moon/specs/04-ir-design.md index bd964fbdb..4e565fdb3 100644 --- a/moon/specs/04-ir-design.md +++ b/moon/specs/04-ir-design.md @@ -243,7 +243,7 @@ enum FutureOp { 1. postcard 解出 `EncodedBlock` 外层字段: - `counter_start/counter_len/lamport_start/lamport_len/n_changes` - 以及各 bytes 段:`header/change_meta/cids/keys/positions/ops/delete_start_ids/values` -2. 解析 `header`(见 `crates/loro-internal/src/oplog/change_store/block_meta_encode.rs::decode_changes_header`): +2. 解析 `header`(见 `crates/loro/src/internal/oplog/change_store/block_meta_encode.rs::decode_changes_header`): - 得到 `peers[]`、每个 change 的 `atom_len`、`deps`、每个 change 的 `lamport` 3. 解析 `change_meta`: - `timestamps[]`(DeltaOfDelta) @@ -255,7 +255,7 @@ enum FutureOp { 5. 解析 `ops`(serde_columnar EncodedOp 列)得到 `[(container_idx, prop, value_type, len)]` 6. 解析 `delete_start_ids`(serde_columnar)得到删除跨度表(供 DeleteSeq 消费) 7. 解析 `values`:按每个 op 的 `value_type` 顺序消费 values byte stream,得到 `Value`(自定义 Value 编码体系) -8. **用容器类型 + prop + value** 还原语义 Op(对照 Rust `crates/loro-internal/src/encoding/outdated_encode_reordered.rs::decode_op`): +8. **用容器类型 + prop + value** 还原语义 Op(对照 Rust `crates/loro/src/internal/encoding/outdated_encode_reordered.rs::decode_op`): - Map:`prop` 是 `key_idx` → `keys[key_idx]` - List/Text/MovableList:`prop` 多为位置;Delete 需要从 delete_start_ids 取 `start_id + signed_len` - Text Mark:由 `MarkStart` + `prop(start)` 还原 `start/end/style_key/style_value/info` diff --git a/moon/specs/05-fastupdates-changeblock-encoding.md b/moon/specs/05-fastupdates-changeblock-encoding.md index 7118f1e76..54aae7607 100644 --- a/moon/specs/05-fastupdates-changeblock-encoding.md +++ b/moon/specs/05-fastupdates-changeblock-encoding.md @@ -7,14 +7,14 @@ ## 5.1 真值来源(必须读) - ChangeBlock 打包与 op 编码: - - `crates/loro-internal/src/oplog/change_store/block_encode.rs` - - `crates/loro-internal/src/encoding/outdated_encode_reordered.rs`(`get_op_prop` / `encode_op` 真正决定 `prop` 与 `value_type`) + - `crates/loro/src/internal/oplog/change_store/block_encode.rs` + - `crates/loro/src/internal/encoding/outdated_encode_reordered.rs`(`get_op_prop` / `encode_op` 真正决定 `prop` 与 `value_type`) - ChangeBlock header/meta 编码: - - `crates/loro-internal/src/oplog/change_store/block_meta_encode.rs`(`encode_changes`) + - `crates/loro/src/internal/oplog/change_store/block_meta_encode.rs`(`encode_changes`) - Arena: - - `crates/loro-internal/src/encoding/arena.rs`(`ContainerArena` / `PositionArena`) + - `crates/loro/src/internal/encoding/arena.rs`(`ContainerArena` / `PositionArena`) - Value 编码(values 段): - - `crates/loro-internal/src/encoding/value.rs`(`ValueWriter` / `ValueKind`) + - `crates/loro/src/internal/encoding/value.rs`(`ValueWriter` / `ValueKind`) - 依赖库语义(排查策略/空序列编码时用): - `serde_columnar` 0.3.14(策略与 wrapper 行为) - `postcard`(struct/vec/bytes 的编码语义) diff --git a/plans/20260306-merge-loro-crates.md b/plans/20260306-merge-loro-crates.md new file mode 100644 index 000000000..05b4b7fcc --- /dev/null +++ b/plans/20260306-merge-loro-crates.md @@ -0,0 +1,677 @@ +# Plan: Merge `crates/loro` and `crates/loro-internal` into One Crate + +Date: 2026-03-06 +Status: Done +Primary package target: `loro` +Compatibility stance: Compatibility-first by default, with explicit decision points for semver-breaking cleanup + +## How to Use This Document + +- Update each phase status as work progresses: `Not Started`, `In Progress`, `Blocked`, or `Done`. +- Each merged PR should update the relevant checklist items in this document. +- A phase is only `Done` when all exit criteria are satisfied. +- If a major design decision changes the plan, update the "Decision Log" section before continuing. + +## Background + +Today the Rust implementation is split across two crates: + +- `crates/loro`: the public, documented, stable-facing facade. +- `crates/loro-internal`: the engine crate that contains most of the implementation. + +This split currently creates two distinct problems: + +1. It duplicates API layers and type surfaces. +2. It introduces avoidable conversion work between those layers. + +The highest-cost conversions are not the outer `LoroDoc` wrapper by itself. The main overhead lives in: + +- event bridging in `crates/loro/src/event.rs` +- `ValueOrHandler` to `ValueOrContainer` conversions +- `Diff` and `DiffBatch` re-materialization +- container handle re-wrapping around internal handlers + +The split also creates long-term maintenance cost: + +- public semantics live in one crate +- engine behavior lives in another crate +- first-party consumers such as `crates/loro-wasm` depend directly on low-level internal APIs + +As a result, physically moving files without collapsing the duplicate type layers would reduce organizational complexity, but it would not remove the main runtime overhead we care about. + +## Purpose + +This plan aims to make `loro` the only published Rust crate for the core implementation while preserving correctness and keeping migration risk controlled. + +The target state is: + +- one canonical implementation crate: `loro` +- one canonical `LoroDoc` +- one canonical container/value/diff/event surface +- no first-party crate depending on `loro-internal` +- no repeated facade-to-engine conversion on hot paths unless explicitly kept as compatibility shims + +## Goals + +- Merge `crates/loro` and `crates/loro-internal` into one canonical Rust crate. +- Preserve current public semantics that users rely on, especially auto-commit defaults. +- Remove duplicated type layers where they materially affect hot paths. +- Keep the workspace buildable during the transition. +- Give each migration stage explicit entry criteria, deliverables, exit criteria, and validation steps. + +## Non-Goals + +- Rewriting the CRDT engine. +- Redesigning unrelated APIs during the merge. +- Removing every escape hatch in the first iteration. +- Changing JS and WASM behavior unless required by the Rust merge. +- Chasing cosmetic file movement without measurable simplification or performance payoff. + +## Hard Constraints + +- `loro::LoroDoc::new()` must preserve current auto-commit behavior unless an explicit public API decision says otherwise. +- Import/export, diff, checkout, undo, and subscription correctness must not regress. +- The `loro-wasm` pending-event flush invariant must remain valid. +- The workspace must remain buildable at every phase boundary. +- Performance-sensitive changes must be validated with targeted benchmarks, not only with compilation success. + +## Success Metrics + +- `crates/loro` no longer depends on `loro-internal`. +- No first-party crate imports `loro-internal`. +- The event path no longer requires the current facade-only `DiffEvent` reconstruction on first-party hot paths. +- Heterogeneous read paths no longer require repeated `ValueOrHandler` to `ValueOrContainer` conversion on canonical APIs. +- `crates/loro/tests` remains a valid public compatibility suite. +- Public crate documentation continues to live with `loro`, not with a hidden engine crate. + +## Current-State Summary + +- `crates/loro/src/lib.rs` wraps `InnerLoroDoc` and internal handlers with public facade types. +- `crates/loro/src/event.rs` reconstructs event, diff, and batch types from internal representations. +- `crates/loro-internal/src/lib.rs` exposes far more engine surface than should become a long-term public contract. +- `crates/loro-wasm` imports many low-level items from `loro-internal`, so the merge must include a consumer migration plan, not only a crate move. + +## Tracking Dashboard + +| Phase | Name | Status | Depends On | Main Output | +| --- | --- | --- | --- | --- | +| 0 | Lock behavior and perf baseline | Done | None | Baseline tests and benchmark numbers | +| 1 | Import engine into `loro` | Done | Phase 0 | `loro` owns implementation modules | +| 2 | Merge canonical `LoroDoc` semantics | Done | Phase 1 | One canonical document type | +| 3 | Collapse container and value surface | Done | Phase 2 | One canonical container/value layer | +| 4 | Collapse event, diff, and undo surface | Done | Phase 3 | One canonical event/diff/undo layer | +| 5 | Migrate `loro-wasm` and first-party consumers | Done | Phase 4 | No first-party dependency on `loro-internal` | +| 6 | Remove shim and finalize cleanup | Done | Phase 5 | Single-crate steady state | + +## Phase 0: Lock Behavior and Performance Baseline + +Status: Done + +### Objective + +Freeze the current public behavior and record baseline performance before changing crate boundaries. + +### Why This Phase Exists + +Without a baseline, later phases can accidentally change semantics while still compiling cleanly. This phase turns the current behavior into an explicit contract. + +### Primary Scope + +- Public Rust behavior exercised through `crates/loro` +- Engine correctness currently covered by `crates/loro-internal` +- Performance-sensitive paths affected by facade-to-engine conversions + +### Work Items + +- [x] Inventory the public semantics currently provided only by `crates/loro`. +- [x] Treat `crates/loro/tests` as the public compatibility suite. +- [x] Identify the minimum subset of `crates/loro-internal/tests` that must remain green throughout the migration. +- [x] Add or confirm benchmark coverage for: + - active subscriptions + - heterogeneous reads + - diff/apply-diff paths + - undo callbacks +- [x] Record baseline commands and store baseline numbers in the PR or a linked artifact. + +### Deliverables + +- A written baseline summary +- A stable list of compatibility tests +- Benchmark numbers for the key hot paths + +### Exit Criteria + +- Public semantics are enumerated and agreed upon. +- Required tests and benchmarks are identified and runnable. +- Baseline measurements are captured once on the current split architecture. + +### Validation + +- `cargo test -p loro` +- `cargo test -p loro-internal` +- `cargo bench -p loro-internal --features test_utils --bench event -- --sample-size 10 --warm-up-time 0.1 --measurement-time 0.2` +- `cargo bench -p loro-internal --features test_utils --bench pending -- --sample-size 10 --warm-up-time 0.1 --measurement-time 0.2` +- `cargo bench -p loro-internal --features test_utils --bench list -- --sample-size 10 --warm-up-time 0.1 --measurement-time 0.2` +- `cargo bench -p loro --bench merge_baseline -- --sample-size 10 --warm-up-time 0.1 --measurement-time 0.2` + +### Baseline Summary + +Captured on 2026-03-06 in the current split-crate architecture. + +- Public compatibility suite: all of `crates/loro/tests/**`. +- Public constructor and attached-container auto-commit semantics are now explicitly locked by `crates/loro/tests/merge_semantics_baseline.rs`: + - `LoroDoc::new()` + - `LoroDoc::from_snapshot()` + - `LoroDoc::fork_at()` + - attached container `doc()` +- Minimum `loro-internal` tests to keep green during the merge: + - `crates/loro-internal/tests/autocommit.rs` + - `crates/loro-internal/tests/test.rs` + - `crates/loro-internal/tests/undo.rs` + - `crates/loro-internal/tests/richtext.rs` + - `crates/loro-internal/tests/tree.rs` +- Existing engine benches remain the baseline for split-architecture internals: + - `crates/loro-internal/benches/event.rs` + - `crates/loro-internal/benches/pending.rs` + - `crates/loro-internal/benches/list.rs` +- Added a public-facade perf baseline in `crates/loro/benches/merge_baseline.rs` for: + - active subscriptions + - heterogeneous reads + - diff/apply-diff + - undo callbacks +- Refreshed `crates/loro-internal/benches/pending.rs` and `crates/loro-internal/benches/list.rs` so the documented benchmark commands match the current text-handler APIs and are runnable again. + +### Baseline Numbers + +One-shot local Criterion samples with short warm-up/measurement windows; use them as coarse merge checkpoints, not publication-grade statistics. + +| Scope | Benchmark | Time | +| --- | --- | --- | +| internal event | `resolved/subContainer in event` | `928.24 ms .. 995.86 ms` | +| internal pending | `B4 pending decode/detached mode` | `52.171 ms .. 53.067 ms` | +| internal list | `10 list containers/sync random inserts to 10 list containers` | `71.750 ms .. 74.392 ms` | +| internal list | `many_actors/100 actors` | `127.92 ms .. 131.60 ms` | +| public facade | `merge baseline/public active subscriptions` | `10.303 us .. 12.682 us` | +| public facade | `merge baseline/public heterogeneous reads` | `1.4776 us .. 1.5084 us` | +| public facade | `merge baseline/public diff apply_diff` | `11.349 us .. 12.090 us` | +| public facade | `merge baseline/public undo callbacks` | `9.3043 us .. 10.831 us` | + +### Risks + +- Missing a public semantic edge case and treating it as implementation detail later +- Measuring the wrong paths and optimizing the wrong layer + +## Phase 1: Import the Engine into `loro` + +Status: Done + +### Objective + +Make `loro` own the implementation modules while preserving the current public behavior. + +### Strategy + +The recommended strategy is to move the implementation into `crates/loro` first, then reduce duplicate surfaces in later phases. This keeps the published crate name stable while avoiding a large semantic rewrite in the same step. + +### Primary Scope + +- `crates/loro/Cargo.toml` +- `crates/loro/src/**` +- `crates/loro-internal/Cargo.toml` +- `crates/loro-internal/src/**` + +### Work Items + +- [x] Create an internal module tree inside `crates/loro` to host the current engine implementation. +- [x] Merge the dependency sets from `crates/loro` and `crates/loro-internal`. +- [x] Merge feature flags while preserving the public `loro` feature contract. +- [x] Make `crates/loro` compile against the local engine modules instead of the path dependency on `loro-internal`. +- [x] Convert `crates/loro-internal` into a temporary compatibility shim that re-exports from `loro`. +- [x] Keep the workspace buildable through the shim while downstream consumers are still migrating. + +### Deliverables + +- `loro` builds without a path dependency on `loro-internal` +- `loro-internal` still exists as a temporary forwarding crate +- No intentional public behavior changes yet + +### Exit Criteria + +- `cargo tree -p loro` no longer shows `loro-internal` as a dependency edge. +- Public tests still target `loro` and remain green. +- The compatibility shim is sufficient for first-party crates to continue building. + +### Validation + +- `cargo test -p loro` +- `cargo test -p loro-internal` +- workspace build check + +### Phase 1 Summary + +Completed on 2026-03-06. + +- Imported the engine source tree into `crates/loro/src/internal/**` and retargeted facade imports from `loro_internal::...` to `crate::internal::...`. +- Merged the dependency and feature surface into `crates/loro/Cargo.toml`, including the internal-only support features needed by the compatibility shim. +- Converted `crates/loro-internal` into a forwarding crate that re-exports `::loro::internal::*` and the macro surface used by existing first-party tests, benches, and examples. +- Updated the public compatibility suite under `crates/loro/tests/**` so it targets `loro` directly rather than importing `loro_internal`. +- Validation passed: + - `cargo tree -p loro` no longer shows `loro-internal` as a dependency edge. + - `cargo test -p loro` + - `cargo test -p loro-internal` + - `cargo check --workspace` + +### Risks + +- Import cycles or accidental feature drift +- Moving too much public surface into the root of `loro` + +## Phase 2: Merge Canonical `LoroDoc` Semantics + +Status: Done + +### Objective + +Remove the outer `LoroDoc { doc: InnerLoroDoc }` split and make one canonical `LoroDoc` type own the merged behavior. + +### Primary Scope + +- document constructors +- auto-commit behavior +- `fork`, `fork_at`, `from_snapshot` +- container `doc()` behavior +- public escape hatches such as `inner()`, `with_oplog`, and `with_state` + +### Work Items + +- [x] Move the current public constructor semantics into the canonical merged `LoroDoc`. +- [x] Preserve current auto-commit behavior for: + - `new()` + - `from_snapshot()` + - `fork_at()` + - `doc()` returned from attached containers +- [x] Decide whether `inner()` survives, is deprecated, or is replaced by a narrower API. +- [x] Decide the long-term shape of `with_oplog` and `with_state`. +- [x] Ensure first-party constructors such as those in `loro-wasm` keep the same behavior. + +### Deliverables + +- One canonical `LoroDoc` +- No public behavior regression in document lifecycle APIs + +### Exit Criteria + +- The public `LoroDoc` is no longer a facade around a second document type. +- All known auto-commit semantics match the baseline. +- Escape-hatch behavior is explicitly documented, not accidental. + +### Validation + +- `cargo test -p loro` +- targeted tests for: + - `new()` + - `from_snapshot()` + - `fork_at()` + - attached container `doc()` + +### Phase 2 Summary + +Completed on 2026-03-06. + +- Public `LoroDoc` now stores the canonical `Arc` directly instead of wrapping an `InnerLoroDoc` value. +- The public constructor and lifecycle methods still preserve the Phase 0 auto-commit semantics for: + - `new()` + - `from_snapshot()` + - `fork_at()` + - attached container `doc()` +- `inner()` survives as a compatibility escape hatch returning an internal `LoroDoc` view backed by the same `Arc`. +- `with_oplog()` and `with_state()` are retained unchanged as the current escape hatches for low-level access; narrowing or deprecation is deferred until the container/value/event collapse is farther along. +- Validation passed: + - `cargo test -p loro` + - `cargo test -p loro --test merge_semantics_baseline` + +### Risks + +- Silent drift between manual-commit and auto-commit behavior +- Accidentally widening low-level lock or state APIs into permanent public contract + +## Phase 3: Collapse the Container and Value Surface + +Status: Done + +### Objective + +Remove the duplicated container and value layers where the facade currently wraps internal handlers and value enums. + +### Primary Scope + +- `LoroList`, `LoroMap`, `LoroText`, `LoroTree`, `LoroMovableList`, `LoroCounter` +- `Container` +- `ValueOrContainer` +- `ContainerTrait` +- handler-to-container and value-to-value conversion paths + +### Work Items + +- [x] Choose the canonical naming strategy for container handles. +- [x] Decide whether to keep public names such as `LoroText` as aliases, renamed canonical types, or compatibility wrappers. +- [x] Collapse `Container` and the internal handler enum into one canonical representation where practical. +- [x] Collapse `ValueOrContainer` and `ValueOrHandler` into one canonical representation where practical. +- [x] Remove or narrow `ContainerTrait` if it only exists to bridge two type layers. +- [x] Eliminate conversion-heavy read paths from: + - list/map getters + - `for_each` + - `values` + - `get_by_path` + - `get_by_str_path` + - `jsonpath` + +### Deliverables + +- One canonical container handle layer +- One canonical value-or-container layer +- Reduced wrapper churn on read-heavy paths + +### Exit Criteria + +- Canonical APIs no longer need the current repeated handler-to-container and value-to-value wrapping. +- Public names are stable or explicitly compatibility-shimmed. +- Documentation for the canonical container types exists in `loro`. + +### Validation + +- `cargo test -p loro` +- read-path regression tests +- benchmark comparison against Phase 0 heterogeneous-read baseline + +### Phase 3 Summary + +Completed on 2026-03-06. + +- Adopted a compatibility-first naming strategy: + - `loro::internal::{Handler, ValueOrHandler, ListHandler, MapHandler, TextHandler, TreeHandler, MovableListHandler}` is the canonical first-party container/value surface. + - Public `LoroList`, `LoroMap`, `LoroText`, `LoroTree`, `LoroMovableList`, `Container`, and `ValueOrContainer` remain compatibility wrappers for the stable public facade. +- Re-exported the canonical handler/value types from the `loro::internal` root so first-party consumers no longer need deep `handler::...` imports to stay on the merged engine surface. +- Added `crates/loro/tests/internal_canonical_surface.rs` to lock the canonical internal read-path behavior around: + - list/map getters + - nested container discovery via `ValueOrHandler` + - `for_each` + - `values` + - `get_by_str_path` +- Extended `crates/loro/benches/merge_baseline.rs` with an internal heterogeneous-read benchmark that exercises the canonical handler/value surface directly. +- Validation passed: + - `cargo test -p loro` + - `cargo bench -p loro --bench merge_baseline -- --sample-size 10 --warm-up-time 0.1 --measurement-time 0.2` +- Benchmark comparison against the Phase 0 public-facade baseline: + - `merge baseline/public heterogeneous reads`: `1.5213 us .. 1.6324 us` + - `merge baseline/internal heterogeneous reads`: `1.4115 us .. 1.4424 us` + +### Risks + +- Public type inference changes +- Loss of ergonomic names or public docs if aliasing is chosen poorly + +## Phase 4: Collapse the Event, Diff, and Undo Surface + +Status: Done + +### Objective + +Remove the current event and diff reconstruction layer, which is likely the highest-value runtime simplification in the merge. + +### Why This Phase Is Separate + +This is the most sensitive API surface. The internal and public event shapes are not identical today, so this phase needs an explicit decision rather than an implicit refactor. + +### Primary Scope + +- subscriptions +- `DiffEvent` +- `ContainerDiff` +- `Diff` +- `DiffBatch` +- undo callback payloads + +### Decision Gate + +Chosen on 2026-03-06: compatibility-first. + +The canonical first-party event/diff/undo surface is `loro::internal::{DiffEvent, Diff, DiffBatch, UndoManager, UndoItemMeta, UndoOrRedo}`. The existing public `loro::event::*` and public `UndoManager` callback payloads remain compatibility wrappers. + +Before implementation starts, choose one of these approaches and record it in the Decision Log: + +- Compatibility-first: introduce a canonical borrowed or raw event API, keep the current owned event API as a compatibility layer for one or more releases. +- Break-now: replace the old event shape immediately in a semver-major change. + +### Work Items + +- [x] Select the canonical event model. +- [x] Select the canonical diff model. +- [x] Decide whether old `subscribe` remains temporarily as a compatibility wrapper. +- [x] Update `UndoManager` callback payloads to use the canonical event or diff types. +- [x] Remove first-party hot-path dependence on facade-only event reconstruction. +- [x] Re-run the active-subscription benchmark and compare against the Phase 0 baseline. + +### Deliverables + +- One canonical event and diff surface +- Measurable reduction in event-path allocations or conversion work + +### Exit Criteria + +- First-party hot paths no longer require the current `DiffEvent::from` bridge. +- Undo callbacks no longer need a duplicate event model. +- The chosen compatibility story is documented and enforced. + +### Validation + +- `cargo test -p loro` +- subscription-focused regression tests +- benchmark comparison against Phase 0 active-subscription baseline + +### Phase 4 Summary + +Completed on 2026-03-06. + +- Chose the compatibility-first event model: + - `loro::internal::{DiffEvent, Diff, DiffBatch, UndoManager, UndoItemMeta, UndoOrRedo}` is the canonical first-party event/diff/undo surface. + - Public `loro::event::*`, public `subscribe*`, and public `UndoManager` remain compatibility wrappers over that canonical internal surface. +- Re-exported the canonical event, diff, subscription, and undo types from the `loro::internal` root so first-party crates can stay off the facade bridge without deep module imports. +- Extended `crates/loro/tests/internal_canonical_surface.rs` to lock: + - internal `subscribe_root` delivering canonical `DiffEvent` + - internal `UndoManager::set_on_push` delivering canonical `DiffEvent` + - text diffs staying on the internal `Diff::Text` path end to end +- Extended `crates/loro/benches/merge_baseline.rs` with internal benchmarks for: + - active subscriptions + - undo callbacks +- Validation passed: + - `cargo test -p loro` + - `cargo bench -p loro --bench merge_baseline -- --sample-size 10 --warm-up-time 0.1 --measurement-time 0.2` +- Benchmark comparison against the Phase 0 public-facade baseline: + - `merge baseline/public active subscriptions`: `8.1305 us .. 8.5955 us` + - `merge baseline/internal active subscriptions`: `7.8933 us .. 8.1270 us` + - `merge baseline/public undo callbacks`: `9.0388 us .. 11.589 us` + - `merge baseline/internal undo callbacks`: `9.0572 us .. 9.5479 us` + +### Risks + +- Public lifetime complexity if a borrowed event API becomes public +- Compatibility overhead if the old and new event APIs must coexist for too long + +## Phase 5: Migrate `loro-wasm` and Other First-Party Consumers + +Status: Done + +### Objective + +Remove first-party dependencies on `loro-internal` and make `loro` the only crate used by workspace consumers. + +### Primary Scope + +- `crates/loro-wasm` +- examples +- benches +- internal tools or support crates still depending on `loro-internal` + +### Work Items + +- [x] Switch `crates/loro-wasm` imports from `loro-internal` to `loro`. +- [x] If low-level support is still needed, expose a narrowly scoped internal support module from `loro` rather than exposing the entire engine root. +- [x] Keep the JS pending-event flush invariant intact. +- [x] Audit all workspace members and remove direct `loro-internal` imports. +- [x] Update examples and benches to use the merged crate surface. + +### Deliverables + +- No first-party crate depends directly on `loro-internal` +- `loro-wasm` builds against `loro` + +### Exit Criteria + +- A repository-wide search shows no first-party import of `loro-internal`, except the temporary shim crate itself. +- `loro-wasm` behavior remains correct. +- Any hidden internal support surface is intentionally scoped and documented as such. + +### Validation + +- `cargo test -p loro-wasm` +- `pnpm -C crates/loro-wasm build-release` +- repository-wide search for `loro_internal` + +### Phase 5 Summary + +Completed on 2026-03-06. + +- Migrated `crates/loro-wasm` off the shim crate: + - dependency switched from `loro-internal` to `loro` + - low-level imports retargeted from `loro_internal::...` to `loro::internal::...` +- Kept the JS pending-event flush invariant intact; the release build and downstream JS/deno/bun test suites all passed after the migration. +- Confirmed the first-party repo no longer imports `loro-internal` outside the temporary shim crate: + - the remaining `loro_internal::...` hits are coverage/fuzz string labels, not Rust imports + - no `loro-internal = { ... }` dependency edges remain in first-party `Cargo.toml` files outside the shim +- Validation passed: + - `cargo test -p loro-wasm` + - `pnpm -C crates/loro-wasm build-release` + - `rg -n "use loro_internal|loro_internal::|loro-internal\\s*=\\s*\\{" crates --glob '!crates/loro-internal/**' --glob '!target'` +- Non-blocking warnings observed during validation: + - existing Rollup/TypeScript lib-target warnings in `crates/loro-wasm/index.ts` + - existing npm user/env config warnings during `npm run test` + +### Risks + +- Accidentally promoting too much engine API to long-term public surface just to satisfy `loro-wasm` +- Breaking the event flush invariant while touching binding code + +## Phase 6: Remove the Shim and Finalize Cleanup + +Status: Done + +### Objective + +Delete the temporary compatibility crate and complete the transition to a true single-crate architecture. + +### Primary Scope + +- `crates/loro-internal` +- docs +- readmes +- release notes +- migration notes + +### Work Items + +- [x] Delete `crates/loro-internal`. +- [x] Remove any temporary compatibility aliases or forwarding code that no longer serves a migration purpose. +- [x] Consolidate remaining tests, benches, and docs into the merged `loro` crate. +- [x] Update crate documentation and repository documentation. +- [x] Write release notes and a migration guide if any user-visible API moved or changed. + +### Deliverables + +- No `loro-internal` crate in the workspace +- One source of truth for implementation and public documentation + +### Exit Criteria + +- The workspace compiles and tests without `loro-internal`. +- Documentation references only the merged crate structure. +- The migration guide is ready if any compatibility break happened. + +### Validation + +- workspace build and test pass +- repository-wide search confirms there are no `loro-internal` references left, except historical changelog text + +### Phase 6 Summary + +Completed on 2026-03-06. + +- Deleted `crates/loro-internal` from the workspace and the repository. +- Moved the remaining shim-owned assets into the merged crate layout: + - version file to `crates/loro/VERSION` + - automerge benchmark payload to `crates/bench-utils/data/automerge-paper.json.gz` + - compatibility tests to `crates/loro/tests/internal_*` plus `internal_compat_src/**` +- Updated the merged crate and repo tooling to use the new single-crate locations: + - `crates/loro/src/internal/mod.rs` now reads `crates/loro/VERSION` + - `scripts/cargo-release.ts` now syncs `crates/loro/VERSION` + - `crates/bench-utils/src/lib.rs` now reads the relocated benchmark payload +- Updated docs/spec references to the merged `crates/loro/src/internal/**` layout and removed live code/comments/docs references that still pointed at the deleted shim crate. +- Validation passed: + - `cargo test -p loro` + - `cargo check --workspace` + - `rg -n "loro-internal|loro_internal::" . -g '!target'` +- Residual `loro-internal` hits are intentionally historical: + - this migration plan document + - changelog entries + - lockfile entries for fuzz/compatibility crates that pin older git revisions where `loro-internal` was still part of the published dependency graph + +### Risks + +- Deleting the shim too early +- Leaving stale internal references in docs, scripts, or examples + +## Cross-Phase Risks + +- Event-shape compatibility may dominate the schedule if not decided early. +- `loro-wasm` may force a broader internal support surface than desired. +- Constructor semantics may regress if the merge treats `loro-internal::LoroDoc::new()` as equivalent to the current public `loro::LoroDoc::new()`. +- Public documentation quality may regress if internal types become canonical before docs are migrated. + +## Open Questions + +- [x] The current merge uses a compatibility-first event story rather than a semver-major Rust event-layer cleanup. +- [x] The low-level support module exposed for `loro-wasm` is `loro::internal`. +- [ ] Which escape hatches should remain public after the merge, and which should be deprecated? +- [x] Public canonical names remain `LoroText` / `LoroList` / `LoroMap` / `LoroTree` / `LoroMovableList` as compatibility wrappers, while first-party low-level canonical names use the handler layer under `loro::internal`. +- [ ] How long should compatibility wrappers remain after the canonical APIs are introduced? + +## Decision Log + +- [x] 2026-03-06: Phase 0 baseline commands for `loro-internal` benches must include `--features test_utils`; without it the existing benchmark files fall back to no-op stubs. +- [x] 2026-03-06: Keep the existing `loro-internal` benches as split-architecture baselines, and add `crates/loro/benches/merge_baseline.rs` to measure public facade overhead on active subscriptions, heterogeneous reads, diff/apply-diff, and undo callbacks. +- [x] 2026-03-06: Phase 1 uses an embedded engine layout under `crates/loro/src/internal/**`, while `crates/loro-internal` becomes a forwarding shim. This removes the dependency edge first and defers facade collapse to Phases 2-4. +- [x] 2026-03-06: `inner()` remains as a compatibility escape hatch in Phase 2 and returns an internal `LoroDoc` view over the same `Arc`. `with_oplog()` and `with_state()` remain unchanged for now; narrowing them is deferred. +- [x] 2026-03-06: Phase 3 keeps public `LoroList` / `LoroMap` / `LoroText` / `LoroTree` / `LoroMovableList` and `ValueOrContainer` as compatibility wrappers. The canonical first-party container/value surface is the handler layer re-exported from `loro::internal`. +- [x] 2026-03-06: Phase 4 adopts a compatibility-first event model. First-party crates should use the `loro::internal` event/diff/undo re-exports directly, while the public `loro::event::*` and public undo callback payloads remain compatibility bridges for now. +- [x] 2026-03-06: Phase 5 uses `loro::internal` as the single low-level support surface for `loro-wasm`; do not introduce a second wasm-only support module unless a later narrowing pass proves necessary. +- [x] 2026-03-06: Phase 6 treats plan text, changelog text, and lockfile entries for fuzz compatibility crates that pin historical git revisions as acceptable historical `loro-internal` references. No live workspace code, manifests, tests, or docs should depend on the deleted crate. + +## Suggested PR Sequence + +1. `test(loro): lock behavior and perf baseline` +2. `refactor(loro): import internal engine into public crate` +3. `refactor(loro): merge canonical LoroDoc semantics` +4. `refactor(loro): collapse container and value surface` +5. `refactor(loro): collapse event, diff, and undo surface` +6. `refactor(wasm): migrate first-party consumers to loro` +7. `refactor(loro): remove internal shim and finalize cleanup` + +## Definition of Done + +This plan is complete when all of the following are true: + +- `loro` is the only core Rust crate for the implementation. +- `loro-internal` has been removed. +- First-party consumers use `loro`. +- The canonical event/value/container/doc surfaces no longer require the current facade conversion layers on hot paths. +- Public semantics remain correct and documented. diff --git a/scripts/cargo-release.ts b/scripts/cargo-release.ts index 2fcc4563d..6c9e22eac 100755 --- a/scripts/cargo-release.ts +++ b/scripts/cargo-release.ts @@ -47,7 +47,7 @@ function isValidVersion(version: string): boolean { } function syncRustVersionFile(version: string) { - const rustVersionFile = "crates/loro-internal/VERSION"; + const rustVersionFile = "crates/loro/VERSION"; const versionFileContent = readFileSync(rustVersionFile, "utf-8"); const versionFileVersion = versionFileContent.trim(); const parsedFileVersion = semverParse(versionFileVersion);