diff --git a/crates/loro-internal/deno.json b/crates/loro-internal/deno.json index e451cf39..b1263a3b 100644 --- a/crates/loro-internal/deno.json +++ b/crates/loro-internal/deno.json @@ -3,7 +3,7 @@ "test": "cargo nextest run --features test_utils", "deny": "cargo deny check", "fuzz": "cargo +nightly fuzz run", - "quick-fuzz": "deno run -A ./scripts/fuzz.ts text text_refactored recursive encoding recursive_txn recursive_refactored", + "quick-fuzz": "deno run -A ./scripts/fuzz.ts text_refactored recursive_refactored", "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/src/diff_calc.rs b/crates/loro-internal/src/diff_calc.rs index 961f1519..cd17d5dd 100644 --- a/crates/loro-internal/src/diff_calc.rs +++ b/crates/loro-internal/src/diff_calc.rs @@ -72,13 +72,17 @@ impl DiffCalculator { let empty_vv: VersionVector = Default::default(); if !after.includes_vv(before) { // if after is not after before, we need to calculate the diff from the beginning - before = &merged; - after = &empty_vv; + before = &empty_vv; + after = &merged; before_frontiers = None; after_frontiers = None; self.has_all = true; } + if before.is_empty() { + self.has_all = true; + } + let (lca, iter) = oplog.iter_from_lca_causally(before, before_frontiers, after, after_frontiers); let mut started_set = FxHashSet::default(); diff --git a/crates/loro-internal/src/loro.rs b/crates/loro-internal/src/loro.rs index ad148ac1..9c9ba9f8 100644 --- a/crates/loro-internal/src/loro.rs +++ b/crates/loro-internal/src/loro.rs @@ -174,6 +174,11 @@ impl LoroDoc { self.import_with(bytes, Default::default()) } + pub fn import_without_state(&mut self, bytes: &[u8]) -> Result<(), LoroError> { + self.detach(); + self.import(bytes) + } + pub fn import_with(&self, bytes: &[u8], origin: InternalString) -> Result<(), LoroError> { let (magic_bytes, input) = bytes.split_at(4); let magic_bytes: [u8; 4] = magic_bytes.try_into().unwrap(); @@ -216,10 +221,10 @@ impl LoroDoc { } ConcreteEncodeMode::Snapshot => { if self.is_empty() { - decode_app_snapshot(self, &input[1..])?; + decode_app_snapshot(self, &input[1..], !self.detached)?; } else { let app = LoroDoc::new(); - decode_app_snapshot(&app, &input[1..])?; + decode_app_snapshot(&app, &input[1..], false)?; let oplog = self.oplog.lock().unwrap(); let updates = app.export_from(oplog.vv()); drop(oplog); diff --git a/crates/loro-internal/src/snapshot_encode.rs b/crates/loro-internal/src/snapshot_encode.rs index 48eab8ef..98f39d2b 100644 --- a/crates/loro-internal/src/snapshot_encode.rs +++ b/crates/loro-internal/src/snapshot_encode.rs @@ -35,18 +35,22 @@ pub fn encode_app_snapshot(app: &LoroDoc) -> Vec { miniz_oxide::deflate::compress_to_vec(&f.encode(), 6) } -pub fn decode_app_snapshot(app: &LoroDoc, bytes: &[u8]) -> Result<(), LoroError> { +pub fn decode_app_snapshot(app: &LoroDoc, bytes: &[u8], with_state: bool) -> Result<(), LoroError> { assert!(app.is_empty()); let bytes = miniz_oxide::inflate::decompress_to_vec(bytes).unwrap(); let data = FinalPhase::decode(&bytes)?; - let mut app_state = app.app_state().lock().unwrap(); - let (state_arena, common) = decode_state(&mut app_state, &data)?; - let arena = app_state.arena.clone(); - decode_oplog( - &mut app.oplog().lock().unwrap(), - &data, - Some((arena, state_arena, common)), - )?; + if with_state { + let mut app_state = app.app_state().lock().unwrap(); + let (state_arena, common) = decode_state(&mut app_state, &data)?; + let arena = app_state.arena.clone(); + decode_oplog( + &mut app.oplog().lock().unwrap(), + &data, + Some((arena, state_arena, common)), + )?; + } else { + decode_oplog(&mut app.oplog().lock().unwrap(), &data, None)?; + } Ok(()) }