loro_internal/
fork.rs

1//! The fork module provides functionality to create a new LoroDoc instance at a specified version
2//! (Frontiers) with minimal overhead.
3//!
4//! # Implementation Overview
5//!
6//! The `fork_at` function in this module allows for the creation of a new document that reflects
7//! the state of the original document at a given version. The function achieves this by:
8//!
9//! ## Exporting Necessary Data:
10//!
11//! - **Change Store Data**: Collects all changes up to the specified version from the change
12//!   store's key-value (kv) data store. It includes the version vector and frontiers for accurate
13//!   identification of the version.
14//!
15//! - **Container Store Data**: Exports the container store's kv data representing the document's
16//!   state at the specified version. This involves checking out to the desired version, exporting
17//!   the state, and efficiently checking back to the latest version.
18//!
19//! - **GC Store Data**: If applicable, exports the gc store's kv data, ensuring that version
20//!   identifiers are included.
21//!
22//! ## Reconstructing the New Document:
23//!
24//! Imports the exported data into a new LoroDoc instance using optimized import mechanisms
25//! similar to those used in fast snapshot imports.
26//!
27//! By focusing on exporting only the necessary data and optimizing state transitions during
28//! version checkout, the `fork_at` function minimizes overhead and efficiently creates new
29//! document instances representing past versions.
30//!
31use std::borrow::Cow;
32
33use crate::{version::Frontiers, LoroDoc};
34
35impl LoroDoc {
36    /// Creates a new LoroDoc at a specified version (Frontiers)
37    pub fn fork_at(&self, frontiers: &Frontiers) -> Self {
38        let bytes = self
39            .export(crate::loro::ExportMode::SnapshotAt {
40                version: Cow::Borrowed(frontiers),
41            })
42            .unwrap();
43        let doc = LoroDoc::new();
44        doc.set_config(&self.config);
45        if self.auto_commit.load(std::sync::atomic::Ordering::Relaxed) {
46            doc.start_auto_commit();
47        }
48        doc.import(&bytes).unwrap();
49        doc
50    }
51}