forked from proxmox-mirrors/proxmox
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 =>
|
field_option_check_or_default_list.extend(quote_spanned! { field_span =>
|
||||||
let #field_ident = #field_ident.ok_or_else(|| {
|
let #field_ident = ::proxmox::api::ApiType::deserialization_check(
|
||||||
::serde::de::Error::missing_field(#field_str)
|
#field_ident,
|
||||||
})?;
|
|| ::serde::de::Error::missing_field(#field_str),
|
||||||
|
)?;
|
||||||
});
|
});
|
||||||
|
|
||||||
field_name_matches.extend(quote_spanned! { field_span =>
|
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
|
/// 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
|
/// simple unconstrainted type like a `String` with no restrictions, so most basic types implement
|
||||||
/// `ApiType` as well.
|
/// `ApiType` as well.
|
||||||
pub trait ApiType {
|
pub trait ApiType: Sized {
|
||||||
/// API types need to provide a `TypeInfo`, providing details about the underlying type.
|
/// API types need to provide a `TypeInfo`, providing details about the underlying type.
|
||||||
fn type_info() -> &'static TypeInfo;
|
fn type_info() -> &'static TypeInfo;
|
||||||
|
|
||||||
@ -190,6 +190,14 @@ pub trait ApiType {
|
|||||||
fn should_skip_serialization(&self) -> bool {
|
fn should_skip_serialization(&self) -> bool {
|
||||||
false
|
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
|
/// 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 {
|
fn should_skip_serialization(&self) -> bool {
|
||||||
self.is_none()
|
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
|
/// 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