1use crate::{
2 cdk::structures::{
3 DefaultMemoryImpl,
4 memory::{MemoryId, VirtualMemory},
5 },
6 manager::MEMORY_MANAGER,
7 registry::{MemoryRegistry, MemoryRegistryError},
8 runtime::{MemoryRuntimeApi, registry::MemoryRegistryInitSummary},
9};
10
11pub struct MemoryApi;
16
17impl MemoryApi {
18 pub fn bootstrap_registry(
20 crate_name: &'static str,
21 start: u8,
22 end: u8,
23 ) -> Result<MemoryRegistryInitSummary, MemoryRegistryError> {
24 MemoryRuntimeApi::bootstrap_registry(crate_name, start, end)
25 }
26
27 pub fn register_memory(
31 id: u8,
32 crate_name: &str,
33 label: &str,
34 ) -> Result<VirtualMemory<DefaultMemoryImpl>, MemoryRegistryError> {
35 if let Some(entry) = MemoryRegistry::get(id)
36 && entry.crate_name == crate_name
37 && entry.label == label
38 {
39 return Ok(open_memory(id));
40 }
41
42 MemoryRegistry::register(id, crate_name, label)?;
43 Ok(open_memory(id))
44 }
45}
46
47fn open_memory(id: u8) -> VirtualMemory<DefaultMemoryImpl> {
49 MEMORY_MANAGER.with_borrow_mut(|mgr| mgr.get(MemoryId::new(id)))
50}
51
52#[cfg(test)]
57mod tests {
58 use super::*;
59 use crate::registry::{MemoryRegistryError, reset_for_tests};
60
61 #[test]
62 fn register_memory_returns_opened_memory_for_reserved_slot() {
63 reset_for_tests();
64 let _ = MemoryApi::bootstrap_registry("crate_a", 1, 3).expect("bootstrap registry");
65
66 let _memory = MemoryApi::register_memory(2, "crate_a", "slot").expect("register memory");
67 }
68
69 #[test]
70 fn register_memory_is_idempotent_for_same_entry() {
71 reset_for_tests();
72 let _ = MemoryApi::bootstrap_registry("crate_a", 1, 3).expect("bootstrap registry");
73 let _ = MemoryApi::register_memory(2, "crate_a", "slot").expect("first register succeeds");
74
75 let _ = MemoryApi::register_memory(2, "crate_a", "slot").expect("second register succeeds");
76 }
77
78 #[test]
79 fn register_memory_rejects_unreserved_id() {
80 reset_for_tests();
81
82 let Err(err) = MemoryApi::register_memory(9, "crate_a", "slot") else {
83 panic!("unreserved slot must fail")
84 };
85 assert!(matches!(err, MemoryRegistryError::NoReservedRange { .. }));
86 }
87
88 #[test]
89 fn register_memory_preserves_duplicate_id_error_for_conflicts() {
90 reset_for_tests();
91 let _ = MemoryApi::bootstrap_registry("crate_a", 1, 3).expect("bootstrap registry");
92 MemoryApi::register_memory(2, "crate_a", "slot").expect("first register succeeds");
93
94 let Err(err) = MemoryApi::register_memory(2, "crate_a", "other") else {
95 panic!("conflicting duplicate register must fail")
96 };
97 assert!(matches!(err, MemoryRegistryError::DuplicateId(2)));
98 }
99}