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};
9use serde::{Deserialize, Serialize};
10use std::sync::Arc;
11
12#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
20pub struct MemoryRequest {
21 authority: String,
22 stable_key: crate::StableKey,
23}
24
25impl<'de> Deserialize<'de> for MemoryRequest {
26 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
27 use serde::de::Error as _;
28 #[derive(Deserialize)]
29 #[serde(deny_unknown_fields)]
30 struct Request {
31 authority: String,
32 stable_key: crate::StableKey,
33 }
34 let request = Request::deserialize(deserializer)?;
35 validate_external_authority(&request.authority).map_err(D::Error::custom)?;
36 validate_external_key(&request.stable_key).map_err(D::Error::custom)?;
37 Ok(Self {
38 authority: request.authority,
39 stable_key: request.stable_key,
40 })
41 }
42}
43
44impl MemoryRequest {
45 pub fn new(
47 authority: impl Into<String>,
48 stable_key: &str,
49 ) -> Result<Self, MemoryDeclarationError> {
50 let authority = authority.into();
51 let stable_key = checked_request_key(&authority, stable_key)?;
52 Ok(Self {
53 authority,
54 stable_key,
55 })
56 }
57
58 #[must_use]
60 pub const fn stable_key(&self) -> &crate::StableKey {
61 &self.stable_key
62 }
63
64 #[must_use]
66 pub fn authority(&self) -> &str {
67 &self.authority
68 }
69}
70
71#[non_exhaustive]
78#[derive(Clone, Debug, Eq, thiserror::Error, PartialEq)]
79pub enum MemoryDeclarationError {
80 #[error("at most 254 external requests are supported")]
81 TooManyDeclarations,
82 #[error("duplicate requested stable key {stable_key}")]
83 DuplicateRequest { stable_key: crate::StableKey },
84 #[error(transparent)]
86 Declaration(#[from] crate::DeclarationSnapshotError),
87 #[error("authority {reason}")]
89 InvalidAuthority {
90 reason: &'static str,
92 },
93 #[error("authority '{authority}' is reserved for ic-memory runtime internals")]
95 ReservedAuthority {
96 authority: String,
98 },
99 #[error("stable key '{stable_key}' is reserved for ic-memory runtime internals")]
101 ReservedStableKey {
102 stable_key: String,
104 },
105}
106
107#[derive(Clone, Debug, Eq, PartialEq)]
119pub struct SealedDeclarationSnapshot {
120 inner: Arc<Vec<MemoryRequest>>,
121}
122
123#[derive(Debug, Eq, PartialEq)]
132pub struct DeclarationSnapshot {
133 declarations: Vec<AllocationDeclaration>,
134}
135
136impl DeclarationSnapshot {
137 pub(crate) fn declarations(&self) -> &[AllocationDeclaration] {
138 &self.declarations
139 }
140
141 pub(crate) fn into_declarations(self) -> Vec<AllocationDeclaration> {
142 self.declarations
143 }
144
145 #[cfg(test)]
147 pub(crate) fn for_test(mut declarations: Vec<AllocationDeclaration>) -> Self {
148 crate::sort::sort_unstable_by(&mut declarations, |a, b| a.stable_key.cmp(&b.stable_key));
149 Self { declarations }
150 }
151}
152
153impl SealedDeclarationSnapshot {
154 pub fn new(mut requests: Vec<MemoryRequest>) -> Result<Self, MemoryDeclarationError> {
157 if requests.len() > 254 {
158 return Err(MemoryDeclarationError::TooManyDeclarations);
159 }
160 crate::sort::sort_unstable_by(&mut requests, |a, b| a.stable_key.cmp(&b.stable_key));
161 for pair in requests.windows(2) {
162 if pair[0].stable_key == pair[1].stable_key {
163 return Err(MemoryDeclarationError::DuplicateRequest {
164 stable_key: pair[1].stable_key.clone(),
165 });
166 }
167 }
168 Ok(Self {
169 inner: Arc::new(requests),
170 })
171 }
172
173 #[must_use]
175 pub fn requests(&self) -> &[MemoryRequest] {
176 &self.inner
177 }
178
179 pub(crate) fn resolve(
180 &self,
181 recovered: &crate::RecoveredLedger,
182 occupied: &[bool; crate::constants::MAX_ALLOCATIONS],
183 historical: Vec<AllocationDeclaration>,
184 pool: &crate::MemoryAllocationPool,
185 ) -> Result<DeclarationSnapshot, crate::MemoryResolutionError> {
186 let ledger = recovered.ledger();
187 if self.requests().len() + historical.len() > 254 {
188 return Err(MemoryDeclarationError::TooManyDeclarations.into());
189 }
190 let mut declarations = Vec::with_capacity(self.requests().len() + historical.len() + 1);
191 declarations.push(internal_ledger_declaration());
192 let mut available_ids = 0..crate::MEMORY_MANAGER_INVALID_ID;
195 for request in self.requests() {
198 let historical = ledger
199 .records()
200 .iter()
201 .find(|record| record.stable_key() == &request.stable_key);
202 pool.validate_authority(&request.stable_key, &request.authority)?;
203 let id = if let Some(record) = historical {
204 pool.validate_id(record.slot().id())?;
207 record.slot().id()
208 } else {
209 available_ids
210 .find(|id| pool.contains(*id) && !occupied[usize::from(*id)])
211 .ok_or_else(|| crate::MemoryResolutionError::Exhausted {
212 stable_key: request.stable_key.clone(),
213 authority: request.authority.clone(),
214 })?
215 };
216 let slot = crate::MemoryManagerSlot::new(id).expect("usable id");
217 declarations.push(AllocationDeclaration {
219 stable_key: request.stable_key.clone(),
220 slot,
221 });
222 }
223 declarations.extend(historical);
224 crate::sort::sort_unstable_by(&mut declarations, |a, b| a.stable_key.cmp(&b.stable_key));
225 Ok(DeclarationSnapshot { declarations })
226 }
227
228 #[cfg(test)]
229 pub(crate) fn shares_storage_with(&self, other: &Self) -> bool {
230 Arc::ptr_eq(&self.inner, &other.inner)
231 }
232}
233
234pub fn checked_request_key(
236 authority: &str,
237 stable_key: &str,
238) -> Result<crate::StableKey, MemoryDeclarationError> {
239 validate_external_authority(authority)?;
240 let stable_key =
241 crate::StableKey::parse(stable_key).map_err(crate::DeclarationSnapshotError::Key)?;
242 validate_external_key(&stable_key)?;
243 Ok(stable_key)
244}
245
246fn validate_external_key(stable_key: &crate::StableKey) -> Result<(), MemoryDeclarationError> {
247 if is_ic_memory_stable_key(stable_key.as_str()) {
248 return Err(MemoryDeclarationError::ReservedStableKey {
249 stable_key: stable_key.as_str().to_string(),
250 });
251 }
252 Ok(())
253}
254
255fn validate_external_authority(value: &str) -> Result<(), MemoryDeclarationError> {
256 reject_internal_authority(value)?;
257 validate_diagnostic_text(value).map_err(|error| MemoryDeclarationError::InvalidAuthority {
258 reason: error.reason(),
259 })
260}
261
262fn reject_internal_authority(value: &str) -> Result<(), MemoryDeclarationError> {
263 if value == IC_MEMORY_AUTHORITY_OWNER {
264 return Err(MemoryDeclarationError::ReservedAuthority {
265 authority: value.to_string(),
266 });
267 }
268 Ok(())
269}
270
271fn internal_ledger_declaration() -> AllocationDeclaration {
272 AllocationDeclaration::memory_manager(IC_MEMORY_LEDGER_STABLE_KEY, MEMORY_MANAGER_LEDGER_ID)
273 .unwrap_or_else(|_| unreachable!("built-in ledger declaration constants are valid"))
274}
275
276#[cfg(test)]
277mod tests;