use edifact_rs::{ValidationIssue, ValidationSeverity};
use crate::DvgwMessageType;
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
#[non_exhaustive]
pub struct DvgwIssue {
pub severity: &'static str,
pub message: String,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub rule_id: Option<String>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub segment_tag: Option<String>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub offset: Option<usize>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub byte_end: Option<usize>,
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
pub suggestion: Option<String>,
}
impl From<ValidationIssue> for DvgwIssue {
fn from(issue: ValidationIssue) -> Self {
let severity = match issue.severity {
ValidationSeverity::Critical | ValidationSeverity::Error => "error",
ValidationSeverity::Warning => "warning",
_ => "info",
};
let rule_id = issue.rule_id().map(str::to_owned);
let segment_tag = issue.segment_tag().map(str::to_owned);
let offset = issue.span().map(|s| s.start);
let byte_end = issue.span().map(|s| s.end);
let suggestion = issue.suggestion().map(str::to_owned);
Self {
severity,
message: issue.message,
rule_id,
segment_tag,
offset,
byte_end,
suggestion,
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
#[non_exhaustive]
pub struct DvgwReport {
pub message_type: DvgwMessageType,
pub message_ref: String,
pub issues: Vec<DvgwIssue>,
}
impl DvgwReport {
pub(crate) fn new(
message_type: DvgwMessageType,
message_ref: String,
issues: Vec<ValidationIssue>,
) -> Self {
Self {
message_type,
message_ref,
issues: issues.into_iter().map(DvgwIssue::from).collect(),
}
}
#[must_use]
pub fn is_valid(&self) -> bool {
self.issues.iter().all(|i| i.severity != "error")
}
pub fn result(self) -> Result<Self, Self> {
if self.is_valid() { Ok(self) } else { Err(self) }
}
pub fn errors(&self) -> impl Iterator<Item = &DvgwIssue> {
self.issues.iter().filter(|i| i.severity == "error")
}
pub fn warnings(&self) -> impl Iterator<Item = &DvgwIssue> {
self.issues.iter().filter(|i| i.severity == "warning")
}
}