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}