chore: Replace `ValidationError::schema` with custom errors

* Replace ValidationError::schema with custom errors

* Fix cargo fmt

* Remove ValidationError::schema function

* Update changelog

* Fix ErrorValidation arguments

Signed-off-by: Maxim Zhiburt <zhiburt@gmail.com>

* Fix more ValidationError calls

Signed-off-by: Maxim Zhiburt <zhiburt@gmail.com>

* Fix issues found in PR

Co-authored-by: dmitry.dygalo <dadygalo@gmail.com>
Signed-off-by: Maxim Zhiburt <zhiburt@gmail.com>

* Fix issues found

Signed-off-by: Maxim Zhiburt <zhiburt@gmail.com>
Co-Authored-by: dmitry.dygalo <dadygalo@gmail.com>

Co-authored-by: dmitry.dygalo <dadygalo@gmail.com>
This commit is contained in:
Maxim Zhiburt 2021-10-06 09:59:54 +03:00 committed by GitHub
parent aaadd99b2c
commit 57c9bca007
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 923 additions and 92 deletions

View File

@ -15,6 +15,7 @@
- **INTERNAL**. A new `Draft201909` variant for the `Draft` enum that is available only under the `draft201909` feature. This feature is considered private and should not be used outside of the testing context.
It allows us to add features from the 2019-09 Draft without exposing them in the public API. Therefore, support for this draft can be added incrementally.
- The `Draft` enum is now marked as `non_exhaustive`.
- `ValidationError::schema` was removed and the calls replaced by proper errors.
### Fixed

565
bench_helpers/Cargo.lock generated
View File

@ -2,30 +2,447 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bench_helpers"
version = "0.1.0"
dependencies = [
"criterion",
"serde",
"serde_json",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bstr"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
dependencies = [
"lazy_static",
"memchr",
"regex-automata",
"serde",
]
[[package]]
name = "bumpalo"
version = "3.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9df67f7bf9ef8498769f994239c45613ef0c5899415fb58e9add412d2c1a538"
[[package]]
name = "cast"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a"
dependencies = [
"rustc_version",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "2.33.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
dependencies = [
"bitflags",
"textwrap",
"unicode-width",
]
[[package]]
name = "criterion"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10"
dependencies = [
"atty",
"cast",
"clap",
"criterion-plot",
"csv",
"itertools",
"lazy_static",
"num-traits",
"oorandom",
"plotters",
"rayon",
"regex",
"serde",
"serde_cbor",
"serde_derive",
"serde_json",
"tinytemplate",
"walkdir",
]
[[package]]
name = "criterion-plot"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57"
dependencies = [
"cast",
"itertools",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
dependencies = [
"cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd"
dependencies = [
"cfg-if",
"crossbeam-utils",
"lazy_static",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
dependencies = [
"cfg-if",
"lazy_static",
]
[[package]]
name = "csv"
version = "1.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1"
dependencies = [
"bstr",
"csv-core",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "csv-core"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
dependencies = [
"memchr",
]
[[package]]
name = "either"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "half"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3"
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "itertools"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
[[package]]
name = "js-sys"
version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"
[[package]]
name = "log"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]]
name = "memoffset"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
dependencies = [
"autocfg",
]
[[package]]
name = "num-traits"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "oorandom"
version = "11.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
[[package]]
name = "plotters"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a"
dependencies = [
"num-traits",
"plotters-backend",
"plotters-svg",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "plotters-backend"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c"
[[package]]
name = "plotters-svg"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "521fa9638fa597e1dc53e9412a4f9cefb01187ee1f7413076f9e6749e2885ba9"
dependencies = [
"plotters-backend",
]
[[package]]
name = "proc-macro2"
version = "1.0.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rayon"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
dependencies = [
"autocfg",
"crossbeam-deque",
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
"lazy_static",
"num_cpus",
]
[[package]]
name = "regex"
version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
[[package]]
name = "regex-syntax"
version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "rustc_version"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [
"semver",
]
[[package]]
name = "ryu"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "semver"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012"
[[package]]
name = "serde"
version = "1.0.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_cbor"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5"
dependencies = [
"half",
"serde",
]
[[package]]
name = "serde_derive"
version = "1.0.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
@ -37,3 +454,151 @@ dependencies = [
"ryu",
"serde",
]
[[package]]
name = "syn"
version = "1.0.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5239bc68e0fef57495900cfea4e8dc75596d9a319d7e16b1e0a440d24e6fe0a0"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]]
name = "tinytemplate"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "unicode-width"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "walkdir"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
dependencies = [
"same-file",
"winapi",
"winapi-util",
]
[[package]]
name = "wasm-bindgen"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b"
dependencies = [
"bumpalo",
"lazy_static",
"log",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc"
[[package]]
name = "web-sys"
version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View File

@ -5,8 +5,14 @@ pub(crate) mod context;
pub(crate) mod options;
use crate::{
error::ErrorIterator, keywords, paths::InstancePath, resolver::Resolver,
schema_node::SchemaNode, validator::Validate, Draft, Output, ValidationError,
error::ErrorIterator,
keywords,
paths::{InstancePath, JSONPointer},
primitive_type::{PrimitiveType, PrimitiveTypesBitMap},
resolver::Resolver,
schema_node::SchemaNode,
validator::Validate,
Draft, Output, ValidationError,
};
use ahash::AHashMap;
use context::CompilationContext;
@ -169,7 +175,12 @@ pub(crate) fn compile_validators<'a, 'c>(
Some(unmatched_keywords),
))
} else {
Err(ValidationError::schema(schema))
Err(ValidationError::single_type_error(
JSONPointer::default(),
relative_path,
reference,
PrimitiveType::String,
))
}
} else {
let mut validators = Vec::with_capacity(object.len());
@ -218,7 +229,14 @@ pub(crate) fn compile_validators<'a, 'c>(
))
}
}
_ => Err(ValidationError::schema(schema)),
_ => Err(ValidationError::multiple_type_error(
JSONPointer::default(),
relative_path,
schema,
PrimitiveTypesBitMap::new()
.add_type(PrimitiveType::Boolean)
.add_type(PrimitiveType::Object),
)),
}
}

View File

@ -656,15 +656,6 @@ impl<'a> ValidationError<'a> {
}
}
pub(crate) fn schema(instance: &'a Value) -> ValidationError<'a> {
ValidationError {
instance_path: JSONPointer::default(),
instance: Cow::Borrowed(instance),
kind: ValidationErrorKind::Schema,
schema_path: JSONPointer::default(),
}
}
pub(crate) fn null_schema() -> ValidationError<'a> {
ValidationError {
instance_path: JSONPointer::default(),

View File

@ -3,6 +3,7 @@ use crate::{
error::{error, no_error, ErrorIterator, ValidationError},
keywords::{boolean::FalseValidator, CompilationResult},
paths::{InstancePath, JSONPointer},
primitive_type::{PrimitiveType, PrimitiveTypesBitMap},
schema_node::SchemaNode,
validator::{format_validators, Validate},
};
@ -153,7 +154,15 @@ pub(crate) fn compile<'a>(
Some(FalseValidator::compile(schema_path))
}
}
_ => Some(Err(ValidationError::schema(schema))),
_ => Some(Err(ValidationError::multiple_type_error(
JSONPointer::default(),
context.clone().into_pointer(),
schema,
PrimitiveTypesBitMap::new()
.add_type(PrimitiveType::Object)
.add_type(PrimitiveType::Array)
.add_type(PrimitiveType::Boolean),
))),
}
} else {
None

View File

@ -1357,13 +1357,15 @@ fn compile_patterns<'a>(
for (pattern, subschema) in obj {
let pattern_context = keyword_context.with_path(pattern.to_string());
if let Ok(compiled_pattern) = Regex::new(pattern) {
if let Ok(node) = compile_validators(subschema, &pattern_context) {
compiled_patterns.push((compiled_pattern, node));
} else {
return Err(ValidationError::schema(subschema));
}
let node = compile_validators(subschema, &pattern_context)?;
compiled_patterns.push((compiled_pattern, node));
} else {
return Err(ValidationError::schema(subschema));
return Err(ValidationError::format(
JSONPointer::default(),
keyword_context.clone().into_pointer(),
subschema,
"regex",
));
}
}
Ok(compiled_patterns)

View File

@ -2,7 +2,8 @@ use crate::{
compilation::{compile_validators, context::CompilationContext, JSONSchema},
error::{ErrorIterator, ValidationError},
output::BasicOutput,
paths::InstancePath,
paths::{InstancePath, JSONPointer},
primitive_type::PrimitiveType,
schema_node::SchemaNode,
validator::{format_iter_of_validators, format_validators, PartialApplication, Validate},
};
@ -136,7 +137,12 @@ pub(crate) fn compile<'a>(
Some(AllOfValidator::compile(items, context))
}
} else {
Some(Err(ValidationError::schema(schema)))
Some(Err(ValidationError::single_type_error(
JSONPointer::default(),
context.clone().into_pointer(),
schema,
PrimitiveType::Array,
)))
}
}

View File

@ -2,6 +2,7 @@ use crate::{
compilation::{compile_validators, context::CompilationContext, JSONSchema},
error::{error, no_error, ErrorIterator, ValidationError},
paths::InstancePath,
primitive_type::PrimitiveType,
schema_node::SchemaNode,
validator::{format_iter_of_validators, PartialApplication, Validate},
};
@ -34,7 +35,12 @@ impl AnyOfValidator {
schema_path: keyword_context.into_pointer(),
}))
} else {
Err(ValidationError::schema(schema))
Err(ValidationError::single_type_error(
JSONPointer::default(),
context.clone().into_pointer(),
schema,
PrimitiveType::Array,
))
}
}
}

View File

@ -3,12 +3,16 @@ use crate::{
error::{error, no_error, ErrorIterator, ValidationError},
keywords::CompilationResult,
paths::{InstancePath, JSONPointer},
primitive_type::PrimitiveType,
schema_node::SchemaNode,
validator::{format_validators, PartialApplication, Validate},
Draft,
};
use serde_json::{Map, Value};
#[cfg(feature = "draft201909")]
use super::helpers::map_get_u64;
pub(crate) struct ContainsValidator {
node: SchemaNode,
schema_path: JSONPointer,
@ -422,33 +426,22 @@ pub(crate) fn compile<'a>(
}
#[cfg(feature = "draft201909")]
Draft::Draft201909 => {
if let Some(min_contains) = parent.get("minContains") {
if let Some(min_contains) = min_contains.as_u64() {
if let Some(max_contains) = parent.get("maxContains") {
if let Some(max_contains) = max_contains.as_u64() {
Some(MinMaxContainsValidator::compile(
schema,
context,
min_contains,
max_contains,
))
} else {
Some(Err(ValidationError::schema(schema)))
}
} else {
Some(MinContainsValidator::compile(schema, context, min_contains))
}
} else {
Some(Err(ValidationError::schema(schema)))
let min_contains = match map_get_u64(parent, context, "minContains").transpose() {
Ok(n) => n,
Err(err) => return Some(Err(err)),
};
let max_contains = match map_get_u64(parent, context, "maxContains").transpose() {
Ok(n) => n,
Err(err) => return Some(Err(err)),
};
match (min_contains, max_contains) {
(Some(min), Some(max)) => {
Some(MinMaxContainsValidator::compile(schema, context, min, max))
}
} else if let Some(max_contains) = parent.get("maxContains") {
if let Some(max_contains) = max_contains.as_u64() {
Some(MaxContainsValidator::compile(schema, context, max_contains))
} else {
Some(Err(ValidationError::schema(schema)))
}
} else {
Some(ContainsValidator::compile(schema, context))
(Some(min), None) => Some(MinContainsValidator::compile(schema, context, min)),
(None, Some(max)) => Some(MaxContainsValidator::compile(schema, context, max)),
(None, None) => Some(ContainsValidator::compile(schema, context)),
}
}
}

View File

@ -6,6 +6,7 @@ use crate::{
error::{error, no_error, ErrorIterator, ValidationError},
keywords::CompilationResult,
paths::{InstancePath, JSONPointer},
primitive_type::PrimitiveType,
validator::Validate,
};
use serde_json::{Map, Value};
@ -246,7 +247,12 @@ pub(crate) fn compile_media_type<'a>(
context.schema_path.clone().into(),
))
}
_ => Some(Err(ValidationError::schema(subschema))),
_ => Some(Err(ValidationError::single_type_error(
JSONPointer::default(),
context.clone().into_pointer(),
content_encoding,
PrimitiveType::String,
))),
}
} else {
Some(ContentMediaTypeValidator::compile(
@ -256,7 +262,12 @@ pub(crate) fn compile_media_type<'a>(
))
}
}
_ => Some(Err(ValidationError::schema(subschema))),
_ => Some(Err(ValidationError::single_type_error(
JSONPointer::default(),
context.clone().into_pointer(),
subschema,
PrimitiveType::String,
))),
}
}
@ -286,7 +297,12 @@ pub(crate) fn compile_content_encoding<'a>(
context.as_pointer_with("contentEncoding"),
))
}
_ => Some(Err(ValidationError::schema(subschema))),
_ => Some(Err(ValidationError::single_type_error(
JSONPointer::default(),
context.clone().into_pointer(),
subschema,
PrimitiveType::String,
))),
}
}

View File

@ -2,7 +2,8 @@ use crate::{
compilation::{compile_validators, context::CompilationContext, JSONSchema},
error::{no_error, ErrorIterator, ValidationError},
keywords::{required, CompilationResult},
paths::InstancePath,
paths::{InstancePath, JSONPointer},
primitive_type::PrimitiveType,
schema_node::SchemaNode,
validator::{format_key_value_validators, Validate},
};
@ -38,7 +39,12 @@ impl DependenciesValidator {
}
Ok(Box::new(DependenciesValidator { dependencies }))
} else {
Err(ValidationError::schema(schema))
Err(ValidationError::single_type_error(
JSONPointer::default(),
context.clone().into_pointer(),
schema,
PrimitiveType::Object,
))
}
}
}

View File

@ -153,7 +153,12 @@ pub(crate) fn compile<'a>(
Some(EnumValidator::compile(schema, items, schema_path))
}
} else {
Some(Err(ValidationError::schema(schema)))
Some(Err(ValidationError::single_type_error(
JSONPointer::default(),
context.clone().into_pointer(),
schema,
PrimitiveType::Array,
)))
}
}

View File

@ -3,6 +3,7 @@ use crate::{
error::{error, no_error, ErrorIterator, ValidationError},
keywords::CompilationResult,
paths::{InstancePath, JSONPointer},
primitive_type::PrimitiveType,
validator::Validate,
};
use num_cmp::NumCmp;
@ -140,7 +141,12 @@ pub(crate) fn compile<'a>(
})))
}
} else {
Some(Err(ValidationError::schema(schema)))
Some(Err(ValidationError::single_type_error(
JSONPointer::default(),
context.clone().into_pointer(),
schema,
PrimitiveType::Number,
)))
}
}

View File

@ -3,6 +3,7 @@ use crate::{
error::{error, no_error, ErrorIterator, ValidationError},
keywords::CompilationResult,
paths::{InstancePath, JSONPointer},
primitive_type::PrimitiveType,
validator::Validate,
};
use num_cmp::NumCmp;
@ -138,7 +139,12 @@ pub(crate) fn compile<'a>(
})))
}
} else {
Some(Err(ValidationError::schema(schema)))
Some(Err(ValidationError::single_type_error(
JSONPointer::default(),
context.clone().into_pointer(),
schema,
PrimitiveType::Number,
)))
}
}

View File

@ -12,6 +12,7 @@ use crate::{
error::{error, no_error, ErrorIterator, ValidationError},
keywords::{pattern, CompilationResult},
paths::{InstancePath, JSONPointer},
primitive_type::PrimitiveType,
validator::Validate,
Draft,
};
@ -488,7 +489,12 @@ pub(crate) fn compile<'a>(
_ => None,
}
} else {
Some(Err(ValidationError::schema(schema)))
Some(Err(ValidationError::single_type_error(
JSONPointer::default(),
context.clone().into_pointer(),
schema,
PrimitiveType::String,
)))
}
}

View File

@ -1,6 +1,11 @@
use num_cmp::NumCmp;
use serde_json::{Map, Value};
use crate::{
compilation::context::CompilationContext, paths::JSONPointer, primitive_type::PrimitiveType,
ValidationError,
};
macro_rules! num_cmp {
($left:expr, $right:expr) => {
if let Some(b) = $right.as_u64() {
@ -49,6 +54,30 @@ pub(crate) fn equal_objects(left: &Map<String, Value>, right: &Map<String, Value
.all(|((ka, va), (kb, vb))| ka == kb && equal(va, vb))
}
#[inline]
pub(crate) fn map_get_u64<'a>(
m: &'a Map<String, Value>,
context: &CompilationContext,
type_name: &str,
) -> Option<Result<u64, ValidationError<'a>>> {
let value = m.get(type_name)?;
match value.as_u64() {
Some(n) => Some(Ok(n)),
None if value.as_i64().is_some() => Some(Err(ValidationError::minimum(
JSONPointer::default(),
context.clone().into_pointer(),
value,
0.into(),
))),
None => Some(Err(ValidationError::single_type_error(
JSONPointer::default(),
context.clone().into_pointer(),
value,
PrimitiveType::Integer,
))),
}
}
#[cfg(test)]
mod tests {
use super::equal;

View File

@ -6,7 +6,7 @@ use crate::{
primitive_type::{PrimitiveType, PrimitiveTypesBitMap},
validator::Validate,
};
use serde_json::{Map, Number, Value};
use serde_json::{json, Map, Number, Value};
use std::convert::TryFrom;
pub(crate) struct MultipleTypesValidator {
@ -24,10 +24,24 @@ impl MultipleTypesValidator {
if let Ok(primitive_type) = PrimitiveType::try_from(string.as_str()) {
types |= primitive_type;
} else {
return Err(ValidationError::schema(item));
return Err(ValidationError::enumeration(
JSONPointer::default(),
schema_path,
item,
&json!([
"array", "boolean", "integer", "null", "number", "object", "string"
]),
));
}
}
_ => return Err(ValidationError::schema(item)),
_ => {
return Err(ValidationError::single_type_error(
JSONPointer::default(),
schema_path,
item,
PrimitiveType::String,
))
}
}
}
Ok(Box::new(MultipleTypesValidator { types, schema_path }))
@ -141,16 +155,29 @@ pub(crate) fn compile<'a>(
Value::String(item) => compile_single_type(item.as_str(), schema_path),
Value::Array(items) => {
if items.len() == 1 {
if let Some(Value::String(item)) = items.iter().next() {
let item = &items[0];
if let Value::String(item) = item {
compile_single_type(item.as_str(), schema_path)
} else {
Some(Err(ValidationError::schema(schema)))
Some(Err(ValidationError::single_type_error(
JSONPointer::default(),
schema_path,
item,
PrimitiveType::String,
)))
}
} else {
Some(MultipleTypesValidator::compile(items, schema_path))
}
}
_ => Some(Err(ValidationError::schema(schema))),
_ => Some(Err(ValidationError::multiple_type_error(
JSONPointer::default(),
context.clone().into_pointer(),
schema,
PrimitiveTypesBitMap::new()
.add_type(PrimitiveType::String)
.add_type(PrimitiveType::Array),
))),
}
}

View File

@ -18,7 +18,12 @@ impl MaxItemsValidator {
if let Some(limit) = schema.as_u64() {
Ok(Box::new(MaxItemsValidator { limit, schema_path }))
} else {
Err(ValidationError::schema(schema))
Err(ValidationError::format(
JSONPointer::default(),
schema_path,
schema,
"max_items int validation",
))
}
}
}

View File

@ -18,7 +18,12 @@ impl MaxLengthValidator {
if let Some(limit) = schema.as_u64() {
Ok(Box::new(MaxLengthValidator { limit, schema_path }))
} else {
Err(ValidationError::schema(schema))
Err(ValidationError::format(
JSONPointer::default(),
schema_path,
schema,
"max_length int validation",
))
}
}
}

View File

@ -18,7 +18,12 @@ impl MaxPropertiesValidator {
if let Some(limit) = schema.as_u64() {
Ok(Box::new(MaxPropertiesValidator { limit, schema_path }))
} else {
Err(ValidationError::schema(schema))
Err(ValidationError::format(
JSONPointer::default(),
schema_path,
schema,
"max_properties int validation",
))
}
}
}

View File

@ -3,6 +3,7 @@ use crate::{
error::{error, no_error, ErrorIterator, ValidationError},
keywords::CompilationResult,
paths::{InstancePath, JSONPointer},
primitive_type::PrimitiveType,
validator::Validate,
};
use num_cmp::NumCmp;
@ -138,7 +139,12 @@ pub(crate) fn compile<'a>(
})))
}
} else {
Some(Err(ValidationError::schema(schema)))
Some(Err(ValidationError::single_type_error(
JSONPointer::default(),
context.clone().into_pointer(),
schema,
PrimitiveType::Number,
)))
}
}

View File

@ -18,7 +18,12 @@ impl MinItemsValidator {
if let Some(limit) = schema.as_u64() {
Ok(Box::new(MinItemsValidator { limit, schema_path }))
} else {
Err(ValidationError::schema(schema))
Err(ValidationError::format(
JSONPointer::default(),
schema_path,
schema,
"min_length int validation",
))
}
}
}

View File

@ -18,7 +18,12 @@ impl MinLengthValidator {
if let Some(limit) = schema.as_u64() {
Ok(Box::new(MinLengthValidator { limit, schema_path }))
} else {
Err(ValidationError::schema(schema))
Err(ValidationError::format(
JSONPointer::default(),
schema_path,
schema,
"min_length int validation",
))
}
}
}

View File

@ -18,7 +18,12 @@ impl MinPropertiesValidator {
if let Some(limit) = schema.as_u64() {
Ok(Box::new(MinPropertiesValidator { limit, schema_path }))
} else {
Err(ValidationError::schema(schema))
Err(ValidationError::format(
JSONPointer::default(),
schema_path,
schema,
"min_properties int validation",
))
}
}
}

View File

@ -3,6 +3,7 @@ use crate::{
error::{error, no_error, ErrorIterator, ValidationError},
keywords::CompilationResult,
paths::{InstancePath, JSONPointer},
primitive_type::PrimitiveType,
validator::Validate,
};
use num_cmp::NumCmp;
@ -138,7 +139,12 @@ pub(crate) fn compile<'a>(
})))
}
} else {
Some(Err(ValidationError::schema(schema)))
Some(Err(ValidationError::single_type_error(
JSONPointer::default(),
context.clone().into_pointer(),
schema,
PrimitiveType::Number,
)))
}
}

View File

@ -3,6 +3,7 @@ use crate::{
error::{error, no_error, ErrorIterator, ValidationError},
keywords::CompilationResult,
paths::{InstancePath, JSONPointer},
primitive_type::PrimitiveType,
validator::Validate,
};
use fraction::{BigFraction, BigUint};
@ -139,7 +140,12 @@ pub(crate) fn compile<'a>(
Some(MultipleOfFloatValidator::compile(multiple_of, schema_path))
}
} else {
Some(Err(ValidationError::schema(schema)))
Some(Err(ValidationError::single_type_error(
JSONPointer::default(),
context.clone().into_pointer(),
schema,
PrimitiveType::Number,
)))
}
}

View File

@ -4,6 +4,7 @@ use crate::{
keywords::CompilationResult,
output::BasicOutput,
paths::{InstancePath, JSONPointer},
primitive_type::PrimitiveType,
schema_node::SchemaNode,
validator::{format_iter_of_validators, PartialApplication, Validate},
};
@ -33,7 +34,12 @@ impl OneOfValidator {
schema_path: keyword_context.into_pointer(),
}))
} else {
Err(ValidationError::schema(schema))
Err(ValidationError::single_type_error(
JSONPointer::default(),
context.clone().into_pointer(),
schema,
PrimitiveType::Array,
))
}
}

View File

@ -3,6 +3,7 @@ use crate::{
error::{error, no_error, ErrorIterator, ValidationError},
keywords::CompilationResult,
paths::InstancePath,
primitive_type::PrimitiveType,
validator::Validate,
};
use serde_json::{Map, Value};
@ -31,7 +32,14 @@ impl PatternValidator {
Value::String(item) => {
let pattern = match convert_regex(item) {
Ok(r) => r,
Err(_) => return Err(ValidationError::schema(pattern)),
Err(_) => {
return Err(ValidationError::format(
JSONPointer::default(),
context.clone().into_pointer(),
pattern,
"regex",
))
}
};
Ok(Box::new(PatternValidator {
original: item.clone(),
@ -39,7 +47,12 @@ impl PatternValidator {
schema_path: context.as_pointer_with("pattern"),
}))
}
_ => Err(ValidationError::schema(pattern)),
_ => Err(ValidationError::single_type_error(
JSONPointer::default(),
context.clone().into_pointer(),
pattern,
PrimitiveType::String,
)),
}
}
}

View File

@ -3,7 +3,8 @@ use crate::{
error::{no_error, ErrorIterator, ValidationError},
keywords::CompilationResult,
output::BasicOutput,
paths::InstancePath,
paths::{InstancePath, JSONPointer},
primitive_type::PrimitiveType,
schema_node::SchemaNode,
validator::{format_validators, PartialApplication, Validate},
};
@ -27,7 +28,14 @@ impl PatternPropertiesValidator {
patterns.push((
match Regex::new(pattern) {
Ok(r) => r,
Err(_) => return Err(ValidationError::schema(subschema)),
Err(_) => {
return Err(ValidationError::format(
JSONPointer::default(),
keyword_context.clone().into_pointer(),
subschema,
"regex",
))
}
},
compile_validators(subschema, &pattern_context)?,
));
@ -133,7 +141,14 @@ impl SingleValuePatternPropertiesValidator {
Ok(Box::new(SingleValuePatternPropertiesValidator {
pattern: match Regex::new(pattern) {
Ok(r) => r,
Err(_) => return Err(ValidationError::schema(schema)),
Err(_) => {
return Err(ValidationError::format(
JSONPointer::default(),
keyword_context.clone().into_pointer(),
schema,
"regex",
))
}
},
node: compile_validators(schema, &pattern_context)?,
}))
@ -229,7 +244,12 @@ pub(crate) fn compile<'a>(
Some(PatternPropertiesValidator::compile(map, context))
}
} else {
Some(Err(ValidationError::schema(schema)))
Some(Err(ValidationError::single_type_error(
JSONPointer::default(),
context.clone().into_pointer(),
schema,
PrimitiveType::Object,
)))
}
}
}

View File

@ -3,7 +3,8 @@ use crate::{
error::{no_error, ErrorIterator, ValidationError},
keywords::CompilationResult,
output::BasicOutput,
paths::InstancePath,
paths::{InstancePath, JSONPointer},
primitive_type::PrimitiveType,
schema_node::SchemaNode,
validator::{format_key_value_validators, PartialApplication, Validate},
};
@ -32,7 +33,12 @@ impl PropertiesValidator {
}
Ok(Box::new(PropertiesValidator { properties }))
}
_ => Err(ValidationError::schema(schema)),
_ => Err(ValidationError::single_type_error(
JSONPointer::default(),
context.clone().into_pointer(),
schema,
PrimitiveType::Object,
)),
}
}
}

View File

@ -3,6 +3,7 @@ use crate::{
error::{error, no_error, ErrorIterator, ValidationError},
keywords::CompilationResult,
paths::{InstancePath, JSONPointer},
primitive_type::PrimitiveType,
validator::Validate,
};
use serde_json::{Map, Value};
@ -19,7 +20,14 @@ impl RequiredValidator {
for item in items {
match item {
Value::String(string) => required.push(string.clone()),
_ => return Err(ValidationError::schema(item)),
_ => {
return Err(ValidationError::single_type_error(
JSONPointer::default(),
schema_path,
item,
PrimitiveType::String,
))
}
}
}
Ok(Box::new(RequiredValidator {
@ -141,16 +149,27 @@ pub(crate) fn compile_with_path(
match schema {
Value::Array(items) => {
if items.len() == 1 {
if let Some(Value::String(item)) = items.iter().next() {
let item = &items[0];
if let Value::String(item) = item {
Some(SingleItemRequiredValidator::compile(item, schema_path))
} else {
Some(Err(ValidationError::schema(schema)))
Some(Err(ValidationError::single_type_error(
JSONPointer::default(),
schema_path,
item,
PrimitiveType::String,
)))
}
} else {
Some(RequiredValidator::compile(items, schema_path))
}
}
_ => Some(Err(ValidationError::schema(schema))),
_ => Some(Err(ValidationError::single_type_error(
JSONPointer::default(),
schema_path,
schema,
PrimitiveType::Array,
))),
}
}

View File

@ -5,7 +5,7 @@ use crate::{
primitive_type::{PrimitiveType, PrimitiveTypesBitMap},
validator::Validate,
};
use serde_json::{Map, Number, Value};
use serde_json::{json, Map, Number, Value};
use std::convert::TryFrom;
use crate::paths::{InstancePath, JSONPointer};
@ -25,10 +25,24 @@ impl MultipleTypesValidator {
if let Ok(primitive_type) = PrimitiveType::try_from(string.as_str()) {
types |= primitive_type;
} else {
return Err(ValidationError::schema(item));
return Err(ValidationError::enumeration(
JSONPointer::default(),
schema_path,
item,
&json!([
"array", "boolean", "integer", "null", "number", "object", "string"
]),
));
}
}
_ => return Err(ValidationError::schema(item)),
_ => {
return Err(ValidationError::single_type_error(
schema_path,
JSONPointer::default(),
item,
PrimitiveType::String,
))
}
}
}
Ok(Box::new(MultipleTypesValidator { types, schema_path }))
@ -380,16 +394,29 @@ pub(crate) fn compile<'a>(
Value::String(item) => compile_single_type(item.as_str(), schema_path),
Value::Array(items) => {
if items.len() == 1 {
if let Some(Value::String(item)) = items.iter().next() {
let item = &items[0];
if let Value::String(item) = item {
compile_single_type(item.as_str(), schema_path)
} else {
Some(Err(ValidationError::schema(schema)))
Some(Err(ValidationError::single_type_error(
JSONPointer::default(),
schema_path,
item,
PrimitiveType::String,
)))
}
} else {
Some(MultipleTypesValidator::compile(items, schema_path))
}
}
_ => Some(Err(ValidationError::schema(schema))),
_ => Some(Err(ValidationError::multiple_type_error(
JSONPointer::default(),
context.clone().into_pointer(),
schema,
PrimitiveTypesBitMap::new()
.add_type(PrimitiveType::String)
.add_type(PrimitiveType::Array),
))),
}
}