use std::{error::Error as StdError, fmt};
use jsonschema::{ValidationError, Validator};
use serde_json::Value;
#[derive(Debug)]
pub struct ValidationIssue {
error: ValidationError<'static>,
}
impl ValidationIssue {
#[must_use]
pub fn instance_path(&self) -> &str {
self.error.instance_path().as_str()
}
#[must_use]
pub fn schema_path(&self) -> &str {
self.error.schema_path().as_str()
}
}
impl fmt::Display for ValidationIssue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.error.fmt(f)
}
}
#[derive(Debug)]
pub struct ValidationErrors {
issues: Vec<ValidationIssue>,
}
impl ValidationErrors {
#[must_use]
pub fn issues(&self) -> &[ValidationIssue] {
&self.issues
}
pub(crate) fn check(validator: &Validator, input: &Value) -> Result<(), Self> {
let issues: Vec<_> = validator
.iter_errors(input)
.map(|error| ValidationIssue {
error: error.to_owned(),
})
.collect();
if issues.is_empty() {
Ok(())
} else {
Err(Self { issues })
}
}
}
impl fmt::Display for ValidationErrors {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} JSON Schema validation failure(s)", self.issues.len())
}
}
impl StdError for ValidationErrors {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
self.issues
.first()
.map(|issue| &issue.error as &(dyn StdError + 'static))
}
}