canic_core/
lib.rs

1//! CANIC crate utilities for multi-canister apps on the Internet Computer.
2pub mod auth;
3pub mod config;
4pub mod env;
5pub mod guard;
6pub mod ids;
7pub mod interface;
8pub mod log;
9pub mod macros;
10pub mod model;
11pub mod ops;
12pub mod perf;
13pub mod spec;
14
15pub use ::canic_cdk as cdk;
16pub use ::canic_memory as memory;
17pub use ::canic_memory::{eager_init, eager_static, ic_memory, ic_memory_range};
18pub use ::canic_types as types;
19pub use ::canic_utils as utils;
20
21pub mod export {
22    pub use ::ctor;
23    pub use ::defer;
24}
25
26pub use thiserror::Error as ThisError;
27
28use crate::cdk::{
29    call::{CallFailed, CandidDecodeFailed, Error as CallError},
30    candid::{CandidType, Error as CandidError},
31};
32use serde::Deserialize;
33
34///
35/// Crate Version
36///
37
38pub const CRATE_NAME: &str = env!("CARGO_PKG_NAME");
39pub const VERSION: &str = env!("CARGO_PKG_VERSION");
40
41///
42/// Error
43///
44/// top level error should handle all sub-errors, but not expose the child candid types
45///
46
47#[derive(CandidType, Debug, Deserialize, ThisError)]
48pub enum Error {
49    #[error("{0}")]
50    AuthError(String),
51
52    #[error("{0}")]
53    ConfigError(String),
54
55    #[error("{0}")]
56    CustomError(String),
57
58    #[error("{0}")]
59    EnvError(String),
60
61    #[error("{0}")]
62    InterfaceError(String),
63
64    #[error("{0}")]
65    ModelError(String),
66
67    #[error("{0}")]
68    OpsError(String),
69
70    #[error("{0}")]
71    SerializeError(String),
72
73    #[error("http request failed: {0}")]
74    HttpRequest(String),
75
76    #[error("http error status: {0}")]
77    HttpErrorCode(u32),
78
79    #[error("http decode failed: {0}")]
80    HttpDecode(String),
81
82    ///
83    /// Test Error
84    /// as we don't want to import dev-dependencies
85    ///
86
87    #[error("{0}")]
88    TestError(String),
89
90    ///
91    /// Common IC errors
92    ///
93    /// CallError          : should be automatic with ?
94    /// CallFailed         : use this for wrapping <T, String> return values
95    /// CandidError        : for decode_one errors etc.  automatic
96    /// CandidDecodeFailed : automatic for calls like ::candid<T>()
97    ///
98
99    #[error("call error: {0}")]
100    CallError(String),
101
102    #[error("call failed: {0}")]
103    CallFailed(String),
104
105    #[error("candid error: {0}")]
106    CandidError(String),
107
108    #[error("candid decode failed: {0}")]
109    CandidDecodeFailed(String),
110}
111
112macro_rules! from_to_string {
113    ($from:ty, $variant:ident) => {
114        impl From<$from> for Error {
115            fn from(e: $from) -> Self {
116                Error::$variant(e.to_string())
117            }
118        }
119    };
120}
121
122impl Error {
123    /// Build a custom error from a string without defining a new variant.
124    #[must_use]
125    pub fn custom<S: Into<String>>(s: S) -> Self {
126        Self::CustomError(s.into())
127    }
128
129    /// Build a test error to avoid extra dev-only dependencies.
130    #[must_use]
131    pub fn test<S: Into<String>>(s: S) -> Self {
132        Self::TestError(s.into())
133    }
134}
135
136from_to_string!(auth::AuthError, AuthError);
137from_to_string!(config::ConfigError, ConfigError);
138from_to_string!(env::EnvError, EnvError);
139from_to_string!(interface::InterfaceError, InterfaceError);
140from_to_string!(model::ModelError, ModelError);
141from_to_string!(ops::OpsError, OpsError);
142from_to_string!(serde_json::Error, HttpDecode);
143
144from_to_string!(CallError, CallError);
145from_to_string!(CallFailed, CallFailed);
146from_to_string!(CandidDecodeFailed, CandidDecodeFailed);
147from_to_string!(CandidError, CandidError);