2026-07-12 11:28:39 +07:00
|
|
|
//! Shallow state diffing — records opaque "modified" markers so the TUI
|
|
|
|
|
//! knows to re-render without computing fine-grained deltas.
|
2026-07-11 13:16:10 +07:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
|
2026-07-12 11:28:39 +07:00
|
|
|
/// A collection of changes tracking which parts of app state have been
|
|
|
|
|
/// modified since the last render sweep.
|
2026-07-11 13:16:10 +07:00
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
|
|
|
pub struct StateDiff {
|
|
|
|
|
changes: Vec<Change>,
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-12 11:28:39 +07:00
|
|
|
/// A single named change — currently always carries a flat `"."` path
|
|
|
|
|
/// and `"modified"` kind because the system does not track granular diffs.
|
2026-07-11 13:16:10 +07:00
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
|
|
|
pub struct Change {
|
|
|
|
|
pub path: String,
|
|
|
|
|
pub kind: String,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl StateDiff {
|
2026-07-12 11:28:39 +07:00
|
|
|
/// Create an empty diff.
|
2026-07-11 13:16:10 +07:00
|
|
|
pub fn new() -> Self {
|
|
|
|
|
StateDiff { changes: Vec::new() }
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-12 11:28:39 +07:00
|
|
|
/// Record a change at `path` of the given `kind`.
|
2026-07-11 13:16:10 +07:00
|
|
|
pub fn add_change(&mut self, path: String, kind: String) {
|
|
|
|
|
self.changes.push(Change { path, kind });
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-12 11:28:39 +07:00
|
|
|
/// Return true if no changes have been recorded.
|
2026-07-11 13:16:10 +07:00
|
|
|
pub fn is_empty(&self) -> bool {
|
|
|
|
|
self.changes.is_empty()
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-12 11:28:39 +07:00
|
|
|
/// Remove all recorded changes.
|
2026-07-11 13:16:10 +07:00
|
|
|
pub fn clear(&mut self) {
|
|
|
|
|
self.changes.clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-12 11:28:39 +07:00
|
|
|
/// Compute a shallow diff between two serialised state values.
|
|
|
|
|
///
|
|
|
|
|
/// Flow: compare with `==`, return an empty vec if equal, otherwise
|
|
|
|
|
/// return a single `Change { ".", "modified" }`.
|
|
|
|
|
///
|
|
|
|
|
/// Why: a placeholder — the current rendering model re-validates the
|
|
|
|
|
/// whole viewport every frame, so fine-grained diffs are unnecessary.
|
|
|
|
|
///
|
|
|
|
|
/// Return: the list of changes (always 0 or 1 entry).
|
2026-07-11 13:16:10 +07:00
|
|
|
pub fn compute_diff(before: &serde_json::Value, after: &serde_json::Value) -> Vec<Change> {
|
|
|
|
|
if before == after {
|
|
|
|
|
return Vec::new();
|
|
|
|
|
}
|
|
|
|
|
vec![Change {
|
|
|
|
|
path: ".".to_string(),
|
|
|
|
|
kind: "modified".to_string(),
|
|
|
|
|
}]
|
|
|
|
|
}
|