Skip to main content

datalogic_rs/error/
code.rs

1//! [`ErrorCode`]: the kind of an [`Error`](super::Error) without its
2//! payload.
3
4use std::fmt;
5use std::str::FromStr;
6
7use super::ErrorKind;
8
9/// What kind of error an [`Error`](super::Error) is, without the details:
10/// one variant per [`ErrorKind`] variant, `Copy`, comparable and hashable.
11/// Read it with [`Error::code`](super::Error::code).
12///
13/// Every variant exists in every build, whatever features are enabled, and
14/// [`Self::as_str`] spells it the way [`Error::tag`](super::Error::tag)
15/// always has, so a host can switch on the code instead of comparing tag
16/// strings, and the bindings carry the same names on the wire.
17///
18/// `#[non_exhaustive]`: a later release may add kinds, so a `match` needs
19/// a wildcard arm.
20#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
21#[non_exhaustive]
22pub enum ErrorCode {
23    /// [`ErrorKind::InvalidOperator`].
24    InvalidOperator,
25    /// [`ErrorKind::InvalidArguments`].
26    InvalidArguments,
27    /// [`ErrorKind::VariableNotFound`].
28    VariableNotFound,
29    /// [`ErrorKind::InvalidContextLevel`].
30    InvalidContextLevel,
31    /// [`ErrorKind::TypeError`].
32    TypeError,
33    /// [`ErrorKind::ArithmeticError`].
34    ArithmeticError,
35    /// [`ErrorKind::Custom`].
36    Custom,
37    /// [`ErrorKind::ParseError`].
38    ParseError,
39    /// [`ErrorKind::Thrown`].
40    Thrown,
41    /// [`ErrorKind::FormatError`].
42    FormatError,
43    /// [`ErrorKind::IndexOutOfBounds`].
44    IndexOutOfBounds,
45    /// [`ErrorKind::ConfigurationError`].
46    ConfigurationError,
47    /// [`ErrorKind::BudgetExceeded`].
48    BudgetExceeded,
49}
50
51impl ErrorCode {
52    /// Every code, in declaration order.
53    pub const ALL: &'static [ErrorCode] = &[
54        ErrorCode::InvalidOperator,
55        ErrorCode::InvalidArguments,
56        ErrorCode::VariableNotFound,
57        ErrorCode::InvalidContextLevel,
58        ErrorCode::TypeError,
59        ErrorCode::ArithmeticError,
60        ErrorCode::Custom,
61        ErrorCode::ParseError,
62        ErrorCode::Thrown,
63        ErrorCode::FormatError,
64        ErrorCode::IndexOutOfBounds,
65        ErrorCode::ConfigurationError,
66        ErrorCode::BudgetExceeded,
67    ];
68
69    /// The code's name, which is also the variant's name and
70    /// [`Error::tag`](super::Error::tag). Stable across releases.
71    pub const fn as_str(self) -> &'static str {
72        match self {
73            ErrorCode::InvalidOperator => "InvalidOperator",
74            ErrorCode::InvalidArguments => "InvalidArguments",
75            ErrorCode::VariableNotFound => "VariableNotFound",
76            ErrorCode::InvalidContextLevel => "InvalidContextLevel",
77            ErrorCode::TypeError => "TypeError",
78            ErrorCode::ArithmeticError => "ArithmeticError",
79            ErrorCode::Custom => "Custom",
80            ErrorCode::ParseError => "ParseError",
81            ErrorCode::Thrown => "Thrown",
82            ErrorCode::FormatError => "FormatError",
83            ErrorCode::IndexOutOfBounds => "IndexOutOfBounds",
84            ErrorCode::ConfigurationError => "ConfigurationError",
85            ErrorCode::BudgetExceeded => "BudgetExceeded",
86        }
87    }
88}
89
90impl fmt::Display for ErrorCode {
91    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92        f.write_str(self.as_str())
93    }
94}
95
96/// The name is not one of [`ErrorCode::ALL`]'s [`as_str`](ErrorCode::as_str).
97#[derive(Debug, Clone, PartialEq, Eq)]
98pub struct UnknownErrorCode;
99
100impl fmt::Display for UnknownErrorCode {
101    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102        f.write_str("unknown error code")
103    }
104}
105
106impl std::error::Error for UnknownErrorCode {}
107
108impl FromStr for ErrorCode {
109    type Err = UnknownErrorCode;
110
111    /// Parse a code from its exact (case-sensitive) name.
112    fn from_str(s: &str) -> Result<Self, Self::Err> {
113        ErrorCode::ALL
114            .iter()
115            .copied()
116            .find(|code| code.as_str() == s)
117            .ok_or(UnknownErrorCode)
118    }
119}
120
121impl ErrorKind {
122    /// This kind's [`ErrorCode`].
123    pub const fn code(&self) -> ErrorCode {
124        match self {
125            ErrorKind::InvalidOperator(_) => ErrorCode::InvalidOperator,
126            ErrorKind::InvalidArguments(_) => ErrorCode::InvalidArguments,
127            ErrorKind::VariableNotFound(_) => ErrorCode::VariableNotFound,
128            ErrorKind::InvalidContextLevel(_) => ErrorCode::InvalidContextLevel,
129            ErrorKind::TypeError(_) => ErrorCode::TypeError,
130            ErrorKind::ArithmeticError(_) => ErrorCode::ArithmeticError,
131            ErrorKind::Custom(_) => ErrorCode::Custom,
132            ErrorKind::ParseError(_) => ErrorCode::ParseError,
133            ErrorKind::Thrown(_) => ErrorCode::Thrown,
134            ErrorKind::FormatError(_) => ErrorCode::FormatError,
135            ErrorKind::IndexOutOfBounds { .. } => ErrorCode::IndexOutOfBounds,
136            ErrorKind::ConfigurationError(_) => ErrorCode::ConfigurationError,
137            ErrorKind::BudgetExceeded { .. } => ErrorCode::BudgetExceeded,
138        }
139    }
140}