Skip to content

Commit

Permalink
Implement without unreachable code
Browse files Browse the repository at this point in the history
  • Loading branch information
Mingun committed Apr 29, 2024
1 parent 648775e commit c010ba0
Showing 1 changed file with 54 additions and 16 deletions.
70 changes: 54 additions & 16 deletions src/serde_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,54 @@ macro_rules! deserialize_variant {
});
}

/// Helper macro that generates different match expressions depending on the presence
/// of default variant
#[macro_export]
#[doc(hidden)]
macro_rules! deserialize_match {
// Only default variant
(
$tag:ident, $de:ident, $enum:ty,
(_ => $($default_variant:tt)+ )
$(,)?
) => (
Ok($crate::deserialize_variant!( $de, $enum, $($default_variant)+ ))
);

// With default variant
(
$tag:ident, $de:ident, $enum:ty,
$(
($variant_tag:literal => $($variant:tt)+ )
),*
, (_ => $($default_variant:tt)+ )
$(,)?
) => (
match $tag.as_ref() {
$(
$variant_tag => Ok($crate::deserialize_variant!( $de, $enum, $($variant)+ )),
)*
_ => Ok($crate::deserialize_variant!( $de, $enum, $($default_variant)+ )),
}
);

// Without default variant
(
$tag:ident, $de:ident, $enum:ty,
$(
($variant_tag:literal => $($variant:tt)+ )
),*
$(,)?
) => (
match $tag.as_ref() {
$(
$variant_tag => Ok($crate::deserialize_variant!( $de, $enum, $($variant)+ )),
)*
_ => Err(A::Error::unknown_field(&$tag, &[$($variant_tag),+])),
}
);
}

/// A helper to implement [`Deserialize`] for [internally tagged] enums which
/// does not use [`Deserializer::deserialize_any`] that produces wrong results
/// with XML because of [serde#1183].
Expand Down Expand Up @@ -118,9 +166,10 @@ macro_rules! deserialize_variant {
/// );
/// ```
///
/// You don't necessarily have to provide all the enumeration variants and can use `_` to put every undefined tag into an enumeration variant.
/// This default variant (`_ => ...`) must be the last one to appear in the macro, like `_ => Other` in the example below:
/// # Example
/// You don't necessarily have to provide all the enumeration variants and can use
/// `_` to put every undefined tag into an enumeration variant.
/// This default variant (`_ => ...`) must be the last one to appear in the macro,
/// like `_ => Other` in the example below:
///
/// ```
/// # use pretty_assertions::assert_eq;
Expand Down Expand Up @@ -180,11 +229,7 @@ macro_rules! impl_deserialize_for_internally_tagged_enum {
(
$enum:ty,
$tag:literal,
$(
($variant_tag:literal => $($variant:tt)+ )
),*
$(, (_ => $($default_variant:tt)? ))?
$(,)?
$($cases:tt)*
) => {
impl<'de> serde::de::Deserialize<'de> for $enum {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
Expand Down Expand Up @@ -235,14 +280,7 @@ macro_rules! impl_deserialize_for_internally_tagged_enum {
}?;

let de = serde::de::value::MapAccessDeserializer::new(map);
match tag.as_ref() {
$(
$variant_tag => Ok(deserialize_variant!( de, $enum, $($variant)+ )),
)*
$( _ => Ok(deserialize_variant!( de, $enum, $($default_variant)+ )), )?
#[allow(unreachable)]
_ => Err(A::Error::unknown_field(&tag, &[$($variant_tag),+])),
}
$crate::deserialize_match!( tag, de, $enum, $($cases)* )
}
}
// Tell the deserializer to deserialize the data as a map,
Expand Down

0 comments on commit c010ba0

Please sign in to comment.