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 crate::text::validate_diagnostic_text;
7use serde::{Deserialize, Deserializer, Serialize, de::Error as _};
8
9#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
14#[serde(deny_unknown_fields)]
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 pub const fn validate(&self) -> Result<(), MemoryManagerRangeError> {
52 match Self::new(self.start, self.end) {
53 Ok(_) => Ok(()),
54 Err(err) => Err(err),
55 }
56 }
57
58 #[must_use]
60 pub const fn start(&self) -> u8 {
61 self.start
62 }
63
64 #[must_use]
66 pub const fn end(&self) -> u8 {
67 self.end
68 }
69}
70
71#[non_exhaustive]
76#[derive(Clone, Copy, Debug, Eq, thiserror::Error, PartialEq)]
77pub enum MemoryManagerRangeError {
78 #[error("MemoryManager ID range is invalid: start={start} end={end}")]
80 InvalidRange {
81 start: u8,
83 end: u8,
85 },
86 #[error("MemoryManager ID {id} is not a usable allocation slot")]
88 InvalidMemoryManagerId {
89 id: u8,
91 },
92}
93
94#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
106pub enum MemoryManagerRangeMode {
107 Reserved,
111 Allowed,
115}
116
117#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
124#[serde(deny_unknown_fields)]
125pub struct MemoryManagerAuthorityRecord {
126 pub(crate) range: MemoryManagerIdRange,
128 pub(crate) authority: String,
130 pub(crate) mode: MemoryManagerRangeMode,
132 #[serde(deserialize_with = "crate::cbor::deserialize_present_option")]
134 pub(crate) purpose: Option<String>,
135}
136
137impl MemoryManagerAuthorityRecord {
138 pub fn new(
140 range: MemoryManagerIdRange,
141 authority: impl Into<String>,
142 mode: MemoryManagerRangeMode,
143 purpose: Option<String>,
144 ) -> Result<Self, MemoryManagerRangeAuthorityError> {
145 let record = Self {
146 range,
147 authority: authority.into(),
148 mode,
149 purpose,
150 };
151 validate_authority_record(&record)?;
152 Ok(record)
153 }
154
155 #[must_use]
157 pub const fn range(&self) -> MemoryManagerIdRange {
158 self.range
159 }
160
161 #[must_use]
163 pub fn authority(&self) -> &str {
164 &self.authority
165 }
166
167 #[must_use]
169 pub const fn mode(&self) -> MemoryManagerRangeMode {
170 self.mode
171 }
172
173 #[must_use]
175 pub fn purpose(&self) -> Option<&str> {
176 self.purpose.as_deref()
177 }
178
179 pub fn validate(&self) -> Result<(), MemoryManagerRangeAuthorityError> {
181 validate_authority_record(self)
182 }
183}
184
185#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize)]
204#[serde(deny_unknown_fields)]
205pub struct MemoryManagerRangeAuthority {
206 authorities: Vec<MemoryManagerAuthorityRecord>,
207}
208
209#[derive(Deserialize)]
210#[serde(deny_unknown_fields)]
211struct MemoryManagerRangeAuthorityDto {
212 authorities: Vec<MemoryManagerAuthorityRecord>,
213}
214
215impl<'de> Deserialize<'de> for MemoryManagerRangeAuthority {
216 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
217 let dto = MemoryManagerRangeAuthorityDto::deserialize(deserializer)?;
218 Self::from_records(dto.authorities).map_err(D::Error::custom)
219 }
220}
221
222impl MemoryManagerRangeAuthority {
223 #[must_use]
225 pub const fn new() -> Self {
226 Self {
227 authorities: Vec::new(),
228 }
229 }
230
231 pub fn from_records(
236 records: Vec<MemoryManagerAuthorityRecord>,
237 ) -> Result<Self, MemoryManagerRangeAuthorityError> {
238 let mut authority = Self::new();
239 for record in records {
240 authority = authority.insert_record(record)?;
241 }
242 Ok(authority)
243 }
244
245 pub fn reserve(
250 self,
251 range: MemoryManagerIdRange,
252 authority: impl Into<String>,
253 ) -> Result<Self, MemoryManagerRangeAuthorityError> {
254 self.reserve_with_purpose(range, authority, None)
255 }
256
257 pub fn reserve_ids(
262 self,
263 start: u8,
264 end: u8,
265 authority: impl Into<String>,
266 ) -> Result<Self, MemoryManagerRangeAuthorityError> {
267 self.reserve(MemoryManagerIdRange::new(start, end)?, authority)
268 }
269
270 pub fn reserve_with_purpose(
275 self,
276 range: MemoryManagerIdRange,
277 authority: impl Into<String>,
278 purpose: Option<String>,
279 ) -> Result<Self, MemoryManagerRangeAuthorityError> {
280 self.insert(range, authority, MemoryManagerRangeMode::Reserved, purpose)
281 }
282
283 pub fn reserve_ids_with_purpose(
288 self,
289 start: u8,
290 end: u8,
291 authority: impl Into<String>,
292 purpose: Option<String>,
293 ) -> Result<Self, MemoryManagerRangeAuthorityError> {
294 self.reserve_with_purpose(MemoryManagerIdRange::new(start, end)?, authority, purpose)
295 }
296
297 pub fn allow(
302 self,
303 range: MemoryManagerIdRange,
304 authority: impl Into<String>,
305 ) -> Result<Self, MemoryManagerRangeAuthorityError> {
306 self.allow_with_purpose(range, authority, None)
307 }
308
309 pub fn allow_ids(
314 self,
315 start: u8,
316 end: u8,
317 authority: impl Into<String>,
318 ) -> Result<Self, MemoryManagerRangeAuthorityError> {
319 self.allow(MemoryManagerIdRange::new(start, end)?, authority)
320 }
321
322 pub fn allow_with_purpose(
327 self,
328 range: MemoryManagerIdRange,
329 authority: impl Into<String>,
330 purpose: Option<String>,
331 ) -> Result<Self, MemoryManagerRangeAuthorityError> {
332 self.insert(range, authority, MemoryManagerRangeMode::Allowed, purpose)
333 }
334
335 pub fn allow_ids_with_purpose(
340 self,
341 start: u8,
342 end: u8,
343 authority: impl Into<String>,
344 purpose: Option<String>,
345 ) -> Result<Self, MemoryManagerRangeAuthorityError> {
346 self.allow_with_purpose(MemoryManagerIdRange::new(start, end)?, authority, purpose)
347 }
348
349 pub fn validate_slot_authority(
351 &self,
352 slot: &AllocationSlotDescriptor,
353 expected_authority: &str,
354 ) -> Result<&MemoryManagerAuthorityRecord, MemoryManagerRangeAuthorityError> {
355 let id = slot
356 .memory_manager_id()
357 .map_err(MemoryManagerRangeAuthorityError::Slot)?;
358 self.validate_id_authority(id, expected_authority)
359 }
360
361 pub fn validate_slot_authority_mode(
363 &self,
364 slot: &AllocationSlotDescriptor,
365 expected_authority: &str,
366 expected_mode: MemoryManagerRangeMode,
367 ) -> Result<&MemoryManagerAuthorityRecord, MemoryManagerRangeAuthorityError> {
368 let id = slot
369 .memory_manager_id()
370 .map_err(MemoryManagerRangeAuthorityError::Slot)?;
371 self.validate_id_authority_mode(id, expected_authority, expected_mode)
372 }
373
374 pub fn validate_id_authority(
376 &self,
377 id: u8,
378 expected_authority: &str,
379 ) -> Result<&MemoryManagerAuthorityRecord, MemoryManagerRangeAuthorityError> {
380 validate_diagnostic_string("expected_authority", expected_authority)?;
381 let record = self.covering_record(id)?;
382
383 if record.authority != expected_authority {
384 return Err(MemoryManagerRangeAuthorityError::AuthorityMismatch {
385 id,
386 expected_authority: expected_authority.to_string(),
387 actual_authority: record.authority.clone(),
388 });
389 }
390
391 Ok(record)
392 }
393
394 pub fn validate_id_authority_mode(
396 &self,
397 id: u8,
398 expected_authority: &str,
399 expected_mode: MemoryManagerRangeMode,
400 ) -> Result<&MemoryManagerAuthorityRecord, MemoryManagerRangeAuthorityError> {
401 let record = self.validate_id_authority(id, expected_authority)?;
402 if record.mode != expected_mode {
403 return Err(MemoryManagerRangeAuthorityError::ModeMismatch {
404 id,
405 authority: record.authority.clone(),
406 expected_mode,
407 actual_mode: record.mode,
408 });
409 }
410 Ok(record)
411 }
412
413 pub fn authority_for_id(
415 &self,
416 id: u8,
417 ) -> Result<Option<&MemoryManagerAuthorityRecord>, MemoryManagerRangeAuthorityError> {
418 validate_memory_manager_id(id).map_err(MemoryManagerRangeAuthorityError::Slot)?;
419 Ok(self
420 .authorities
421 .iter()
422 .find(|record| record.range.contains(id)))
423 }
424
425 #[must_use]
431 pub fn authorities(&self) -> &[MemoryManagerAuthorityRecord] {
432 &self.authorities
433 }
434
435 pub fn validate_complete_coverage(
441 &self,
442 target: MemoryManagerIdRange,
443 ) -> Result<(), MemoryManagerRangeAuthorityError> {
444 if self.authorities.is_empty() {
445 return Err(MemoryManagerRangeAuthorityError::MissingCoverage {
446 start: target.start(),
447 end: target.end(),
448 });
449 }
450
451 for record in &self.authorities {
452 if record.range.start() < target.start() || record.range.end() > target.end() {
453 return Err(
454 MemoryManagerRangeAuthorityError::RangeOutsideCoverageTarget {
455 start: record.range.start(),
456 end: record.range.end(),
457 target_start: target.start(),
458 target_end: target.end(),
459 },
460 );
461 }
462 }
463
464 let mut next_uncovered = u16::from(target.start());
465 let target_end = u16::from(target.end());
466 for record in &self.authorities {
467 let record_start = u16::from(record.range.start());
468 let record_end = u16::from(record.range.end());
469
470 if record_start > next_uncovered {
471 let start = u8::try_from(next_uncovered).map_err(|_| {
472 MemoryManagerRangeAuthorityError::MissingCoverage {
473 start: target.start(),
474 end: target.end(),
475 }
476 })?;
477 return Err(MemoryManagerRangeAuthorityError::MissingCoverage {
478 start,
479 end: record.range.start() - 1,
480 });
481 }
482
483 if record_end >= next_uncovered {
484 next_uncovered = record_end + 1;
485 }
486 }
487
488 if next_uncovered <= target_end {
489 let start = u8::try_from(next_uncovered).map_err(|_| {
490 MemoryManagerRangeAuthorityError::MissingCoverage {
491 start: target.start(),
492 end: target.end(),
493 }
494 })?;
495 return Err(MemoryManagerRangeAuthorityError::MissingCoverage {
496 start,
497 end: target.end(),
498 });
499 }
500
501 Ok(())
502 }
503
504 fn insert(
505 self,
506 range: MemoryManagerIdRange,
507 authority: impl Into<String>,
508 mode: MemoryManagerRangeMode,
509 purpose: Option<String>,
510 ) -> Result<Self, MemoryManagerRangeAuthorityError> {
511 let record = MemoryManagerAuthorityRecord {
512 range,
513 authority: authority.into(),
514 mode,
515 purpose,
516 };
517 self.insert_record(record)
518 }
519
520 fn insert_record(
521 mut self,
522 record: MemoryManagerAuthorityRecord,
523 ) -> Result<Self, MemoryManagerRangeAuthorityError> {
524 validate_authority_record(&record)?;
525
526 for existing in &self.authorities {
527 if ranges_overlap(existing.range, record.range) {
528 return Err(MemoryManagerRangeAuthorityError::OverlappingRanges {
529 existing_start: existing.range.start(),
530 existing_end: existing.range.end(),
531 candidate_start: record.range.start(),
532 candidate_end: record.range.end(),
533 });
534 }
535 }
536
537 self.authorities.push(record);
538 self.authorities.sort_by_key(|record| record.range.start());
539 Ok(self)
540 }
541
542 fn covering_record(
543 &self,
544 id: u8,
545 ) -> Result<&MemoryManagerAuthorityRecord, MemoryManagerRangeAuthorityError> {
546 let Some(record) = self.authority_for_id(id)? else {
547 return Err(MemoryManagerRangeAuthorityError::UnclaimedId { id });
548 };
549 Ok(record)
550 }
551}
552
553fn validate_authority_record(
554 record: &MemoryManagerAuthorityRecord,
555) -> Result<(), MemoryManagerRangeAuthorityError> {
556 record.range.validate()?;
557 validate_diagnostic_string("authority", &record.authority)?;
558 if let Some(purpose) = &record.purpose {
559 validate_diagnostic_string("purpose", purpose)?;
560 }
561 Ok(())
562}
563
564#[non_exhaustive]
569#[derive(Clone, Debug, Eq, thiserror::Error, PartialEq)]
570pub enum MemoryManagerRangeAuthorityError {
571 #[error(transparent)]
573 Range(#[from] MemoryManagerRangeError),
574 #[error("{0}")]
576 Slot(#[from] MemoryManagerSlotError),
577 #[error(
579 "MemoryManager authority range {candidate_start}-{candidate_end} overlaps existing range {existing_start}-{existing_end}"
580 )]
581 OverlappingRanges {
582 existing_start: u8,
584 existing_end: u8,
586 candidate_start: u8,
588 candidate_end: u8,
590 },
591 #[error("{field} {reason}")]
593 InvalidDiagnosticString {
594 field: &'static str,
596 reason: &'static str,
598 },
599 #[error("MemoryManager ID {id} is not covered by an authority range")]
601 UnclaimedId {
602 id: u8,
604 },
605 #[error(
607 "MemoryManager ID {id} belongs to authority '{actual_authority}', not '{expected_authority}'"
608 )]
609 AuthorityMismatch {
610 id: u8,
612 expected_authority: String,
614 actual_authority: String,
616 },
617 #[error(
619 "MemoryManager ID {id} belongs to authority '{authority}' with mode {actual_mode:?}, not {expected_mode:?}"
620 )]
621 ModeMismatch {
622 id: u8,
624 authority: String,
626 expected_mode: MemoryManagerRangeMode,
628 actual_mode: MemoryManagerRangeMode,
630 },
631 #[error("MemoryManager authority coverage is missing range {start}-{end}")]
633 MissingCoverage {
634 start: u8,
636 end: u8,
638 },
639 #[error(
641 "MemoryManager authority range {start}-{end} is outside coverage target {target_start}-{target_end}"
642 )]
643 RangeOutsideCoverageTarget {
644 start: u8,
646 end: u8,
648 target_start: u8,
650 target_end: u8,
652 },
653}
654
655const fn ranges_overlap(left: MemoryManagerIdRange, right: MemoryManagerIdRange) -> bool {
656 left.start() <= right.end() && right.start() <= left.end()
657}
658
659fn validate_diagnostic_string(
660 field: &'static str,
661 value: &str,
662) -> Result<(), MemoryManagerRangeAuthorityError> {
663 validate_diagnostic_text(value).map_err(|error| {
664 MemoryManagerRangeAuthorityError::InvalidDiagnosticString {
665 field,
666 reason: error.reason(),
667 }
668 })
669}