hypertask_engine 0.2.0

The core logic engine used to run hypertask
Documentation
use std::error::Error;
use std::fmt;

#[derive(Debug)]
pub enum HyperTaskErrorDomain {
    Config,
    Context,
    Input,
    Mutation,
    Query,
    ScoreCalculator,
    Task,
}

impl fmt::Display for HyperTaskErrorDomain {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "{}",
            match self {
                HyperTaskErrorDomain::Config => "config",
                HyperTaskErrorDomain::Context => "context",
                HyperTaskErrorDomain::Input => "input",
                HyperTaskErrorDomain::Mutation => "mutation",
                HyperTaskErrorDomain::Query => "query",
                HyperTaskErrorDomain::ScoreCalculator => "scoreCalculator",
                HyperTaskErrorDomain::Task => "task",
            }
        )
    }
}

#[derive(Debug)]
pub enum HyperTaskErrorAction {
    Create,
    Delete,
    Parse,
    Read,
    Run,
    Write,
}

impl fmt::Display for HyperTaskErrorAction {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "{}",
            match self {
                HyperTaskErrorAction::Create => "create",
                HyperTaskErrorAction::Delete => "delete",
                HyperTaskErrorAction::Parse => "parse",
                HyperTaskErrorAction::Read => "read",
                HyperTaskErrorAction::Run => "run",
                HyperTaskErrorAction::Write => "write",
            }
        )
    }
}

#[derive(Debug)]
pub struct HyperTaskError {
    domain: HyperTaskErrorDomain,
    action: HyperTaskErrorAction,
    meta: Option<String>,
    source: Option<Box<dyn Error + 'static>>,
}

pub type HyperTaskResult<T> = Result<T, HyperTaskError>;

impl HyperTaskError {
    pub fn new(domain: HyperTaskErrorDomain, action: HyperTaskErrorAction) -> Self {
        Self {
            domain,
            action,
            meta: None,
            source: None,
        }
    }

    pub fn msg(mut self, meta: &'static str) -> Self {
        self.meta = Some(meta.to_owned());
        self
    }

    pub fn with_msg<F: Fn() -> String>(mut self, meta_factory: F) -> Self {
        self.meta = Some(meta_factory());
        self
    }

    pub fn from<E: 'static + Error>(mut self, source: E) -> Self {
        self.source = Some(Box::new(source));
        self
    }
}

impl fmt::Display for HyperTaskError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "HyperTaskError[{}::{}]", self.domain, self.action)?;

        if let Some(meta_text) = &self.meta {
            write!(f, ": {}", meta_text)?
        }

        Ok(())
    }
}

impl Error for HyperTaskError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        if let Some(source_box) = &self.source {
            Some(source_box.as_ref())
        } else {
            None
        }
    }
}

impl From<HyperTaskError> for String {
    fn from(error: HyperTaskError) -> Self {
        format!("{}", error)
    }
}

pub fn print_error_chain(err: &(dyn Error + 'static)) {
    print_error_chain_recursive(err, 1)
}

pub fn print_error_chain_recursive(err: &(dyn Error + 'static), i: u32) {
    println!("Error {}: {}", i, err);

    if let Some(boxed_source) = err.source() {
        print_error_chain_recursive(boxed_source, i + 1);
    }
}