Skip to main content

canic_core/
lib.rs

1//! Core Canic library used inside canisters.
2//!
3//! Most users should depend on the `canic` facade crate, which re-exports this crate
4//! under `canic::core` and exposes the common entrypoint macros:
5//! - `canic::build!` (in `build.rs`) to validate/embed `canic.toml`
6//! - `canic::start!` (in `lib.rs`) to wire lifecycle hooks and export endpoints
7//!
8//! ## Layering
9//!
10//! Canic is organized to keep endpoint code thin and coordination centralized:
11//! - `access/` contains access expressions, predicates, and metrics for boundary enforcement.
12//! - `workflow/` implements orchestration and lifecycle workflows.
13//! - `domain/` contains pure value and decision helpers.
14//! - `model/` contains pure runtime state models shared by ops and storage.
15//! - `ops/` provides mechanical, reusable side-effecting operations.
16//! - `storage/` owns stable-memory-backed schemas and helpers.
17//! - `view/` exposes internal read-only projections over stored/runtime state.
18//! - macro entrypoints live in the `canic` facade crate.
19//!
20//! The default flow is: endpoints → workflow → domain/decision helpers → ops → storage/model.
21
22#[doc(hidden)]
23pub mod access;
24pub mod api;
25#[doc(hidden)]
26pub mod bootstrap;
27pub mod cdk;
28#[doc(hidden)]
29pub mod control_plane_support;
30#[doc(hidden)]
31pub mod dispatch;
32pub mod dto;
33#[doc(hidden)]
34pub mod error;
35mod format;
36pub mod ids;
37#[doc(hidden)]
38pub mod ingress;
39pub mod log;
40pub mod memory;
41mod memory_macros;
42pub mod perf;
43pub mod protocol;
44pub mod replay_policy;
45#[doc(hidden)]
46pub mod role_contract;
47#[doc(hidden)]
48pub mod shared_support;
49#[doc(hidden)]
50pub mod state_contract;
51#[cfg(test)]
52pub mod test;
53
54pub(crate) mod config;
55pub(crate) mod domain;
56pub(crate) mod infra;
57pub(crate) mod lifecycle;
58pub(crate) mod model;
59pub(crate) mod ops;
60pub(crate) mod storage;
61pub(crate) mod view;
62pub(crate) mod workflow;
63
64pub(crate) use error::{InternalError, InternalErrorClass, InternalErrorOrigin};
65
66/// Internal re-exports required for macro expansion.
67/// Not part of the public API.
68#[doc(hidden)]
69pub mod __reexports {
70    pub use ::ic_memory;
71    pub use ::ic_memory::__reexports::ctor;
72}
73
74///
75/// Consts
76///
77
78pub const CRATE_NAME: &str = env!("CARGO_PKG_NAME");
79pub const VERSION: &str = env!("CARGO_PKG_VERSION");
80pub const CANIC_MEMORY_MIN: u8 = role_contract::allocation::CANIC_CORE_MIN_ID;
81pub const CANIC_MEMORY_MAX: u8 = role_contract::allocation::CANIC_CORE_MAX_ID;
82// Canonical hardcoded 1 MiB chunk size for Canic wasm staging/install flows.
83// The management canister wasm chunk store rejects larger payloads.
84pub const CANIC_WASM_CHUNK_BYTES: usize = 1_048_576;
85
86crate::ic_memory_range!(
87    authority = CANIC_CORE_MEMORY_AUTHORITY,
88    start = role_contract::allocation::CANIC_CORE_MIN_ID,
89    end = role_contract::allocation::CANIC_CORE_MAX_ID,
90);
91
92#[cfg(test)]
93const _: () = {
94    fn __canic_memory_test_bootstrap() {
95        crate::api::runtime::MemoryRuntimeApi::bootstrap_registry()
96            .expect("test stable-memory bootstrap");
97    }
98
99    #[crate::__reexports::ctor::ctor(
100        unsafe,
101        anonymous,
102        crate_path = crate::__reexports::ctor
103    )]
104    fn __canic_install_memory_test_bootstrap_hook() {
105        crate::memory::runtime::install_test_bootstrap_hook(__canic_memory_test_bootstrap);
106    }
107};
108
109#[macro_export]
110macro_rules! perf {
111    ($($label:tt)*) => {{
112        $crate::perf::PERF_LAST.with(|last| {
113            let now = $crate::perf::perf_counter();
114            let then = *last.borrow();
115            let delta = now.saturating_sub(then);
116
117            *last.borrow_mut() = now;
118
119            let label = format!($($label)*);
120            $crate::perf::record_checkpoint(module_path!(), &label, delta);
121        });
122    }};
123}
124
125#[cfg(test)]
126#[macro_export]
127macro_rules! assert_err_variant {
128    ($err:expr, $pat:pat $(if $guard:expr)? $(,)?) => {{
129        match $err {
130            $pat $(if $guard)? => {}
131            other => panic!("unexpected error variant: {other:?}"),
132        }
133    }};
134}
135
136#[cfg(test)]
137mod memory_bootstrap_tests {
138    #[test]
139    fn installs_host_test_bootstrap_hook() {
140        assert!(crate::memory::runtime::has_test_bootstrap_hook());
141    }
142}