use super::*;
use crate::element::*;
use crate::error::{Error, Result};
use serde::{Deserialize, Serialize};
#[inline]
fn is_false(v: &bool) -> bool {
!v
}
#[inline]
fn u32_is_zero(v: &u32) -> bool {
*v == 0
}
#[inline]
fn u32_is_max(v: &u32) -> bool {
*v == u32::MAX
}
macro_rules! lockbox_validator {
($t: ty, $e: ident, $v: ident, $link:expr, $name:expr) => {
#[doc = "Validator for a [`"]
#[doc = $name]
#[doc = "`]["]
#[doc = $link]
#[doc = "].\n\n"]
#[doc = "This validator will only pass a "]
#[doc = $name]
#[doc = " value. Validation passes if:\n\n"]
#[doc = "- The number of bytes in the lockbox is less than or equal to `max_len`\n"]
#[doc = "- The number of bytes in the lockbox is greater than or equal to `min_len`\n"]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(deny_unknown_fields, default)]
pub struct $v {
/// An optional comment explaining the validator.
#[serde(skip_serializing_if = "String::is_empty")]
pub comment: String,
#[serde(skip_serializing_if = "u32_is_max")]
pub max_len: u32,
#[serde(skip_serializing_if = "u32_is_zero")]
pub min_len: u32,
#[serde(skip_serializing_if = "is_false")]
pub size: bool,
}
impl std::default::Default for $v {
fn default() -> Self {
Self {
comment: String::new(),
max_len: u32::MAX,
min_len: u32::MIN,
size: false,
}
}
}
impl $v {
pub fn new() -> Self {
Self::default()
}
pub fn comment(mut self, comment: impl Into<String>) -> Self {
self.comment = comment.into();
self
}
pub fn max_len(mut self, max_len: u32) -> Self {
self.max_len = max_len;
self
}
pub fn min_len(mut self, min_len: u32) -> Self {
self.min_len = min_len;
self
}
pub fn size(mut self, size: bool) -> Self {
self.size = size;
self
}
pub fn build(self) -> Validator {
Validator::$e(Box::new(self))
}
pub(crate) fn validate(&self, parser: &mut Parser) -> Result<()> {
let elem = parser
.next()
.ok_or_else(|| Error::FailValidate(concat!("Expected a ",$name).to_string()))??;
let elem = if let Element::$e(v) = elem {
v
} else {
return Err(Error::FailValidate(format!(
concat!("Expected ", $name, ", got {}"),
elem.name()
)));
};
let len = elem.as_bytes().len() as u32;
if len > self.max_len {
return Err(Error::FailValidate(
concat!($name, " is longer than max_len").to_string()
));
}
if len < self.min_len {
return Err(Error::FailValidate(
concat!($name, " is shorter than min_len").to_string()
));
}
Ok(())
}
fn query_check_self(&self, other: &Self) -> bool {
self.size || (u32_is_max(&other.max_len) && u32_is_zero(&other.min_len))
}
pub(crate) fn query_check(&self, other: &Validator) -> bool {
match other {
Validator::$e(other) => self.query_check_self(other),
Validator::Multi(list) => list.iter().all(|other| match other {
Validator::$e(other) => self.query_check_self(other),
_ => false,
}),
Validator::Any => true,
_ => false,
}
}
}
};
($t: ty, $e: ident, $v: ident) => {
lockbox_validator!($t, $e, $v, concat!("fog_crypto::lockbox::", stringify!($t)), stringify!($t));
}
}
lockbox_validator!(DataLockbox, DataLockbox, DataLockboxValidator);
lockbox_validator!(IdentityLockbox, IdentityLockbox, IdentityLockboxValidator);
lockbox_validator!(StreamLockbox, StreamLockbox, StreamLockboxValidator);
lockbox_validator!(LockLockbox, LockLockbox, LockLockboxValidator);