Skip to main content

canic_core/
memory_macros.rs

1//! Module: memory_macros
2//!
3//! Responsibility: adapt explicit Canic memory authorities to `ic-memory` registration.
4//! Does not own: authority values, stable keys, memory IDs, or bootstrap ordering.
5//! Boundary: queues declarations for ic-memory sealing and opens only committed slots.
6
7/// Declare a stable-memory slot with an explicit authority and ABI-stable key.
8///
9/// Use this for every Canic-managed memory. The stable key, not crate or Rust
10/// type identity, is the durable allocation identity.
11#[macro_export]
12macro_rules! ic_memory_key {
13    (authority = CANIC_CORE_MEMORY_AUTHORITY, $($rest:tt)*) => {
14        $crate::ic_memory_key!(authority = $crate::memory::CANIC_CORE_MEMORY_AUTHORITY, $($rest)*)
15    };
16    (authority = CANIC_CONTROL_PLANE_MEMORY_AUTHORITY, $($rest:tt)*) => {
17        $crate::ic_memory_key!(authority = $crate::memory::CANIC_CONTROL_PLANE_MEMORY_AUTHORITY, $($rest)*)
18    };
19    (authority = $authority:expr, key = $stable_key:literal $(,)?) => {{
20        $crate::__reexports::ic_memory::ic_memory_declaration!(authority = $authority, key = $stable_key);
21        $crate::memory::runtime::assert_memory_bootstrap_ready($stable_key);
22        $crate::__reexports::ic_memory::open_default_memory_manager_memory($stable_key)
23            .expect("ic-memory committed key binding must exist before opening stable memory")
24    }};
25}
26
27/// Select the final host pool, including framework grants.
28///
29/// Additional grants
30/// must name each linked component's permanent namespace. Exclusions protect
31/// actual unmanaged physical memory, never component partitions.
32#[macro_export]
33macro_rules! memory_allocation_pool {
34    (authorities = [$(($owner:expr, $prefix:expr)),* $(,)?], exclusions = [$(($start:expr, $end:expr)),* $(,)?] $(,)?) => {
35        const _: () = {
36            #[$crate::__reexports::ctor::ctor(unsafe, anonymous, crate_path = $crate::__reexports::ctor)]
37            fn __canic_register_memory_pool() {
38                let pool = $crate::memory::pool::framework_pool(
39                    vec![$($crate::__reexports::ic_memory::MemoryAuthority::new($owner, $prefix).expect("valid host memory grant")),*],
40                    vec![$($crate::__reexports::ic_memory::MemoryManagerIdRange::new($start, $end).expect("valid unmanaged exclusion")),*],
41                ).expect("disjoint host memory grants");
42                $crate::memory::pool::register(pool).expect("one host memory pool before bootstrap");
43            }
44        };
45    };
46}
47
48/// Register the artifact's composed memory admission before Canic bootstrap.
49///
50/// Supply a semantic `ic_memory::PolicyIdentity` and a synchronous callback taking
51/// `&mut ic_memory::BootstrapAdmission` and returning `Result<(), E>` where `E`
52/// implements `Error + Send + Sync + 'static`. Register once per artifact, not per
53/// database. Select host namespace grants separately with `memory_allocation_pool!`.
54#[macro_export]
55macro_rules! memory_bootstrap_admission {
56    (identity = $identity:expr, prepare = $prepare:path $(,)?) => {
57        const _: () = {
58            #[ $crate::__reexports::ctor::ctor(unsafe, anonymous, crate_path = $crate::__reexports::ctor) ]
59            fn __canic_register_memory_admission() {
60                fn __canic_prepare_memory_admission(admission: &mut $crate::__reexports::ic_memory::BootstrapAdmission<'_>)
61                    -> ::core::result::Result<(), $crate::memory::registry::MemoryRegistryError>
62                {
63                    $prepare(admission).map_err(|source| $crate::memory::registry::MemoryRegistryError::Admission { source: ::std::boxed::Box::new(source) })
64                }
65                $crate::memory::admission::register(
66                    $crate::memory::admission::MemoryBootstrapAdmission::new($identity, __canic_prepare_memory_admission),
67                ).expect("Canic memory admission registration failed");
68            }
69        };
70    };
71}