use super::*;
use crate::element::*;
use crate::error::{Error, Result};
use serde::{Deserialize, Serialize};
#[inline]
fn is_false(v: &bool) -> bool {
!v
}
#[inline]
fn is_nan(v: &f32) -> bool {
v.is_nan()
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields, default)]
pub struct F32Validator {
#[serde(skip_serializing_if = "String::is_empty")]
pub comment: String,
#[serde(skip_serializing_if = "is_nan")]
pub max: f32,
#[serde(skip_serializing_if = "is_nan")]
pub min: f32,
#[serde(skip_serializing_if = "is_false")]
pub ex_max: bool,
#[serde(skip_serializing_if = "is_false")]
pub ex_min: bool,
#[serde(rename = "in", skip_serializing_if = "Vec::is_empty")]
pub in_list: Vec<f32>,
#[serde(rename = "nin", skip_serializing_if = "Vec::is_empty")]
pub nin_list: Vec<f32>,
#[serde(skip_serializing_if = "is_false")]
pub query: bool,
#[serde(skip_serializing_if = "is_false")]
pub ord: bool,
}
impl std::default::Default for F32Validator {
fn default() -> Self {
Self {
comment: String::new(),
max: f32::NAN,
min: f32::NAN,
ex_max: false,
ex_min: false,
in_list: Vec::new(),
nin_list: Vec::new(),
query: false,
ord: false,
}
}
}
impl F32Validator {
pub fn new() -> Self {
Self::default()
}
pub fn comment(mut self, comment: impl Into<String>) -> Self {
self.comment = comment.into();
self
}
pub fn max(mut self, max: f32) -> Self {
self.max = max;
self
}
pub fn min(mut self, min: f32) -> Self {
self.min = min;
self
}
pub fn ex_max(mut self, ex_max: bool) -> Self {
self.ex_max = ex_max;
self
}
pub fn ex_min(mut self, ex_min: bool) -> Self {
self.ex_min = ex_min;
self
}
pub fn in_add(mut self, add: f32) -> Self {
self.in_list.push(add);
self
}
pub fn nin_add(mut self, add: f32) -> Self {
self.nin_list.push(add);
self
}
pub fn query(mut self, query: bool) -> Self {
self.query = query;
self
}
pub fn ord(mut self, ord: bool) -> Self {
self.ord = ord;
self
}
pub fn build(self) -> Validator {
Validator::F32(Box::new(self))
}
pub(crate) fn validate(&self, parser: &mut Parser) -> Result<()> {
let elem = parser
.next()
.ok_or_else(|| Error::FailValidate("Expected a f32".to_string()))??;
let elem = if let Element::F32(v) = elem {
v
} else {
return Err(Error::FailValidate(format!(
"Expected F32, got {}",
elem.name()
)));
};
let bytes = elem.to_ne_bytes();
if !self.in_list.is_empty() && !self.in_list.iter().any(|v| v.to_ne_bytes() == bytes) {
return Err(Error::FailValidate("F32 is not on `in` list".to_string()));
}
if self.nin_list.iter().any(|v| v.to_ne_bytes() == bytes) {
return Err(Error::FailValidate("F32 is on `nin` list".to_string()));
}
if !self.max.is_nan() && ((self.ex_max && elem >= self.max) || (elem > self.max)) {
return Err(Error::FailValidate(
"F32 greater than maximum allowed".to_string(),
));
}
if !self.min.is_nan() && ((self.ex_min && elem <= self.min) || (elem < self.min)) {
return Err(Error::FailValidate(
"F32 less than maximum allowed".to_string(),
));
}
Ok(())
}
fn query_check_f32(&self, other: &Self) -> bool {
(self.query || (other.in_list.is_empty() && other.nin_list.is_empty()))
&& (self.ord
|| (!other.ex_min && !other.ex_max && other.min.is_nan() && other.max.is_nan()))
}
pub(crate) fn query_check(&self, other: &Validator) -> bool {
match other {
Validator::F32(other) => self.query_check_f32(other),
Validator::Multi(list) => list.iter().all(|other| match other {
Validator::F32(other) => self.query_check_f32(other),
_ => false,
}),
Validator::Any => true,
_ => false,
}
}
}