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