bytesize_serde/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use std::fmt;
4
5use bytesize::ByteSize;
6use serde::{de, Serialize, Serializer};
7
8pub fn serialize<S>(size: &ByteSize, serializer: S) -> Result<S::Ok, S::Error>
9where
10    S: Serializer,
11{
12    if serializer.is_human_readable() {
13        <str>::serialize(size.to_string().as_str(), serializer)
14    } else {
15        size.0.serialize(serializer)
16    }
17}
18
19pub fn deserialize<'de, D>(deserializer: D) -> Result<ByteSize, D::Error>
20where
21    D: de::Deserializer<'de>,
22{
23    struct Helper;
24    impl<'de> de::Visitor<'de> for Helper {
25        type Value = ByteSize;
26
27        fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
28            formatter.write_str("an integer or string")
29        }
30
31        // TOML Integer(i64)
32        fn visit_i64<E: de::Error>(self, value: i64) -> Result<Self::Value, E> {
33            if let Ok(val) = u64::try_from(value) {
34                Ok(ByteSize(val))
35            } else {
36                Err(E::invalid_value(
37                    de::Unexpected::Signed(value),
38                    &"integer overflow",
39                ))
40            }
41        }
42
43        // JSON Integer(u64)
44        fn visit_u64<E: de::Error>(self, value: u64) -> Result<Self::Value, E> {
45            Ok(ByteSize(value))
46        }
47
48        fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
49            if let Ok(val) = value.parse() {
50                Ok(val)
51            } else {
52                Err(E::invalid_value(
53                    de::Unexpected::Str(value),
54                    &"parsable string",
55                ))
56            }
57        }
58    }
59
60    if deserializer.is_human_readable() {
61        deserializer.deserialize_any(Helper)
62    } else {
63        deserializer.deserialize_u64(Helper)
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    use quickcheck_macros::quickcheck;
72    use serde::Deserialize;
73
74    #[derive(Serialize, Deserialize)]
75    #[serde(transparent)]
76    struct W(#[serde(with = "self")] ByteSize);
77
78    #[quickcheck]
79    fn deserializes_any(x: u64) {
80        let _: W = serde_json::from_str(&x.to_string()).unwrap();
81    }
82
83    #[quickcheck]
84    fn serde_with_bincode(x: u64) {
85        let w = W(ByteSize::b(x));
86
87        let ser = bincode::serialize(&w).unwrap();
88        let de: W = bincode::deserialize(&ser).unwrap();
89
90        assert_eq!(w.0, de.0);
91    }
92
93    #[quickcheck]
94    fn serializes_any(x: u64) {
95        serde_json::to_string(&ByteSize(x).to_string()).unwrap();
96    }
97
98    #[test]
99    fn deserialize_sizes() {
100        #[track_caller]
101        fn check_str(s: &str) {
102            assert_eq!(
103                serde_json::from_str::<W>(&format!("{:?}", s)).unwrap().0,
104                s.parse().unwrap()
105            );
106        }
107
108        #[track_caller]
109        fn check(s: &str) {
110            assert_eq!(serde_json::from_str::<W>(s).unwrap().0, s.parse().unwrap());
111        }
112
113        check_str("5 MB");
114        check_str("12.34 KB");
115        check("123");
116        check("0");
117    }
118}