1#![warn(missing_docs)]
45#![doc(html_root_url="https://docs.rs/serde-humantime/0.1.1")]
46
47extern crate humantime;
48extern crate serde;
49
50#[cfg(test)]
51#[macro_use]
52extern crate serde_derive;
53#[cfg(test)]
54extern crate serde_json;
55
56use serde::de::{Deserialize, Deserializer, Visitor, Error, Unexpected};
57use std::fmt;
58use std::time::Duration;
59
60pub struct De<T>(T);
65
66impl<T> De<T> {
67 pub fn into_inner(self) -> T {
69 self.0
70 }
71}
72
73impl<'de> Deserialize<'de> for De<Duration> {
74 fn deserialize<D>(d: D) -> Result<De<Duration>, D::Error>
75 where D: Deserializer<'de>
76 {
77 deserialize(d).map(De)
78 }
79}
80
81impl<'de> Deserialize<'de> for De<Option<Duration>> {
82 fn deserialize<D>(d: D) -> Result<De<Option<Duration>>, D::Error>
83 where D: Deserializer<'de>
84 {
85 match Option::<De<Duration>>::deserialize(d)? {
86 Some(De(dur)) => Ok(De(Some(dur))),
87 None => Ok(De(None)),
88 }
89 }
90}
91
92pub fn deserialize<'de, D>(d: D) -> Result<Duration, D::Error>
97 where D: Deserializer<'de>
98{
99 struct V;
100
101 impl<'de2> Visitor<'de2> for V {
102 type Value = Duration;
103
104 fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
105 fmt.write_str("a duration")
106 }
107
108 fn visit_str<E>(self, v: &str) -> Result<Duration, E>
109 where E: Error
110 {
111 humantime::parse_duration(v).map_err(|_| E::invalid_value(Unexpected::Str(v), &self))
112 }
113 }
114
115 d.deserialize_str(V)
116}
117
118#[cfg(test)]
119mod test {
120 use super::*;
121
122 #[test]
123 fn with() {
124 #[derive(Deserialize)]
125 struct Foo {
126 #[serde(with = "super")]
127 time: Duration,
128 }
129
130 let json = r#"{"time": "15 seconds"}"#;
131 let foo = serde_json::from_str::<Foo>(json).unwrap();
132 assert_eq!(foo.time, Duration::from_secs(15));
133 }
134
135 #[test]
136 fn de_option() {
137 #[derive(Deserialize)]
138 struct Foo {
139 time: De<Option<Duration>>,
140 }
141
142 let json = r#"{"time": "15 seconds"}"#;
143 let foo = serde_json::from_str::<Foo>(json).unwrap();
144 assert_eq!(foo.time.into_inner(), Some(Duration::from_secs(15)));
145
146 let json = r#"{"time": null}"#;
147 let foo = serde_json::from_str::<Foo>(json).unwrap();
148 assert_eq!(foo.time.into_inner(), None);
149
150 let json = r#"{}"#;
151 let foo = serde_json::from_str::<Foo>(json).unwrap();
152 assert_eq!(foo.time.into_inner(), None);
153 }
154}