mod issue;
mod problem;
mod shortcut;
mod toissue;
use std::process::{
Termination,
ExitCode
};
use core::default::Default;
pub use toissue::ToIssue;
pub use issue::Issue;
use problem::Problem;
use crate::terminal::TERMINAL;
use shortcut::Attachment;
pub struct Report<Object: ToIssue> {
problems: Vec<Problem<Object>>
}
impl<Object: ToIssue> const Default for Report<Object> {
fn default() -> Self {return Self {
problems: Vec::new()
}}
}
impl<Object: ToIssue> Report<Object> {
#[inline]
pub fn warn(&mut self, object: Object) -> () {
TERMINAL.write().error(object.to_issue());
self.problems.push(Problem::new(object));
}
#[inline]
pub unsafe fn abort<Type>(self) -> Act<Type, Object> {return Act {
problems: self.problems,
result: None
}}
#[inline]
pub fn fail<Type>(mut self, with: Object) -> Act<Type, Object> {
TERMINAL.write().error(with.to_issue());
self.problems.push(Problem::new(with));
return Act {
problems: self.problems,
result: None
}
}
#[inline]
pub fn succeed<Type>(self, value: Type) -> Act<Type, Object> {return Act {
problems: self.problems,
result: Some(value)
}}
#[inline]
pub fn attach<'valid, Inferior>(&'valid mut self, act: Act<Inferior, Object>) -> Attachment<'valid, Inferior, Object> {
self.problems.extend(act.problems);
self.problems.sort_by(|first, second| first.at.cmp(&second.at));
return Attachment {
report: Some(self),
result: act.result
}
}
}
pub struct Act<Type, Object: ToIssue> {
problems: Vec<Problem<Object>>,
pub result: Option<Type>
}
impl<Object: ToIssue> Termination for Act<(), Object> {
fn report(self) -> ExitCode {return match self.result {
Some(()) => ExitCode::SUCCESS,
None => self.problems.last().unwrap().object.to_issue().code
}}
}