use std::borrow::Cow;
#[derive(Debug, Clone)]
pub struct Length {
pub min: Option<u64>,
pub max: Option<u64>,
pub eq: Option<u64>,
}
#[cfg(feature = "proc")]
impl quote::ToTokens for Length {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
use quote::quote;
let min = if let Some(min) = self.min {
quote!(Some(#min))
} else {
quote!(None)
};
let max = if let Some(max) = self.max {
quote!(Some(#max))
} else {
quote!(None)
};
let eq = if let Some(eq) = self.eq {
quote!(Some(#eq))
} else {
quote!(None)
};
tokens.extend(quote! {
(::prove::length::Length {
min: #min,
max: #max,
eq: #eq,
})
});
}
}
impl Length {
pub fn validate<T>(&self, val: T) -> bool
where
T: HasLen,
{
if let Some(len) = val.length() {
if let Some(eq) = self.eq {
return len == eq;
}
if let Some(min) = self.min {
if len < min {
return false;
}
}
if let Some(max) = self.max {
if len > max {
return false;
}
}
}
true
}
}
pub trait HasLen {
fn length(&self) -> Option<u64>;
}
impl HasLen for String {
fn length(&self) -> Option<u64> {
Some(self.chars().count() as u64)
}
}
impl<'a> HasLen for &'a String {
fn length(&self) -> Option<u64> {
Some(self.chars().count() as u64)
}
}
impl<'a> HasLen for &'a str {
fn length(&self) -> Option<u64> {
Some(self.chars().count() as u64)
}
}
impl<'a> HasLen for Cow<'a, str> {
fn length(&self) -> Option<u64> {
Some(self.len() as u64)
}
}
impl<T> HasLen for Vec<T> {
fn length(&self) -> Option<u64> {
Some(self.len() as u64)
}
}
impl<'a, T> HasLen for &'a Vec<T> {
fn length(&self) -> Option<u64> {
Some(self.len() as u64)
}
}
impl<T> HasLen for Option<T>
where
T: HasLen,
{
fn length(&self) -> Option<u64> {
match self {
None => None,
Some(v) => v.length(),
}
}
}
impl<'a, T> HasLen for &'a Option<T>
where
T: HasLen,
{
fn length(&self) -> Option<u64> {
match self {
None => None,
Some(v) => v.length(),
}
}
}