use koruma::{Validate, validator};
use std::fmt;
#[validator]
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct NumberRangeValidation {
min: i32,
max: i32,
#[koruma(value)]
actual: i32,
}
impl Validate<i32> for NumberRangeValidation {
fn validate(&self, value: &i32) -> bool {
!(*value < self.min || *value > self.max)
}
}
#[validator]
#[derive(Clone, Debug)]
pub struct GenericRangeValidation<T> {
pub min: T,
pub max: T,
#[koruma(value)]
actual: T,
}
impl<T: PartialOrd + Clone> Validate<T> for GenericRangeValidation<T> {
fn validate(&self, value: &T) -> bool {
*value >= self.min && *value <= self.max
}
}
#[validator]
#[derive(Clone, Debug)]
pub struct PrefixBytesValidation<'a, const N: usize> {
pub prefix: &'a [u8],
#[koruma(value)]
actual: [u8; N],
}
impl<'a, const N: usize> Validate<[u8; N]> for PrefixBytesValidation<'a, N> {
fn validate(&self, value: &[u8; N]) -> bool {
value.starts_with(self.prefix)
}
}
#[validator]
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct StringLengthValidation {
min: usize,
max: usize,
#[koruma(value)]
input: String,
}
impl Validate<String> for StringLengthValidation {
fn validate(&self, value: &String) -> bool {
let len = value.chars().count();
!(len < self.min || len > self.max)
}
}
#[validator]
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct EvenNumberValidation {
#[koruma(value)]
actual: i32,
}
impl Validate<i32> for EvenNumberValidation {
fn validate(&self, value: &i32) -> bool {
value % 2 == 0
}
}
#[validator]
#[derive(Clone, Debug)]
pub struct VecLenValidation<T> {
pub min: usize,
pub max: usize,
#[koruma(value)]
actual: Vec<T>,
}
impl<T> Validate<Vec<T>> for VecLenValidation<T> {
fn validate(&self, value: &Vec<T>) -> bool {
let len = value.len();
!(len < self.min || len > self.max)
}
}
impl<T> VecLenValidation<T> {
pub fn actual_len(&self) -> usize {
self.actual.len()
}
}
#[validator]
pub struct RequiredValidation<T> {
#[koruma(value, skip_capture)]
#[allow(dead_code)]
actual: Option<T>,
}
impl<T> Clone for RequiredValidation<T> {
fn clone(&self) -> Self {
Self { actual: None }
}
}
impl<T> fmt::Debug for RequiredValidation<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RequiredValidation")
.field("actual", &"<skipped>")
.finish()
}
}
impl<T> Validate<Option<T>> for RequiredValidation<Option<T>> {
fn validate(&self, value: &Option<T>) -> bool {
value.is_some()
}
}
#[validator]
#[derive(Clone, Debug)]
pub struct MatchesStringValidation {
pub expected: String,
#[koruma(value)]
actual: String,
}
impl Validate<String> for MatchesStringValidation {
fn validate(&self, value: &String) -> bool {
value == &self.expected
}
}
#[validator]
#[derive(Clone, Debug)]
pub struct MatchesStaticStrValidation {
pub expected: &'static str,
#[koruma(value)]
actual: String,
}
impl Validate<String> for MatchesStaticStrValidation {
fn validate(&self, value: &String) -> bool {
value == self.expected
}
}
#[validator]
#[derive(Clone, Debug)]
pub struct StartsWithValidation<T: AsRef<str>> {
pub prefix: &'static str,
#[koruma(value)]
actual: T,
}
impl<T: AsRef<str>> Validate<T> for StartsWithValidation<T> {
fn validate(&self, value: &T) -> bool {
value.as_ref().starts_with(self.prefix)
}
}
impl<T: AsRef<str>> fmt::Display for StartsWithValidation<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Must start with '{}'", self.prefix)
}
}