canic_core/ops/storage/
env.rs1use crate::{Error, ThisError, ops::storage::StorageOpsError};
2use crate::{
3 cdk::{api::canister_self, types::Principal},
4 ids::{CanisterRole, SubnetRole},
5 model::memory::Env,
6};
7
8pub use crate::model::memory::env::EnvData;
9
10#[derive(Debug, ThisError)]
15pub enum EnvOpsError {
16 #[error("env import missing required fields: {0}")]
17 MissingFields(String),
18
19 #[error("failed to determine current canister role")]
20 CanisterRoleUnavailable,
21
22 #[error("failed to determine current parent principal")]
23 ParentPidUnavailable,
24
25 #[error("failed to determine current subnet principal")]
26 SubnetPidUnavailable,
27
28 #[error("failed to determine current subnet role")]
29 SubnetRoleUnavailable,
30
31 #[error("failed to determine current root principal")]
32 RootPidUnavailable,
33}
34
35impl From<EnvOpsError> for Error {
36 fn from(err: EnvOpsError) -> Self {
37 StorageOpsError::from(err).into()
38 }
39}
40
41pub struct EnvOps;
52
53impl EnvOps {
54 pub fn import(env: EnvData) -> Result<(), Error> {
59 let mut missing = Vec::new();
60 if env.prime_root_pid.is_none() {
61 missing.push("prime_root_pid");
62 }
63 if env.subnet_role.is_none() {
64 missing.push("subnet_role");
65 }
66 if env.subnet_pid.is_none() {
67 missing.push("subnet_pid");
68 }
69 if env.root_pid.is_none() {
70 missing.push("root_pid");
71 }
72 if env.canister_role.is_none() {
73 missing.push("canister_role");
74 }
75 if env.parent_pid.is_none() {
76 missing.push("parent_pid");
77 }
78
79 if !missing.is_empty() {
80 return Err(EnvOpsError::MissingFields(missing.join(", ")).into());
81 }
82
83 Env::import(env);
84 Ok(())
85 }
86
87 pub fn set_prime_root_pid(pid: Principal) {
88 Env::set_prime_root_pid(pid);
89 }
90
91 pub fn set_subnet_role(role: SubnetRole) {
92 Env::set_subnet_role(role);
93 }
94
95 pub fn set_subnet_pid(pid: Principal) {
96 Env::set_subnet_pid(pid);
97 }
98
99 pub fn set_root_pid(pid: Principal) {
100 Env::set_root_pid(pid);
101 }
102
103 pub fn set_canister_role(role: CanisterRole) {
104 Env::set_canister_role(role);
105 }
106
107 #[must_use]
112 pub fn is_prime_root() -> bool {
113 Self::prime_root_pid() == Self::root_pid()
114 }
115
116 #[must_use]
117 pub fn is_prime_subnet() -> bool {
118 Self::subnet_role().is_prime()
119 }
120
121 #[must_use]
122 pub fn is_root() -> bool {
123 Self::root_pid() == canister_self()
124 }
125
126 #[cfg(test)]
131 pub fn try_get_subnet_role() -> Result<SubnetRole, Error> {
132 Env::get_subnet_role().ok_or_else(|| EnvOpsError::SubnetRoleUnavailable.into())
133 }
134
135 #[cfg(test)]
136 pub fn try_get_canister_role() -> Result<CanisterRole, Error> {
137 Env::get_canister_role().ok_or_else(|| EnvOpsError::CanisterRoleUnavailable.into())
138 }
139
140 #[cfg(test)]
141 pub fn try_get_subnet_pid() -> Result<Principal, Error> {
142 Env::get_subnet_pid().ok_or_else(|| EnvOpsError::SubnetPidUnavailable.into())
143 }
144
145 #[cfg(test)]
146 pub fn try_get_root_pid() -> Result<Principal, Error> {
147 Env::get_root_pid().ok_or_else(|| EnvOpsError::RootPidUnavailable.into())
148 }
149
150 #[cfg(test)]
151 pub fn try_get_prime_root_pid() -> Result<Principal, Error> {
152 Env::get_prime_root_pid().ok_or_else(|| EnvOpsError::RootPidUnavailable.into())
153 }
154
155 #[cfg(test)]
156 pub fn try_get_parent_pid() -> Result<Principal, Error> {
157 Env::get_parent_pid().ok_or_else(|| EnvOpsError::ParentPidUnavailable.into())
158 }
159
160 #[must_use]
165 pub fn subnet_role() -> SubnetRole {
166 Env::get_subnet_role()
167 .expect("EnvOps::subnet_role called before environment initialization")
168 }
169
170 #[must_use]
171 pub fn canister_role() -> CanisterRole {
172 Env::get_canister_role()
173 .expect("EnvOps::canister_role called before environment initialization")
174 }
175
176 #[must_use]
177 pub fn subnet_pid() -> Principal {
178 Env::get_subnet_pid().expect("EnvOps::subnet_pid called before environment initialization")
179 }
180
181 #[must_use]
182 pub fn root_pid() -> Principal {
183 Env::get_root_pid().expect("EnvOps::root_pid called before environment initialization")
184 }
185
186 #[must_use]
187 pub fn prime_root_pid() -> Principal {
188 Env::get_prime_root_pid()
189 .expect("EnvOps::prime_root_pid called before environment initialization")
190 }
191
192 #[must_use]
193 pub fn parent_pid() -> Principal {
194 Env::get_parent_pid().expect("EnvOps::parent_pid called before environment initialization")
195 }
196
197 #[must_use]
203 pub fn export() -> EnvData {
204 Env::export()
205 }
206}