1use crate::{
2 declaration::AllocationDeclaration,
3 slot::{
4 IC_MEMORY_AUTHORITY_OWNER, IC_MEMORY_LEDGER_STABLE_KEY, MEMORY_MANAGER_LEDGER_ID,
5 is_ic_memory_stable_key,
6 },
7 text::validate_diagnostic_text,
8};
9#[cfg(any(test, feature = "test-support"))]
10use serde::Deserialize;
11use serde::Serialize;
12use std::sync::Arc;
13
14#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
25pub struct MemoryRequest {
26 authority: String,
27 stable_key: crate::StableKey,
28}
29
30#[cfg(any(test, feature = "test-support"))]
31impl<'de> Deserialize<'de> for MemoryRequest {
32 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
33 use serde::de::Error as _;
34 #[derive(Deserialize)]
35 #[serde(deny_unknown_fields)]
36 struct Request {
37 authority: String,
38 stable_key: crate::StableKey,
39 }
40 let request = Request::deserialize(deserializer)?;
41 validate_external_authority(&request.authority).map_err(D::Error::custom)?;
42 validate_external_key(&request.stable_key).map_err(D::Error::custom)?;
43 Ok(Self {
44 authority: request.authority,
45 stable_key: request.stable_key,
46 })
47 }
48}
49
50impl MemoryRequest {
51 pub fn new(
53 authority: impl Into<String>,
54 stable_key: &str,
55 ) -> Result<Self, MemoryDeclarationError> {
56 let authority = authority.into();
57 let stable_key = checked_request_key(&authority, stable_key)?;
58 Ok(Self {
59 authority,
60 stable_key,
61 })
62 }
63
64 #[must_use]
66 pub const fn stable_key(&self) -> &crate::StableKey {
67 &self.stable_key
68 }
69
70 #[must_use]
72 pub fn authority(&self) -> &str {
73 &self.authority
74 }
75}
76
77#[non_exhaustive]
84#[derive(Clone, Debug, Eq, thiserror::Error, PartialEq)]
85pub enum MemoryDeclarationError {
86 #[error("at most 254 external requests are supported")]
87 TooManyDeclarations,
88 #[error("duplicate requested stable key {stable_key}")]
89 DuplicateRequest { stable_key: crate::StableKey },
90 #[error(transparent)]
92 Key(#[from] crate::StableKeyError),
93 #[error("authority {reason}")]
95 InvalidAuthority {
96 reason: &'static str,
98 },
99 #[error("authority '{authority}' is reserved for ic-memory runtime internals")]
101 ReservedAuthority {
102 authority: String,
104 },
105 #[error("stable key '{stable_key}' is reserved for ic-memory runtime internals")]
107 ReservedStableKey {
108 stable_key: String,
110 },
111}
112
113#[derive(Clone, Debug, Eq, PartialEq)]
125pub struct SealedDeclarationSnapshot {
126 inner: Arc<Vec<MemoryRequest>>,
127}
128
129#[derive(Debug, Eq, PartialEq)]
138pub struct DeclarationSnapshot {
139 declarations: Vec<AllocationDeclaration>,
140}
141
142impl DeclarationSnapshot {
143 pub(crate) fn declarations(&self) -> &[AllocationDeclaration] {
144 &self.declarations
145 }
146
147 pub(crate) fn into_declarations(self) -> Vec<AllocationDeclaration> {
148 self.declarations
149 }
150
151 #[cfg(test)]
153 pub(crate) fn for_test(mut declarations: Vec<AllocationDeclaration>) -> Self {
154 crate::sort::sort_unstable_by(&mut declarations, |a, b| a.stable_key.cmp(&b.stable_key));
155 Self { declarations }
156 }
157}
158
159impl SealedDeclarationSnapshot {
160 pub fn new(mut requests: Vec<MemoryRequest>) -> Result<Self, MemoryDeclarationError> {
163 if requests.len() > 254 {
164 return Err(MemoryDeclarationError::TooManyDeclarations);
165 }
166 crate::sort::sort_unstable_by(&mut requests, |a, b| a.stable_key.cmp(&b.stable_key));
167 for pair in requests.windows(2) {
168 if pair[0].stable_key == pair[1].stable_key {
169 return Err(MemoryDeclarationError::DuplicateRequest {
170 stable_key: pair[1].stable_key.clone(),
171 });
172 }
173 }
174 Ok(Self {
175 inner: Arc::new(requests),
176 })
177 }
178
179 #[must_use]
181 pub fn requests(&self) -> &[MemoryRequest] {
182 &self.inner
183 }
184
185 pub(crate) fn resolve(
186 &self,
187 recovered: &crate::RecoveredLedger,
188 occupied: &[bool; crate::constants::MAX_ALLOCATIONS],
189 historical: Vec<AllocationDeclaration>,
190 pool: &crate::MemoryAllocationPool,
191 ) -> Result<DeclarationSnapshot, crate::MemoryResolutionError> {
192 let ledger = recovered.ledger();
193 if self.requests().len() + historical.len() > 254 {
194 return Err(MemoryDeclarationError::TooManyDeclarations.into());
195 }
196 let mut declarations = Vec::with_capacity(self.requests().len() + historical.len() + 1);
197 declarations.push(internal_ledger_declaration());
198 let mut available_ids = 0..crate::MEMORY_MANAGER_INVALID_ID;
201 for request in self.requests() {
204 let historical = ledger
205 .records()
206 .iter()
207 .find(|record| record.stable_key() == &request.stable_key);
208 pool.validate_authority(&request.stable_key, &request.authority)?;
209 let id = if let Some(record) = historical {
210 pool.validate_id(record.slot().id())?;
213 record.slot().id()
214 } else {
215 available_ids
216 .find(|id| pool.contains(*id) && !occupied[usize::from(*id)])
217 .ok_or_else(|| crate::MemoryResolutionError::Exhausted {
218 stable_key: request.stable_key.clone(),
219 authority: request.authority.clone(),
220 })?
221 };
222 let slot = crate::MemoryManagerSlot::new(id).expect("usable id");
223 declarations.push(AllocationDeclaration {
225 stable_key: request.stable_key.clone(),
226 slot,
227 });
228 }
229 declarations.extend(historical);
230 crate::sort::sort_unstable_by(&mut declarations, |a, b| a.stable_key.cmp(&b.stable_key));
231 Ok(DeclarationSnapshot { declarations })
232 }
233
234 #[cfg(test)]
235 pub(crate) fn shares_storage_with(&self, other: &Self) -> bool {
236 Arc::ptr_eq(&self.inner, &other.inner)
237 }
238}
239
240pub fn checked_request_key(
242 authority: &str,
243 stable_key: &str,
244) -> Result<crate::StableKey, MemoryDeclarationError> {
245 validate_external_authority(authority)?;
246 let stable_key = crate::StableKey::parse(stable_key)?;
247 validate_external_key(&stable_key)?;
248 Ok(stable_key)
249}
250
251fn validate_external_key(stable_key: &crate::StableKey) -> Result<(), MemoryDeclarationError> {
252 if is_ic_memory_stable_key(stable_key.as_str()) {
253 return Err(MemoryDeclarationError::ReservedStableKey {
254 stable_key: stable_key.as_str().to_string(),
255 });
256 }
257 Ok(())
258}
259
260fn validate_external_authority(value: &str) -> Result<(), MemoryDeclarationError> {
261 reject_internal_authority(value)?;
262 validate_diagnostic_text(value).map_err(|error| MemoryDeclarationError::InvalidAuthority {
263 reason: error.reason(),
264 })
265}
266
267fn reject_internal_authority(value: &str) -> Result<(), MemoryDeclarationError> {
268 if value == IC_MEMORY_AUTHORITY_OWNER {
269 return Err(MemoryDeclarationError::ReservedAuthority {
270 authority: value.to_string(),
271 });
272 }
273 Ok(())
274}
275
276fn internal_ledger_declaration() -> AllocationDeclaration {
277 AllocationDeclaration {
278 stable_key: crate::StableKey::parse(IC_MEMORY_LEDGER_STABLE_KEY)
279 .expect("built-in ledger key is valid"),
280 slot: crate::MemoryManagerSlot::new(MEMORY_MANAGER_LEDGER_ID)
281 .expect("built-in ledger ID is usable"),
282 }
283}
284
285#[cfg(test)]
286mod tests;