Created
February 9, 2019 20:04
-
-
Save rust-play/2e212d29e38110fc3d8f22ff920712be to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::fmt; | |
use serde::de::{self, Deserialize, Deserializer, Visitor, SeqAccess, MapAccess}; | |
#[allow(dead_code)] | |
struct Duration { | |
secs: u64, | |
nanos: u32, | |
} | |
impl Duration { | |
fn new(_: u64, _: u32) -> Self { | |
unimplemented!() | |
} | |
} | |
impl<'de> Deserialize<'de> for Duration { | |
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | |
where | |
D: Deserializer<'de>, | |
{ | |
enum Field { Secs, Nanos }; | |
// This part could also be generated independently by: | |
// | |
// #[derive(Deserialize)] | |
// #[serde(field_identifier, rename_all = "lowercase")] | |
// enum Field { Secs, Nanos } | |
impl<'de> Deserialize<'de> for Field { | |
fn deserialize<D>(deserializer: D) -> Result<Field, D::Error> | |
where | |
D: Deserializer<'de>, | |
{ | |
struct FieldVisitor; | |
impl<'de> Visitor<'de> for FieldVisitor { | |
type Value = Field; | |
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
formatter.write_str("`secs` or `nanos`") | |
} | |
fn visit_str<E>(self, value: &str) -> Result<Field, E> | |
where | |
E: de::Error, | |
{ | |
match value { | |
"secs" => Ok(Field::Secs), | |
"nanos" => Ok(Field::Nanos), | |
_ => Err(de::Error::unknown_field(value, FIELDS)), | |
} | |
} | |
} | |
deserializer.deserialize_identifier(FieldVisitor) | |
} | |
} | |
struct DurationVisitor; | |
impl<'de> Visitor<'de> for DurationVisitor { | |
type Value = Duration; | |
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
formatter.write_str("struct Duration") | |
} | |
fn visit_seq<V>(self, mut seq: V) -> Result<Duration, V::Error> | |
where | |
V: SeqAccess<'de>, | |
{ | |
let secs = seq.next_element()? | |
.ok_or_else(|| de::Error::invalid_length(0, &self))?; | |
let nanos = seq.next_element()? | |
.ok_or_else(|| de::Error::invalid_length(1, &self))?; | |
Ok(Duration::new(secs, nanos)) | |
} | |
fn visit_map<V>(self, mut map: V) -> Result<Duration, V::Error> | |
where | |
V: MapAccess<'de>, | |
{ | |
let mut secs = None; | |
let mut nanos = None; | |
while let Some(key) = map.next_key()? { | |
match key { | |
Field::Secs => { | |
if secs.is_some() { | |
return Err(de::Error::duplicate_field("secs")); | |
} | |
secs = Some(map.next_value()?); | |
} | |
Field::Nanos => { | |
if nanos.is_some() { | |
return Err(de::Error::duplicate_field("nanos")); | |
} | |
nanos = Some(map.next_value()?); | |
} | |
} | |
} | |
let secs = secs.ok_or_else(|| de::Error::missing_field("secs"))?; | |
let nanos = nanos.ok_or_else(|| de::Error::missing_field("nanos"))?; | |
Ok(Duration::new(secs, nanos)) | |
} | |
} | |
const FIELDS: &'static [&'static str] = &["secs", "nanos"]; | |
deserializer.deserialize_struct("Duration", FIELDS, DurationVisitor) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment