Skip to main content

canic_core/
memory_macros.rs

1/// Declare a stable-memory slot with an explicit ABI-stable key.
2///
3/// Use this for every Canic-managed memory. The stable key, not crate or Rust
4/// type identity, is the durable allocation identity.
5#[macro_export]
6macro_rules! ic_memory_key {
7    ($stable_key:literal, $label:path, $id:expr) => {{
8        const _: () = {
9            #[ $crate::__reexports::ctor::ctor(unsafe, anonymous, crate_path = $crate::__reexports::ctor) ]
10            fn __canic_declare_memory_slot() {
11                $crate::memory::registry::defer_register_with_key(
12                    $id,
13                    env!("CARGO_PKG_NAME"),
14                    stringify!($label),
15                    $stable_key,
16                )
17                .expect("memory id declaration validation failed");
18            }
19        };
20
21        let _type_check: Option<$label> = None;
22
23        $crate::memory::open_validated_memory(stringify!($label), $id)
24    }};
25}
26
27/// Reserve a contiguous block of stable-memory IDs for the current crate.
28#[macro_export]
29macro_rules! ic_memory_range {
30    ($start:expr, $end:expr) => {{
31        $crate::memory::registry::defer_reserve_range(env!("CARGO_PKG_NAME"), $start, $end)
32            .expect("memory range reservation validation failed");
33        $crate::memory::runtime::registry::MemoryRegistryRuntime::commit_pending_if_initialized()
34            .expect("late memory range registration commit failed");
35    }};
36}
37
38/// Register one eager-init body for execution during lifecycle bootstrap.
39#[macro_export]
40macro_rules! eager_init {
41    ($body:block) => {
42        const _: () = {
43            fn __canic_registered_eager_init_body() {
44                $body
45            }
46
47            #[ $crate::__reexports::ctor::ctor(unsafe, anonymous, crate_path = $crate::__reexports::ctor) ]
48            fn __canic_register_eager_init() {
49                $crate::memory::runtime::defer_eager_init(__canic_registered_eager_init_body);
50            }
51        };
52    };
53}
54
55/// Declare a thread-local static and schedule an eager initialization touch.
56#[macro_export]
57macro_rules! eager_static {
58    ($vis:vis static $name:ident : $ty:ty = $init:expr;) => {
59        thread_local! {
60            $vis static $name: $ty = $init;
61        }
62
63        const _: () = {
64            fn __canic_touch_tls() {
65                $name.with(|_| {});
66            }
67
68            #[ $crate::__reexports::ctor::ctor(unsafe, anonymous, crate_path = $crate::__reexports::ctor) ]
69            fn __canic_register_eager_tls() {
70                $crate::memory::runtime::defer_tls_initializer(__canic_touch_tls);
71            }
72        };
73    };
74}