mirror of
https://git.proxmox.com/git/proxmox
synced 2025-08-06 22:00:02 +00:00
macro: support 'pattern' verifier in structs
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
26e4b205ac
commit
3c31381fb2
@ -108,6 +108,12 @@ pub struct ParameterDefinition {
|
|||||||
#[builder(default)]
|
#[builder(default)]
|
||||||
pub format: Option<syn::Path>,
|
pub format: Option<syn::Path>,
|
||||||
|
|
||||||
|
/// Patterns are regular expressions. When a literal string is provided, a `lazy_static` regex
|
||||||
|
/// is created for the verifier. Otherwise it is taken as an expression (i.e. a path) to an
|
||||||
|
/// existing regex variable/method.
|
||||||
|
#[builder(default)]
|
||||||
|
pub pattern: Option<syn::Expr>,
|
||||||
|
|
||||||
#[builder(default)]
|
#[builder(default)]
|
||||||
pub serialize_with: Option<syn::Path>,
|
pub serialize_with: Option<syn::Path>,
|
||||||
#[builder(default)]
|
#[builder(default)]
|
||||||
@ -149,6 +155,9 @@ impl ParameterDefinition {
|
|||||||
"format" => {
|
"format" => {
|
||||||
def.format(Some(value.expect_path()?));
|
def.format(Some(value.expect_path()?));
|
||||||
}
|
}
|
||||||
|
"pattern" => {
|
||||||
|
def.pattern(Some(value.expect_expr()?));
|
||||||
|
}
|
||||||
"serialize_with" => {
|
"serialize_with" => {
|
||||||
def.serialize_with(Some(value.expect_path()?));
|
def.serialize_with(Some(value.expect_path()?));
|
||||||
}
|
}
|
||||||
|
@ -510,6 +510,12 @@ fn handle_struct_named(
|
|||||||
bail!("derive_default is not finished");
|
bail!("derive_default is not finished");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let serialize_as_string = definition
|
||||||
|
.remove("serialize_as_string")
|
||||||
|
.map(|e| e.expect_lit_bool_direct())
|
||||||
|
.transpose()?
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
let type_s = type_ident.to_string();
|
let type_s = type_ident.to_string();
|
||||||
let type_span = type_ident.span();
|
let type_span = type_ident.span();
|
||||||
let type_str = syn::LitStr::new(&type_s, type_span);
|
let type_str = syn::LitStr::new(&type_s, type_span);
|
||||||
@ -541,10 +547,23 @@ fn handle_struct_named(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let impl_verify = named_struct_impl_verify(item.span(), &fields)?;
|
let impl_verify = named_struct_impl_verify(item.span(), &fields)?;
|
||||||
let impl_serialize =
|
let (impl_serialize, impl_deserialize) = if serialize_as_string {
|
||||||
named_struct_derive_serialize(item.span(), type_ident, &type_str, &fields)?;
|
let expected = format!("valid {}", type_ident);
|
||||||
let impl_deserialize =
|
(
|
||||||
named_struct_derive_deserialize(item.span(), type_ident, &type_str, &fields)?;
|
quote_spanned! { item.span() =>
|
||||||
|
::serde_plain::derive_serialize_from_display!(#type_ident);
|
||||||
|
},
|
||||||
|
quote_spanned! { item.span() =>
|
||||||
|
::serde_plain::derive_deserialize_from_str!(#type_ident, #expected);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
named_struct_derive_serialize(item.span(), type_ident, &type_str, &fields)?,
|
||||||
|
named_struct_derive_deserialize(item.span(), type_ident, &type_str, &fields)?,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
let accessors = named_struct_impl_accessors(item.span(), type_ident, &fields)?;
|
let accessors = named_struct_impl_accessors(item.span(), type_ident, &fields)?;
|
||||||
|
|
||||||
let impl_default = if derive_default {
|
let impl_default = if derive_default {
|
||||||
@ -645,6 +664,32 @@ fn named_struct_impl_verify(span: Span, fields: &[StructField]) -> Result<TokenS
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(ref value) = field.def.pattern {
|
||||||
|
match value {
|
||||||
|
syn::Expr::Lit(regex) => body.extend(quote_spanned! { value.span() =>
|
||||||
|
{
|
||||||
|
::lazy_static::lazy_static! {
|
||||||
|
static ref RE: ::regex::Regex = ::regex::Regex::new(#regex).unwrap();
|
||||||
|
}
|
||||||
|
if !RE.is_match(&self.#field_ident) {
|
||||||
|
error_string.push_str(&format!(
|
||||||
|
"field {} does not match the allowed pattern: {}",
|
||||||
|
#field_str,
|
||||||
|
#regex,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
regex => body.extend(quote_spanned! { value.span() =>
|
||||||
|
if !#regex.is_match(&self.#field_ident) {
|
||||||
|
error_string.push_str(
|
||||||
|
&format!("field {} does not match the allowed pattern", #field_str)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !body.is_empty() {
|
if !body.is_empty() {
|
||||||
|
Loading…
Reference in New Issue
Block a user