canic_core/model/memory/
env.rs

1use crate::{
2    cdk::structures::{DefaultMemoryImpl, cell::Cell, memory::VirtualMemory},
3    eager_static, ic_memory,
4    ids::{CanisterRole, SubnetRole},
5    memory::impl_storable_bounded,
6    model::memory::id::ENV_ID,
7};
8use candid::{CandidType, Principal};
9use serde::{Deserialize, Serialize};
10use std::cell::RefCell;
11
12//
13// ENV
14// All the environment variables a canister needs
15//
16
17eager_static! {
18    static ENV: RefCell<Cell<EnvData, VirtualMemory<DefaultMemoryImpl>>> =
19        RefCell::new(Cell::init(
20            ic_memory!(EnvData, ENV_ID),
21            EnvData::default(),
22        ));
23}
24
25///
26/// EnvData
27///
28/// `prime_root_pid` : passed to the root during install arguments.
29/// `parent_pid`     : passed to the root during install arguments.
30///
31/// All other fields are derived during install/upgrade and cached locally so
32/// every canister can answer questions about its environment without touching
33/// global state.
34///
35
36#[derive(CandidType, Clone, Debug, Default, Deserialize, Serialize)]
37pub struct EnvData {
38    // app
39    pub prime_root_pid: Option<Principal>,
40
41    // subnet
42    pub subnet_role: Option<SubnetRole>,
43    pub subnet_pid: Option<Principal>,
44    pub root_pid: Option<Principal>,
45
46    // canister
47    pub canister_role: Option<CanisterRole>,
48    pub parent_pid: Option<Principal>,
49}
50
51impl_storable_bounded!(EnvData, 256, true);
52
53///
54/// Env
55///
56
57pub struct Env;
58
59impl Env {
60    //
61    // ---- Prime Root PID ----
62    //
63
64    #[must_use]
65    pub(crate) fn get_prime_root_pid() -> Option<Principal> {
66        ENV.with_borrow(|cell| cell.get().prime_root_pid)
67    }
68
69    pub(crate) fn set_prime_root_pid(pid: Principal) {
70        ENV.with_borrow_mut(|cell| {
71            let mut data = cell.get().clone();
72            data.prime_root_pid = Some(pid);
73            cell.set(data);
74        });
75    }
76
77    //
78    // ---- Subnet Type ----
79    //
80
81    #[must_use]
82    pub(crate) fn get_subnet_role() -> Option<SubnetRole> {
83        ENV.with_borrow(|cell| cell.get().subnet_role.clone())
84    }
85
86    pub(crate) fn set_subnet_role(role: SubnetRole) {
87        ENV.with_borrow_mut(|cell| {
88            let mut data = cell.get().clone();
89            data.subnet_role = Some(role);
90            cell.set(data);
91        });
92    }
93
94    //
95    // ---- Subnet PID ----
96    //
97
98    #[must_use]
99    pub(crate) fn get_subnet_pid() -> Option<Principal> {
100        ENV.with_borrow(|cell| cell.get().subnet_pid)
101    }
102
103    pub(crate) fn set_subnet_pid(pid: Principal) {
104        ENV.with_borrow_mut(|cell| {
105            let mut data = cell.get().clone();
106            data.subnet_pid = Some(pid);
107            cell.set(data);
108        });
109    }
110
111    //
112    // ---- Root PID ----
113    //
114
115    #[must_use]
116    pub(crate) fn get_root_pid() -> Option<Principal> {
117        ENV.with_borrow(|cell| cell.get().root_pid)
118    }
119
120    pub(crate) fn set_root_pid(pid: Principal) {
121        ENV.with_borrow_mut(|cell| {
122            let mut data = cell.get().clone();
123            data.root_pid = Some(pid);
124            cell.set(data);
125        });
126    }
127
128    //
129    // ---- Canister Type ----
130    //
131
132    #[must_use]
133    pub(crate) fn get_canister_role() -> Option<CanisterRole> {
134        ENV.with_borrow(|cell| cell.get().canister_role.clone())
135    }
136
137    /// Set/replace the current canister role.
138    pub(crate) fn set_canister_role(role: CanisterRole) {
139        ENV.with_borrow_mut(|cell| {
140            let mut data = cell.get().clone();
141            data.canister_role = Some(role);
142            cell.set(data);
143        });
144    }
145
146    //
147    // ---- Parent PID ----
148    //
149
150    #[must_use]
151    pub(crate) fn get_parent_pid() -> Option<Principal> {
152        ENV.with_borrow(|cell| cell.get().parent_pid)
153    }
154
155    //
156    // ---- Import / Export ----
157    //
158
159    /// Import a complete EnvData record, replacing any existing state.
160    pub(crate) fn import(data: EnvData) {
161        ENV.with_borrow_mut(|cell| {
162            cell.set(data);
163        });
164    }
165
166    #[must_use]
167    pub(crate) fn export() -> EnvData {
168        ENV.with_borrow(|cell| cell.get().clone())
169    }
170}