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 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 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}