use std::fmt::Display;
use log::debug;
use saphyr::AnnotatedMapping;
use saphyr::MarkedYaml;
use saphyr::YamlData;
use crate::Context;
use crate::Result;
use crate::Validator;
use crate::YamlSchema;
#[derive(Debug, PartialEq)]
pub struct NotSchema {
pub not: Box<YamlSchema>,
}
impl Display for NotSchema {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "not: {}", self.not)
}
}
impl<'r> TryFrom<&MarkedYaml<'r>> for NotSchema {
type Error = crate::Error;
fn try_from(value: &MarkedYaml<'r>) -> Result<Self> {
if let YamlData::Mapping(mapping) = &value.data {
NotSchema::try_from(mapping)
} else {
Err(expected_mapping!(value))
}
}
}
impl<'r> TryFrom<&AnnotatedMapping<'r, MarkedYaml<'r>>> for NotSchema {
type Error = crate::Error;
fn try_from(mapping: &AnnotatedMapping<'r, MarkedYaml<'r>>) -> crate::Result<Self> {
if let Some(value) = mapping.get(&MarkedYaml::value_from_str("not")) {
let schema: YamlSchema = value.try_into()?;
Ok(NotSchema {
not: Box::new(schema),
})
} else {
Err(generic_error!("No `not` key found!"))
}
}
}
impl Validator for NotSchema {
fn validate(&self, context: &Context, value: &saphyr::MarkedYaml) -> crate::Result<()> {
debug!(
"Not: Validating value: {:?} against schema: {}",
value, self.not
);
let sub_context = context.get_sub_context();
let sub_result = self.not.validate(&sub_context, value);
match sub_result {
Ok(()) | Err(crate::Error::FailFast) => {
if !sub_context.has_errors() {
context.add_error(value, "Value matches schema in `not`");
fail_fast!(context);
}
}
Err(e) => return Err(e),
}
Ok(())
}
}