canic_memory/runtime/
registry.rs1use crate::registry::{
2 MemoryRange, MemoryRangeEntry, MemoryRangeSnapshot, MemoryRegistry, MemoryRegistryEntry,
3 MemoryRegistryError, drain_pending_ranges, drain_pending_registrations,
4};
5
6#[derive(Debug)]
15pub struct MemoryRegistryInitSummary {
16 pub ranges: Vec<(String, MemoryRange)>,
17 pub entries: Vec<(u8, MemoryRegistryEntry)>,
18}
19
20pub struct MemoryRegistryRuntime;
34
35impl MemoryRegistryRuntime {
36 pub fn init(
44 initial_range: Option<(&str, u8, u8)>,
45 ) -> Result<MemoryRegistryInitSummary, MemoryRegistryError> {
46 if let Some((crate_name, start, end)) = initial_range {
48 MemoryRegistry::reserve_range(crate_name, start, end)?;
49 }
50
51 let mut ranges = drain_pending_ranges();
53 ranges.sort_by_key(|(_, start, _)| *start);
54 for (crate_name, start, end) in ranges {
55 MemoryRegistry::reserve_range(&crate_name, start, end)?;
56 }
57
58 let mut regs = drain_pending_registrations();
60 regs.sort_by_key(|(id, _, _)| *id);
61 for (id, crate_name, label) in regs {
62 MemoryRegistry::register(id, &crate_name, &label)?;
63 }
64
65 Ok(MemoryRegistryInitSummary {
66 ranges: MemoryRegistry::export_ranges(),
67 entries: MemoryRegistry::export(),
68 })
69 }
70
71 #[must_use]
73 pub fn snapshot_entries() -> Vec<(u8, MemoryRegistryEntry)> {
74 MemoryRegistry::export()
75 }
76
77 #[must_use]
79 pub fn snapshot_ranges() -> Vec<(String, MemoryRange)> {
80 MemoryRegistry::export_ranges()
81 }
82
83 #[must_use]
85 pub fn snapshot_range_entries() -> Vec<MemoryRangeEntry> {
86 MemoryRegistry::export_range_entries()
87 }
88
89 #[must_use]
91 pub fn snapshot_ids_by_range() -> Vec<MemoryRangeSnapshot> {
92 MemoryRegistry::export_ids_by_range()
93 }
94
95 #[must_use]
97 pub fn get(id: u8) -> Option<MemoryRegistryEntry> {
98 MemoryRegistry::get(id)
99 }
100}
101
102#[cfg(test)]
107mod tests {
108 use super::*;
109 use crate::registry::{defer_register, defer_reserve_range, reset_for_tests};
110
111 #[test]
112 fn init_applies_initial_and_pending() {
113 reset_for_tests();
114 defer_reserve_range("crate_b", 5, 6);
115 defer_register(5, "crate_b", "B5");
116
117 let summary =
118 MemoryRegistryRuntime::init(Some(("crate_a", 1, 3))).expect("init should succeed");
119
120 assert_eq!(summary.ranges.len(), 2);
121 assert_eq!(summary.entries.len(), 1);
122 assert_eq!(summary.entries[0].0, 5);
123 assert_eq!(summary.entries[0].1.label, "B5");
124 }
125
126 #[test]
127 fn init_is_idempotent_for_same_initial_range() {
128 reset_for_tests();
129
130 MemoryRegistryRuntime::init(Some(("crate_a", 1, 3))).expect("first init should succeed");
131 MemoryRegistryRuntime::init(Some(("crate_a", 1, 3))).expect("second init should succeed");
132 }
133
134 #[test]
135 fn init_returns_error_on_conflict() {
136 reset_for_tests();
137 defer_reserve_range("crate_a", 1, 3);
138 defer_reserve_range("crate_b", 3, 4);
139
140 let err = MemoryRegistryRuntime::init(None).unwrap_err();
141 assert!(matches!(err, MemoryRegistryError::Overlap { .. }));
142 }
143}