#![deny(missing_docs)]
#![deny(warnings)]
pub mod error;
mod report;
pub mod schema;
use either::Either;
use serde_json::Value;
use std::{collections, fmt};
pub use report::ValidationReport;
type RefResolver<'a> = &'a dyn Fn(&str) -> Option<Value>;
type Schemas = collections::HashMap<schema::common::id::Id, Value>;
pub fn validate(instance: &Value, schema: Value) -> ValidationReport {
validate_with_resolver(instance, schema, None, None)
}
pub fn validate_with_resolver(
instance: &Value,
schema: Value,
pointer: Option<&str>,
ref_resolver: Option<RefResolver>,
) -> ValidationReport {
let validable_schema = schema::common::ref_::get_schema(&schema, None, pointer);
match validable_schema {
Either::Left((validable_schema, parent_id)) => {
let parent_id = parent_id.as_ref();
let absolute_schemas = validable_schema.get_schemas(parent_id, true);
let mut relative_schemas = validable_schema.get_schemas(parent_id, false);
relative_schemas.insert(schema::common::id::Id::Relative(String::new()), schema);
let ref_resolver = ref_resolver.unwrap_or(&schema::common::ref_::resolve_ref);
let mut state = schema::common::state::State {
absolute_schemas,
ref_resolver,
};
validable_schema.validate(instance, &mut state, &relative_schemas, parent_id)
}
Either::Right(err) => ValidationReport {
errors: Some(vec![err]),
..Default::default()
},
}
}
trait Validable: fmt::Debug {
fn get_schemas(&self, parent_id: Option<&schema::common::id::Id>, is_absolute: bool)
-> Schemas;
fn validate(
&self,
instance: &Value,
state: &mut schema::common::state::State,
relative_schemas: &Schemas,
parent_id: Option<&schema::common::id::Id>,
) -> ValidationReport;
}
#[cfg(test)]
mod tests {
use super::*;
pub(crate) fn assert_validate(
instance: Value,
schema: Value,
errors: Option<error::ValidationErrors>,
) {
let actual = validate(&instance, schema);
let expected = ValidationReport {
errors,
ids: actual.ids.clone(),
evaluated: actual.evaluated.clone(),
};
assert_eq!(actual, expected);
}
}