Skip to content

Commit

Permalink
feat: change new validation code
Browse files Browse the repository at this point in the history
  • Loading branch information
indietyp committed Sep 23, 2024
1 parent 196c498 commit 85f7bc3
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 189 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
use error_stack::Report;
use error_stack::{Report, ReportSink};
use serde::{Deserialize, Serialize};
use serde_json::{json, Value as JsonValue};
use thiserror::Error;

use crate::schema::{
data_type::constraint::{ConstraintError, ValueConstraints},
DataTypeLabel,
};
use crate::schema::{data_type::constraint::ValueConstraints, DataTypeLabel};

#[derive(Debug, Error)]
pub enum ArrayValidationError {
Expand Down Expand Up @@ -82,97 +79,82 @@ pub struct ArraySchema {
}

impl ArraySchema {
pub fn validate_value(&self, values: &[JsonValue]) -> Result<(), Report<ArrayValidationError>> {
let mut validation_status = Ok::<(), Report<ArrayValidationError>>(());
pub fn validate_value(
&self,
values: &[JsonValue],
) -> Result<(), Report<[ArrayValidationError]>> {
let mut validation_status = ReportSink::new();

if let Some(expected) = &self.r#const {
if expected != values {
extend_report!(
validation_status,
ArrayValidationError::InvalidConstValue {
expected: expected.clone(),
actual: values.to_owned(),
}
);
validation_status.capture(ArrayValidationError::InvalidConstValue {
expected: expected.clone(),
actual: values.to_owned(),
});
}
}

if !self.r#enum.is_empty() && !self.r#enum.iter().any(|expected| expected == values) {
extend_report!(
validation_status,
ArrayValidationError::InvalidEnumValue {
expected: self.r#enum.clone(),
actual: values.to_owned(),
}
);
validation_status.capture(ArrayValidationError::InvalidEnumValue {
expected: self.r#enum.clone(),
actual: values.to_owned(),
});
}

let num_values = values.len();

let mut values = values.iter();

let mut item_status = Ok::<(), Report<ConstraintError>>(());
let mut item_status = ReportSink::new();
for (value, constraint) in values
.by_ref()
.take(self.prefix_items.len())
.zip(&self.prefix_items)
{
if let Err(error) = constraint.validate_value(value) {
extend_report!(item_status, error);
item_status.add(error);
}
}

let expected_num_items = self.prefix_items.len().max(self.min_items.unwrap_or(0));
if num_values < expected_num_items {
extend_report!(
validation_status,
ArrayValidationError::MinItems {
actual: num_values,
expected: expected_num_items,
}
);
validation_status.capture(ArrayValidationError::MinItems {
actual: num_values,
expected: expected_num_items,
});
}
if let Some(max_items) = self.max_items {
if num_values > max_items {
extend_report!(
validation_status,
ArrayValidationError::MaxItems {
actual: num_values,
expected: max_items,
}
);
validation_status.capture(ArrayValidationError::MaxItems {
actual: num_values,
expected: max_items,
});
}
}

match &self.items {
None | Some(ItemsConstraints::Boolean(true)) => {}
Some(ItemsConstraints::Boolean(false)) => {
if values.next().is_some() {
extend_report!(
validation_status,
ArrayValidationError::MaxItems {
actual: num_values,
expected: self.prefix_items.len(),
}
);
validation_status.capture(ArrayValidationError::MaxItems {
actual: num_values,
expected: self.prefix_items.len(),
});
}
}
Some(ItemsConstraints::Value(items)) => {
for value in values {
if let Err(error) = items.validate_value(value) {
extend_report!(item_status, error);
item_status.add(error);
}
}
}
}

if let Err(error) = item_status {
extend_report!(
validation_status,
error.change_context(ArrayValidationError::Items)
);
if let Err(error) = item_status.finish() {
validation_status.add(error.change_context(ArrayValidationError::Items));
}

validation_status
validation_status.finish()
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::collections::HashSet;

use error_stack::Report;
use error_stack::{Report, ReportSink};
use serde::{Deserialize, Serialize};
use serde_json::json;
use thiserror::Error;
Expand Down Expand Up @@ -38,31 +38,25 @@ pub struct BooleanSchema {
}

impl BooleanSchema {
pub fn validate_value(&self, boolean: bool) -> Result<(), Report<BooleanValidationError>> {
let mut status = Ok::<(), Report<BooleanValidationError>>(());
pub fn validate_value(&self, boolean: bool) -> Result<(), Report<[BooleanValidationError]>> {
let mut status = ReportSink::new();

if let Some(expected) = &self.r#const {
if *expected != boolean {
extend_report!(
status,
BooleanValidationError::InvalidConstValue {
expected: *expected,
actual: boolean,
}
);
status.capture(BooleanValidationError::InvalidConstValue {
expected: *expected,
actual: boolean,
});
}
}

if !self.r#enum.is_empty() && !self.r#enum.contains(&boolean) {
extend_report!(
status,
BooleanValidationError::InvalidEnumValue {
expected: self.r#enum.clone(),
actual: boolean,
}
);
status.capture(BooleanValidationError::InvalidEnumValue {
expected: self.r#enum.clone(),
actual: boolean,
});
}

status
status.finish()
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use error_stack::{bail, Report};
use error_stack::{bail, Report, ReportSink};
use serde::{Deserialize, Serialize};
use serde_json::{json, Number as JsonNumber};
use thiserror::Error;
Expand Down Expand Up @@ -111,24 +111,24 @@ fn float_less(lhs: f64, rhs: f64) -> bool {
}

impl NumberSchema {
pub fn validate_value(&self, number: &JsonNumber) -> Result<(), Report<NumberValidationError>> {
pub fn validate_value(
&self,
number: &JsonNumber,
) -> Result<(), Report<[NumberValidationError]>> {
let Some(float) = number.as_f64() else {
bail!(NumberValidationError::InsufficientPrecision {
bail![NumberValidationError::InsufficientPrecision {
actual: number.clone()
});
},];
};

let mut status = Ok::<(), Report<NumberValidationError>>(());
let mut status = ReportSink::new();

if let Some(expected) = self.r#const {
if float_eq(expected, float) {
extend_report!(
status,
NumberValidationError::InvalidConstValue {
expected,
actual: float,
}
);
status.capture(NumberValidationError::InvalidConstValue {
expected,
actual: float,
});
}
}

Expand All @@ -138,56 +138,41 @@ impl NumberSchema {
.iter()
.any(|expected| float_eq(float, *expected))
{
extend_report!(
status,
NumberValidationError::InvalidEnumValue {
expected: self.r#enum.clone(),
actual: float.to_owned(),
}
);
status.capture(NumberValidationError::InvalidEnumValue {
expected: self.r#enum.clone(),
actual: float.to_owned(),
});
}

if let Some(minimum) = self.minimum {
if self.exclusive_minimum {
if float_less_eq(float, minimum) {
extend_report!(
status,
NumberValidationError::ExclusiveMinimum {
actual: float,
expected: minimum
}
);
status.capture(NumberValidationError::ExclusiveMinimum {
actual: float,
expected: minimum,
});
}
} else if float_less(float, minimum) {
extend_report!(
status,
NumberValidationError::ExclusiveMinimum {
actual: float,
expected: minimum
}
);
status.capture(NumberValidationError::ExclusiveMinimum {
actual: float,
expected: minimum,
});
}
}

if let Some(maximum) = self.maximum {
if self.exclusive_maximum {
if float_less_eq(maximum, float) {
extend_report!(
status,
NumberValidationError::ExclusiveMaximum {
actual: float,
expected: maximum
}
);
status.capture(NumberValidationError::ExclusiveMaximum {
actual: float,
expected: maximum,
});
}
} else if float_less(maximum, float) {
extend_report!(
status,
NumberValidationError::Maximum {
actual: float,
expected: maximum
}
);
status.capture(NumberValidationError::Maximum {
actual: float,
expected: maximum,
});
}
}

Expand All @@ -198,17 +183,14 @@ impl NumberSchema {
reason = "Validation requires floating point arithmetic"
)]
if !float_eq(float % expected, 0.0) {
extend_report!(
status,
NumberValidationError::MultipleOf {
actual: float,
expected
}
);
status.capture(NumberValidationError::MultipleOf {
actual: float,
expected,
});
}
}

status
status.finish()
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use error_stack::Report;
use error_stack::{Report, ReportSink};
use serde::{Deserialize, Serialize};
use serde_json::{json, Map as JsonMap, Value as JsonValue};
use thiserror::Error;
Expand Down Expand Up @@ -46,31 +46,25 @@ impl ObjectSchema {
pub fn validate_value(
&self,
object: &JsonMap<String, JsonValue>,
) -> Result<(), Report<ObjectValidationError>> {
let mut validation_status = Ok::<(), Report<ObjectValidationError>>(());
) -> Result<(), Report<[ObjectValidationError]>> {
let mut validation_status = ReportSink::new();

if let Some(expected) = &self.r#const {
if expected != object {
extend_report!(
validation_status,
ObjectValidationError::InvalidConstValue {
expected: expected.clone(),
actual: object.clone(),
}
);
validation_status.capture(ObjectValidationError::InvalidConstValue {
expected: expected.clone(),
actual: object.clone(),
});
}
}

if !self.r#enum.is_empty() && !self.r#enum.iter().any(|expected| expected == object) {
extend_report!(
validation_status,
ObjectValidationError::InvalidEnumValue {
expected: self.r#enum.clone(),
actual: object.clone(),
}
);
validation_status.capture(ObjectValidationError::InvalidEnumValue {
expected: self.r#enum.clone(),
actual: object.clone(),
});
}

validation_status
validation_status.finish()
}
}
Loading

0 comments on commit 85f7bc3

Please sign in to comment.