xsd_types/value/
hex_binary.rs

1use std::{
2	borrow::Borrow,
3	fmt,
4	ops::{Deref, DerefMut},
5	str::FromStr,
6};
7
8use crate::{
9	lexical::{self, LexicalFormOf},
10	Datatype, ParseXsd, XsdValue,
11};
12
13const CHARS: [char; 16] = [
14	'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
15];
16
17#[derive(Debug, thiserror::Error)]
18#[error("invalid hexadecimal")]
19pub struct InvalidHex;
20
21#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
22pub struct HexBinaryBuf(Vec<u8>);
23
24impl HexBinaryBuf {
25	pub fn new() -> Self {
26		Self::default()
27	}
28
29	pub fn from_bytes(bytes: Vec<u8>) -> Self {
30		Self(bytes)
31	}
32
33	pub fn decode(input: impl AsRef<[u8]>) -> Result<Self, InvalidHex> {
34		let input = input.as_ref();
35		let mut bytes = Vec::with_capacity(input.len() / 2);
36
37		let mut iter = input.iter();
38		while let Some(&a) = iter.next() {
39			let a = decode_char(a)?;
40
41			match iter.next() {
42				Some(&b) => {
43					let b = decode_char(b)?;
44					bytes.push(a << 4 | b)
45				}
46				None => return Err(InvalidHex),
47			}
48		}
49
50		Ok(Self(bytes))
51	}
52
53	pub fn into_bytes(self) -> Vec<u8> {
54		self.0
55	}
56
57	pub fn as_bytes(&self) -> &[u8] {
58		&self.0
59	}
60
61	pub fn as_hex_binary(&self) -> &HexBinary {
62		HexBinary::new(&self.0)
63	}
64
65	pub fn as_hex_binary_mut(&mut self) -> &mut HexBinary {
66		HexBinary::new_mut(&mut self.0)
67	}
68}
69
70fn decode_char(c: u8) -> Result<u8, InvalidHex> {
71	match c {
72		b'0'..=b'9' => Ok(c - b'0'),
73		b'A'..=b'F' => Ok(0xa + (c - b'A')),
74		b'a'..=b'f' => Ok(0xa + (c - b'a')),
75		_ => Err(InvalidHex),
76	}
77}
78
79impl fmt::Display for HexBinaryBuf {
80	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81		self.as_hex_binary().fmt(f)
82	}
83}
84
85impl From<Vec<u8>> for HexBinaryBuf {
86	fn from(value: Vec<u8>) -> Self {
87		HexBinaryBuf::from_bytes(value)
88	}
89}
90
91impl FromStr for HexBinaryBuf {
92	type Err = InvalidHex;
93
94	fn from_str(s: &str) -> Result<Self, Self::Err> {
95		Self::decode(s)
96	}
97}
98
99impl AsRef<[u8]> for HexBinaryBuf {
100	fn as_ref(&self) -> &[u8] {
101		self.as_bytes()
102	}
103}
104
105impl AsRef<HexBinary> for HexBinaryBuf {
106	fn as_ref(&self) -> &HexBinary {
107		self.as_hex_binary()
108	}
109}
110
111impl Borrow<HexBinary> for HexBinaryBuf {
112	fn borrow(&self) -> &HexBinary {
113		self.as_hex_binary()
114	}
115}
116
117impl Deref for HexBinaryBuf {
118	type Target = HexBinary;
119
120	fn deref(&self) -> &Self::Target {
121		self.as_hex_binary()
122	}
123}
124
125impl DerefMut for HexBinaryBuf {
126	fn deref_mut(&mut self) -> &mut Self::Target {
127		self.as_hex_binary_mut()
128	}
129}
130
131impl XsdValue for HexBinaryBuf {
132	fn datatype(&self) -> Datatype {
133		Datatype::HexBinary
134	}
135}
136
137impl ParseXsd for HexBinaryBuf {
138	type LexicalForm = lexical::HexBinary;
139}
140
141impl LexicalFormOf<HexBinaryBuf> for lexical::HexBinary {
142	type ValueError = std::convert::Infallible;
143
144	fn try_as_value(&self) -> Result<HexBinaryBuf, Self::ValueError> {
145		Ok(self.value())
146	}
147}
148
149#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
150pub struct HexBinary([u8]);
151
152impl HexBinary {
153	pub fn new(bytes: &[u8]) -> &Self {
154		unsafe { std::mem::transmute(bytes) }
155	}
156
157	pub fn new_mut(bytes: &mut [u8]) -> &mut Self {
158		unsafe { std::mem::transmute(bytes) }
159	}
160
161	pub fn chars(&self) -> Chars {
162		Chars {
163			pending: None,
164			bytes: self.0.iter(),
165		}
166	}
167
168	pub fn as_bytes(&self) -> &[u8] {
169		&self.0
170	}
171}
172
173impl<'a> From<&'a [u8]> for &'a HexBinary {
174	fn from(value: &'a [u8]) -> Self {
175		HexBinary::new(value)
176	}
177}
178
179impl<'a> From<&'a mut [u8]> for &'a HexBinary {
180	fn from(value: &'a mut [u8]) -> Self {
181		HexBinary::new(value)
182	}
183}
184
185impl<'a> From<&'a mut [u8]> for &'a mut HexBinary {
186	fn from(value: &'a mut [u8]) -> Self {
187		HexBinary::new_mut(value)
188	}
189}
190
191impl fmt::Display for HexBinary {
192	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
193		for c in self.chars() {
194			c.fmt(f)?
195		}
196
197		Ok(())
198	}
199}
200
201impl ToOwned for HexBinary {
202	type Owned = HexBinaryBuf;
203
204	fn to_owned(&self) -> Self::Owned {
205		HexBinaryBuf::from_bytes(self.as_bytes().to_vec())
206	}
207}
208
209impl XsdValue for HexBinary {
210	fn datatype(&self) -> Datatype {
211		Datatype::HexBinary
212	}
213}
214
215pub struct Chars<'a> {
216	pending: Option<char>,
217	bytes: std::slice::Iter<'a, u8>,
218}
219
220impl<'a> Iterator for Chars<'a> {
221	type Item = char;
222
223	fn next(&mut self) -> Option<Self::Item> {
224		self.pending.take().or_else(|| {
225			self.bytes.next().map(|v| {
226				let a = v >> 4;
227				let b = v & 0x0f;
228
229				self.pending = Some(CHARS[b as usize]);
230				CHARS[a as usize]
231			})
232		})
233	}
234}
235
236#[cfg(test)]
237mod tests {
238	use super::*;
239
240	const TESTS: [(&'static [u8], &'static str); 9] = [
241		(b"M", "4D"),
242		(b"Ma", "4D61"),
243		(b"Man", "4D616E"),
244		(b"light w", "6C696768742077"),
245		(b"light wo", "6C6967687420776F"),
246		(b"light wor", "6C6967687420776F72"),
247		(b"light work", "6C6967687420776F726B"),
248		(b"light work.", "6C6967687420776F726B2E"),
249		(
250			b"Many hands make light work.",
251			"4D616E792068616E6473206D616B65206C6967687420776F726B2E",
252		),
253	];
254
255	#[test]
256	fn encoding() {
257		for (input, expected) in TESTS {
258			let output = HexBinary::new(input).to_string();
259			assert_eq!(output, expected)
260		}
261	}
262
263	#[test]
264	fn decoding() {
265		for (expected, input) in TESTS {
266			let output = HexBinaryBuf::decode(input).unwrap();
267			assert_eq!(output.as_bytes(), expected)
268		}
269	}
270}