icarus_canister/
result.rs1use candid::{CandidType, Deserialize};
4use serde::Serialize;
5
6pub type IcarusResult<T> = Result<T, IcarusError>;
8
9#[derive(Debug, Clone, Serialize, Deserialize, CandidType)]
11pub enum IcarusError {
12 Unauthorized(String),
14 ValidationError { field: String, message: String },
16 NotFound(String),
18 AlreadyExists(String),
20 StorageError(String),
22 Other(String),
24}
25
26impl IcarusError {
27 pub fn unauthorized() -> Self {
29 Self::Unauthorized("Unauthorized access".to_string())
30 }
31
32 pub fn validation(field: impl Into<String>, message: impl Into<String>) -> Self {
34 Self::ValidationError {
35 field: field.into(),
36 message: message.into(),
37 }
38 }
39
40 pub fn not_found(resource: impl Into<String>) -> Self {
42 Self::NotFound(format!("{} not found", resource.into()))
43 }
44
45 pub fn already_exists(resource: impl Into<String>) -> Self {
47 Self::AlreadyExists(format!("{} already exists", resource.into()))
48 }
49
50 pub fn storage(message: impl Into<String>) -> Self {
52 Self::StorageError(message.into())
53 }
54
55 pub fn trap(self) -> ! {
57 ic_cdk::trap(self.to_string())
58 }
59}
60
61impl std::fmt::Display for IcarusError {
62 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63 match self {
64 Self::Unauthorized(msg) => write!(f, "Unauthorized: {}", msg),
65 Self::ValidationError { field, message } => {
66 write!(f, "Validation error on '{}': {}", field, message)
67 }
68 Self::NotFound(msg) => write!(f, "Not found: {}", msg),
69 Self::AlreadyExists(msg) => write!(f, "Already exists: {}", msg),
70 Self::StorageError(msg) => write!(f, "Storage error: {}", msg),
71 Self::Other(msg) => write!(f, "{}", msg),
72 }
73 }
74}
75
76impl std::error::Error for IcarusError {}
77
78impl From<String> for IcarusError {
79 fn from(s: String) -> Self {
80 Self::Other(s)
81 }
82}
83
84impl From<&str> for IcarusError {
85 fn from(s: &str) -> Self {
86 Self::Other(s.to_string())
87 }
88}
89
90pub trait TrapExt<T> {
92 fn unwrap_or_trap(self) -> T;
94}
95
96impl<T> TrapExt<T> for Result<T, IcarusError> {
97 fn unwrap_or_trap(self) -> T {
98 match self {
99 Ok(v) => v,
100 Err(e) => e.trap(),
101 }
102 }
103}