byte_unit_serde/
byte.rs

1//! A [`serde`] wrapper, that can be used to serialize and deserialize [`u64`]
2//! types using [`Byte`] representation.
3
4use std::marker::PhantomData;
5
6use byte_unit::Byte;
7use serde::{Deserialize, Serialize, Serializer};
8
9/// Serializes a [`u64`] via [`Byte`] type.
10///
11/// This function is desined to use with the `serde_derive`'s
12/// `with` and `serialize_with` annotations.
13pub fn deserialize<'a, T, D>(der: D) -> Result<T, D::Error>
14where
15    D: serde::Deserializer<'a>,
16    T: TryFrom<Deser<'a, D>, Error = D::Error>,
17{
18    T::try_from(Deser(der, PhantomData))
19}
20
21/// Deserializes a [`u64`] via [`byte_unit::Byte`] type.
22///
23/// This function is desined to use with the `serde_derive`'s
24/// `with` and `serialize_with` annotations.
25pub fn serialize<T, S>(val: &T, ser: S) -> Result<S::Ok, S::Error>
26where
27    S: Serializer,
28    for<'a> Ser<&'a T>: Serialize,
29{
30    Ser::from(val).serialize(ser)
31}
32
33/// A wrapper type which provides [`TryFrom`] implementation for types which
34/// can be deserialized by using the [`Byte`] type's [`Deserialize`] implementation.
35#[derive(Debug)]
36pub struct Deser<'a, D>(D, PhantomData<&'a ()>);
37
38impl<'a, D> TryFrom<Deser<'a, D>> for u64
39where
40    D: serde::Deserializer<'a>,
41{
42    type Error = D::Error;
43
44    fn try_from(value: Deser<'a, D>) -> Result<Self, Self::Error> {
45        let byte = Byte::deserialize(value.0)?;
46        Ok(byte.as_u64())
47    }
48}
49
50impl<'a, D> TryFrom<Deser<'a, D>> for Option<u64>
51where
52    D: serde::Deserializer<'a>,
53{
54    type Error = D::Error;
55
56    fn try_from(value: Deser<'a, D>) -> Result<Self, Self::Error> {
57        let byte = Option::<Byte>::deserialize(value.0)?;
58        Ok(byte.map(Byte::as_u64))
59    }
60}
61
62/// A wrapper which provides [`Serialize`] implementation for types which
63/// can be serialized by using the [`Byte`] type's [`Serialize`] implementation.
64#[derive(Debug)]
65pub struct Ser<T>(T);
66
67impl Serialize for Ser<&u64> {
68    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
69    where
70        S: Serializer,
71    {
72        Byte::from_u64(*self.0).serialize(serializer)
73    }
74}
75
76impl Serialize for Ser<&Option<u64>> {
77    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
78    where
79        S: Serializer,
80    {
81        self.0.map(Byte::from_u64).serialize(serializer)
82    }
83}
84
85impl<T> From<T> for Ser<T> {
86    fn from(value: T) -> Self {
87        Self(value)
88    }
89}
90
91#[cfg(test)]
92mod tests {
93    use serde::{Deserialize, Serialize};
94    use serde_json::json;
95
96    #[derive(Debug, Serialize, Deserialize)]
97    struct Values {
98        #[serde(with = "super")]
99        size: u64,
100    }
101
102    #[test]
103    fn test_deserialize_byte() {
104        let test_cases = [
105            (json!({ "size": "1024kB" }), 1_024_000),
106            (json!({ "size": "1024MiB" }), 1_073_741_824),
107            (json!({ "size": "1kB" }), 1000),
108            (json!({ "size": "1kiB" }), 1024),
109            (json!({ "size": "1" }), 1),
110        ];
111
112        for (json, expected) in test_cases {
113            let values: Values = serde_json::from_value(json).unwrap();
114            assert_eq!(values.size, expected);
115        }
116    }
117
118    #[test]
119    fn test_serialize_byte() {
120        let test_cases = [
121            (Values { size: 1_024_000 }, json!({ "size": "1.024 MB" })),
122            (
123                Values {
124                    size: 1_073_741_824,
125                },
126                json!({ "size": "1 GiB" }),
127            ),
128            (Values { size: 1000 }, json!({ "size": "1 KB" })),
129            (Values { size: 1024 }, json!({ "size": "1 KiB" })),
130            (Values { size: 1 }, json!({ "size": "1 B" })),
131        ];
132
133        for (value, expected) in test_cases {
134            let json = json!(value);
135            assert_eq!(json, expected);
136        }
137    }
138}