use std::error::Error;
use std::fmt;
#[derive(Debug)]
pub struct ListenerError(Box<dyn Error + Send + Sync + 'static>);
impl ListenerError {
pub fn new<E>(error: E) -> Self
where
E: Error + Send + Sync + 'static,
{
Self(Box::new(error))
}
pub fn message<S: Into<String>>(msg: S) -> Self {
Self(msg.into().into())
}
#[must_use]
pub fn inner(&self) -> &(dyn Error + Send + Sync + 'static) {
self.0.as_ref()
}
#[must_use]
pub fn into_inner(self) -> Box<dyn Error + Send + Sync + 'static> {
self.0
}
}
impl fmt::Display for ListenerError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}
impl Error for ListenerError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
Some(self.0.as_ref())
}
}
impl From<Box<dyn Error + Send + Sync + 'static>> for ListenerError {
fn from(boxed: Box<dyn Error + Send + Sync + 'static>) -> Self {
Self(boxed)
}
}
impl From<&str> for ListenerError {
fn from(s: &str) -> Self {
Self::message(s)
}
}
impl From<String> for ListenerError {
fn from(s: String) -> Self {
Self::message(s)
}
}
pub(crate) fn panic_payload_to_listener_error(
payload: Box<dyn std::any::Any + Send>,
) -> ListenerError {
let detail = if let Some(s) = payload.downcast_ref::<&'static str>() {
(*s).to_owned()
} else if let Some(s) = payload.downcast_ref::<String>() {
s.clone()
} else {
String::from("<non-string panic payload>")
};
ListenerError::message(format!("listener panicked: {detail}"))
}