ic_canister_kit/functions/
pausable.rs1pub trait Reasonable {
7 fn message(&self) -> &str;
9}
10
11pub trait Pausable<Reason: Reasonable> {
13 fn pause_query(&self) -> &Option<Reason>;
17
18 fn pause_replace(&mut self, reason: Option<Reason>);
22
23 fn pause_is_paused(&self) -> bool {
27 self.pause_query().is_some()
28 }
29 fn pause_is_running(&self) -> bool {
31 !self.pause_is_paused()
32 }
33 fn pause_must_be_running(&self) -> Result<(), String> {
35 if let Some(reason) = &self.pause_query() {
36 return Err(format!("Canister is paused: {}", reason.message()));
37 }
38 Ok(())
39 }
40 fn pause_must_be_paused(&self) -> Result<(), String> {
42 if self.pause_is_running() {
43 return Err("Canister is running. Not paused.".into());
44 }
45 Ok(())
46 }
47}
48
49pub mod basic {
53 use std::fmt::Display;
54
55 use candid::CandidType;
56 use serde::{Deserialize, Serialize};
57
58 use crate::{
59 functions::types::{Pausable, Reasonable},
60 types::TimestampNanos,
61 };
62
63 #[derive(CandidType, Serialize, Deserialize, Debug, Clone)]
65 pub struct PauseReason {
66 pub timestamp_nanos: TimestampNanos,
68
69 pub message: String,
71 }
72
73 impl Display for PauseReason {
74 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75 f.write_str(&format!("{:?}", self))
76 }
77 }
78
79 impl std::error::Error for PauseReason {}
80
81 impl Reasonable for PauseReason {
82 fn message(&self) -> &str {
83 &self.message
84 }
85 }
86
87 impl PauseReason {
88 pub fn new(message: String) -> Self {
90 PauseReason {
91 timestamp_nanos: crate::times::now(),
92 message,
93 }
94 }
95 }
96
97 #[derive(CandidType, Serialize, Deserialize, Debug, Clone, Default)]
99 pub struct Pause(Option<PauseReason>);
100
101 impl Pausable<PauseReason> for Pause {
102 fn pause_query(&self) -> &Option<PauseReason> {
104 &self.0
105 }
106 fn pause_replace(&mut self, reason: Option<PauseReason>) {
109 self.0 = reason;
110 }
111 }
112}