qleany-common 2.0.1

Shared entities, database, events, and undo/redo infrastructure for Qleany
Documentation
// Generated by Qleany v1.11.0 from snapshot.tera

use crate::types::EntityId;
use serde::{Deserialize, Serialize};
use std::any::Any;

/// Snapshot of an entity tree for undo.
///
/// Capture is O(1): `store_snapshot` is a whole-store `im::HashMap` clone (structural
/// sharing). Restore is *scoped*: `root_ids` records the subtree roots passed to
/// `snapshot(ids)`, and the per-entity `Repository::restore` walks that subtree (in both
/// the snapshot and the live store) and reconciles only it, leaving other trunks untouched.
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct EntityTreeSnapshot {
    /// Whole-store snapshot captured at `snapshot(ids)` time (O(1) `im` clone).
    #[serde(skip)]
    pub store_snapshot: Option<StoreSnapshot>,
    /// The subtree roots (the `ids` passed to `snapshot`). Restore is scoped to these.
    #[serde(default)]
    pub root_ids: Vec<EntityId>,
}

// ─────────────────────────────────────────────────────────────────────────────
// Store-level snapshot (type-erased so snapshot.rs doesn't depend on HashMapStore)
// ─────────────────────────────────────────────────────────────────────────────

/// Trait for type-erased store snapshots.
pub trait StoreSnapshotTrait: std::fmt::Debug + Send + Sync {
    fn clone_box(&self) -> Box<dyn StoreSnapshotTrait>;
    fn as_any(&self) -> &dyn Any;
}

impl Clone for Box<dyn StoreSnapshotTrait> {
    fn clone(&self) -> Self {
        self.clone_box()
    }
}

/// Type-erased store snapshot for undo fast path.
#[derive(Debug, Clone)]
pub struct StoreSnapshot {
    inner: Box<dyn StoreSnapshotTrait>,
}

impl StoreSnapshot {
    pub fn new<T: StoreSnapshotTrait + 'static>(inner: T) -> Self {
        Self {
            inner: Box::new(inner),
        }
    }

    pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
        self.inner.as_any().downcast_ref()
    }
}