easy_hex/
deserialize.rs

1use std::{fmt, marker::PhantomData};
2
3use serde::{
4    de::{Error, Unexpected, Visitor},
5    Deserialize, Deserializer,
6};
7
8use crate::{decode::fast_deserialize_into, Hex, UpperHex};
9
10struct Vis<T>(PhantomData<T>);
11impl<'a, T> Visitor<'a> for Vis<T>
12where
13    T: for<'b> TryFrom<&'b [u8]>,
14{
15    type Value = T;
16
17    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
18        write!(formatter, "a hexadecimal string")
19    }
20
21    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
22    where
23        E: Error,
24    {
25        let value: T = fast_deserialize_into::<T>(v)
26            .map_err(|_| Error::invalid_type(Unexpected::Str(v), &self))?;
27        Ok(value)
28    }
29}
30
31impl<'a, T> Deserialize<'a> for Hex<T>
32where
33    T: for<'b> TryFrom<&'b [u8]>,
34{
35    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
36    where
37        D: Deserializer<'a>,
38    {
39        deserializer.deserialize_str(Vis(PhantomData)).map(Hex)
40    }
41}
42
43impl<'a, T> Deserialize<'a> for UpperHex<T>
44where
45    T: for<'b> TryFrom<&'b [u8]>,
46{
47    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
48    where
49        D: Deserializer<'a>,
50    {
51        deserializer.deserialize_str(Vis(PhantomData)).map(UpperHex)
52    }
53}
54
55/// Deserialize function for a hex string. Can handle the output of
56/// either `Hex` or `UpperHex`.
57pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
58where
59    D: Deserializer<'de>,
60    T: for<'a> TryFrom<&'a [u8]>,
61{
62    Hex::<T>::deserialize(deserializer).map(|v| v.0)
63}
64
65#[cfg(test)]
66mod tests {
67    use serde_derive::Deserialize;
68
69    use crate::tests::from_json;
70
71    use super::*;
72
73    #[derive(Deserialize)]
74    struct Test {
75        _a: Hex<Vec<u8>>,
76        _b: UpperHex<Vec<u8>>,
77        #[serde(deserialize_with = "deserialize")]
78        _c: Vec<u8>,
79    }
80
81    #[test]
82    fn test_from_lower() {
83        let hex: Hex<_> = from_json(r#"{"data":"0199ff"}"#);
84        assert_eq!(hex, Hex([1_u8, 0x99, 0xff]));
85    }
86
87    #[test]
88    fn test_from_upper() {
89        let hex: Hex<_> = from_json(r#"{"data":"0199FF"}"#);
90        assert_eq!(hex, Hex([1_u8, 0x99, 0xff]));
91    }
92
93    #[test]
94    fn test_from_mixed() {
95        let hex: Hex<_> = from_json(r#"{"data":"0199fF"}"#);
96        assert_eq!(hex, Hex([1_u8, 0x99, 0xff]));
97    }
98
99    #[test]
100    fn test_upper_from_lower() {
101        let hex: UpperHex<_> = from_json(r#"{"data":"0199ff"}"#);
102        assert_eq!(hex, UpperHex([1_u8, 0x99, 0xff]));
103    }
104
105    #[test]
106    fn test_upper_from_upper() {
107        let hex: UpperHex<_> = from_json(r#"{"data":"0199FF"}"#);
108        assert_eq!(hex, UpperHex([1_u8, 0x99, 0xff]));
109    }
110
111    #[test]
112    fn test_upper_from_mixed() {
113        let hex: UpperHex<_> = from_json(r#"{"data":"0199fF"}"#);
114        assert_eq!(hex, UpperHex([1_u8, 0x99, 0xff]));
115    }
116}