1use crate::{declaration::AllocationDeclaration, key::StableKey, slot::AllocationSlotDescriptor};
2use std::sync::Arc;
3
4#[derive(Clone, Debug, Eq, PartialEq)]
22pub struct ValidatedAllocations {
23 inner: Arc<ValidatedState>,
24}
25
26#[derive(Clone, Debug, Eq, PartialEq)]
27struct ValidatedState {
28 base_generation: u64,
30 declarations: Vec<AllocationDeclaration>,
32 runtime_fingerprint: Option<String>,
34}
35
36impl ValidatedAllocations {
37 pub(crate) fn new(
38 base_generation: u64,
39 declarations: Vec<AllocationDeclaration>,
40 runtime_fingerprint: Option<String>,
41 ) -> Self {
42 Self {
43 inner: Arc::new(ValidatedState {
44 base_generation,
45 declarations,
46 runtime_fingerprint,
47 }),
48 }
49 }
50
51 #[must_use]
53 pub fn base_generation(&self) -> u64 {
54 self.inner.base_generation
55 }
56
57 #[must_use]
59 pub fn declarations(&self) -> &[AllocationDeclaration] {
60 &self.inner.declarations
61 }
62
63 #[must_use]
65 pub fn runtime_fingerprint(&self) -> Option<&str> {
66 self.inner.runtime_fingerprint.as_deref()
67 }
68
69 #[must_use]
71 pub fn slot_for(&self, key: &StableKey) -> Option<&AllocationSlotDescriptor> {
72 self.declarations()
73 .iter()
74 .find(|declaration| &declaration.stable_key == key)
75 .map(|declaration| &declaration.slot)
76 }
77
78 pub(crate) const fn confirm_persisted(self, generation: u64) -> CommittedAllocations {
79 CommittedAllocations {
80 validated: self,
81 generation,
82 }
83 }
84}
85
86#[derive(Clone, Debug, Eq, PartialEq)]
105pub struct CommittedAllocations {
106 validated: ValidatedAllocations,
107 generation: u64,
108}
109
110impl CommittedAllocations {
111 #[must_use]
113 pub const fn generation(&self) -> u64 {
114 self.generation
115 }
116
117 #[must_use]
119 pub fn declarations(&self) -> &[AllocationDeclaration] {
120 self.validated.declarations()
121 }
122
123 #[must_use]
125 pub fn runtime_fingerprint(&self) -> Option<&str> {
126 self.validated.runtime_fingerprint()
127 }
128
129 #[must_use]
131 pub fn slot_for(&self, key: &StableKey) -> Option<&AllocationSlotDescriptor> {
132 self.validated.slot_for(key)
133 }
134
135 pub(crate) fn without_stable_key_prefix(mut self, prefix: &str) -> Self {
136 let mut state = Arc::unwrap_or_clone(self.validated.inner);
137 state
138 .declarations
139 .retain(|declaration| !declaration.stable_key.as_str().starts_with(prefix));
140 self.validated.inner = Arc::new(state);
141 self
142 }
143}
144
145#[cfg(test)]
146mod tests {
147 use super::*;
148
149 #[test]
150 fn filtering_governance_does_not_change_shared_capabilities() {
151 let validated = ValidatedAllocations::new(
152 1,
153 vec![
154 AllocationDeclaration::memory_manager(
155 crate::IC_MEMORY_LEDGER_STABLE_KEY,
156 0,
157 "ledger",
158 )
159 .unwrap(),
160 AllocationDeclaration::memory_manager("app.rows.v1", 100, "rows").unwrap(),
161 ],
162 Some("host".to_string()),
163 );
164 let committed = validated.clone().confirm_persisted(2);
165 let filtered = committed
166 .clone()
167 .without_stable_key_prefix(crate::IC_MEMORY_STABLE_KEY_PREFIX);
168
169 assert_eq!(validated.declarations().len(), 2);
170 assert_eq!(committed.declarations().len(), 2);
171 assert_eq!(filtered.declarations().len(), 1);
172 assert_eq!(
173 filtered.declarations()[0].stable_key().as_str(),
174 "app.rows.v1"
175 );
176 assert_eq!(filtered.generation(), committed.generation());
177 assert_eq!(
178 filtered.runtime_fingerprint(),
179 committed.runtime_fingerprint()
180 );
181 }
182}