Skip to main content

o2_api_types/
parse.rs

1use std::{
2    fmt::Display,
3    str::FromStr,
4};
5
6use serde::{
7    Deserializer,
8    Serializer,
9};
10
11pub struct HexDisplayFromStr;
12
13impl<T> serde_with::SerializeAs<T> for HexDisplayFromStr
14where
15    T: Display,
16{
17    fn serialize_as<S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
18    where
19        S: Serializer,
20    {
21        let s = format!("0x{value}");
22        serializer.serialize_str(&s)
23    }
24}
25
26impl<'de, T> serde_with::DeserializeAs<'de, T> for HexDisplayFromStr
27where
28    T: FromStr,
29    T::Err: Display,
30{
31    fn deserialize_as<D>(deserializer: D) -> Result<T, D::Error>
32    where
33        D: Deserializer<'de>,
34    {
35        use serde::Deserialize;
36        let s = String::deserialize(deserializer)?;
37        let trimmed = s.strip_prefix("0x").unwrap_or(&s);
38        T::from_str(trimmed).map_err(serde::de::Error::custom)
39    }
40}
41
42pub fn serialize_hex<S, A>(value: A, serializer: S) -> Result<S::Ok, S::Error>
43where
44    S: Serializer,
45    A: Display,
46{
47    serializer.serialize_str(&format!("0x{value}"))
48}
49
50pub struct HexVecFromStr;
51
52impl serde_with::SerializeAs<Vec<u8>> for HexVecFromStr {
53    fn serialize_as<S>(value: &Vec<u8>, serializer: S) -> Result<S::Ok, S::Error>
54    where
55        S: Serializer,
56    {
57        let hex_str = value.iter().map(|b| format!("{b:02x}")).collect::<String>();
58        let hex_str = format!("0x{hex_str}");
59        serializer.serialize_str(&hex_str)
60    }
61}
62
63impl<'de> serde_with::DeserializeAs<'de, Vec<u8>> for HexVecFromStr {
64    fn deserialize_as<D>(deserializer: D) -> Result<Vec<u8>, D::Error>
65    where
66        D: Deserializer<'de>,
67    {
68        use serde::{
69            Deserialize,
70            de,
71        };
72        use serde_json::Value;
73
74        let value = Value::deserialize(deserializer)?;
75
76        match value {
77            Value::String(hex_str) => {
78                let trimmed = hex_str.strip_prefix("0x").unwrap_or(&hex_str);
79
80                (0..trimmed.len())
81                    .step_by(2)
82                    .map(|i| u8::from_str_radix(&trimmed[i..i + 2], 16))
83                    .collect::<Result<Vec<u8>, _>>()
84                    .map_err(de::Error::custom)
85            }
86            Value::Array(arr) => arr
87                .into_iter()
88                .map(|v| match v {
89                    Value::Number(n) => {
90                        if let Some(u) = n.as_u64() {
91                            if u <= 255 {
92                                Ok(u as u8)
93                            } else {
94                                Err(de::Error::custom(format!(
95                                    "Number {u} is out of range for u8"
96                                )))
97                            }
98                        } else {
99                            Err(de::Error::custom("Invalid number in array"))
100                        }
101                    }
102                    _ => Err(de::Error::custom("Array must contain only numbers")),
103                })
104                .collect::<Result<Vec<u8>, _>>(),
105            _ => Err(de::Error::custom("Expected hex string or array of numbers")),
106        }
107    }
108}