diff --git a/Cargo.lock b/Cargo.lock index bb2e9cc..01ee217 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -262,6 +262,12 @@ dependencies = [ "x11rb", ] +[[package]] +name = "archery" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ca55ee147b1926dbea904f50fe4902494e97bc742205abbbf10c709e43815f" + [[package]] name = "arrayref" version = "0.3.9" @@ -1319,6 +1325,7 @@ version = "0.1.0" dependencies = [ "figcraft-color", "figcraft-geom", + "imbl", "serde", "serde_json", "thiserror 2.0.21", @@ -2050,6 +2057,28 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65b27460c2c92b037f3f94c538ed9a3342f3fdf923606781629ccb35f82d042a" +[[package]] +name = "imbl" +version = "7.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46bad832b9b463ed9398b8506488cc2e3b897a9d44f13af115f382aac71f4fec" +dependencies = [ + "archery", + "equivalent", + "imbl-sized-chunks", + "rand_core", + "rand_xoshiro", + "serde_core", + "version_check", + "wide", +] + +[[package]] +name = "imbl-sized-chunks" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0813be332553f857953298749fa19549e8b61b80589757c29b4e2a804fa9c6" + [[package]] name = "indexmap" version = "2.14.2" @@ -3233,6 +3262,15 @@ dependencies = [ "rand_core", ] +[[package]] +name = "rand_xoshiro" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41" +dependencies = [ + "rand_core", +] + [[package]] name = "range-alloc" version = "0.1.5" @@ -3513,6 +3551,15 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" +[[package]] +name = "safe_arch" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323" +dependencies = [ + "bytemuck", +] + [[package]] name = "same-file" version = "1.0.6" @@ -4735,6 +4782,16 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wide" +version = "0.7.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03" +dependencies = [ + "bytemuck", + "safe_arch", +] + [[package]] name = "winapi-util" version = "0.1.11" diff --git a/Cargo.toml b/Cargo.toml index afcdfb4..f1b0c48 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ serde = { version = "1", features = ["derive", "rc"] } serde_json = { version = "1", features = ["float_roundtrip"] } log = "0.4" proptest = "1" +imbl = { version = "7", features = ["serde"] } # rendering / formats tiny-skia = "0.12" diff --git a/crates/doc/Cargo.toml b/crates/doc/Cargo.toml index af5409d..5609ed8 100644 --- a/crates/doc/Cargo.toml +++ b/crates/doc/Cargo.toml @@ -14,3 +14,4 @@ figcraft-color = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } thiserror = { workspace = true } +imbl = { workspace = true } diff --git a/crates/doc/src/lib.rs b/crates/doc/src/lib.rs index 8776d78..8588ba2 100644 --- a/crates/doc/src/lib.rs +++ b/crates/doc/src/lib.rs @@ -65,6 +65,16 @@ pub enum DocError { pub type DocResult = Result; +/// The set of touched node ids. Never part of equality or serialisation. +#[derive(Clone, Debug, Default)] +pub struct Dirty(pub std::collections::BTreeSet); + +impl PartialEq for Dirty { + fn eq(&self, _: &Self) -> bool { + true + } +} + /// Raw image bytes (encoded PNG/JPEG/…) kept by content hash. #[derive(Clone, Debug, PartialEq)] pub struct ImageData { @@ -79,7 +89,10 @@ pub struct Document { pub name: String, /// Page ids in order. pub pages: Vec, - nodes: BTreeMap>, + nodes: imbl::OrdMap>, + /// Nodes touched since the last [`take_dirty`](Self::take_dirty) (edited, added or removed). + #[serde(skip)] + dirty: Dirty, next_id: u64, #[serde(default)] pub styles: Vec