semeion/
error.rs

1use std::fmt::{self, Debug, Display};
2
3pub trait Any: std::error::Error {
4    /// Gets a reference to self via the Any trait, used to emulate dynamic
5    /// typing and downcast this trait to its concrete type.
6    fn as_any(&self) -> &dyn std::any::Any;
7}
8
9/// Represents any possible error.
10///
11/// This enum allows to encode the errors that can be raised by this library as
12/// well as allow to encode a custom error, that will need to be propagated via
13/// the APIs exposed by this library, which originates in the user's code.
14#[derive(Debug)]
15pub enum Error {
16    /// The most generic and possibly useless type of error, to be raised when
17    /// no other information is available.
18    Unknown,
19    /// The Code variant allows to encode errors as simple signed integers.
20    Code(i32),
21    /// The Message variant allows to encode the error as a string.
22    Message(String),
23    /// The Any variant allows to encode any type of error with performance costs
24    /// due to the heap allocations, and type erasure.
25    ///
26    /// # Example
27    /// ```
28    /// use std::fmt;
29    ///
30    /// #[derive(Debug)]
31    /// enum MyError {
32    ///     Audio,
33    ///     Game,
34    ///     InvalidArg { err: String }
35    /// }
36    ///
37    /// impl fmt::Display for MyError {
38    ///     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39    ///         write!(f, "{:?}", self)
40    ///     }
41    /// }
42    ///
43    /// impl std::error::Error for MyError {}
44    ///
45    /// impl semeion::error::Any for MyError {
46    ///     fn as_any(&self) -> &dyn std::any::Any {
47    ///         self
48    ///     }
49    /// }
50    ///
51    /// // we can get a `semeion::Error` from any of the public APIs
52    /// let err = semeion::Error::with_err(MyError::Audio);
53    ///
54    /// // and downcast it back to its original concrete type with
55    /// if let semeion::Error::Any(err) = err {
56    ///     let my_err = err.as_any().downcast_ref::<MyError>().unwrap();
57    /// }
58    /// ```
59    Any(Box<dyn Any + Send>),
60}
61
62impl fmt::Display for Error {
63    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64        match self {
65            Self::Unknown => write!(f, "Error unknown"),
66            Self::Code(code) => write!(f, "{}", code),
67            Self::Message(message) => write!(f, "{}", message),
68            Self::Any(err) => write!(f, "{}", err),
69        }
70    }
71}
72
73impl std::error::Error for Error {}
74
75impl Error {
76    /// Constructs a new Error with the given message.
77    pub fn with_message(message: impl Display) -> Self {
78        Self::Message(message.to_string())
79    }
80
81    /// Constructs a new Error with the given custom value.
82    pub fn with_err(err: impl Any + Send + 'static) -> Self {
83        Self::Any(Box::new(err))
84    }
85}