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))
}
}