use std::{
any::Any,
fmt,
sync::{Arc, Mutex, MutexGuard, PoisonError},
};
use tokio::sync::mpsc;
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum SendError<E = ()> {
ActorNotRunning(E),
ActorStopped,
}
impl<E> SendError<E> {
pub fn reset(self) -> SendError<()> {
match self {
SendError::ActorNotRunning(_) => SendError::ActorNotRunning(()),
SendError::ActorStopped => SendError::ActorStopped,
}
}
}
impl<E> fmt::Debug for SendError<E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SendError::ActorNotRunning(_) => {
write!(f, "ActorNotRunning")
}
SendError::ActorStopped => write!(f, "ActorStopped"),
}
}
}
impl<E> fmt::Display for SendError<E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SendError::ActorNotRunning(_) => write!(f, "actor not running"),
SendError::ActorStopped => write!(f, "actor stopped"),
}
}
}
impl<T> From<mpsc::error::SendError<T>> for SendError<T> {
fn from(err: mpsc::error::SendError<T>) -> Self {
SendError::ActorNotRunning(err.0)
}
}
impl<E> std::error::Error for SendError<E> {}
#[derive(Clone)]
#[allow(missing_debug_implementations)]
pub struct PanicErr(Arc<Mutex<Box<dyn Any + Send>>>);
impl PanicErr {
pub fn new<E>(err: E) -> Self
where
E: Send + 'static,
{
PanicErr(Arc::new(Mutex::new(Box::new(err))))
}
pub fn new_boxed(err: Box<dyn Any + Send>) -> Self {
PanicErr(Arc::new(Mutex::new(err)))
}
pub fn with_str<F, R>(
&self,
f: F,
) -> Result<Option<R>, PoisonError<MutexGuard<'_, Box<dyn Any + Send>>>>
where
F: FnOnce(&str) -> R,
{
self.with(|any| {
any.downcast_ref::<&'static str>()
.copied()
.or_else(|| any.downcast_ref::<String>().map(String::as_str))
.map(|s| f(s))
})
}
pub fn with_downcast_ref<T, F, R>(
&self,
f: F,
) -> Result<Option<R>, PoisonError<MutexGuard<'_, Box<dyn Any + Send>>>>
where
T: 'static,
F: FnOnce(&T) -> R,
{
let lock = self.0.lock()?;
Ok(lock.downcast_ref().map(f))
}
pub fn with<F, R>(&self, f: F) -> Result<R, PoisonError<MutexGuard<'_, Box<dyn Any + Send>>>>
where
F: FnOnce(&Box<dyn Any + Send>) -> R,
{
let lock = self.0.lock()?;
Ok(f(&lock))
}
}