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}