1use crate::{declaration::AllocationDeclaration, key::StableKey, slot::MemoryManagerSlot};
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<&MemoryManagerSlot> {
72 slot_for_key(self.declarations(), key.as_str())
73 }
74
75 pub(crate) const fn confirm_persisted(self, generation: u64) -> CommittedAllocations {
76 CommittedAllocations {
77 validated: self,
78 generation,
79 }
80 }
81}
82
83pub fn slot_for_key<'a>(
86 declarations: &'a [AllocationDeclaration],
87 key: &str,
88) -> Option<&'a MemoryManagerSlot> {
89 declarations
90 .iter()
91 .find(|declaration| declaration.stable_key.as_str() == key)
92 .map(|declaration| &declaration.slot)
93}
94
95#[derive(Clone, Debug, Eq, PartialEq)]
114pub struct CommittedAllocations {
115 validated: ValidatedAllocations,
116 generation: u64,
117}
118
119impl CommittedAllocations {
120 #[must_use]
122 pub const fn generation(&self) -> u64 {
123 self.generation
124 }
125
126 #[must_use]
128 pub fn declarations(&self) -> &[AllocationDeclaration] {
129 self.validated.declarations()
130 }
131
132 #[must_use]
134 pub fn runtime_fingerprint(&self) -> Option<&str> {
135 self.validated.runtime_fingerprint()
136 }
137
138 #[must_use]
140 pub fn slot_for(&self, key: &StableKey) -> Option<&MemoryManagerSlot> {
141 self.validated.slot_for(key)
142 }
143
144 pub(crate) fn into_application_allocations(mut self) -> Self {
147 Arc::make_mut(&mut self.validated.inner)
148 .declarations
149 .retain(|declaration| !crate::is_ic_memory_stable_key(declaration.stable_key.as_str()));
150 self
151 }
152}
153
154#[cfg(test)]
155mod tests {
156 use super::*;
157
158 #[test]
159 fn filtering_governance_does_not_change_shared_capabilities() {
160 let validated = ValidatedAllocations::new(
161 1,
162 vec![
163 AllocationDeclaration::memory_manager(
164 crate::IC_MEMORY_LEDGER_STABLE_KEY,
165 0,
166 "ledger",
167 )
168 .unwrap(),
169 AllocationDeclaration::memory_manager("app.rows.v1", 100, "rows").unwrap(),
170 ],
171 Some("host".to_string()),
172 );
173 let committed = validated.clone().confirm_persisted(2);
174 let filtered = committed.clone().into_application_allocations();
175
176 assert_eq!(validated.declarations().len(), 2);
177 assert_eq!(committed.declarations().len(), 2);
178 assert_eq!(filtered.declarations().len(), 1);
179 assert_eq!(
180 filtered.declarations()[0].stable_key().as_str(),
181 "app.rows.v1"
182 );
183 assert_eq!(filtered.generation(), committed.generation());
184 assert_eq!(
185 filtered.runtime_fingerprint(),
186 committed.runtime_fingerprint()
187 );
188 }
189}