fix: Precision loss in `minimum`, `maximum`, `exclusiveMinimum` and `exclusiveMaximum` validators
This commit is contained in:
parent
093ea199ea
commit
f169c8e527
|
@ -36,6 +36,7 @@
|
||||||
|
|
||||||
- Wrong implementation of `is_valid` for `additionalProperties: false` keyword case. [#61](https://github.com/Stranger6667/jsonschema-rs/pull/61)
|
- Wrong implementation of `is_valid` for `additionalProperties: false` keyword case. [#61](https://github.com/Stranger6667/jsonschema-rs/pull/61)
|
||||||
- Possible panic due to type conversion in some numeric validators. [#72](https://github.com/Stranger6667/jsonschema-rs/pull/72)
|
- Possible panic due to type conversion in some numeric validators. [#72](https://github.com/Stranger6667/jsonschema-rs/pull/72)
|
||||||
|
- Precision loss in `minimum`, `maximum`, `exclusiveMinimum` and `exclusiveMaximum` validators. [#84](https://github.com/Stranger6667/jsonschema-rs/issues/84)
|
||||||
|
|
||||||
## [0.2.0] - 2020-03-30
|
## [0.2.0] - 2020-03-30
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ chrono = ">= 0.2"
|
||||||
rayon = "1"
|
rayon = "1"
|
||||||
reqwest = { version = ">= 0.10", features = ["blocking", "json"]}
|
reqwest = { version = ">= 0.10", features = ["blocking", "json"]}
|
||||||
parking_lot = ">= 0.1"
|
parking_lot = ">= 0.1"
|
||||||
|
num-cmp = ">= 0.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
paste = ">= 0.1"
|
paste = ">= 0.1"
|
||||||
|
|
|
@ -3,55 +3,92 @@ use crate::{
|
||||||
compilation::{CompilationContext, JSONSchema},
|
compilation::{CompilationContext, JSONSchema},
|
||||||
error::{error, no_error, CompilationError, ErrorIterator, ValidationError},
|
error::{error, no_error, CompilationError, ErrorIterator, ValidationError},
|
||||||
};
|
};
|
||||||
|
use num_cmp::NumCmp;
|
||||||
use serde_json::{Map, Value};
|
use serde_json::{Map, Value};
|
||||||
|
|
||||||
pub struct ExclusiveMaximumValidator {
|
pub struct ExclusiveMaximumU64Validator {
|
||||||
|
limit: u64,
|
||||||
|
}
|
||||||
|
pub struct ExclusiveMaximumI64Validator {
|
||||||
|
limit: i64,
|
||||||
|
}
|
||||||
|
pub struct ExclusiveMaximumF64Validator {
|
||||||
limit: f64,
|
limit: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExclusiveMaximumValidator {
|
macro_rules! validate {
|
||||||
#[inline]
|
($validator: ty) => {
|
||||||
pub(crate) fn compile(schema: &Value) -> CompilationResult {
|
impl Validate for $validator {
|
||||||
if let Value::Number(limit) = schema {
|
fn validate<'a>(
|
||||||
return Ok(Box::new(ExclusiveMaximumValidator {
|
&self,
|
||||||
limit: limit.as_f64().expect("Always valid"),
|
schema: &'a JSONSchema,
|
||||||
}));
|
instance: &'a Value,
|
||||||
}
|
) -> ErrorIterator<'a> {
|
||||||
Err(CompilationError::SchemaError)
|
if self.is_valid(schema, instance) {
|
||||||
}
|
no_error()
|
||||||
}
|
} else {
|
||||||
|
error(ValidationError::exclusive_maximum(
|
||||||
|
instance,
|
||||||
|
self.limit as f64,
|
||||||
|
)) // do not cast
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Validate for ExclusiveMaximumValidator {
|
fn is_valid(&self, _: &JSONSchema, instance: &Value) -> bool {
|
||||||
fn validate<'a>(&self, _: &'a JSONSchema, instance: &'a Value) -> ErrorIterator<'a> {
|
if let Value::Number(item) = instance {
|
||||||
if let Value::Number(item) = instance {
|
return if let Some(item) = item.as_u64() {
|
||||||
let item = item.as_f64().expect("Always valid");
|
NumCmp::num_lt(item, self.limit)
|
||||||
if item >= self.limit {
|
} else if let Some(item) = item.as_i64() {
|
||||||
return error(ValidationError::exclusive_maximum(instance, self.limit));
|
NumCmp::num_lt(item, self.limit)
|
||||||
|
} else {
|
||||||
|
let item = item.as_f64().expect("Always valid");
|
||||||
|
NumCmp::num_lt(item, self.limit)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name(&self) -> String {
|
||||||
|
format!("exclusiveMaximum: {}", self.limit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
no_error()
|
};
|
||||||
}
|
|
||||||
|
|
||||||
fn is_valid(&self, _: &JSONSchema, instance: &Value) -> bool {
|
|
||||||
if let Value::Number(item) = instance {
|
|
||||||
let item = item.as_f64().expect("Always valid");
|
|
||||||
if item >= self.limit {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn name(&self) -> String {
|
|
||||||
format!("exclusiveMaximum: {}", self.limit)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
validate!(ExclusiveMaximumU64Validator);
|
||||||
|
validate!(ExclusiveMaximumI64Validator);
|
||||||
|
validate!(ExclusiveMaximumF64Validator);
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn compile(
|
pub fn compile(
|
||||||
_: &Map<String, Value>,
|
_: &Map<String, Value>,
|
||||||
schema: &Value,
|
schema: &Value,
|
||||||
_: &CompilationContext,
|
_: &CompilationContext,
|
||||||
) -> Option<CompilationResult> {
|
) -> Option<CompilationResult> {
|
||||||
Some(ExclusiveMaximumValidator::compile(schema))
|
if let Value::Number(limit) = schema {
|
||||||
|
return if let Some(limit) = limit.as_u64() {
|
||||||
|
Some(Ok(Box::new(ExclusiveMaximumU64Validator { limit })))
|
||||||
|
} else if let Some(limit) = limit.as_i64() {
|
||||||
|
Some(Ok(Box::new(ExclusiveMaximumI64Validator { limit })))
|
||||||
|
} else {
|
||||||
|
let limit = limit.as_f64().expect("Always valid");
|
||||||
|
Some(Ok(Box::new(ExclusiveMaximumF64Validator { limit })))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Some(Err(CompilationError::SchemaError))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::tests_util;
|
||||||
|
use serde_json::{json, Value};
|
||||||
|
use test_case::test_case;
|
||||||
|
|
||||||
|
#[test_case(json!({"exclusiveMaximum": 1u64 << 54}), json!(1u64 << 54))]
|
||||||
|
#[test_case(json!({"exclusiveMaximum": 1i64 << 54}), json!(1i64 << 54))]
|
||||||
|
#[test_case(json!({"exclusiveMaximum": 1u64 << 54}), json!(1u64 << 54 + 1))]
|
||||||
|
#[test_case(json!({"exclusiveMaximum": 1i64 << 54}), json!(1i64 << 54 + 1))]
|
||||||
|
fn is_not_valid(schema: Value, instance: Value) {
|
||||||
|
tests_util::is_not_valid(schema, instance)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,53 +3,92 @@ use crate::{
|
||||||
compilation::{CompilationContext, JSONSchema},
|
compilation::{CompilationContext, JSONSchema},
|
||||||
error::{error, no_error, CompilationError, ErrorIterator, ValidationError},
|
error::{error, no_error, CompilationError, ErrorIterator, ValidationError},
|
||||||
};
|
};
|
||||||
|
use num_cmp::NumCmp;
|
||||||
use serde_json::{Map, Value};
|
use serde_json::{Map, Value};
|
||||||
|
|
||||||
pub struct ExclusiveMinimumValidator {
|
pub struct ExclusiveMinimumU64Validator {
|
||||||
|
limit: u64,
|
||||||
|
}
|
||||||
|
pub struct ExclusiveMinimumI64Validator {
|
||||||
|
limit: i64,
|
||||||
|
}
|
||||||
|
pub struct ExclusiveMinimumF64Validator {
|
||||||
limit: f64,
|
limit: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExclusiveMinimumValidator {
|
macro_rules! validate {
|
||||||
#[inline]
|
($validator: ty) => {
|
||||||
pub(crate) fn compile(schema: &Value) -> CompilationResult {
|
impl Validate for $validator {
|
||||||
if let Value::Number(limit) = schema {
|
fn validate<'a>(
|
||||||
let limit = limit.as_f64().expect("Always valid");
|
&self,
|
||||||
return Ok(Box::new(ExclusiveMinimumValidator { limit }));
|
schema: &'a JSONSchema,
|
||||||
}
|
instance: &'a Value,
|
||||||
Err(CompilationError::SchemaError)
|
) -> ErrorIterator<'a> {
|
||||||
}
|
if self.is_valid(schema, instance) {
|
||||||
}
|
no_error()
|
||||||
|
} else {
|
||||||
|
error(ValidationError::exclusive_minimum(
|
||||||
|
instance,
|
||||||
|
self.limit as f64,
|
||||||
|
)) // do not cast
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Validate for ExclusiveMinimumValidator {
|
fn is_valid(&self, _: &JSONSchema, instance: &Value) -> bool {
|
||||||
fn validate<'a>(&self, _: &'a JSONSchema, instance: &'a Value) -> ErrorIterator<'a> {
|
if let Value::Number(item) = instance {
|
||||||
if let Value::Number(item) = instance {
|
return if let Some(item) = item.as_u64() {
|
||||||
let item = item.as_f64().expect("Always valid");
|
NumCmp::num_gt(item, self.limit)
|
||||||
if item <= self.limit {
|
} else if let Some(item) = item.as_i64() {
|
||||||
return error(ValidationError::exclusive_minimum(instance, self.limit));
|
NumCmp::num_gt(item, self.limit)
|
||||||
|
} else {
|
||||||
|
let item = item.as_f64().expect("Always valid");
|
||||||
|
NumCmp::num_gt(item, self.limit)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name(&self) -> String {
|
||||||
|
format!("exclusiveMinimum: {}", self.limit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
no_error()
|
};
|
||||||
}
|
|
||||||
|
|
||||||
fn is_valid(&self, _: &JSONSchema, instance: &Value) -> bool {
|
|
||||||
if let Value::Number(item) = instance {
|
|
||||||
let item = item.as_f64().expect("Always valid");
|
|
||||||
if item <= self.limit {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn name(&self) -> String {
|
|
||||||
format!("exclusiveMinimum: {}", self.limit)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
validate!(ExclusiveMinimumU64Validator);
|
||||||
|
validate!(ExclusiveMinimumI64Validator);
|
||||||
|
validate!(ExclusiveMinimumF64Validator);
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn compile(
|
pub fn compile(
|
||||||
_: &Map<String, Value>,
|
_: &Map<String, Value>,
|
||||||
schema: &Value,
|
schema: &Value,
|
||||||
_: &CompilationContext,
|
_: &CompilationContext,
|
||||||
) -> Option<CompilationResult> {
|
) -> Option<CompilationResult> {
|
||||||
Some(ExclusiveMinimumValidator::compile(schema))
|
if let Value::Number(limit) = schema {
|
||||||
|
return if let Some(limit) = limit.as_u64() {
|
||||||
|
Some(Ok(Box::new(ExclusiveMinimumU64Validator { limit })))
|
||||||
|
} else if let Some(limit) = limit.as_i64() {
|
||||||
|
Some(Ok(Box::new(ExclusiveMinimumI64Validator { limit })))
|
||||||
|
} else {
|
||||||
|
let limit = limit.as_f64().expect("Always valid");
|
||||||
|
Some(Ok(Box::new(ExclusiveMinimumF64Validator { limit })))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Some(Err(CompilationError::SchemaError))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::tests_util;
|
||||||
|
use serde_json::{json, Value};
|
||||||
|
use test_case::test_case;
|
||||||
|
|
||||||
|
#[test_case(json!({"exclusiveMinimum": 1u64 << 54}), json!(1u64 << 54))]
|
||||||
|
#[test_case(json!({"exclusiveMinimum": 1i64 << 54}), json!(1i64 << 54))]
|
||||||
|
#[test_case(json!({"exclusiveMinimum": 1u64 << 54}), json!(1u64 << 54 - 1))]
|
||||||
|
#[test_case(json!({"exclusiveMinimum": 1i64 << 54}), json!(1i64 << 54 - 1))]
|
||||||
|
fn is_not_valid(schema: Value, instance: Value) {
|
||||||
|
tests_util::is_not_valid(schema, instance)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,54 +3,87 @@ use crate::{
|
||||||
compilation::{CompilationContext, JSONSchema},
|
compilation::{CompilationContext, JSONSchema},
|
||||||
error::{error, no_error, CompilationError, ErrorIterator, ValidationError},
|
error::{error, no_error, CompilationError, ErrorIterator, ValidationError},
|
||||||
};
|
};
|
||||||
|
use num_cmp::NumCmp;
|
||||||
use serde_json::{Map, Value};
|
use serde_json::{Map, Value};
|
||||||
|
|
||||||
pub struct MaximumValidator {
|
pub struct MaximumU64Validator {
|
||||||
|
limit: u64,
|
||||||
|
}
|
||||||
|
pub struct MaximumI64Validator {
|
||||||
|
limit: i64,
|
||||||
|
}
|
||||||
|
pub struct MaximumF64Validator {
|
||||||
limit: f64,
|
limit: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MaximumValidator {
|
macro_rules! validate {
|
||||||
#[inline]
|
($validator: ty) => {
|
||||||
pub(crate) fn compile(schema: &Value) -> CompilationResult {
|
impl Validate for $validator {
|
||||||
if let Value::Number(limit) = schema {
|
fn validate<'a>(
|
||||||
let limit = limit.as_f64().expect("Always valid");
|
&self,
|
||||||
return Ok(Box::new(MaximumValidator { limit }));
|
schema: &'a JSONSchema,
|
||||||
}
|
instance: &'a Value,
|
||||||
Err(CompilationError::SchemaError)
|
) -> ErrorIterator<'a> {
|
||||||
}
|
if self.is_valid(schema, instance) {
|
||||||
}
|
no_error()
|
||||||
|
} else {
|
||||||
|
error(ValidationError::maximum(instance, self.limit as f64)) // do not cast
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Validate for MaximumValidator {
|
fn is_valid(&self, _: &JSONSchema, instance: &Value) -> bool {
|
||||||
fn validate<'a>(&self, _: &'a JSONSchema, instance: &'a Value) -> ErrorIterator<'a> {
|
if let Value::Number(item) = instance {
|
||||||
if let Value::Number(item) = instance {
|
return if let Some(item) = item.as_u64() {
|
||||||
let item = item.as_f64().expect("Always valid");
|
!NumCmp::num_gt(item, self.limit)
|
||||||
if item > self.limit {
|
} else if let Some(item) = item.as_i64() {
|
||||||
return error(ValidationError::maximum(instance, self.limit));
|
!NumCmp::num_gt(item, self.limit)
|
||||||
|
} else {
|
||||||
|
let item = item.as_f64().expect("Always valid");
|
||||||
|
!NumCmp::num_gt(item, self.limit)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name(&self) -> String {
|
||||||
|
format!("maximum: {}", self.limit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
no_error()
|
};
|
||||||
}
|
|
||||||
|
|
||||||
fn is_valid(&self, _: &JSONSchema, instance: &Value) -> bool {
|
|
||||||
if let Value::Number(item) = instance {
|
|
||||||
let item = item.as_f64().expect("Always valid");
|
|
||||||
if item > self.limit {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn name(&self) -> String {
|
|
||||||
format!("maximum: {}", self.limit)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
validate!(MaximumU64Validator);
|
||||||
|
validate!(MaximumI64Validator);
|
||||||
|
validate!(MaximumF64Validator);
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn compile(
|
pub fn compile(
|
||||||
_: &Map<String, Value>,
|
_: &Map<String, Value>,
|
||||||
schema: &Value,
|
schema: &Value,
|
||||||
_: &CompilationContext,
|
_: &CompilationContext,
|
||||||
) -> Option<CompilationResult> {
|
) -> Option<CompilationResult> {
|
||||||
Some(MaximumValidator::compile(schema))
|
if let Value::Number(limit) = schema {
|
||||||
|
return if let Some(limit) = limit.as_u64() {
|
||||||
|
Some(Ok(Box::new(MaximumU64Validator { limit })))
|
||||||
|
} else if let Some(limit) = limit.as_i64() {
|
||||||
|
Some(Ok(Box::new(MaximumI64Validator { limit })))
|
||||||
|
} else {
|
||||||
|
let limit = limit.as_f64().expect("Always valid");
|
||||||
|
Some(Ok(Box::new(MaximumF64Validator { limit })))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Some(Err(CompilationError::SchemaError))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::tests_util;
|
||||||
|
use serde_json::{json, Value};
|
||||||
|
use test_case::test_case;
|
||||||
|
|
||||||
|
#[test_case(json!({"maximum": 1u64 << 54}), json!(1u64 << 54 + 1))]
|
||||||
|
#[test_case(json!({"maximum": 1i64 << 54}), json!(1i64 << 54 + 1))]
|
||||||
|
fn is_not_valid(schema: Value, instance: Value) {
|
||||||
|
tests_util::is_not_valid(schema, instance)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,54 +3,87 @@ use crate::{
|
||||||
compilation::{CompilationContext, JSONSchema},
|
compilation::{CompilationContext, JSONSchema},
|
||||||
error::{error, no_error, CompilationError, ErrorIterator, ValidationError},
|
error::{error, no_error, CompilationError, ErrorIterator, ValidationError},
|
||||||
};
|
};
|
||||||
|
use num_cmp::NumCmp;
|
||||||
use serde_json::{Map, Value};
|
use serde_json::{Map, Value};
|
||||||
|
|
||||||
pub struct MinimumValidator {
|
pub struct MinimumU64Validator {
|
||||||
|
limit: u64,
|
||||||
|
}
|
||||||
|
pub struct MinimumI64Validator {
|
||||||
|
limit: i64,
|
||||||
|
}
|
||||||
|
pub struct MinimumF64Validator {
|
||||||
limit: f64,
|
limit: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MinimumValidator {
|
macro_rules! validate {
|
||||||
#[inline]
|
($validator: ty) => {
|
||||||
pub(crate) fn compile(schema: &Value) -> CompilationResult {
|
impl Validate for $validator {
|
||||||
if let Value::Number(limit) = schema {
|
fn validate<'a>(
|
||||||
let limit = limit.as_f64().expect("Always valid");
|
&self,
|
||||||
return Ok(Box::new(MinimumValidator { limit }));
|
schema: &'a JSONSchema,
|
||||||
}
|
instance: &'a Value,
|
||||||
Err(CompilationError::SchemaError)
|
) -> ErrorIterator<'a> {
|
||||||
}
|
if self.is_valid(schema, instance) {
|
||||||
}
|
no_error()
|
||||||
|
} else {
|
||||||
|
error(ValidationError::minimum(instance, self.limit as f64)) // do not cast
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Validate for MinimumValidator {
|
fn is_valid(&self, _: &JSONSchema, instance: &Value) -> bool {
|
||||||
fn validate<'a>(&self, _: &'a JSONSchema, instance: &'a Value) -> ErrorIterator<'a> {
|
if let Value::Number(item) = instance {
|
||||||
if let Value::Number(item) = instance {
|
return if let Some(item) = item.as_u64() {
|
||||||
let item = item.as_f64().expect("Always valid");
|
!NumCmp::num_lt(item, self.limit)
|
||||||
if item < self.limit {
|
} else if let Some(item) = item.as_i64() {
|
||||||
return error(ValidationError::minimum(instance, self.limit));
|
!NumCmp::num_lt(item, self.limit)
|
||||||
|
} else {
|
||||||
|
let item = item.as_f64().expect("Always valid");
|
||||||
|
!NumCmp::num_lt(item, self.limit)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn name(&self) -> String {
|
||||||
|
format!("minimum: {}", self.limit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
no_error()
|
};
|
||||||
}
|
|
||||||
|
|
||||||
fn is_valid(&self, _: &JSONSchema, instance: &Value) -> bool {
|
|
||||||
if let Value::Number(item) = instance {
|
|
||||||
let item = item.as_f64().expect("Always valid");
|
|
||||||
if item < self.limit {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn name(&self) -> String {
|
|
||||||
format!("minimum: {}", self.limit)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
validate!(MinimumU64Validator);
|
||||||
|
validate!(MinimumI64Validator);
|
||||||
|
validate!(MinimumF64Validator);
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn compile(
|
pub fn compile(
|
||||||
_: &Map<String, Value>,
|
_: &Map<String, Value>,
|
||||||
schema: &Value,
|
schema: &Value,
|
||||||
_: &CompilationContext,
|
_: &CompilationContext,
|
||||||
) -> Option<CompilationResult> {
|
) -> Option<CompilationResult> {
|
||||||
Some(MinimumValidator::compile(schema))
|
if let Value::Number(limit) = schema {
|
||||||
|
return if let Some(limit) = limit.as_u64() {
|
||||||
|
Some(Ok(Box::new(MinimumU64Validator { limit })))
|
||||||
|
} else if let Some(limit) = limit.as_i64() {
|
||||||
|
Some(Ok(Box::new(MinimumI64Validator { limit })))
|
||||||
|
} else {
|
||||||
|
let limit = limit.as_f64().expect("Always valid");
|
||||||
|
Some(Ok(Box::new(MinimumF64Validator { limit })))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Some(Err(CompilationError::SchemaError))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::tests_util;
|
||||||
|
use serde_json::{json, Value};
|
||||||
|
use test_case::test_case;
|
||||||
|
|
||||||
|
#[test_case(json!({"minimum": 1u64 << 54}), json!(1u64 << 54 - 1))]
|
||||||
|
#[test_case(json!({"minimum": 1i64 << 54}), json!(1i64 << 54 - 1))]
|
||||||
|
fn is_not_valid(schema: Value, instance: Value) {
|
||||||
|
tests_util::is_not_valid(schema, instance)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
16
src/lib.rs
16
src/lib.rs
|
@ -46,7 +46,6 @@
|
||||||
missing_docs,
|
missing_docs,
|
||||||
missing_debug_implementations,
|
missing_debug_implementations,
|
||||||
trivial_casts,
|
trivial_casts,
|
||||||
trivial_numeric_casts,
|
|
||||||
unused_extern_crates,
|
unused_extern_crates,
|
||||||
unused_import_braces,
|
unused_import_braces,
|
||||||
unused_qualifications,
|
unused_qualifications,
|
||||||
|
@ -82,6 +81,21 @@ pub fn is_valid(schema: &Value, instance: &Value) -> bool {
|
||||||
compiled.is_valid(instance)
|
compiled.is_valid(instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests_util {
|
||||||
|
use super::JSONSchema;
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
|
pub fn is_not_valid(schema: Value, instance: Value) {
|
||||||
|
let compiled = JSONSchema::compile(&schema, None).unwrap();
|
||||||
|
assert!(!compiled.is_valid(&instance), "{} should not be valid");
|
||||||
|
assert!(
|
||||||
|
compiled.validate(&instance).is_err(),
|
||||||
|
"{} should not be valid"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
Loading…
Reference in New Issue