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")))]
|
#[cfg(all(feature = "unstable", feature = "alloc", not(feature = "std")))]
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
#[cfg(feature = "unstable")]
|
#[cfg(feature = "unstable")]
|
||||||
use core::nonzero::{NonZero, Zeroable};
|
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")]
|
#[cfg(feature = "unstable")]
|
||||||
impl<T> Deserialize for NonZero<T> where T: Deserialize + PartialEq + Zeroable + Zero {
|
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 {
|
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;
|
use std::rc::Rc;
|
||||||
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
use alloc::rc::Rc;
|
use alloc::rc::Rc;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::sync::Arc;
|
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"))]
|
#[cfg(all(feature = "std", feature = "unstable"))]
|
||||||
impl Serialize for net::IpAddr {
|
impl Serialize for net::IpAddr {
|
||||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
|
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
|
||||||
use std::net;
|
use std::net;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
@ -745,6 +746,28 @@ declare_tests! {
|
|||||||
Token::SeqEnd,
|
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 {
|
test_net_ipv4addr {
|
||||||
"1.2.3.4".parse::<net::Ipv4Addr>().unwrap() => &[Token::Str("1.2.3.4")],
|
"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::net;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::str;
|
use std::str;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
extern crate serde_test;
|
extern crate serde_test;
|
||||||
use self::serde_test::{
|
use self::serde_test::{
|
||||||
@ -324,6 +325,19 @@ declare_ser_tests! {
|
|||||||
Token::SeqEnd,
|
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 {
|
test_net_ipv4addr {
|
||||||
"1.2.3.4".parse::<net::Ipv4Addr>().unwrap() => &[Token::Str("1.2.3.4")],
|
"1.2.3.4".parse::<net::Ipv4Addr>().unwrap() => &[Token::Str("1.2.3.4")],
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user