Skip to main content

canic_core/
lib.rs

1//! Core Canic library used inside canisters.
2//!
3//! Canister roles should depend on the `canic` facade crate, which exposes the
4//! supported API/DTO/ID surfaces and 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/policy/pure/` contains pure policy decisions invoked by workflow.
14//! - `ops/` provides deterministic state access, conversion, and approved single-step effects.
15//! - `model/` owns authoritative runtime state and storage invariants.
16//! - `storage/` contains passive persisted schemas and stable-memory representations.
17//! - `view/` exposes internal read-only projections over stored/runtime state.
18//! - macro entrypoints live in the `canic` facade crate.
19//!
20//! The dependency flow is: endpoints → workflow → policy → ops → model.
21
22#[doc(hidden)]
23pub mod access;
24pub mod api;
25#[doc(hidden)]
26pub mod bootstrap;
27#[doc(hidden)]
28pub mod cdk;
29#[doc(hidden)]
30pub mod control_plane_support;
31pub mod diagnostics;
32#[doc(hidden)]
33pub mod dispatch;
34pub mod dto;
35#[doc(hidden)]
36mod error;
37mod format;
38pub mod ids;
39#[doc(hidden)]
40pub mod ingress;
41pub mod log;
42pub mod memory;
43mod memory_macros;
44pub mod perf;
45pub mod protocol;
46pub mod replay_policy;
47#[doc(hidden)]
48pub mod role_contract;
49#[doc(hidden)]
50pub mod shared_support;
51#[doc(hidden)]
52pub mod state_contract;
53#[cfg(test)]
54pub mod test;
55
56pub(crate) mod config;
57pub(crate) mod domain;
58pub(crate) mod infra;
59pub(crate) mod lifecycle;
60pub(crate) mod model;
61pub(crate) mod ops;
62pub(crate) mod storage;
63pub(crate) mod view;
64pub(crate) mod workflow;
65
66pub(crate) use error::InternalError;
67
68/// Internal re-exports required for macro expansion.
69/// Not part of the public API.
70#[doc(hidden)]
71pub mod __reexports {
72    pub use ::ic_memory;
73    pub use ::ic_memory::__reexports::ctor;
74}
75
76///
77/// Consts
78///
79
80pub const VERSION: &str = env!("CARGO_PKG_VERSION");
81// Canonical hardcoded 1 MiB chunk size for Canic wasm staging/install flows.
82// The management canister wasm chunk store rejects larger payloads.
83pub const CANIC_WASM_CHUNK_BYTES: usize = 1_048_576;
84/// Existing byte-lane envelope, including bounded publication metadata.
85pub const CANIC_WASM_CHUNK_REQUEST_MAX_BYTES: usize = CANIC_WASM_CHUNK_BYTES + 64 * 1024;
86
87crate::ic_memory_range!(
88    authority = CANIC_CORE_MEMORY_AUTHORITY,
89    start = role_contract::allocation::CANIC_CORE_MIN_ID,
90    end = role_contract::allocation::CANIC_CORE_LOWER_MAX_ID,
91);
92crate::ic_memory_range!(
93    authority = CANIC_CORE_MEMORY_AUTHORITY,
94    start = role_contract::allocation::CANIC_CORE_UPPER_MIN_ID,
95    end = role_contract::allocation::CANIC_CORE_MAX_ID,
96);
97ic_memory_range!(
98    authority = CANIC_CORE_MEMORY_AUTHORITY,
99    start = role_contract::allocation::CANIC_CORE_AUTH_MIN_ID,
100    end = role_contract::allocation::CANIC_CORE_AUTH_MAX_ID,
101);
102
103#[cfg(test)]
104const _: () = {
105    fn __canic_memory_test_bootstrap() {
106        crate::api::runtime::MemoryRuntimeApi::bootstrap_registry()
107            .expect("test stable-memory bootstrap");
108    }
109
110    #[crate::__reexports::ctor::ctor(
111        unsafe,
112        anonymous,
113        crate_path = crate::__reexports::ctor
114    )]
115    fn __canic_install_memory_test_bootstrap_hook() {
116        crate::memory::runtime::install_test_bootstrap_hook(__canic_memory_test_bootstrap);
117    }
118};
119
120#[macro_export]
121macro_rules! perf {
122    ($($label:tt)*) => {{
123        $crate::perf::PERF_LAST.with(|last| {
124            let now = $crate::perf::perf_counter();
125            let then = *last.borrow();
126            let delta = now.saturating_sub(then);
127
128            *last.borrow_mut() = now;
129
130            let label = format!($($label)*);
131            $crate::perf::record_checkpoint(module_path!(), &label, delta);
132        });
133    }};
134}
135
136#[cfg(test)]
137#[macro_export]
138macro_rules! assert_err_variant {
139    ($err:expr, $pat:pat $(if $guard:expr)? $(,)?) => {{
140        match $err {
141            $pat $(if $guard)? => {}
142            other => panic!("unexpected error variant: {other:?}"),
143        }
144    }};
145}
146
147#[cfg(test)]
148mod memory_bootstrap_tests {
149    #[test]
150    fn installs_host_test_bootstrap_hook() {
151        assert!(crate::memory::runtime::has_test_bootstrap_hook());
152    }
153}