array_bytes/hex/
dehexify.rs

1// core
2use core::str;
3// self
4use crate::prelude::*;
5
6static HEX2DIGIT: [Option<u8>; 256] = {
7	let mut table = [None; 256];
8	let mut i = 0;
9
10	while i <= 9 {
11		table[b'0' as usize + i] = Some(i as u8);
12
13		i += 1;
14	}
15
16	i = 0;
17
18	while i <= 5 {
19		table[b'a' as usize + i] = Some((10 + i) as u8);
20		table[b'A' as usize + i] = Some((10 + i) as u8);
21
22		i += 1;
23	}
24
25	table
26};
27
28/// Dehexify the given hex to `Self`.
29///
30/// # Examples
31/// ```
32/// use array_bytes::{Dehexify, Error};
33/// use smallvec::SmallVec;
34///
35/// // Unsigned.
36/// assert_eq!(u8::dehexify("34"), Ok(52));
37/// assert_eq!(u16::dehexify("208"), Ok(520));
38/// assert_eq!(u32::dehexify("0x4f5da2"), Ok(5_201_314));
39/// assert_eq!(u64::dehexify("0x4F5DA2"), Ok(5_201_314));
40/// assert_eq!(u128::dehexify("4f5da2"), Ok(5_201_314));
41/// assert_eq!(usize::dehexify("4F5DA2"), Ok(5_201_314));
42/// // Array.
43/// assert_eq!(
44/// 	<[u8; 17]>::dehexify("0x4c6f7665204a616e6520466f7265766572"),
45/// 	Ok(*b"Love Jane Forever")
46/// );
47/// // SmallVec.
48/// assert_eq!(
49/// 	SmallVec::dehexify("0x4c6f7665204a616e6520466f7265766572").unwrap().into_vec(),
50/// 	b"Love Jane Forever".to_vec()
51/// );
52/// assert_eq!(SmallVec::dehexify("我爱你"), Err(Error::InvalidLength));
53/// assert_eq!(SmallVec::dehexify("0x我爱你"), Err(Error::InvalidLength));
54/// // Vec.
55/// assert_eq!(
56/// 	<Vec<u8>>::dehexify("0x4c6f7665204a616e6520466f7265766572"),
57/// 	Ok(b"Love Jane Forever".to_vec())
58/// );
59/// assert_eq!(
60/// 	<Vec<u8>>::dehexify("我爱你 "),
61/// 	Err(Error::InvalidCharacter { character: 'æ', index: 0 })
62/// );
63/// assert_eq!(
64/// 	<Vec<u8>>::dehexify(" 我爱你"),
65/// 	Err(Error::InvalidCharacter { character: ' ', index: 0 })
66/// );
67/// ```
68pub trait Dehexify
69where
70	Self: Sized,
71{
72	/// Dehexify `Self` from hex.
73	fn dehexify<H>(hex: H) -> Result<Self>
74	where
75		H: AsRef<[u8]>;
76}
77macro_rules! impl_dehexify_for_unsigned {
78	($($t:ty,)+) => {
79		$(impl Dehexify for $t {
80			fn dehexify<H>(hex: H) -> Result<Self>
81			where
82				H: AsRef<[u8]>,
83			{
84				let hex = strip_0x(hex.as_ref());
85				let hex = str::from_utf8(hex).map_err(Error::Utf8Error)?;
86
87				Self::from_str_radix(hex, 16).map_err(Error::ParseIntError)
88			}
89		})+
90	};
91}
92impl_dehexify_for_unsigned! {
93	usize,
94	u8,
95	u16,
96	u32,
97	u64,
98	u128,
99}
100impl<const N: usize> Dehexify for [u8; N] {
101	fn dehexify<H>(hex: H) -> Result<Self>
102	where
103		H: AsRef<[u8]>,
104	{
105		dehexify_array(hex)
106	}
107}
108impl Dehexify for SmallVec<[u8; 64]> {
109	fn dehexify<H>(hex: H) -> Result<Self>
110	where
111		H: AsRef<[u8]>,
112	{
113		dehexify_bytes(hex)
114	}
115}
116impl Dehexify for Vec<u8> {
117	fn dehexify<H>(hex: H) -> Result<Self>
118	where
119		H: AsRef<[u8]>,
120	{
121		dehexify_bytes(hex).map(|sv| sv.into_vec())
122	}
123}
124#[test]
125fn dehexify_should_work() {
126	// Unsigned.
127	assert_eq!(u8::dehexify("34"), Ok(52));
128	assert_eq!(u16::dehexify("208"), Ok(520));
129	assert_eq!(u32::dehexify("0x4f5da2"), Ok(5_201_314));
130	assert_eq!(u64::dehexify("0x4F5DA2"), Ok(5_201_314));
131	assert_eq!(u128::dehexify("4f5da2"), Ok(5_201_314));
132	assert_eq!(usize::dehexify("4F5DA2"), Ok(5_201_314));
133	// Array.
134	assert_eq!(
135		<[u8; 17]>::dehexify("0x4c6f7665204a616e6520466f7265766572"),
136		Ok(*b"Love Jane Forever")
137	);
138	// SmallVec.
139	assert_eq!(
140		SmallVec::dehexify("0x4c6f7665204a616e6520466f7265766572").unwrap().into_vec(),
141		b"Love Jane Forever".to_vec()
142	);
143	assert_eq!(SmallVec::dehexify("我爱你"), Err(Error::InvalidLength));
144	assert_eq!(SmallVec::dehexify("0x我爱你"), Err(Error::InvalidLength));
145	// Vec.
146	assert_eq!(
147		<Vec<u8>>::dehexify("0x4c6f7665204a616e6520466f7265766572"),
148		Ok(b"Love Jane Forever".to_vec())
149	);
150	assert_eq!(
151		<Vec<u8>>::dehexify("我爱你 "),
152		Err(Error::InvalidCharacter { character: 'æ', index: 0 })
153	);
154	assert_eq!(
155		<Vec<u8>>::dehexify(" 我爱你"),
156		Err(Error::InvalidCharacter { character: ' ', index: 0 })
157	);
158}
159
160/// Dehexify hex into a mutable slice source.
161///
162/// # Examples
163/// ```
164/// let mut array = [0; 17];
165///
166/// assert_eq!(
167/// 	array_bytes::dehexify_slice_mut("0x4c6f7665204a616e6520466f7265766572", &mut array),
168/// 	Ok(b"Love Jane Forever".as_slice())
169/// );
170/// assert_eq!(array, *b"Love Jane Forever");
171/// ```
172pub fn dehexify_slice_mut<H>(hex: H, slice_src: &mut [u8]) -> Result<&[u8]>
173where
174	H: AsRef<[u8]>,
175{
176	let hex = strip_0x(hex.as_ref());
177
178	if hex.len() % 2 != 0 {
179		Err(Error::InvalidLength)?;
180	}
181
182	let expected_len = hex.len() >> 1;
183
184	if expected_len != slice_src.len() {
185		Err(Error::MismatchedLength { expect: expected_len })?;
186	}
187
188	for (byte, i) in slice_src.iter_mut().zip((0..hex.len()).step_by(2)) {
189		*byte = dehexify_ascii((&hex[i], i), (&hex[i + 1], i + 1))?;
190	}
191
192	Ok(slice_src)
193}
194#[test]
195fn dehexify_slice_mut_should_work() {
196	let mut bytes = [0; 17];
197	assert_eq!(
198		dehexify_slice_mut("0x4c6f7665204a616e6520466f7265766572", &mut bytes),
199		Ok(b"Love Jane Forever".as_slice())
200	);
201	assert_eq!(bytes, *b"Love Jane Forever");
202
203	let mut bytes = [0; 17];
204	assert_eq!(
205		dehexify_slice_mut("0x4c6f7665204a616e6520466f7265766572".as_bytes(), &mut bytes),
206		Ok(b"Love Jane Forever".as_slice())
207	);
208	assert_eq!(bytes, *b"Love Jane Forever");
209
210	let mut bytes = [0; 17];
211	assert_eq!(
212		dehexify_slice_mut("4c6f7665204a616e6520466f7265766572", &mut bytes),
213		Ok(b"Love Jane Forever".as_slice())
214	);
215	assert_eq!(bytes, *b"Love Jane Forever");
216
217	let mut bytes = [0; 17];
218	assert_eq!(
219		dehexify_slice_mut("4c6f7665204a616e6520466f7265766572".as_bytes(), &mut bytes),
220		Ok(b"Love Jane Forever".as_slice())
221	);
222	assert_eq!(bytes, *b"Love Jane Forever");
223
224	assert_eq!(dehexify_slice_mut("0", &mut []), Err(Error::InvalidLength));
225	assert_eq!(dehexify_slice_mut("0x0", &mut []), Err(Error::InvalidLength));
226
227	assert_eq!(dehexify_slice_mut("00", &mut []), Err(Error::MismatchedLength { expect: 1 }));
228	assert_eq!(dehexify_slice_mut("0x0001", &mut []), Err(Error::MismatchedLength { expect: 2 }));
229
230	assert_eq!(
231		dehexify_slice_mut("fg", &mut [0]),
232		Err(Error::InvalidCharacter { character: 'g', index: 1 })
233	);
234	assert_eq!(
235		dehexify_slice_mut("0xyz", &mut [0]),
236		Err(Error::InvalidCharacter { character: 'y', index: 0 })
237	);
238}
239
240/// Dehexify hex to a fixed length bytes vector then convert it to `T` where `T: From<[u8; N]>`.
241///
242/// # Examples
243/// ```
244/// #[derive(Debug, PartialEq)]
245/// struct Ljf([u8; 17]);
246/// impl From<[u8; 17]> for Ljf {
247/// 	fn from(array: [u8; 17]) -> Self {
248/// 		Self(array)
249/// 	}
250/// }
251///
252/// assert_eq!(
253/// 	array_bytes::dehexify_array_then_into::<_, Ljf, 17>("0x4c6f7665204a616e6520466f7265766572"),
254/// 	Ok(Ljf(*b"Love Jane Forever"))
255/// );
256/// ```
257pub fn dehexify_array_then_into<H, T, const N: usize>(hex: H) -> Result<T>
258where
259	H: AsRef<[u8]>,
260	T: From<[u8; N]>,
261{
262	Ok(dehexify_array(hex)?.into())
263}
264#[test]
265fn dehexify_array_then_into_should_work() {
266	assert_eq!(
267		dehexify_array_then_into::<_, Ljfn, 17>("0x4c6f7665204a616e6520466f7265766572"),
268		Ok(Ljfn(*b"Love Jane Forever"))
269	);
270	assert_eq!(
271		dehexify_array_then_into::<_, Ljfn, 17>("4c6f7665204a616e6520466f7265766572"),
272		Ok(Ljfn(*b"Love Jane Forever"))
273	);
274
275	assert_eq!(
276		dehexify_array_then_into::<_, Ljfn, 17>("0x4c6f7665204a616e6520466f7265766572".as_bytes()),
277		Ok(Ljfn(*b"Love Jane Forever"))
278	);
279	assert_eq!(
280		dehexify_array_then_into::<_, Ljfn, 17>("4c6f7665204a616e6520466f7265766572".as_bytes()),
281		Ok(Ljfn(*b"Love Jane Forever"))
282	);
283}
284
285/// Dehexify hex to a bytes vector then convert it to `T` where `T: From<Vec<u8>`.
286///
287/// # Examples
288/// ```
289/// #[derive(Debug, PartialEq)]
290/// struct Ljf(Vec<u8>);
291/// impl From<Vec<u8>> for Ljf {
292/// 	fn from(vec: Vec<u8>) -> Self {
293/// 		Self(vec)
294/// 	}
295/// }
296///
297/// assert_eq!(
298/// 	array_bytes::dehexify_vec_then_into::<_, Ljf>("0x4c6f7665204a616e6520466f7265766572"),
299/// 	Ok(Ljf(b"Love Jane Forever".to_vec()))
300/// );
301/// ```
302pub fn dehexify_vec_then_into<H, T>(hex: H) -> Result<T>
303where
304	H: AsRef<[u8]>,
305	T: From<Vec<u8>>,
306{
307	Ok(dehexify_bytes(hex.as_ref())?.into_vec().into())
308}
309#[test]
310fn dehexify_vec_then_into_should_work() {
311	assert_eq!(
312		dehexify_vec_then_into::<_, Ljf>("0x4c6f7665204a616e6520466f7265766572"),
313		Ok(Ljf(b"Love Jane Forever".to_vec()))
314	);
315	assert_eq!(
316		dehexify_vec_then_into::<_, Ljf>("4c6f7665204a616e6520466f7265766572"),
317		Ok(Ljf(b"Love Jane Forever".to_vec()))
318	);
319
320	assert_eq!(
321		dehexify_vec_then_into::<_, Ljf>("0x4c6f7665204a616e6520466f7265766572".as_bytes()),
322		Ok(Ljf(b"Love Jane Forever".to_vec()))
323	);
324	assert_eq!(
325		dehexify_vec_then_into::<_, Ljf>("4c6f7665204a616e6520466f7265766572".as_bytes()),
326		Ok(Ljf(b"Love Jane Forever".to_vec()))
327	);
328}
329
330#[inline(always)]
331fn dehexify_array<H, const N: usize>(hex: H) -> Result<[u8; N]>
332where
333	H: AsRef<[u8]>,
334{
335	let bytes = dehexify_bytes(hex)?;
336
337	op::slice2array(&bytes)
338}
339
340#[inline(always)]
341fn dehexify_bytes<H>(hex: H) -> Result<SmallVec<[u8; 64]>>
342where
343	H: AsRef<[u8]>,
344{
345	let hex = strip_0x(hex.as_ref());
346
347	if hex.len() % 2 != 0 {
348		Err(Error::InvalidLength)?;
349	}
350
351	let cap = hex.len() / 2;
352	let mut bytes = <SmallVec<[u8; 64]>>::with_capacity(cap);
353
354	// The capacity is fixed, it's safe to set the length; qed.
355	unsafe {
356		bytes.set_len(cap);
357	}
358
359	let bytes_ptr = bytes.as_mut_ptr();
360
361	for i in 0..cap {
362		let high = HEX2DIGIT[hex[i * 2] as usize]
363			.ok_or(Error::InvalidCharacter { character: hex[i * 2] as char, index: i * 2 })?;
364		let low = HEX2DIGIT[hex[i * 2 + 1] as usize].ok_or(Error::InvalidCharacter {
365			character: hex[i * 2 + 1] as char,
366			index: i * 2 + 1,
367		})?;
368
369		unsafe {
370			*bytes_ptr.add(i) = (high << 4) | low;
371		}
372	}
373
374	Ok(bytes)
375}
376
377#[inline(always)]
378pub(super) fn strip_0x(hex: &[u8]) -> &[u8] {
379	if hex.len() >= 2 && hex[0] == b'0' && hex[1] == b'x' {
380		&hex[2..]
381	} else {
382		hex
383	}
384}
385
386#[inline(always)]
387fn dehexify_ascii((hex0, hex0_idx): (&u8, usize), (hex1, hex1_idx): (&u8, usize)) -> Result<u8> {
388	let ascii = HEX2DIGIT[*hex0 as usize]
389		.ok_or(Error::InvalidCharacter { character: *hex0 as _, index: hex0_idx })?
390		<< 4 | HEX2DIGIT[*hex1 as usize]
391		.ok_or(Error::InvalidCharacter { character: *hex1 as _, index: hex1_idx })?;
392
393	Ok(ascii)
394}