jppe/fields/
hex.rs

1#[cfg(feature = "serde")]
2use serde::{Serialize, Serializer, Deserialize, Deserializer, de::Error as DeError};
3use crate::std::*;
4use crate::parser::ThisError;
5
6#[derive(Debug, ThisError)]
7pub enum HexStringParseError {
8    #[error("invalid hex string: `{0}`")]
9    InvalidHexString(String),
10}
11
12
13#[derive(Debug, PartialEq, Eq, Clone, Hash)]
14pub struct HexString {
15    inner: Vec<u8>,
16}
17
18
19const HEX_LOWER: &[u8; 16] = b"0123456789abcdef";
20const HEX_UPPER: &[u8; 16] = b"0123456789ABCDEF";
21
22
23#[inline]
24fn is_hex(value: u8) -> Option<u8> {
25    match value {
26        b'0'..=b'9' => Some(value - 0x30),
27        b'a'..=b'f' => Some(value - 0x57),
28        b'A'..=b'F' => Some(value - 0x37),
29        _ => None,
30    }
31}
32
33
34#[inline]
35fn parse_hex<T: AsRef<[u8]>>(t: T) -> Result<Vec<u8>, HexStringParseError> {
36    let s = t.as_ref();
37
38    if s.len() % 2 != 0 {
39        return Err(HexStringParseError::InvalidHexString(str::from_utf8(s).unwrap_or_default().to_string()));
40    }
41
42    let mut vlist = vec![];
43
44    for v in s.chunks(2) {
45        if let Some(v0) = is_hex(v[0]) {
46            if let Some(v1) = is_hex(v[1]) {
47                vlist.push(v0 << 4 | v1);
48            }
49            else {
50                return Err(HexStringParseError::InvalidHexString(str::from_utf8(s).unwrap_or_default().to_string()));
51            }
52        }
53        else {
54            return Err(HexStringParseError::InvalidHexString(str::from_utf8(s).unwrap_or_default().to_string()));
55        }
56    }
57
58    Ok(vlist)
59}
60
61
62impl HexString {
63    pub fn new<T: AsRef<[u8]>>(t: T) -> Self {
64        Self{ inner: t.as_ref().to_vec() }
65    }
66
67    pub fn from_bytes<T: AsRef<[u8]>>(t: T) -> Result<Self, HexStringParseError> {
68        Ok(Self { inner: parse_hex(t)? })
69    }
70
71    pub fn push(&mut self, c: u8) {
72        self.inner.push(c);
73    }
74
75    pub fn push_str(&mut self, s: &str) -> Result<(), HexStringParseError> {
76        let value = parse_hex(s)?;
77
78        self.inner.extend(value);
79
80        Ok(())
81    }
82
83    pub fn to_hex_lowercase(&self) -> String {
84        let mut vstring = String::new();
85
86        for v in &self.inner {
87            vstring.push(HEX_LOWER[(*v >> 4) as usize].into());
88            vstring.push(HEX_LOWER[(*v & 0xf) as usize].into());
89        }
90
91        vstring
92    }
93
94    pub fn to_hex_uppercase(&self) -> String {
95        let mut vstring = String::new();
96
97        for v in &self.inner {
98            vstring.push(HEX_UPPER[(*v >> 4) as usize].into());
99            vstring.push(HEX_UPPER[(*v & 0xf) as usize].into());
100        }
101
102        vstring
103    }
104}
105
106
107impl FromStr for HexString {
108    type Err = HexStringParseError;
109
110    fn from_str(s: &str) -> Result<Self, Self::Err> {
111        Ok(Self { inner: parse_hex(s)? })
112    }
113}
114
115
116impl ToString for HexString {
117    fn to_string(&self) -> String {
118        self.to_hex_lowercase()
119    }
120}
121
122
123impl ops::Deref for HexString {
124    type Target = [u8];
125
126    fn deref(&self) -> &Self::Target {
127        &self.inner
128    }
129}
130
131
132impl ops::DerefMut for HexString {
133    fn deref_mut(&mut self) -> &mut Self::Target {
134        &mut self.inner
135    }
136}
137
138
139#[cfg(feature = "serde")]
140impl Serialize for HexString {
141    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
142    where
143        S: Serializer,
144    {
145        serializer.collect_str(&self.to_string())
146    }
147}
148
149
150#[cfg(feature = "serde")]
151impl<'de> Deserialize<'de> for HexString {
152    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
153    where
154        D: Deserializer<'de>
155    {
156        let value = Deserialize::deserialize(deserializer)?;
157
158        HexString::from_str(value).map_err(D::Error::custom)
159    }
160}
161
162
163pub fn encode<T: AsRef<[u8]>>(s: T) -> Result<String, HexStringParseError> {
164    Ok(HexString{ inner: s.as_ref().to_vec() }.to_string())
165}
166
167
168pub fn decode<T: AsRef<[u8]>>(s: T) -> Result<String, HexStringParseError> {
169    Ok(String::from_utf8(HexString::from_bytes(s)?.inner).unwrap_or_default())
170}
171
172
173#[cfg(test)]
174mod tests {
175    #[cfg(feature = "serde")]
176    use serde::{Deserialize, Serialize};
177    use super::*;
178
179    #[test]
180    fn test_hex_string() {
181        assert_eq!(HexString::from_bytes(b"09afAF").unwrap().to_string(), "09afaf");
182        assert_eq!(HexString::from_bytes("09afAF".as_bytes()).unwrap().to_string(), "09afaf");
183        assert_eq!(HexString::from_bytes("09afAF").unwrap().to_string(), "09afaf");
184        assert_eq!(HexString::from_bytes("09afAF".to_string()).unwrap().to_string(), "09afaf");
185
186        assert_eq!(HexString::from_str("09afAF").unwrap().to_string(), "09afaf");
187
188        assert_eq!(HexString::from_str("0").is_err(), true);
189        assert_eq!(HexString::from_str("0g").is_err(), true);
190        assert_eq!(HexString::from_str("0G").is_err(), true);
191        assert_eq!(HexString::from_str("0z").is_err(), true);
192        assert_eq!(HexString::from_str("0Z").is_err(), true);
193
194        let mut value = HexString::from_str("09af").unwrap();
195        value.push(0x01);
196        value.push(0x02);
197        value.push_str("ff").unwrap();
198        assert_eq!(value.push_str("fg").is_err(), true);
199        assert_eq!(value.to_string(), "09af0102ff")
200    }
201
202    #[test]
203    fn test_hex_string_encode_decode() {
204        assert_eq!(encode("jankincai").unwrap(), "6a616e6b696e636169");
205        assert_eq!(encode(b"jankincai\x00\xff").unwrap(), "6a616e6b696e63616900ff");
206        assert_eq!(encode("jankincai".to_string()).unwrap(), "6a616e6b696e636169");
207        assert_eq!(encode("jankincai".as_bytes()).unwrap(), "6a616e6b696e636169");
208
209        assert_eq!(decode("6a616e6b696e636169").unwrap(), "jankincai");
210        assert_eq!(decode(b"6a616e6b696e636169").unwrap(), "jankincai");
211        assert_eq!(decode("6a616e6b696e636169".to_string()).unwrap(), "jankincai");
212        assert_eq!(decode("6a616e6b696e636169".as_bytes()).unwrap(), "jankincai");
213
214        assert_eq!(decode("6a616e6b696e636169fg").is_err(), true);
215    }
216
217    #[cfg(feature = "serde")]
218    #[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
219    struct Example {
220        pub value: HexString,
221    }
222
223    #[test]
224    #[cfg(feature = "serde")]
225    fn test_hex_string_serde() {
226        // HexString
227        let example = Example {value: HexString::from_str("01afaf").unwrap()};
228
229        let example_string = serde_json::to_string(&example).unwrap();
230        assert_eq!(example_string, "{\"value\":\"01afaf\"}");
231        let example_new: Example = serde_json::from_str(&example_string).unwrap();
232        assert_eq!(example, example_new);
233    }
234}