macro: support Option in deserialization
When deserializing we currently expect all fields to be available, but we actually want Option types to be truly optional... Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
ce5fa31721
commit
50eadf23fb
@ -539,9 +539,10 @@ fn handle_struct_named(
|
||||
});
|
||||
|
||||
field_option_check_or_default_list.extend(quote_spanned! { field_span =>
|
||||
let #field_ident = #field_ident.ok_or_else(|| {
|
||||
::serde::de::Error::missing_field(#field_str)
|
||||
})?;
|
||||
let #field_ident = ::proxmox::api::ApiType::deserialization_check(
|
||||
#field_ident,
|
||||
|| ::serde::de::Error::missing_field(#field_str),
|
||||
)?;
|
||||
});
|
||||
|
||||
field_name_matches.extend(quote_spanned! { field_span =>
|
||||
|
@ -164,7 +164,7 @@ impl dyn ApiMethodInfo + Send + Sync {
|
||||
/// While this is very useful for structural types, we sometimes to want to be able to pass a
|
||||
/// simple unconstrainted type like a `String` with no restrictions, so most basic types implement
|
||||
/// `ApiType` as well.
|
||||
pub trait ApiType {
|
||||
pub trait ApiType: Sized {
|
||||
/// API types need to provide a `TypeInfo`, providing details about the underlying type.
|
||||
fn type_info() -> &'static TypeInfo;
|
||||
|
||||
@ -190,6 +190,14 @@ pub trait ApiType {
|
||||
fn should_skip_serialization(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn deserialization_check<F, E>(this: Option<Self>, missing_error: F) -> Result<Self, E>
|
||||
where
|
||||
F: FnOnce() -> E,
|
||||
{
|
||||
this.ok_or_else(missing_error)
|
||||
}
|
||||
}
|
||||
|
||||
/// Option types are supposed to wrap their underlying types with an `optional:` text in their
|
||||
@ -244,6 +252,14 @@ impl<T: ApiType> ApiType for Option<T> {
|
||||
fn should_skip_serialization(&self) -> bool {
|
||||
self.is_none()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn deserialization_check<F, E>(this: Option<Self>, _missing_error: F) -> Result<Self, E>
|
||||
where
|
||||
F: FnOnce() -> E,
|
||||
{
|
||||
Ok(this.unwrap_or(None))
|
||||
}
|
||||
}
|
||||
|
||||
/// Any `Result<T, Error>` of course gets the same info as `T`, since this only means that it can
|
||||
|
Loading…
Reference in New Issue
Block a user