api: macro: implement minimum/maximum_length checks
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
f1f4c14819
commit
b77733c8ef
@ -96,6 +96,10 @@ pub struct ParameterDefinition {
|
||||
#[builder(default)]
|
||||
pub minimum: Option<syn::Expr>,
|
||||
#[builder(default)]
|
||||
pub maximum_length: Option<syn::Expr>,
|
||||
#[builder(default)]
|
||||
pub minimum_length: Option<syn::Expr>,
|
||||
#[builder(default)]
|
||||
pub validate: Option<syn::Expr>,
|
||||
}
|
||||
|
||||
@ -122,6 +126,12 @@ impl ParameterDefinition {
|
||||
"minimum" => {
|
||||
def.minimum(Some(value.expect_expr()?));
|
||||
}
|
||||
"maximum_length" => {
|
||||
def.maximum_length(Some(value.expect_expr()?));
|
||||
}
|
||||
"minimum_length" => {
|
||||
def.minimum_length(Some(value.expect_expr()?));
|
||||
}
|
||||
"validate" => {
|
||||
def.validate(Some(value.expect_expr()?));
|
||||
}
|
||||
|
@ -580,32 +580,57 @@ fn handle_struct_named(
|
||||
})
|
||||
}
|
||||
|
||||
fn named_struct_impl_verify(
|
||||
span: Span,
|
||||
fields: &[StructField],
|
||||
) -> Result<TokenStream, Error> {
|
||||
fn named_struct_impl_verify(span: Span, fields: &[StructField]) -> Result<TokenStream, Error> {
|
||||
let mut body = TokenStream::new();
|
||||
for field in fields {
|
||||
let field_ident = field.ident;
|
||||
let field_str = &field.strlit;
|
||||
|
||||
if let Some(ref minimum) = field.def.minimum {
|
||||
body.extend(quote_spanned! { minimum.span() =>
|
||||
let minimum = #minimum;
|
||||
if !::proxmox::api::verify::TestMinMax::test_minimum(&self.#field_ident, &minimum) {
|
||||
if let Some(ref value) = field.def.minimum {
|
||||
body.extend(quote_spanned! { value.span() =>
|
||||
let value = #value;
|
||||
if !::proxmox::api::verify::TestMinMax::test_minimum(&self.#field_ident, &value) {
|
||||
error_string.push_str(
|
||||
&format!("field {} out of range, must be >= {}", #field_str, minimum)
|
||||
&format!("field {} out of range, must be >= {}", #field_str, value)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(ref maximum) = field.def.maximum {
|
||||
body.extend(quote_spanned! { maximum.span() =>
|
||||
let maximum = #maximum;
|
||||
if !::proxmox::api::verify::TestMinMax::test_maximum(&self.#field_ident, &maximum) {
|
||||
if let Some(ref value) = field.def.maximum {
|
||||
body.extend(quote_spanned! { value.span() =>
|
||||
let value = #value;
|
||||
if !::proxmox::api::verify::TestMinMax::test_maximum(&self.#field_ident, &value) {
|
||||
error_string.push_str(
|
||||
&format!("field {} out of range, must be <= {}", #field_str, maximum)
|
||||
&format!("field {} out of range, must be <= {}", #field_str, value)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(ref value) = field.def.minimum_length {
|
||||
body.extend(quote_spanned! { value.span() =>
|
||||
let value = #value;
|
||||
if !::proxmox::api::verify::TestMinMaxLen::test_minimum_length(
|
||||
&self.#field_ident,
|
||||
value,
|
||||
) {
|
||||
error_string.push_str(
|
||||
&format!("field {} too short, must be >= {} characters", #field_str, value)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(ref value) = field.def.maximum_length {
|
||||
body.extend(quote_spanned! { value.span() =>
|
||||
let value = #value;
|
||||
if !::proxmox::api::verify::TestMinMaxLen::test_maximum_length(
|
||||
&self.#field_ident,
|
||||
value,
|
||||
) {
|
||||
error_string.push_str(
|
||||
&format!("field {} too long, must be <= {} characters", #field_str, value)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -74,3 +74,32 @@ where
|
||||
self.as_ref().map(|x| *x <= *maximum).unwrap_or(true)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TestMinMaxLen<Mark> {
|
||||
fn test_minimum_length(&self, minimum: usize) -> bool;
|
||||
fn test_maximum_length(&self, maximum: usize) -> bool;
|
||||
}
|
||||
|
||||
impl<T: AsRef<str>> TestMinMaxLen<mark::Default> for T {
|
||||
#[inline]
|
||||
fn test_minimum_length(&self, minimum: usize) -> bool {
|
||||
self.as_ref().len() >= minimum
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn test_maximum_length(&self, maximum: usize) -> bool {
|
||||
self.as_ref().len() <= maximum
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsRef<str>> TestMinMaxLen<mark::Special> for Option<T> {
|
||||
#[inline]
|
||||
fn test_minimum_length(&self, minimum: usize) -> bool {
|
||||
self.as_ref().map(|x| x.as_ref().len() >= minimum).unwrap_or(true)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn test_maximum_length(&self, maximum: usize) -> bool {
|
||||
self.as_ref().map(|x| x.as_ref().len() <= maximum).unwrap_or(true)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user