Skip to main content

canic_core/diagnostics/
mod.rs

1//! Module: canic_core::diagnostics
2//!
3//! Responsibility: own compact diagnostic identities available to runtime code.
4//! Does not own: host rendering, allocation history, producer coverage, or public error mapping.
5//! Boundary: raw identities preserve decoded values; registered identities alone authorize producers.
6
7pub mod codes;
8
9use std::fmt::{self, Debug, Display};
10
11///
12/// DiagnosticCode
13///
14/// Lossless raw diagnostic identity decoded from a boundary or retained for
15/// observation. Possessing this value does not grant producer authority.
16///
17
18#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
19#[repr(transparent)]
20pub struct DiagnosticCode(u16);
21
22impl DiagnosticCode {
23    /// Preserve any decoded raw identity, including unknown future values.
24    #[must_use]
25    pub const fn from_raw(raw: u16) -> Self {
26        Self(raw)
27    }
28
29    /// Return the lossless numeric identity.
30    #[must_use]
31    pub const fn raw(self) -> u16 {
32        self.0
33    }
34}
35
36impl Debug for DiagnosticCode {
37    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38        Display::fmt(self, f)
39    }
40}
41
42impl Display for DiagnosticCode {
43    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44        write!(f, "E{}", self.0)
45    }
46}
47
48///
49/// RegisteredDiagnosticCode
50///
51/// Centrally allocated producer identity. Only the canonical declaration tree
52/// can construct this type from a number.
53///
54
55#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
56#[repr(transparent)]
57pub struct RegisteredDiagnosticCode(u16);
58
59impl RegisteredDiagnosticCode {
60    /// Return this registered producer identity as its lossless raw value.
61    #[must_use]
62    pub const fn raw_code(self) -> DiagnosticCode {
63        DiagnosticCode(self.0)
64    }
65}
66
67impl Debug for RegisteredDiagnosticCode {
68    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69        Display::fmt(self, f)
70    }
71}
72
73impl Display for RegisteredDiagnosticCode {
74    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75        Display::fmt(&self.raw_code(), f)
76    }
77}
78
79pub(in crate::diagnostics) const fn registered(raw: u16) -> RegisteredDiagnosticCode {
80    assert!(raw != 0, "diagnostic code zero is not allocatable");
81    RegisteredDiagnosticCode(raw)
82}
83
84#[cfg(test)]
85mod tests {
86    use super::*;
87
88    #[test]
89    fn raw_and_registered_formatting_is_compact_and_numeric() {
90        let raw = DiagnosticCode::from_raw(65_000);
91        let registered = codes::ACCESS_UNAVAILABLE;
92
93        assert_eq!(raw.raw(), 65_000);
94        assert_eq!(raw.to_string(), "E65000");
95        assert_eq!(format!("{raw:?}"), "E65000");
96        assert_eq!(registered.raw_code().raw(), 1);
97        assert_eq!(registered.to_string(), "E1");
98        assert_eq!(format!("{registered:?}"), "E1");
99    }
100}