use crate::diagnostic::Diagnostic;
#[derive(Debug, Clone)]
pub struct Outcome<T> {
pub value: T,
pub diagnostics: Vec<Diagnostic>,
}
impl<T> Outcome<T> {
pub fn new(value: T) -> Self {
Self {
value,
diagnostics: Vec::new(),
}
}
pub fn with_diagnostics(value: T, diagnostics: Vec<Diagnostic>) -> Self {
Self { value, diagnostics }
}
pub fn into_value(self) -> T {
self.value
}
pub fn has_errors(&self) -> bool {
self.diagnostics
.iter()
.any(|d| d.severity == crate::diagnostic::Severity::Error)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::diagnostic::Diagnostic;
#[test]
fn new_has_no_diagnostics() {
let outcome = Outcome::new(42);
assert_eq!(outcome.value, 42);
assert!(outcome.diagnostics.is_empty());
assert!(!outcome.has_errors());
}
#[test]
fn has_errors_detects_error_severity() {
let outcome = Outcome::with_diagnostics((), vec![Diagnostic::warning("just a warning")]);
assert!(!outcome.has_errors());
let outcome = Outcome::with_diagnostics((), vec![Diagnostic::error("a real error")]);
assert!(outcome.has_errors());
let outcome = Outcome::with_diagnostics((), vec![Diagnostic::hint("a hint")]);
assert!(!outcome.has_errors());
}
#[test]
fn into_value_discards_diagnostics() {
let outcome = Outcome::with_diagnostics("hello", vec![Diagnostic::hint("hint")]);
assert_eq!(outcome.into_value(), "hello");
}
}