Use the variant_identifier macro for OsString

This commit is contained in:
Markus Westerlind 2017-09-14 17:04:26 +02:00
parent e36915300f
commit 945d12c0b4

View File

@ -887,13 +887,17 @@ macro_rules! parse_ip_impl {
} }
} }
macro_rules! deserialize_enum { macro_rules! variant_identifier {
($name: ident $name_kind: ident ( $($variant: ident; $bytes: expr; $index: expr),* ) $deserializer: expr) => { (
$name_kind: ident ( $($variant: ident; $bytes: expr; $index: expr),* )
$expecting_message: expr,
$variants_name: ident
) => {
enum $name_kind { enum $name_kind {
$( $variant ),* $( $variant ),*
} }
static VARIANTS: &'static [&'static str] = &[ $( stringify!($variant) ),*]; static $variants_name: &'static [&'static str] = &[ $( stringify!($variant) ),*];
impl<'de> Deserialize<'de> for $name_kind { impl<'de> Deserialize<'de> for $name_kind {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
@ -906,7 +910,7 @@ macro_rules! deserialize_enum {
type Value = $name_kind; type Value = $name_kind;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("`V4` or `V6`") formatter.write_str($expecting_message)
} }
fn visit_u32<E>(self, value: u32) -> Result<Self::Value, E> fn visit_u32<E>(self, value: u32) -> Result<Self::Value, E>
@ -929,7 +933,7 @@ macro_rules! deserialize_enum {
$( $(
stringify!($variant) => Ok($name_kind :: $variant), stringify!($variant) => Ok($name_kind :: $variant),
)* )*
_ => Err(Error::unknown_variant(value, VARIANTS)), _ => Err(Error::unknown_variant(value, $variants_name)),
} }
} }
@ -943,7 +947,7 @@ macro_rules! deserialize_enum {
)* )*
_ => { _ => {
match str::from_utf8(value) { match str::from_utf8(value) {
Ok(value) => Err(Error::unknown_variant(value, VARIANTS)), Ok(value) => Err(Error::unknown_variant(value, $variants_name)),
Err(_) => Err(Error::invalid_value(Unexpected::Bytes(value), &self)), Err(_) => Err(Error::invalid_value(Unexpected::Bytes(value), &self)),
} }
} }
@ -954,6 +958,20 @@ macro_rules! deserialize_enum {
deserializer.deserialize_identifier(KindVisitor) deserializer.deserialize_identifier(KindVisitor)
} }
} }
}
}
macro_rules! deserialize_enum {
(
$name: ident $name_kind: ident ( $($variant: ident; $bytes: expr; $index: expr),* )
$expecting_message: expr,
$deserializer: expr
) => {
variant_identifier!{
$name_kind ( $($variant; $bytes; $index),* )
$expecting_message,
VARIANTS
}
struct EnumVisitor; struct EnumVisitor;
impl<'de> Visitor<'de> for EnumVisitor { impl<'de> Visitor<'de> for EnumVisitor {
@ -991,7 +1009,9 @@ impl<'de> Deserialize<'de> for net::IpAddr {
} else { } else {
use self::net::IpAddr; use self::net::IpAddr;
deserialize_enum!{ deserialize_enum!{
IpAddr IpAddrKind (V4; b"V4"; 0, V6; b"V6"; 1) deserializer IpAddr IpAddrKind (V4; b"V4"; 0, V6; b"V6"; 1)
"`V4` or `V6`",
deserializer
} }
} }
} }
@ -1034,7 +1054,9 @@ impl<'de> Deserialize<'de> for net::SocketAddr {
} else { } else {
use self::net::SocketAddr; use self::net::SocketAddr;
deserialize_enum!{ deserialize_enum!{
SocketAddr SocketAddrKind (V4; b"V4"; 0, V6; b"V6"; 1) deserializer SocketAddr SocketAddrKind (V4; b"V4"; 0, V6; b"V6"; 1)
"`V4` or `V6`",
deserializer
} }
} }
} }
@ -1129,70 +1151,10 @@ impl<'de> Deserialize<'de> for PathBuf {
// #[derive(Deserialize)] // #[derive(Deserialize)]
// #[serde(variant_identifier)] // #[serde(variant_identifier)]
#[cfg(all(feature = "std", any(unix, windows)))] #[cfg(all(feature = "std", any(unix, windows)))]
enum OsStringKind { variant_identifier!{
Unix, OsStringKind (Unix; b"Unix"; 0, Windows; b"Windows"; 1)
Windows, "`Unix` or `Windows`",
} OSSTR_VARIANTS
#[cfg(all(feature = "std", any(unix, windows)))]
static OSSTR_VARIANTS: &'static [&'static str] = &["Unix", "Windows"];
#[cfg(all(feature = "std", any(unix, windows)))]
impl<'de> Deserialize<'de> for OsStringKind {
fn deserialize<D>(deserializer: D) -> Result<OsStringKind, D::Error>
where
D: Deserializer<'de>,
{
struct KindVisitor;
impl<'de> Visitor<'de> for KindVisitor {
type Value = OsStringKind;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("`Unix` or `Windows`")
}
fn visit_u32<E>(self, value: u32) -> Result<OsStringKind, E>
where
E: Error,
{
match value {
0 => Ok(OsStringKind::Unix),
1 => Ok(OsStringKind::Windows),
_ => Err(Error::invalid_value(Unexpected::Unsigned(value as u64), &self),),
}
}
fn visit_str<E>(self, value: &str) -> Result<OsStringKind, E>
where
E: Error,
{
match value {
"Unix" => Ok(OsStringKind::Unix),
"Windows" => Ok(OsStringKind::Windows),
_ => Err(Error::unknown_variant(value, OSSTR_VARIANTS)),
}
}
fn visit_bytes<E>(self, value: &[u8]) -> Result<OsStringKind, E>
where
E: Error,
{
match value {
b"Unix" => Ok(OsStringKind::Unix),
b"Windows" => Ok(OsStringKind::Windows),
_ => {
match str::from_utf8(value) {
Ok(value) => Err(Error::unknown_variant(value, OSSTR_VARIANTS)),
Err(_) => Err(Error::invalid_value(Unexpected::Bytes(value), &self)),
}
}
}
}
}
deserializer.deserialize_identifier(KindVisitor)
}
} }
#[cfg(all(feature = "std", any(unix, windows)))] #[cfg(all(feature = "std", any(unix, windows)))]