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: registers declarations during static initialization and opens only committed slots.
6
7// Register through the public function so Canic authority constants remain the
8// single string definitions; the upstream macro intentionally accepts literals only.
9#[doc(hidden)]
10#[macro_export]
11macro_rules! __canic_ic_memory_key {
12    ($authority:expr, $stable_key:literal, $label:path, $id:expr) => {{
13        const _: () = {
14            #[ $crate::__reexports::ctor::ctor(unsafe, anonymous, crate_path = $crate::__reexports::ctor) ]
15            fn __canic_register_static_memory_declaration() {
16                let _ = core::marker::PhantomData::<$label>;
17                $crate::__reexports::ic_memory::register_static_memory_manager_declaration(
18                    $id,
19                    $authority,
20                    stringify!($label),
21                    $stable_key,
22                )
23                .expect("Canic static memory declaration failed");
24            }
25        };
26
27        $crate::memory::runtime::assert_memory_bootstrap_ready(stringify!($label), $id);
28        $crate::__reexports::ic_memory::open_default_memory_manager_memory($stable_key, $id)
29            .expect("Canic failed to open committed stable memory; bootstrap must run first and the stable key/id must match the committed declaration")
30    }};
31}
32
33/// Declare a stable-memory slot with an explicit authority and ABI-stable key.
34///
35/// Use this for every Canic-managed memory. The stable key, not crate or Rust
36/// type identity, is the durable allocation identity.
37#[macro_export]
38macro_rules! ic_memory_key {
39    (authority = CANIC_CORE_MEMORY_AUTHORITY, key = $stable_key:literal, ty = $label:path, id = $id:expr $(,)?) => {
40        $crate::__canic_ic_memory_key!(
41            $crate::memory::CANIC_CORE_MEMORY_AUTHORITY,
42            $stable_key,
43            $label,
44            $id
45        )
46    };
47    (authority = CANIC_CONTROL_PLANE_MEMORY_AUTHORITY, key = $stable_key:literal, ty = $label:path, id = $id:expr $(,)?) => {{
48        $crate::__canic_ic_memory_key!(
49            $crate::memory::CANIC_CONTROL_PLANE_MEMORY_AUTHORITY,
50            $stable_key,
51            $label,
52            $id
53        )
54    }};
55    (authority = $authority:literal, key = $stable_key:literal, ty = $label:path, id = $id:expr $(,)?) => {{ $crate::__canic_ic_memory_key!($authority, $stable_key, $label, $id) }};
56    (authority = $authority:path, key = $stable_key:literal, ty = $label:path, id = $id:expr $(,)?) => {{ $crate::__canic_ic_memory_key!($authority, $stable_key, $label, $id) }};
57}
58
59// Register an authority range from a centralized authority value.
60#[doc(hidden)]
61#[macro_export]
62macro_rules! __canic_ic_memory_range {
63    ($authority:expr, $start:expr, $end:expr, $mode:ident) => {
64        const _: () = {
65            #[ $crate::__reexports::ctor::ctor(unsafe, anonymous, crate_path = $crate::__reexports::ctor) ]
66            fn __canic_register_static_memory_range() {
67                $crate::__reexports::ic_memory::register_static_memory_manager_range(
68                    $start,
69                    $end,
70                    $authority,
71                    $crate::__reexports::ic_memory::MemoryManagerRangeMode::$mode,
72                    None,
73                )
74                .expect("Canic static memory range declaration failed");
75            }
76        };
77    };
78}
79
80/// Declare a MemoryManager ID range owned by an explicit authority.
81#[macro_export]
82macro_rules! ic_memory_range {
83    (authority = CANIC_CORE_MEMORY_AUTHORITY, start = $start:expr, end = $end:expr $(,)?) => {
84        $crate::__canic_ic_memory_range!(
85            $crate::memory::CANIC_CORE_MEMORY_AUTHORITY,
86            $start,
87            $end,
88            Reserved
89        );
90    };
91    (authority = CANIC_CORE_MEMORY_AUTHORITY, start = $start:expr, end = $end:expr, mode = $mode:ident $(,)?) => {
92        $crate::__canic_ic_memory_range!(
93            $crate::memory::CANIC_CORE_MEMORY_AUTHORITY,
94            $start,
95            $end,
96            $mode
97        );
98    };
99    (authority = CANIC_CONTROL_PLANE_MEMORY_AUTHORITY, start = $start:expr, end = $end:expr $(,)?) => {
100        $crate::__canic_ic_memory_range!(
101            $crate::memory::CANIC_CONTROL_PLANE_MEMORY_AUTHORITY,
102            $start,
103            $end,
104            Reserved
105        );
106    };
107    (authority = CANIC_CONTROL_PLANE_MEMORY_AUTHORITY, start = $start:expr, end = $end:expr, mode = $mode:ident $(,)?) => {
108        $crate::__canic_ic_memory_range!(
109            $crate::memory::CANIC_CONTROL_PLANE_MEMORY_AUTHORITY,
110            $start,
111            $end,
112            $mode
113        );
114    };
115    (authority = $authority:literal, start = $start:expr, end = $end:expr $(,)?) => {
116        $crate::__canic_ic_memory_range!($authority, $start, $end, Reserved);
117    };
118    (authority = $authority:literal, start = $start:expr, end = $end:expr, mode = $mode:ident $(,)?) => {
119        $crate::__canic_ic_memory_range!($authority, $start, $end, $mode);
120    };
121    (authority = $authority:path, start = $start:expr, end = $end:expr $(,)?) => {
122        $crate::__canic_ic_memory_range!($authority, $start, $end, Reserved);
123    };
124    (authority = $authority:path, start = $start:expr, end = $end:expr, mode = $mode:ident $(,)?) => {
125        $crate::__canic_ic_memory_range!($authority, $start, $end, $mode);
126    };
127}
128
129/// Register one eager-init body for execution during lifecycle bootstrap.
130#[macro_export]
131macro_rules! eager_init {
132    ($body:block) => {
133        $crate::__reexports::ic_memory::eager_init!($body);
134    };
135}
136
137/// Declare a thread-local static and schedule an eager initialization touch.
138#[macro_export]
139macro_rules! eager_static {
140    ($vis:vis static $name:ident : $ty:ty = $init:expr;) => {
141        thread_local! {
142            $vis static $name: $ty = $init;
143        }
144
145        const _: () = {
146            fn __canic_touch_tls() {
147                $name.with(|_| {});
148            }
149
150            #[ $crate::__reexports::ctor::ctor(unsafe, anonymous, crate_path = $crate::__reexports::ctor) ]
151            fn __canic_register_eager_tls() {
152                $crate::memory::runtime::defer_tls_initializer(__canic_touch_tls);
153            }
154        };
155    };
156}