use std::fmt;
use super::errors::JobHandleError;
use super::traits::JobResult;
#[derive(strum::Display)]
pub enum JobCompletion {
Finished(Box<dyn JobResult>),
Cancelled,
Panicked(Box<dyn std::any::Any + Send + 'static>),
}
impl fmt::Debug for JobCompletion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
JobCompletion::Finished(result) => {
if let Some(debuggable) = result
.as_any()
.downcast_ref::<Box<dyn fmt::Debug + Send + Sync>>()
{
write!(f, "Finished({:?})", debuggable)
} else {
write!(f, "Finished(Box<dyn JobResult>)")
}
}
JobCompletion::Cancelled => write!(f, "Cancelled"),
JobCompletion::Panicked(_) => write!(f, "Panicked(<payload>)"),
}
}
}
impl<T: JobResult> From<T> for JobCompletion {
fn from(result: T) -> Self {
Self::Finished(Box::new(result))
}
}
impl TryFrom<JobCompletion> for Box<dyn JobResult> {
type Error = JobHandleError;
fn try_from(jc: JobCompletion) -> Result<Self, Self::Error> {
jc.result()
}
}
impl JobCompletion {
pub fn result(self) -> Result<Box<dyn JobResult>, JobHandleError> {
match self {
JobCompletion::Finished(r) => Ok(r),
JobCompletion::Cancelled => Err(JobHandleError::JobCancelled),
JobCompletion::Panicked(e) => Err(e.into()),
}
}
pub fn result_ref(&self) -> Option<&dyn JobResult> {
match self {
JobCompletion::Finished(r) => Some(&**r),
_ => None,
}
}
pub fn unwrap(self) -> Box<dyn JobResult> {
self.result()
.unwrap_or_else(|e| panic!("Job did not finish. no result available. {}", e))
}
pub fn finished(&self) -> bool {
match self {
JobCompletion::Finished(_) => true,
JobCompletion::Cancelled => false,
JobCompletion::Panicked(_) => false,
}
}
pub fn unwrap_err(self) -> JobHandleError {
self.err()
.unwrap_or_else(|| panic!("Job finished. no error available"))
}
pub fn err(self) -> Option<JobHandleError> {
self.result().err()
}
}