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