forked from Proxmox/proxmox
api, macro: implement 'format' verifier for structs
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
b77733c8ef
commit
fab0210287
@ -101,6 +101,12 @@ pub struct ParameterDefinition {
|
||||
pub minimum_length: Option<syn::Expr>,
|
||||
#[builder(default)]
|
||||
pub validate: Option<syn::Expr>,
|
||||
|
||||
/// Formats are module paths. The module must contain a verify function:
|
||||
/// `fn verify(Option<&str>) -> bool`, and a `NAME` constant used in error messages to refer to
|
||||
/// the format name.
|
||||
#[builder(default)]
|
||||
pub format: Option<syn::Path>,
|
||||
}
|
||||
|
||||
impl ParameterDefinition {
|
||||
@ -135,6 +141,9 @@ impl ParameterDefinition {
|
||||
"validate" => {
|
||||
def.validate(Some(value.expect_expr()?));
|
||||
}
|
||||
"format" => {
|
||||
def.format(Some(value.expect_path()?));
|
||||
}
|
||||
other => c_bail!(key.span(), "invalid key in type definition: {}", other),
|
||||
}
|
||||
}
|
||||
|
@ -635,6 +635,18 @@ fn named_struct_impl_verify(span: Span, fields: &[StructField]) -> Result<TokenS
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(ref value) = field.def.format {
|
||||
body.extend(quote_spanned! { value.span() =>
|
||||
if !#value::verify(::proxmox::api::meta::AsOptionStr::as_option_str(
|
||||
&self.#field_ident,
|
||||
)) {
|
||||
error_string.push_str(
|
||||
&format!("field {} does not match format {}", #field_str, #value::NAME)
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if !body.is_empty() {
|
||||
|
@ -257,6 +257,13 @@ impl Expression {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expect_path(self) -> Result<syn::Path, Error> {
|
||||
match self {
|
||||
Expression::Expr(Expr::Path(path)) => Ok(path.path),
|
||||
other => c_bail!(other.span(), "expected expression, found {:?}", other),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expect_object(self) -> Result<Object, Error> {
|
||||
match self {
|
||||
Expression::Object(obj) => Ok(obj),
|
||||
|
@ -26,3 +26,31 @@ where
|
||||
*self = Some(value);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AsOptionStr {
|
||||
fn as_option_str(&self) -> Option<&str>;
|
||||
}
|
||||
|
||||
impl AsOptionStr for String {
|
||||
fn as_option_str(&self) -> Option<&str> {
|
||||
Some(self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl AsOptionStr for str {
|
||||
fn as_option_str(&self) -> Option<&str> {
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsOptionStr for Option<String> {
|
||||
fn as_option_str(&self) -> Option<&str> {
|
||||
self.as_ref().map(String::as_str)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsOptionStr for Option<&str> {
|
||||
fn as_option_str(&self) -> Option<&str> {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user