1use candid::{CandidType, Principal, utils::ArgumentEncoder};
2use serde::de::DeserializeOwned;
3
4use super::{
5 Pic, PicCallError, PicSerialGuard, StandaloneCanisterFixtureError,
6 try_acquire_pic_serial_guard, try_pic,
7};
8
9const DEFAULT_EXTRA_INSTALL_CYCLES: u128 = 0;
10
11pub struct StandaloneCanisterFixture {
16 pic: Pic,
17 canister_id: Principal,
18 _serial_guard: PicSerialGuard,
19}
20
21impl StandaloneCanisterFixture {
22 #[must_use]
24 pub const fn pic(&self) -> &Pic {
25 &self.pic
26 }
27
28 #[must_use]
30 pub const fn pic_mut(&mut self) -> &mut Pic {
31 &mut self.pic
32 }
33
34 #[must_use]
36 pub const fn canister_id(&self) -> Principal {
37 self.canister_id
38 }
39
40 #[must_use]
42 pub fn into_parts(self) -> (Pic, Principal) {
43 (self.pic, self.canister_id)
44 }
45
46 pub fn update_call<T, A>(&self, method: &str, args: A) -> Result<T, PicCallError>
48 where
49 T: CandidType + DeserializeOwned,
50 A: ArgumentEncoder,
51 {
52 self.pic.update_call(self.canister_id, method, args)
53 }
54
55 #[track_caller]
61 pub fn update_call_or_panic<T, A>(&self, method: &str, args: A) -> T
62 where
63 T: CandidType + DeserializeOwned,
64 A: ArgumentEncoder,
65 {
66 self.pic
67 .update_call_or_panic(self.canister_id, method, args)
68 }
69
70 pub fn update_call_as<T, A>(
72 &self,
73 caller: Principal,
74 method: &str,
75 args: A,
76 ) -> Result<T, PicCallError>
77 where
78 T: CandidType + DeserializeOwned,
79 A: ArgumentEncoder,
80 {
81 self.pic
82 .update_call_as(self.canister_id, caller, method, args)
83 }
84
85 #[track_caller]
91 pub fn update_call_as_or_panic<T, A>(&self, caller: Principal, method: &str, args: A) -> T
92 where
93 T: CandidType + DeserializeOwned,
94 A: ArgumentEncoder,
95 {
96 self.pic
97 .update_call_as_or_panic(self.canister_id, caller, method, args)
98 }
99
100 pub fn query_call<T, A>(&self, method: &str, args: A) -> Result<T, PicCallError>
102 where
103 T: CandidType + DeserializeOwned,
104 A: ArgumentEncoder,
105 {
106 self.pic.query_call(self.canister_id, method, args)
107 }
108
109 #[track_caller]
115 pub fn query_call_or_panic<T, A>(&self, method: &str, args: A) -> T
116 where
117 T: CandidType + DeserializeOwned,
118 A: ArgumentEncoder,
119 {
120 self.pic.query_call_or_panic(self.canister_id, method, args)
121 }
122
123 pub fn query_call_as<T, A>(
125 &self,
126 caller: Principal,
127 method: &str,
128 args: A,
129 ) -> Result<T, PicCallError>
130 where
131 T: CandidType + DeserializeOwned,
132 A: ArgumentEncoder,
133 {
134 self.pic
135 .query_call_as(self.canister_id, caller, method, args)
136 }
137
138 #[track_caller]
144 pub fn query_call_as_or_panic<T, A>(&self, caller: Principal, method: &str, args: A) -> T
145 where
146 T: CandidType + DeserializeOwned,
147 A: ArgumentEncoder,
148 {
149 self.pic
150 .query_call_as_or_panic(self.canister_id, caller, method, args)
151 }
152}
153
154#[must_use]
157pub fn install_prebuilt_canister(wasm: Vec<u8>, init_bytes: Vec<u8>) -> StandaloneCanisterFixture {
158 try_install_prebuilt_canister(wasm, init_bytes)
159 .unwrap_or_else(|err| panic!("failed to install prebuilt canister fixture: {err}"))
160}
161
162pub fn try_install_prebuilt_canister(
165 wasm: Vec<u8>,
166 init_bytes: Vec<u8>,
167) -> Result<StandaloneCanisterFixture, StandaloneCanisterFixtureError> {
168 try_install_prebuilt_canister_with_cycles(wasm, init_bytes, DEFAULT_EXTRA_INSTALL_CYCLES)
169}
170
171#[must_use]
174pub fn install_prebuilt_canister_with_cycles(
175 wasm: Vec<u8>,
176 init_bytes: Vec<u8>,
177 install_cycles: u128,
178) -> StandaloneCanisterFixture {
179 try_install_prebuilt_canister_with_cycles(wasm, init_bytes, install_cycles)
180 .unwrap_or_else(|err| panic!("failed to install prebuilt canister fixture: {err}"))
181}
182
183pub fn try_install_prebuilt_canister_with_cycles(
186 wasm: Vec<u8>,
187 init_bytes: Vec<u8>,
188 install_cycles: u128,
189) -> Result<StandaloneCanisterFixture, StandaloneCanisterFixtureError> {
190 let serial_guard =
191 try_acquire_pic_serial_guard().map_err(StandaloneCanisterFixtureError::SerialGuard)?;
192 let pic = try_pic().map_err(StandaloneCanisterFixtureError::Start)?;
193 let canister_id = pic
194 .try_create_and_install_with_args(wasm, init_bytes, install_cycles)
195 .map_err(StandaloneCanisterFixtureError::Install)?;
196
197 Ok(StandaloneCanisterFixture {
198 pic,
199 canister_id,
200 _serial_guard: serial_guard,
201 })
202}