use super::*;
use serde::de::{Deserializer, EnumAccess, VariantAccess, Visitor};
use std::fmt::{self, Formatter};
macro_rules! impl_deserialize_choice {
($name:ident : $(($field:ident, $field_name:literal)),*) => {
impl<'de> Deserialize<'de> for $name {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
#[serde(field_identifier)]
#[serde(rename_all = "kebab-case")]
enum Tag {
$($field,)*
Other(String),
}
struct EnumVisitor;
impl<'de> Visitor<'de> for EnumVisitor {
type Value = $name;
fn expecting(&self, f: &mut Formatter) -> fmt::Result {
f.write_str("enum ")?;
f.write_str(stringify!($name))
}
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
where
A: EnumAccess<'de>,
{
match data.variant()? {
$(
(Tag::$field, variant) => variant.unit_variant().map(|_| $name::$field),
)*
(Tag::Other(t), v) => v.unit_variant().map(|_| $name::Other(t)),
}
}
}
const VARIANTS: &'static [&'static str] = &[
$($field_name,)*
"<any other tag>"
];
deserializer.deserialize_enum(stringify!($name), VARIANTS, EnumVisitor)
}
}
};
}
#[derive(Debug, PartialEq)]
enum Choice {
One,
Two,
Other(String),
}
impl_deserialize_choice!(Choice: (One, "one"), (Two, "two"));
#[allow(dead_code)]
#[derive(Debug, PartialEq)]
enum Choice2 {
First,
Second,
Other(String),
}
impl_deserialize_choice!(Choice2: (First, "first"), (Second, "second"));
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename_all = "kebab-case")]
enum Choice3 {
One(usize),
Two(String),
#[serde(other)]
Other,
}
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename_all = "kebab-case")]
enum Choice4 {
One {
inner: [(); 1],
},
Two {
inner: [(); 1],
},
#[serde(other)]
Other,
}
#[path = "variable_name/fixed_size.rs"]
mod fixed_size;
#[path = "variable_name/variable_size.rs"]
mod variable_size;