Skip to main content

common/
snapshot.rs

1// Generated by Qleany v1.11.0 from snapshot.tera
2
3use crate::types::EntityId;
4use serde::{Deserialize, Serialize};
5use std::any::Any;
6
7/// Snapshot of an entity tree for undo.
8///
9/// Capture is O(1): `store_snapshot` is a whole-store `im::HashMap` clone (structural
10/// sharing). Restore is *scoped*: `root_ids` records the subtree roots passed to
11/// `snapshot(ids)`, and the per-entity `Repository::restore` walks that subtree (in both
12/// the snapshot and the live store) and reconciles only it, leaving other trunks untouched.
13#[derive(Debug, Clone, Default, Serialize, Deserialize)]
14pub struct EntityTreeSnapshot {
15    /// Whole-store snapshot captured at `snapshot(ids)` time (O(1) `im` clone).
16    #[serde(skip)]
17    pub store_snapshot: Option<StoreSnapshot>,
18    /// The subtree roots (the `ids` passed to `snapshot`). Restore is scoped to these.
19    #[serde(default)]
20    pub root_ids: Vec<EntityId>,
21}
22
23// ─────────────────────────────────────────────────────────────────────────────
24// Store-level snapshot (type-erased so snapshot.rs doesn't depend on HashMapStore)
25// ─────────────────────────────────────────────────────────────────────────────
26
27/// Trait for type-erased store snapshots.
28pub trait StoreSnapshotTrait: std::fmt::Debug + Send + Sync {
29    fn clone_box(&self) -> Box<dyn StoreSnapshotTrait>;
30    fn as_any(&self) -> &dyn Any;
31}
32
33impl Clone for Box<dyn StoreSnapshotTrait> {
34    fn clone(&self) -> Self {
35        self.clone_box()
36    }
37}
38
39/// Type-erased store snapshot for undo fast path.
40#[derive(Debug, Clone)]
41pub struct StoreSnapshot {
42    inner: Box<dyn StoreSnapshotTrait>,
43}
44
45impl StoreSnapshot {
46    pub fn new<T: StoreSnapshotTrait + 'static>(inner: T) -> Self {
47        Self {
48            inner: Box::new(inner),
49        }
50    }
51
52    pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
53        self.inner.as_any().downcast_ref()
54    }
55}