Skip to main content

meta_language/
snapshots.rs

1use std::sync::Arc;
2
3use crate::link_network::LinkNetwork;
4
5/// Immutable versioned view of a links network.
6#[derive(Clone, Debug, PartialEq, Eq)]
7pub struct NetworkSnapshot {
8    version: u64,
9    parent_version: Option<u64>,
10    provenance: String,
11    network: Arc<LinkNetwork>,
12}
13
14impl NetworkSnapshot {
15    /// Creates an immutable snapshot from a network value.
16    #[must_use]
17    pub fn new(version: u64, network: LinkNetwork, provenance: impl Into<String>) -> Self {
18        Self {
19            version,
20            parent_version: None,
21            provenance: provenance.into(),
22            network: Arc::new(network),
23        }
24    }
25
26    /// Snapshot version.
27    #[must_use]
28    pub const fn version(&self) -> u64 {
29        self.version
30    }
31
32    /// Parent version when this snapshot was committed from a mutable snapshot.
33    #[must_use]
34    pub const fn parent_version(&self) -> Option<u64> {
35        self.parent_version
36    }
37
38    /// Human-readable change provenance for this snapshot.
39    #[must_use]
40    pub fn provenance(&self) -> &str {
41        &self.provenance
42    }
43
44    /// Immutable network data held by this snapshot.
45    #[must_use]
46    pub fn network(&self) -> &LinkNetwork {
47        self.network.as_ref()
48    }
49
50    /// Number of immutable snapshot handles sharing the same network value.
51    #[must_use]
52    pub fn shared_snapshot_count(&self) -> usize {
53        Arc::strong_count(&self.network)
54    }
55
56    /// Creates an editable snapshot fork from this immutable snapshot.
57    #[must_use]
58    pub fn to_mutable(&self, provenance: impl Into<String>) -> MutableNetworkSnapshot {
59        MutableNetworkSnapshot {
60            base_version: self.version,
61            network: self.network().clone(),
62            provenance: provenance.into(),
63        }
64    }
65
66    fn committed(
67        version: u64,
68        parent_version: u64,
69        network: LinkNetwork,
70        provenance: String,
71    ) -> Self {
72        Self {
73            version,
74            parent_version: Some(parent_version),
75            provenance,
76            network: Arc::new(network),
77        }
78    }
79}
80
81/// Editable fork of an immutable network snapshot.
82#[derive(Clone, Debug, PartialEq, Eq)]
83pub struct MutableNetworkSnapshot {
84    base_version: u64,
85    network: LinkNetwork,
86    provenance: String,
87}
88
89impl MutableNetworkSnapshot {
90    /// Version this mutable snapshot was forked from.
91    #[must_use]
92    pub const fn base_version(&self) -> u64 {
93        self.base_version
94    }
95
96    /// Human-readable provenance that will be attached when committed.
97    #[must_use]
98    pub fn provenance(&self) -> &str {
99        &self.provenance
100    }
101
102    /// Immutable view of the editable network.
103    #[must_use]
104    pub const fn network(&self) -> &LinkNetwork {
105        &self.network
106    }
107
108    /// Mutable view of the editable network.
109    pub fn network_mut(&mut self) -> &mut LinkNetwork {
110        &mut self.network
111    }
112
113    /// Commits this mutable snapshot as the next sequential version.
114    #[must_use]
115    pub fn commit(self) -> NetworkSnapshot {
116        let next_version = self
117            .base_version
118            .checked_add(1)
119            .expect("snapshot version overflow");
120        self.commit_as(next_version)
121    }
122
123    /// Commits this mutable snapshot with an explicit forward version.
124    #[must_use]
125    pub fn commit_as(self, version: u64) -> NetworkSnapshot {
126        assert!(
127            version > self.base_version,
128            "snapshot version must move forward"
129        );
130        NetworkSnapshot::committed(version, self.base_version, self.network, self.provenance)
131    }
132}
133
134impl LinkNetwork {
135    /// Captures the current network as an immutable versioned snapshot.
136    #[must_use]
137    pub fn snapshot(&self, version: u64, provenance: impl Into<String>) -> NetworkSnapshot {
138        NetworkSnapshot::new(version, self.clone(), provenance)
139    }
140}