Skip to main content

canic_core/dto/
error.rs

1use crate::{
2    access::AccessError,
3    diagnostics::{DiagnosticCode, RegisteredDiagnosticCode},
4    dto::prelude::*,
5};
6use std::fmt::{self, Display};
7
8///
9/// Error
10///
11/// Public API error payload. Only registered runtime reasons may originate a
12/// value; Candid/Serde decoding may still preserve any raw `u16`.
13///
14
15#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
16pub struct Error {
17    code: u16,
18}
19
20impl Error {
21    /// Originate a public error from a registered reason.
22    #[must_use]
23    pub const fn from_registered(code: RegisteredDiagnosticCode) -> Self {
24        Self {
25            code: code.raw_code().raw(),
26        }
27    }
28
29    /// Observe the lossless diagnostic identity.
30    #[must_use]
31    pub const fn code(&self) -> DiagnosticCode {
32        DiagnosticCode::from_raw(self.code)
33    }
34
35    /// Observe the raw Candid `nat16` value.
36    #[must_use]
37    pub const fn raw_code(&self) -> u16 {
38        self.code
39    }
40}
41
42impl Display for Error {
43    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44        Display::fmt(&self.code(), f)
45    }
46}
47
48impl From<AccessError> for Error {
49    fn from(err: AccessError) -> Self {
50        match err {
51            AccessError::Internal(error) => error.into(),
52            error => {
53                let diagnostic = error
54                    .diagnostic_codes()
55                    .expect("non-internal access errors have registered reasons");
56                Self::from_registered(diagnostic.public)
57            }
58        }
59    }
60}