1use crate::registry::{
2 MemoryRange, MemoryRegistry, MemoryRegistryEntry, MemoryRegistryError, MemoryRegistryView,
3 drain_pending_ranges, drain_pending_registrations,
4};
5
6#[derive(Debug)]
12pub struct MemoryRegistrySummary {
13 pub ranges: Vec<(String, MemoryRange)>,
14 pub entries: MemoryRegistryView,
15}
16
17pub struct MemoryRegistryOps;
23
24impl MemoryRegistryOps {
25 pub fn init_memory(
31 initial_range: Option<(&str, u8, u8)>,
32 ) -> Result<MemoryRegistrySummary, MemoryRegistryError> {
33 if let Some((crate_name, start, end)) = initial_range {
34 MemoryRegistry::reserve_range(crate_name, start, end)?;
35 }
36
37 let mut ranges = drain_pending_ranges();
38 ranges.sort_by_key(|(_, start, _)| *start);
39 for (crate_name, start, end) in ranges {
40 MemoryRegistry::reserve_range(crate_name, start, end)?;
41 }
42
43 let mut regs = drain_pending_registrations();
44 regs.sort_by_key(|(id, _, _)| *id);
45 for (id, crate_name, label) in regs {
46 MemoryRegistry::register(id, crate_name, label)?;
47 }
48
49 Ok(MemoryRegistrySummary {
50 ranges: MemoryRegistry::export_ranges(),
51 entries: MemoryRegistry::export(),
52 })
53 }
54
55 #[must_use]
56 pub fn export() -> MemoryRegistryView {
57 MemoryRegistry::export()
58 }
59
60 #[must_use]
61 pub fn export_ranges() -> Vec<(String, MemoryRange)> {
62 MemoryRegistry::export_ranges()
63 }
64
65 #[must_use]
66 pub fn get(id: u8) -> Option<MemoryRegistryEntry> {
67 MemoryRegistry::get(id)
68 }
69}
70
71#[cfg(test)]
76mod tests {
77 use super::*;
78 use crate::registry::{defer_register, defer_reserve_range, reset_for_tests};
79
80 #[test]
81 fn init_memory_applies_initial_and_pending() {
82 reset_for_tests();
83 defer_reserve_range("crate_b", 5, 6);
84 defer_register(5, "crate_b", "B5");
85
86 let summary =
87 MemoryRegistryOps::init_memory(Some(("crate_a", 1, 3))).expect("init should succeed");
88
89 assert_eq!(summary.ranges.len(), 2);
90 assert_eq!(summary.entries.len(), 1);
91 assert_eq!(summary.entries[0].0, 5);
92 assert_eq!(summary.entries[0].1.label.as_ref(), "B5");
93 }
94
95 #[test]
96 fn init_memory_is_idempotent_for_same_initial_range() {
97 reset_for_tests();
98
99 MemoryRegistryOps::init_memory(Some(("crate_a", 1, 3))).expect("first init should succeed");
100 MemoryRegistryOps::init_memory(Some(("crate_a", 1, 3)))
101 .expect("second init should succeed");
102 }
103
104 #[test]
105 fn init_memory_returns_error_on_conflict() {
106 reset_for_tests();
107 defer_reserve_range("crate_a", 1, 3);
108 defer_reserve_range("crate_b", 3, 4);
109
110 let err = MemoryRegistryOps::init_memory(None).unwrap_err();
111 assert!(matches!(
112 err,
113 MemoryRegistryError::Overlap(_, _, _, _, _, _)
114 ));
115 }
116}