use super::types::{ValidationError, ValidationResult};
use super::version::SpecVersion;
use colored::*;
use serde::{Deserialize, Serialize};
use std::time::Duration;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidationReport {
pub spec_version: SpecVersion,
#[serde(flatten)]
pub results: ValidationResult,
pub duration: Duration,
pub levels_checked: Vec<String>,
}
impl ValidationReport {
pub fn new(spec_version: SpecVersion) -> Self {
Self {
spec_version,
results: ValidationResult::new(),
duration: Duration::from_secs(0),
levels_checked: Vec::new(),
}
}
pub fn is_valid(&self) -> bool {
self.results.is_valid()
}
pub fn has_warnings(&self) -> bool {
self.results.has_warnings()
}
pub fn error_count(&self) -> usize {
self.results.error_count()
}
pub fn warning_count(&self) -> usize {
self.results.warning_count()
}
pub fn errors(&self) -> &[ValidationError] {
&self.results.errors
}
pub fn warnings(&self) -> &[ValidationError] {
&self.results.warnings
}
pub fn merge_results(&mut self, results: ValidationResult) {
self.results.merge(results);
}
pub fn display(&self) {
println!("đ {} Validation Report", "OpenAPI".bright_cyan());
println!(
"đ Version: {}",
self.spec_version.to_string().bright_blue()
);
println!("âąī¸ Duration: {}ms", self.duration.as_millis());
println!("đ Levels checked: {}", self.levels_checked.join(", "));
println!();
if self.is_valid() && !self.has_warnings() {
println!("{} Specification is valid!", "â
".green());
return;
}
if !self.results.errors.is_empty() {
println!("{} {} found:", "â".red(), "Errors".red());
for error in &self.results.errors {
println!(" {} {}", "âĸ".red(), error.message);
if let Some(path) = &error.path {
println!(" {} {}", "at".dimmed(), path.dimmed());
}
if let Some(line) = error.line {
println!(
" {} line {}, column {}",
"at".dimmed(),
line.to_string().dimmed(),
error.column.unwrap_or(0).to_string().dimmed()
);
}
}
println!();
}
if !self.results.warnings.is_empty() {
println!("{} {} found:", "â ī¸".yellow(), "Warnings".yellow());
for warning in &self.results.warnings {
println!(" {} {}", "âĸ".yellow(), warning.message);
if let Some(path) = &warning.path {
println!(" {} {}", "at".dimmed(), path.dimmed());
}
}
println!();
}
if !self.results.info.is_empty() {
println!("{} {} found:", "âšī¸".blue(), "Information".blue());
for info in &self.results.info {
println!(" {} {}", "âĸ".blue(), info.message);
if let Some(path) = &info.path {
println!(" {} {}", "at".dimmed(), path.dimmed());
}
}
println!();
}
let error_text = if self.error_count() == 1 {
"error"
} else {
"errors"
};
let warning_text = if self.warning_count() == 1 {
"warning"
} else {
"warnings"
};
println!(
"đ Summary: {} {}, {} {}",
self.error_count().to_string().red(),
error_text,
self.warning_count().to_string().yellow(),
warning_text
);
}
}