use crate::schema::Schema;
use crate::vm::validate;
use failure::Error;
use json_pointer::JsonPointer;
use std::borrow::Cow;
#[derive(Debug, Default, Eq, PartialEq, Clone, Hash)]
pub struct Validator {
config: Config,
}
impl Validator {
pub fn new() -> Self {
Self::new_with_config(Config::default())
}
pub fn new_with_config(config: Config) -> Self {
Self { config }
}
pub fn validate<'a>(
&self,
schema: &'a Schema,
instance: &'a serde_json::Value,
) -> Result<Vec<ValidationError<'a>>, Error> {
validate(
self.config.max_errors,
self.config.max_depth,
schema,
instance,
)
}
}
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub struct Config {
max_errors: usize,
max_depth: usize,
}
impl Config {
pub fn new() -> Self {
Self::default()
}
pub fn max_errors(&mut self, max_errors: usize) -> &mut Self {
self.max_errors = max_errors;
self
}
pub fn max_depth(&mut self, max_depth: usize) -> &mut Self {
self.max_depth = max_depth;
self
}
}
impl Default for Config {
fn default() -> Self {
Self {
max_errors: 0,
max_depth: 32,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ValidationError<'a> {
instance_path: JsonPointer<Cow<'a, str>, Vec<Cow<'a, str>>>,
schema_path: JsonPointer<Cow<'a, str>, Vec<Cow<'a, str>>>,
}
impl<'a> ValidationError<'a> {
pub fn new(
instance_path: JsonPointer<Cow<'a, str>, Vec<Cow<'a, str>>>,
schema_path: JsonPointer<Cow<'a, str>, Vec<Cow<'a, str>>>,
) -> ValidationError<'a> {
ValidationError {
instance_path,
schema_path,
}
}
pub fn instance_path(&self) -> &JsonPointer<Cow<'a, str>, Vec<Cow<'a, str>>> {
&self.instance_path
}
pub fn schema_path(&self) -> &JsonPointer<Cow<'a, str>, Vec<Cow<'a, str>>> {
&self.schema_path
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::schema::Schema;
use serde_json::json;
#[test]
fn infinite_loop() -> Result<(), Error> {
let validator = Validator::new();
assert!(validator
.validate(
&Schema::from_serde(serde_json::from_value(json!({
"definitions": {
"a": { "ref": "a" },
},
"ref": "a",
}))?)?,
&json!({})
)
.is_err());
Ok(())
}
#[test]
fn max_errors() -> Result<(), Error> {
let mut config = Config::new();
config.max_errors(3);
let validator = Validator::new_with_config(config);
assert_eq!(
validator
.validate(
&Schema::from_serde(serde_json::from_value(json!({
"elements": { "type": "string" },
}))?)?,
&json!([null, null, null, null, null,])
)
.unwrap()
.len(),
3
);
Ok(())
}
}