human_bandwidth/binary_system/
serde.rs

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