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