1use super::descriptor::AllocationSlotDescriptor;
2use super::memory_manager::{
3 MEMORY_MANAGER_INVALID_ID, MEMORY_MANAGER_MAX_ID, MEMORY_MANAGER_MIN_ID,
4 MemoryManagerSlotError, validate_memory_manager_id,
5};
6use serde::{Deserialize, Serialize};
7
8const DIAGNOSTIC_STRING_MAX_BYTES: usize = 256;
9
10#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
15pub struct MemoryManagerIdRange {
16 pub(crate) start: u8,
17 pub(crate) end: u8,
18}
19
20impl MemoryManagerIdRange {
21 pub const fn new(start: u8, end: u8) -> Result<Self, MemoryManagerRangeError> {
23 if start > end {
24 return Err(MemoryManagerRangeError::InvalidRange { start, end });
25 }
26 if start == MEMORY_MANAGER_INVALID_ID {
27 return Err(MemoryManagerRangeError::InvalidMemoryManagerId { id: start });
28 }
29 if end == MEMORY_MANAGER_INVALID_ID {
30 return Err(MemoryManagerRangeError::InvalidMemoryManagerId { id: end });
31 }
32 Ok(Self { start, end })
33 }
34
35 #[must_use]
37 pub const fn all_usable() -> Self {
38 Self {
39 start: MEMORY_MANAGER_MIN_ID,
40 end: MEMORY_MANAGER_MAX_ID,
41 }
42 }
43
44 #[must_use]
46 pub const fn contains(&self, id: u8) -> bool {
47 id >= self.start && id <= self.end
48 }
49
50 #[must_use]
52 pub const fn start(&self) -> u8 {
53 self.start
54 }
55
56 #[must_use]
58 pub const fn end(&self) -> u8 {
59 self.end
60 }
61}
62
63#[derive(Clone, Copy, Debug, Eq, thiserror::Error, PartialEq)]
68pub enum MemoryManagerRangeError {
69 #[error("MemoryManager ID range is invalid: start={start} end={end}")]
71 InvalidRange {
72 start: u8,
74 end: u8,
76 },
77 #[error("MemoryManager ID {id} is not a usable allocation slot")]
79 InvalidMemoryManagerId {
80 id: u8,
82 },
83}
84
85#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
92pub enum MemoryManagerRangeMode {
93 Reserved,
97 Allowed,
101}
102
103#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
108pub struct MemoryManagerAuthorityRecord {
109 pub range: MemoryManagerIdRange,
111 pub authority: String,
113 pub mode: MemoryManagerRangeMode,
115 pub purpose: Option<String>,
117}
118
119#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
129pub struct MemoryManagerRangeAuthority {
130 authorities: Vec<MemoryManagerAuthorityRecord>,
131}
132
133impl MemoryManagerRangeAuthority {
134 #[must_use]
136 pub const fn new() -> Self {
137 Self {
138 authorities: Vec::new(),
139 }
140 }
141
142 pub fn from_records(
147 records: Vec<MemoryManagerAuthorityRecord>,
148 ) -> Result<Self, MemoryManagerRangeAuthorityError> {
149 let mut authority = Self::new();
150 for record in records {
151 authority = authority.insert_record(record)?;
152 }
153 Ok(authority)
154 }
155
156 pub fn reserve(
161 self,
162 range: MemoryManagerIdRange,
163 authority: impl Into<String>,
164 ) -> Result<Self, MemoryManagerRangeAuthorityError> {
165 self.reserve_with_purpose(range, authority, None)
166 }
167
168 pub fn reserve_ids(
173 self,
174 start: u8,
175 end: u8,
176 authority: impl Into<String>,
177 ) -> Result<Self, MemoryManagerRangeAuthorityError> {
178 self.reserve(MemoryManagerIdRange::new(start, end)?, authority)
179 }
180
181 pub fn reserve_with_purpose(
186 self,
187 range: MemoryManagerIdRange,
188 authority: impl Into<String>,
189 purpose: Option<String>,
190 ) -> Result<Self, MemoryManagerRangeAuthorityError> {
191 self.insert(range, authority, MemoryManagerRangeMode::Reserved, purpose)
192 }
193
194 pub fn reserve_ids_with_purpose(
199 self,
200 start: u8,
201 end: u8,
202 authority: impl Into<String>,
203 purpose: Option<String>,
204 ) -> Result<Self, MemoryManagerRangeAuthorityError> {
205 self.reserve_with_purpose(MemoryManagerIdRange::new(start, end)?, authority, purpose)
206 }
207
208 pub fn allow(
213 self,
214 range: MemoryManagerIdRange,
215 authority: impl Into<String>,
216 ) -> Result<Self, MemoryManagerRangeAuthorityError> {
217 self.allow_with_purpose(range, authority, None)
218 }
219
220 pub fn allow_ids(
225 self,
226 start: u8,
227 end: u8,
228 authority: impl Into<String>,
229 ) -> Result<Self, MemoryManagerRangeAuthorityError> {
230 self.allow(MemoryManagerIdRange::new(start, end)?, authority)
231 }
232
233 pub fn allow_with_purpose(
238 self,
239 range: MemoryManagerIdRange,
240 authority: impl Into<String>,
241 purpose: Option<String>,
242 ) -> Result<Self, MemoryManagerRangeAuthorityError> {
243 self.insert(range, authority, MemoryManagerRangeMode::Allowed, purpose)
244 }
245
246 pub fn allow_ids_with_purpose(
251 self,
252 start: u8,
253 end: u8,
254 authority: impl Into<String>,
255 purpose: Option<String>,
256 ) -> Result<Self, MemoryManagerRangeAuthorityError> {
257 self.allow_with_purpose(MemoryManagerIdRange::new(start, end)?, authority, purpose)
258 }
259
260 pub fn validate_slot_authority(
262 &self,
263 slot: &AllocationSlotDescriptor,
264 expected_authority: &str,
265 ) -> Result<&MemoryManagerAuthorityRecord, MemoryManagerRangeAuthorityError> {
266 let id = slot
267 .memory_manager_id()
268 .map_err(MemoryManagerRangeAuthorityError::Slot)?;
269 self.validate_id_authority(id, expected_authority)
270 }
271
272 pub fn validate_slot_authority_mode(
274 &self,
275 slot: &AllocationSlotDescriptor,
276 expected_authority: &str,
277 expected_mode: MemoryManagerRangeMode,
278 ) -> Result<&MemoryManagerAuthorityRecord, MemoryManagerRangeAuthorityError> {
279 let id = slot
280 .memory_manager_id()
281 .map_err(MemoryManagerRangeAuthorityError::Slot)?;
282 self.validate_id_authority_mode(id, expected_authority, expected_mode)
283 }
284
285 pub fn validate_id_authority(
287 &self,
288 id: u8,
289 expected_authority: &str,
290 ) -> Result<&MemoryManagerAuthorityRecord, MemoryManagerRangeAuthorityError> {
291 validate_diagnostic_string("expected_authority", expected_authority)?;
292 let record = self.covering_record(id)?;
293
294 if record.authority != expected_authority {
295 return Err(MemoryManagerRangeAuthorityError::AuthorityMismatch {
296 id,
297 expected_authority: expected_authority.to_string(),
298 actual_authority: record.authority.clone(),
299 });
300 }
301
302 Ok(record)
303 }
304
305 pub fn validate_id_authority_mode(
307 &self,
308 id: u8,
309 expected_authority: &str,
310 expected_mode: MemoryManagerRangeMode,
311 ) -> Result<&MemoryManagerAuthorityRecord, MemoryManagerRangeAuthorityError> {
312 let record = self.validate_id_authority(id, expected_authority)?;
313 if record.mode != expected_mode {
314 return Err(MemoryManagerRangeAuthorityError::ModeMismatch {
315 id,
316 authority: record.authority.clone(),
317 expected_mode,
318 actual_mode: record.mode,
319 });
320 }
321 Ok(record)
322 }
323
324 pub fn authority_for_id(
326 &self,
327 id: u8,
328 ) -> Result<Option<&MemoryManagerAuthorityRecord>, MemoryManagerRangeAuthorityError> {
329 validate_memory_manager_id(id).map_err(MemoryManagerRangeAuthorityError::Slot)?;
330 Ok(self
331 .authorities
332 .iter()
333 .find(|record| record.range.contains(id)))
334 }
335
336 #[must_use]
342 pub fn authorities(&self) -> &[MemoryManagerAuthorityRecord] {
343 &self.authorities
344 }
345
346 #[must_use]
348 pub fn to_records(&self) -> Vec<MemoryManagerAuthorityRecord> {
349 self.authorities.clone()
350 }
351
352 pub fn validate_complete_coverage(
358 &self,
359 target: MemoryManagerIdRange,
360 ) -> Result<(), MemoryManagerRangeAuthorityError> {
361 if self.authorities.is_empty() {
362 return Err(MemoryManagerRangeAuthorityError::MissingCoverage {
363 start: target.start(),
364 end: target.end(),
365 });
366 }
367
368 for record in &self.authorities {
369 if record.range.start() < target.start() || record.range.end() > target.end() {
370 return Err(
371 MemoryManagerRangeAuthorityError::RangeOutsideCoverageTarget {
372 start: record.range.start(),
373 end: record.range.end(),
374 target_start: target.start(),
375 target_end: target.end(),
376 },
377 );
378 }
379 }
380
381 let mut next_uncovered = u16::from(target.start());
382 let target_end = u16::from(target.end());
383 for record in &self.authorities {
384 let record_start = u16::from(record.range.start());
385 let record_end = u16::from(record.range.end());
386
387 if record_start > next_uncovered {
388 return Err(MemoryManagerRangeAuthorityError::MissingCoverage {
389 start: u8::try_from(next_uncovered).expect("valid MemoryManager ID"),
390 end: record.range.start() - 1,
391 });
392 }
393
394 if record_end >= next_uncovered {
395 next_uncovered = record_end + 1;
396 }
397 }
398
399 if next_uncovered <= target_end {
400 return Err(MemoryManagerRangeAuthorityError::MissingCoverage {
401 start: u8::try_from(next_uncovered).expect("valid MemoryManager ID"),
402 end: target.end(),
403 });
404 }
405
406 Ok(())
407 }
408
409 fn insert(
410 self,
411 range: MemoryManagerIdRange,
412 authority: impl Into<String>,
413 mode: MemoryManagerRangeMode,
414 purpose: Option<String>,
415 ) -> Result<Self, MemoryManagerRangeAuthorityError> {
416 let record = MemoryManagerAuthorityRecord {
417 range,
418 authority: authority.into(),
419 mode,
420 purpose,
421 };
422 self.insert_record(record)
423 }
424
425 fn insert_record(
426 mut self,
427 record: MemoryManagerAuthorityRecord,
428 ) -> Result<Self, MemoryManagerRangeAuthorityError> {
429 validate_diagnostic_string("authority", &record.authority)?;
430 if let Some(purpose) = &record.purpose {
431 validate_diagnostic_string("purpose", purpose)?;
432 }
433
434 for existing in &self.authorities {
435 if ranges_overlap(existing.range, record.range) {
436 return Err(MemoryManagerRangeAuthorityError::OverlappingRanges {
437 existing_start: existing.range.start(),
438 existing_end: existing.range.end(),
439 candidate_start: record.range.start(),
440 candidate_end: record.range.end(),
441 });
442 }
443 }
444
445 self.authorities.push(record);
446 self.authorities.sort_by_key(|record| record.range.start());
447 Ok(self)
448 }
449
450 fn covering_record(
451 &self,
452 id: u8,
453 ) -> Result<&MemoryManagerAuthorityRecord, MemoryManagerRangeAuthorityError> {
454 let Some(record) = self.authority_for_id(id)? else {
455 return Err(MemoryManagerRangeAuthorityError::UnclaimedId { id });
456 };
457 Ok(record)
458 }
459}
460
461#[derive(Clone, Debug, Eq, thiserror::Error, PartialEq)]
466pub enum MemoryManagerRangeAuthorityError {
467 #[error(transparent)]
469 Range(#[from] MemoryManagerRangeError),
470 #[error("{0}")]
472 Slot(#[from] MemoryManagerSlotError),
473 #[error(
475 "MemoryManager authority range {candidate_start}-{candidate_end} overlaps existing range {existing_start}-{existing_end}"
476 )]
477 OverlappingRanges {
478 existing_start: u8,
480 existing_end: u8,
482 candidate_start: u8,
484 candidate_end: u8,
486 },
487 #[error("{field} {reason}")]
489 InvalidDiagnosticString {
490 field: &'static str,
492 reason: &'static str,
494 },
495 #[error("MemoryManager ID {id} is not covered by an authority range")]
497 UnclaimedId {
498 id: u8,
500 },
501 #[error(
503 "MemoryManager ID {id} belongs to authority '{actual_authority}', not '{expected_authority}'"
504 )]
505 AuthorityMismatch {
506 id: u8,
508 expected_authority: String,
510 actual_authority: String,
512 },
513 #[error(
515 "MemoryManager ID {id} belongs to authority '{authority}' with mode {actual_mode:?}, not {expected_mode:?}"
516 )]
517 ModeMismatch {
518 id: u8,
520 authority: String,
522 expected_mode: MemoryManagerRangeMode,
524 actual_mode: MemoryManagerRangeMode,
526 },
527 #[error("MemoryManager authority coverage is missing range {start}-{end}")]
529 MissingCoverage {
530 start: u8,
532 end: u8,
534 },
535 #[error(
537 "MemoryManager authority range {start}-{end} is outside coverage target {target_start}-{target_end}"
538 )]
539 RangeOutsideCoverageTarget {
540 start: u8,
542 end: u8,
544 target_start: u8,
546 target_end: u8,
548 },
549}
550
551const fn ranges_overlap(left: MemoryManagerIdRange, right: MemoryManagerIdRange) -> bool {
552 left.start() <= right.end() && right.start() <= left.end()
553}
554
555fn validate_diagnostic_string(
556 field: &'static str,
557 value: &str,
558) -> Result<(), MemoryManagerRangeAuthorityError> {
559 if value.is_empty() {
560 return Err(MemoryManagerRangeAuthorityError::InvalidDiagnosticString {
561 field,
562 reason: "must not be empty",
563 });
564 }
565 if value.len() > DIAGNOSTIC_STRING_MAX_BYTES {
566 return Err(MemoryManagerRangeAuthorityError::InvalidDiagnosticString {
567 field,
568 reason: "must be at most 256 bytes",
569 });
570 }
571 if !value.is_ascii() {
572 return Err(MemoryManagerRangeAuthorityError::InvalidDiagnosticString {
573 field,
574 reason: "must be ASCII",
575 });
576 }
577 if value.bytes().any(|byte| byte.is_ascii_control()) {
578 return Err(MemoryManagerRangeAuthorityError::InvalidDiagnosticString {
579 field,
580 reason: "must not contain ASCII control characters",
581 });
582 }
583 Ok(())
584}
585
586impl crate::policy::RangeAuthority for MemoryManagerRangeAuthority {
587 type Error = MemoryManagerRangeAuthorityError;
588
589 fn validate_slot(&self, slot: &AllocationSlotDescriptor) -> Result<(), Self::Error> {
590 let id = slot.memory_manager_id()?;
591 if self.authority_for_id(id)?.is_none() {
592 return Err(MemoryManagerRangeAuthorityError::UnclaimedId { id });
593 }
594 Ok(())
595 }
596}