Skip to main content

maybe_fatal/code/
mod.rs

1//! Diagnostic codes.
2//!
3//! Provides the [`DiagnosticCode`] type for identifiying [`Diagnostic`](crate::Diagnostic)s.
4
5pub use discriminant::{DefaultDiscriminant, Discriminant};
6
7mod discriminant;
8
9use core::{
10    fmt::{self, Display, Formatter},
11    str::Utf8Error,
12};
13
14/// A code that identifies a given kind of diagnostic.
15///
16/// These are meant to be used by users as unchanging identifiers by which they can look up more
17/// detailed information about the diagnostic.
18#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
19pub struct DiagnosticCode<D = DefaultDiscriminant> {
20    /// A short prefix corresponding to the broad category the diagnostic belongs to.
21    prefix: [u8; 3],
22
23    /// The numeric discriminant.
24    pub discriminant: D,
25}
26
27impl<D> DiagnosticCode<D> {
28    /// Constructs a new [`DiagnosticCode`].
29    ///
30    /// # Errors
31    ///
32    /// If `prefix` is not valid UTF-8, an error variant will be returned.
33    ///
34    /// # See Also
35    ///
36    /// - [`new_unchecked`](Self::new_unchecked)
37    pub fn new(prefix: [u8; 3], discriminant: D) -> Result<Self, Utf8Error> {
38        match str::from_utf8(&prefix) {
39            Ok(_) => Ok(unsafe { Self::new_unchecked(prefix, discriminant) }),
40            Err(err) => Err(err),
41        }
42    }
43
44    /// Constructs a new [`DiagnosticCode`].
45    ///
46    /// # Safety
47    ///
48    /// The caller is responsible for ensuring `prefix` is valid UTF-8. For a safe alternative, see
49    /// [`new`].
50    ///
51    /// # See Also
52    ///
53    /// - [`new`]
54    ///
55    /// [`new`]: Self::new
56    pub const unsafe fn new_unchecked(prefix: [u8; 3], discriminant: D) -> Self {
57        Self {
58            prefix,
59            discriminant,
60        }
61    }
62
63    /// Gets this code's prefix as a slice of raw, UTF-8-encoded bytes.
64    ///
65    /// # See Also
66    ///
67    /// - [`prefix_str`](Self::prefix_str)
68    pub const fn prefix_bytes(&self) -> &[u8; 3] {
69        &self.prefix
70    }
71
72    /// Gets this code's prefix as a [string slice](str).
73    ///
74    /// # See Also
75    ///
76    /// - [`prefix_bytes`](Self::prefix_bytes)
77    pub const fn prefix_str(&self) -> &str {
78        unsafe { str::from_utf8_unchecked(&self.prefix) }
79    }
80}
81
82impl<D> Display for DiagnosticCode<D>
83where
84    D: Discriminant,
85{
86    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
87        write!(
88            f,
89            "{}{:0width$}",
90            self.prefix_str(),
91            self.discriminant,
92            width = D::MAX_N_DIGITS,
93        )
94    }
95}