Serialize and Deserialize for std::time::Duration
This commit is contained in:
parent
b289edd4a4
commit
c4b5a42615
@ -53,6 +53,9 @@ use alloc::arc::Arc;
|
||||
#[cfg(all(feature = "unstable", feature = "alloc", not(feature = "std")))]
|
||||
use alloc::boxed::Box;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::time::Duration;
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
use core::nonzero::{NonZero, Zeroable};
|
||||
|
||||
@ -982,6 +985,135 @@ impl<'a, T: ?Sized> Deserialize for Cow<'a, T> where T: ToOwned, T::Owned: Deser
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// This is a cleaned-up version of the impl generated by:
|
||||
//
|
||||
// #[derive(Deserialize)]
|
||||
// #[serde(deny_unknown_fields)]
|
||||
// struct Duration {
|
||||
// secs: u64,
|
||||
// nanos: u32,
|
||||
// }
|
||||
#[cfg(feature = "std")]
|
||||
impl Deserialize for Duration {
|
||||
fn deserialize<D>(deserializer: &mut D) -> Result<Self, D::Error>
|
||||
where D: Deserializer,
|
||||
{
|
||||
enum Field { Secs, Nanos };
|
||||
|
||||
impl Deserialize for Field {
|
||||
fn deserialize<D>(deserializer: &mut D) -> Result<Field, D::Error>
|
||||
where D: Deserializer,
|
||||
{
|
||||
struct FieldVisitor;
|
||||
|
||||
impl Visitor for FieldVisitor {
|
||||
type Value = Field;
|
||||
|
||||
fn visit_usize<E>(&mut self, value: usize) -> Result<Field, E>
|
||||
where E: Error,
|
||||
{
|
||||
match value {
|
||||
0usize => Ok(Field::Secs),
|
||||
1usize => Ok(Field::Nanos),
|
||||
_ => Err(Error::invalid_value("expected a field")),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_str<E>(&mut self, value: &str) -> Result<Field, E>
|
||||
where E: Error,
|
||||
{
|
||||
match value {
|
||||
"secs" => Ok(Field::Secs),
|
||||
"nanos" => Ok(Field::Nanos),
|
||||
_ => Err(Error::unknown_field(value)),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(&mut self, value: &[u8]) -> Result<Field, E>
|
||||
where E: Error,
|
||||
{
|
||||
match value {
|
||||
b"secs" => Ok(Field::Secs),
|
||||
b"nanos" => Ok(Field::Nanos),
|
||||
_ => {
|
||||
let value = String::from_utf8_lossy(value);
|
||||
Err(Error::unknown_field(&value))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_struct_field(FieldVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
struct DurationVisitor;
|
||||
|
||||
impl Visitor for DurationVisitor {
|
||||
type Value = Duration;
|
||||
|
||||
fn visit_seq<V>(&mut self, mut visitor: V) -> Result<Duration, V::Error>
|
||||
where V: SeqVisitor,
|
||||
{
|
||||
let secs: u64 = match try!(visitor.visit()) {
|
||||
Some(value) => value,
|
||||
None => {
|
||||
try!(visitor.end());
|
||||
return Err(Error::invalid_length(0));
|
||||
}
|
||||
};
|
||||
let nanos: u32 = match try!(visitor.visit()) {
|
||||
Some(value) => value,
|
||||
None => {
|
||||
try!(visitor.end());
|
||||
return Err(Error::invalid_length(1));
|
||||
}
|
||||
};
|
||||
try!(visitor.end());
|
||||
Ok(Duration::new(secs, nanos))
|
||||
}
|
||||
|
||||
fn visit_map<V>(&mut self, mut visitor: V) -> Result<Duration, V::Error>
|
||||
where V: MapVisitor,
|
||||
{
|
||||
let mut secs: Option<u64> = None;
|
||||
let mut nanos: Option<u32> = None;
|
||||
while let Some(key) = try!(visitor.visit_key::<Field>()) {
|
||||
match key {
|
||||
Field::Secs => {
|
||||
if secs.is_some() {
|
||||
return Err(<V::Error as Error>::duplicate_field("secs"));
|
||||
}
|
||||
secs = Some(try!(visitor.visit_value()));
|
||||
}
|
||||
Field::Nanos => {
|
||||
if nanos.is_some() {
|
||||
return Err(<V::Error as Error>::duplicate_field("nanos"));
|
||||
}
|
||||
nanos = Some(try!(visitor.visit_value()));
|
||||
}
|
||||
}
|
||||
}
|
||||
try!(visitor.end());
|
||||
let secs = match secs {
|
||||
Some(secs) => secs,
|
||||
None => try!(visitor.missing_field("secs")),
|
||||
};
|
||||
let nanos = match nanos {
|
||||
Some(nanos) => nanos,
|
||||
None => try!(visitor.missing_field("nanos")),
|
||||
};
|
||||
Ok(Duration::new(secs, nanos))
|
||||
}
|
||||
}
|
||||
|
||||
const FIELDS: &'static [&'static str] = &["secs", "nanos"];
|
||||
deserializer.deserialize_struct("Duration", FIELDS, DurationVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
impl<T> Deserialize for NonZero<T> where T: Deserialize + PartialEq + Zeroable + Zero {
|
||||
fn deserialize<D>(deserializer: &mut D) -> Result<NonZero<T>, D::Error> where D: Deserializer {
|
||||
|
@ -50,6 +50,8 @@ use std::path;
|
||||
use std::rc::Rc;
|
||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||
use alloc::rc::Rc;
|
||||
#[cfg(feature = "std")]
|
||||
use std::time::Duration;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::sync::Arc;
|
||||
@ -624,6 +626,20 @@ impl<T, E> Serialize for Result<T, E> where T: Serialize, E: Serialize {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Serialize for Duration {
|
||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||
where S: Serializer,
|
||||
{
|
||||
let mut state = try!(serializer.serialize_struct("Duration", 2));
|
||||
try!(serializer.serialize_struct_elt(&mut state, "secs", self.as_secs()));
|
||||
try!(serializer.serialize_struct_elt(&mut state, "nanos", self.subsec_nanos()));
|
||||
serializer.serialize_struct_end(state)
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(all(feature = "std", feature = "unstable"))]
|
||||
impl Serialize for net::IpAddr {
|
||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||
|
@ -1,6 +1,7 @@
|
||||
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
|
||||
use std::net;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Duration;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
@ -745,6 +746,28 @@ declare_tests! {
|
||||
Token::SeqEnd,
|
||||
],
|
||||
}
|
||||
test_duration {
|
||||
Duration::new(1, 2) => &[
|
||||
Token::StructStart("Duration", 2),
|
||||
Token::StructSep,
|
||||
Token::Str("secs"),
|
||||
Token::U64(1),
|
||||
|
||||
Token::StructSep,
|
||||
Token::Str("nanos"),
|
||||
Token::U32(2),
|
||||
Token::StructEnd,
|
||||
],
|
||||
Duration::new(1, 2) => &[
|
||||
Token::SeqStart(Some(2)),
|
||||
Token::SeqSep,
|
||||
Token::I64(1),
|
||||
|
||||
Token::SeqSep,
|
||||
Token::I64(2),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
}
|
||||
test_net_ipv4addr {
|
||||
"1.2.3.4".parse::<net::Ipv4Addr>().unwrap() => &[Token::Str("1.2.3.4")],
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
use std::net;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str;
|
||||
use std::time::Duration;
|
||||
|
||||
extern crate serde_test;
|
||||
use self::serde_test::{
|
||||
@ -324,6 +325,19 @@ declare_ser_tests! {
|
||||
Token::SeqEnd,
|
||||
],
|
||||
}
|
||||
test_duration {
|
||||
Duration::new(1, 2) => &[
|
||||
Token::StructStart("Duration", 2),
|
||||
Token::StructSep,
|
||||
Token::Str("secs"),
|
||||
Token::U64(1),
|
||||
|
||||
Token::StructSep,
|
||||
Token::Str("nanos"),
|
||||
Token::U32(2),
|
||||
Token::StructEnd,
|
||||
],
|
||||
}
|
||||
test_net_ipv4addr {
|
||||
"1.2.3.4".parse::<net::Ipv4Addr>().unwrap() => &[Token::Str("1.2.3.4")],
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user