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