human_bandwidth/
serde.rs

1//! Serde support for humanized bandwidth.
2//!
3//! # Example
4//! ```
5//! use serde::{Serialize, Deserialize};
6//! use bandwidth::Bandwidth;
7//!
8//! #[derive(Serialize, Deserialize)]
9//! struct Foo {
10//!     #[serde(with = "human_bandwidth::serde")]
11//!     bandwidth: Bandwidth,
12//! }
13//! ```
14//!
15//! Or use the `Serde` wrapper type:
16//!
17//! ```
18//! use serde::{Serialize, Deserialize};
19//! use human_bandwidth::serde::Serde;
20//! use bandwidth::Bandwidth;
21//!
22//! #[derive(Serialize, Deserialize)]
23//! struct Foo {
24//!     bandwidth: Vec<Serde<Bandwidth>>,
25//! }
26//! ```
27
28use bandwidth::Bandwidth;
29use serde::{de, ser, Deserialize, Deserializer, Serialize, Serializer};
30use std::fmt;
31use std::ops::{Deref, DerefMut};
32
33/// Deserializes a `Bandwidth` in human-readable format.
34///
35/// This function can be used with `serde_derive`'s `with` and
36/// `deserialize_with` annotations.
37pub fn deserialize<'a, T, D>(d: D) -> Result<T, D::Error>
38where
39    Serde<T>: Deserialize<'a>,
40    D: Deserializer<'a>,
41{
42    Serde::deserialize(d).map(Serde::into_inner)
43}
44
45/// Serializes a `Bandwidth` in human-readable format.
46///
47/// This function can be used with `serde_derive`'s `with` and
48/// `serialize_with` annotations.
49pub fn serialize<T, S>(d: &T, s: S) -> Result<S::Ok, S::Error>
50where
51    for<'a> Serde<&'a T>: Serialize,
52    S: Serializer,
53{
54    Serde::from(d).serialize(s)
55}
56
57/// A wrapper type which implements `Serialize` and `Deserialize` for
58/// types involving `Bandwidth`.
59#[derive(Copy, Clone, Eq, Hash, PartialEq)]
60pub struct Serde<T>(T);
61
62impl<T> fmt::Debug for Serde<T>
63where
64    T: fmt::Debug,
65{
66    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
67        self.0.fmt(formatter)
68    }
69}
70
71impl<T> Deref for Serde<T> {
72    type Target = T;
73
74    fn deref(&self) -> &T {
75        &self.0
76    }
77}
78
79impl<T> DerefMut for Serde<T> {
80    fn deref_mut(&mut self) -> &mut T {
81        &mut self.0
82    }
83}
84
85impl<T> Serde<T> {
86    /// Consumes the `De`, returning the inner value.
87    pub fn into_inner(self) -> T {
88        self.0
89    }
90}
91
92impl<T> From<T> for Serde<T> {
93    fn from(val: T) -> Serde<T> {
94        Serde(val)
95    }
96}
97
98impl<'de> Deserialize<'de> for Serde<Bandwidth> {
99    fn deserialize<D>(d: D) -> Result<Serde<Bandwidth>, D::Error>
100    where
101        D: Deserializer<'de>,
102    {
103        struct V;
104
105        impl de::Visitor<'_> for V {
106            type Value = Bandwidth;
107
108            fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
109                fmt.write_str("a bandwidth")
110            }
111
112            fn visit_str<E>(self, v: &str) -> Result<Bandwidth, E>
113            where
114                E: de::Error,
115            {
116                crate::parse_bandwidth(v)
117                    .map_err(|_| E::invalid_value(de::Unexpected::Str(v), &self))
118            }
119        }
120
121        d.deserialize_str(V).map(Serde)
122    }
123}
124
125impl<'de> Deserialize<'de> for Serde<Option<Bandwidth>> {
126    fn deserialize<D>(d: D) -> Result<Serde<Option<Bandwidth>>, D::Error>
127    where
128        D: Deserializer<'de>,
129    {
130        match Option::<Serde<Bandwidth>>::deserialize(d)? {
131            Some(Serde(dur)) => Ok(Serde(Some(dur))),
132            None => Ok(Serde(None)),
133        }
134    }
135}
136
137impl ser::Serialize for Serde<&Bandwidth> {
138    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
139    where
140        S: ser::Serializer,
141    {
142        crate::format_bandwidth(*self.0)
143            .to_string()
144            .serialize(serializer)
145    }
146}
147
148impl ser::Serialize for Serde<Bandwidth> {
149    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
150    where
151        S: ser::Serializer,
152    {
153        crate::format_bandwidth(self.0)
154            .to_string()
155            .serialize(serializer)
156    }
157}
158
159impl ser::Serialize for Serde<&Option<Bandwidth>> {
160    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
161    where
162        S: ser::Serializer,
163    {
164        match *self.0 {
165            Some(dur) => serializer.serialize_some(&Serde(dur)),
166            None => serializer.serialize_none(),
167        }
168    }
169}
170
171impl ser::Serialize for Serde<Option<Bandwidth>> {
172    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
173    where
174        S: ser::Serializer,
175    {
176        Serde(&self.0).serialize(serializer)
177    }
178}
179
180#[cfg(test)]
181mod tests {
182    use super::*;
183
184    #[test]
185    fn with() {
186        #[derive(Serialize, Deserialize)]
187        struct Foo {
188            #[serde(with = "super")]
189            bandwidth: Bandwidth,
190        }
191
192        let json = r#"{"bandwidth": "1kbps"}"#;
193        let foo = serde_json::from_str::<Foo>(json).unwrap();
194        assert_eq!(foo.bandwidth, Bandwidth::from_kbps(1));
195        let reverse = serde_json::to_string(&foo).unwrap();
196        assert_eq!(reverse, r#"{"bandwidth":"1kbps"}"#);
197    }
198
199    #[test]
200    fn with_option() {
201        #[derive(Serialize, Deserialize)]
202        struct Foo {
203            #[serde(with = "super", default)]
204            bandwidth: Option<Bandwidth>,
205        }
206
207        let json = r#"{"bandwidth": "15Mbps"}"#;
208        let foo = serde_json::from_str::<Foo>(json).unwrap();
209        assert_eq!(foo.bandwidth, Some(Bandwidth::from_mbps(15)));
210        let reverse = serde_json::to_string(&foo).unwrap();
211        assert_eq!(reverse, r#"{"bandwidth":"15Mbps"}"#);
212
213        let json = r#"{"bandwidth": null}"#;
214        let foo = serde_json::from_str::<Foo>(json).unwrap();
215        assert_eq!(foo.bandwidth, None);
216        let reverse = serde_json::to_string(&foo).unwrap();
217        assert_eq!(reverse, r#"{"bandwidth":null}"#);
218
219        let json = r#"{}"#;
220        let foo = serde_json::from_str::<Foo>(json).unwrap();
221        assert_eq!(foo.bandwidth, None);
222    }
223}