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!` / `canic::build_root!` (in `build.rs`) to validate/embed `canic.toml`
6//! - `canic::start!` / `canic::start_root!` (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//! - `ops/` provides mechanical, reusable side-effecting operations.
15//! - `storage/` owns stable-memory-backed schemas and helpers.
16//! - `view/` exposes internal read-only projections over stored/runtime state.
17//! - macro entrypoints live in the `canic` facade crate.
18//!
19//! The default flow is: endpoints → workflow → domain/decision helpers → ops → storage.
20
21#[doc(hidden)]
22pub mod __control_plane_core;
23#[doc(hidden)]
24pub mod access;
25pub mod api;
26#[doc(hidden)]
27pub mod bootstrap;
28#[doc(hidden)]
29pub mod dispatch;
30pub mod dto;
31#[doc(hidden)]
32pub mod error;
33mod format;
34pub mod ids;
35#[doc(hidden)]
36pub mod ingress;
37pub mod log;
38pub mod perf;
39pub mod protocol;
40#[cfg(test)]
41pub mod test;
42
43pub(crate) mod config;
44pub(crate) mod domain;
45pub(crate) mod infra;
46pub(crate) mod lifecycle;
47pub(crate) mod ops;
48pub(crate) mod storage;
49pub(crate) mod view;
50pub(crate) mod workflow;
51
52pub use {
53    ::canic_cdk as cdk,
54    ::canic_memory as memory,
55    ::canic_memory::{eager_init, eager_static, ic_memory, ic_memory_range},
56};
57
58pub(crate) use error::{InternalError, InternalErrorClass, InternalErrorOrigin};
59
60/// Internal re-exports required for macro expansion.
61/// Not part of the public API.
62#[doc(hidden)]
63pub mod __reexports {
64    pub use ::ctor;
65}
66
67///
68/// Consts
69///
70
71pub const CRATE_NAME: &str = env!("CARGO_PKG_NAME");
72pub const VERSION: &str = env!("CARGO_PKG_VERSION");
73pub const CANIC_MEMORY_MIN: u8 = storage::stable::CANIC_MEMORY_MIN;
74pub const CANIC_MEMORY_MAX: u8 = storage::stable::CANIC_MEMORY_MAX;
75// Canonical hardcoded 1 MiB chunk size for Canic wasm staging/install flows.
76// The management canister wasm chunk store rejects larger payloads.
77pub const CANIC_WASM_CHUNK_BYTES: usize = 1_048_576;
78
79#[cfg(test)]
80const _: () = {
81    use std::sync::Once;
82
83    fn __canic_memory_test_bootstrap() {
84        static ONCE: Once = Once::new();
85
86        ONCE.call_once(|| {
87            crate::api::runtime::MemoryRuntimeApi::bootstrap_registry()
88                .expect("test stable-memory bootstrap");
89        });
90    }
91
92    #[canic_memory::__reexports::ctor::ctor(
93        unsafe,
94        anonymous,
95        crate_path = canic_memory::__reexports::ctor
96    )]
97    fn __canic_install_memory_test_bootstrap_hook() {
98        canic_memory::runtime::install_test_bootstrap_hook(__canic_memory_test_bootstrap);
99    }
100};
101
102#[macro_export]
103macro_rules! perf {
104    ($($label:tt)*) => {{
105        $crate::perf::PERF_LAST.with(|last| {
106            let now = $crate::perf::perf_counter();
107            let then = *last.borrow();
108            let delta = now.saturating_sub(then);
109
110            *last.borrow_mut() = now;
111
112            let label = format!($($label)*);
113            $crate::perf::record_checkpoint(module_path!(), &label, delta);
114        });
115    }};
116}
117
118#[cfg(test)]
119#[macro_export]
120macro_rules! assert_err_variant {
121    ($err:expr, $pat:pat $(if $guard:expr)? $(,)?) => {{
122        match $err {
123            $pat $(if $guard)? => {}
124            other => panic!("unexpected error variant: {other:?}"),
125        }
126    }};
127}
128
129#[cfg(test)]
130mod memory_bootstrap_tests {
131    #[test]
132    fn installs_host_test_bootstrap_hook() {
133        assert!(canic_memory::runtime::has_test_bootstrap_hook());
134    }
135}