pub trait Reasonable {
fn message(&self) -> &str;
}
pub trait Pausable<Reason: Reasonable> {
fn pause_query(&self) -> &Option<Reason>;
fn pause_replace(&mut self, reason: Option<Reason>);
fn pause_is_paused(&self) -> bool {
self.pause_query().is_some()
}
fn pause_is_running(&self) -> bool {
!self.pause_is_paused()
}
fn pause_must_be_running(&self) -> Result<(), String> {
if let Some(reason) = &self.pause_query() {
return Err(format!("Canister is paused: {}", reason.message()));
}
Ok(())
}
fn pause_must_be_paused(&self) -> Result<(), String> {
if self.pause_is_running() {
return Err("Canister is running. Not paused.".into());
}
Ok(())
}
}
pub mod basic {
use std::fmt::Display;
use candid::CandidType;
use serde::{Deserialize, Serialize};
use crate::{
functions::types::{Pausable, Reasonable},
types::TimestampNanos,
};
#[derive(CandidType, Serialize, Deserialize, Debug, Clone)]
pub struct PauseReason {
pub timestamp_nanos: TimestampNanos,
pub message: String,
}
impl Display for PauseReason {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&format!("{:?}", self))
}
}
impl std::error::Error for PauseReason {}
impl Reasonable for PauseReason {
fn message(&self) -> &str {
&self.message
}
}
impl PauseReason {
pub fn new(message: String) -> Self {
PauseReason {
timestamp_nanos: crate::times::now(),
message,
}
}
}
#[derive(CandidType, Serialize, Deserialize, Debug, Clone, Default)]
pub struct Pause(Option<PauseReason>);
impl Pausable<PauseReason> for Pause {
fn pause_query(&self) -> &Option<PauseReason> {
&self.0
}
fn pause_replace(&mut self, reason: Option<PauseReason>) {
self.0 = reason;
}
}
}