array_bytes/
lib.rs

1#![allow(clippy::tabs_in_doc_comments)]
2#![deny(missing_docs)]
3#![no_std]
4
5//! A collection of array/bytes/hex utilities.
6//!
7//! Completely optimized for blockchain development.
8//! Especially the Substrate.
9
10extern crate alloc;
11
12#[cfg(test)] mod test;
13
14// core
15use core::{cmp::Ordering, convert::TryInto, result::Result as CoreResult, str};
16// alloc
17use alloc::{format, string::String, vec::Vec};
18// crates.io
19#[cfg(feature = "serde")] use serde::{de::Error as DeError, Deserialize, Deserializer};
20// use thiserror::Error as ThisError;
21
22/// The main result of array-bytes.
23pub type Result<T> = CoreResult<T, Error>;
24
25/// Try to convert the given hex to a specific type.
26///
27/// # Examples
28/// ```
29/// use array_bytes::TryFromHex;
30///
31/// assert_eq!(u128::try_from_hex("0x1a2b3c4d5e6f"), Ok(28772997619311));
32/// ```
33pub trait TryFromHex
34where
35	Self: Sized,
36{
37	/// Try to convert [`Self`] from hex.
38	fn try_from_hex<H>(hex: H) -> Result<Self>
39	where
40		H: AsRef<[u8]>;
41}
42macro_rules! impl_num_try_from_hex {
43	($($t:ty,)+) => {
44		$(impl TryFromHex for $t {
45			fn try_from_hex<H>(hex: H) -> Result<Self>
46			where
47				H: AsRef<[u8]>,
48			{
49				let hex = strip_0x(hex.as_ref());
50				let hex = str::from_utf8(hex).map_err(Error::Utf8Error)?;
51
52				Self::from_str_radix(hex, 16).map_err(Error::ParseIntError)
53			}
54		})+
55	};
56}
57impl_num_try_from_hex! {
58	isize,
59	i8,
60	i16,
61	i32,
62	i64,
63	i128,
64	usize,
65	u8,
66	u16,
67	u32,
68	u64,
69	u128,
70}
71macro_rules! impl_array_try_from_hex {
72	($($t:ty,)+) => {
73		$(impl TryFromHex for $t {
74			fn try_from_hex<H>(hex: H) -> Result<Self>
75			where
76				H: AsRef<[u8]>,
77			{
78				hex2array(hex)
79			}
80		})+
81	};
82}
83impl_array_try_from_hex! {
84	[u8; 1],
85	[u8; 2],
86	[u8; 3],
87	[u8; 4],
88	[u8; 5],
89	[u8; 6],
90	[u8; 7],
91	[u8; 8],
92	[u8; 9],
93	[u8; 10],
94	[u8; 11],
95	[u8; 12],
96	[u8; 13],
97	[u8; 14],
98	[u8; 15],
99	[u8; 16],
100	[u8; 17],
101	[u8; 18],
102	[u8; 19],
103	[u8; 20],
104	[u8; 21],
105	[u8; 22],
106	[u8; 23],
107	[u8; 24],
108	[u8; 25],
109	[u8; 26],
110	[u8; 27],
111	[u8; 28],
112	[u8; 29],
113	[u8; 30],
114	[u8; 31],
115	[u8; 32],
116	[u8; 33],
117	[u8; 34],
118	[u8; 35],
119	[u8; 36],
120	[u8; 37],
121	[u8; 38],
122	[u8; 39],
123	[u8; 40],
124	[u8; 41],
125	[u8; 42],
126	[u8; 43],
127	[u8; 44],
128	[u8; 45],
129	[u8; 46],
130	[u8; 47],
131	[u8; 48],
132	[u8; 49],
133	[u8; 50],
134	[u8; 51],
135	[u8; 52],
136	[u8; 53],
137	[u8; 54],
138	[u8; 55],
139	[u8; 56],
140	[u8; 57],
141	[u8; 58],
142	[u8; 59],
143	[u8; 60],
144	[u8; 61],
145	[u8; 62],
146	[u8; 63],
147	[u8; 64],
148	[u8; 128],
149	[u8; 256],
150	[u8; 512],
151}
152impl TryFromHex for Vec<u8> {
153	fn try_from_hex<H>(hex: H) -> Result<Self>
154	where
155		H: AsRef<[u8]>,
156	{
157		hex2bytes(hex)
158	}
159}
160
161/// Convert the given type to hex.
162///
163/// # Examples
164/// ```
165/// use array_bytes::Hex;
166///
167/// assert_eq!(28772997619311_u128.hex("0x"), "0x1a2b3c4d5e6f");
168/// ```
169pub trait Hex {
170	/// Convert [`Self`] to hex with the given prefix.
171	fn hex(self, prefix: &str) -> String;
172}
173macro_rules! impl_num_hex {
174	($($t:ty,)+) => {
175		$(
176			impl Hex for $t {
177				fn hex(self, prefix: &str) -> String {
178					format!("{prefix}{self:x}")
179				}
180			}
181			impl Hex for &$t {
182				fn hex(self, prefix: &str) -> String {
183					format!("{prefix}{self:x}")
184				}
185			}
186		)+
187	};
188}
189impl_num_hex! {
190	isize,
191	i8,
192	i16,
193	i32,
194	i64,
195	i128,
196	usize,
197	u8,
198	u16,
199	u32,
200	u64,
201	u128,
202}
203macro_rules! impl_array_hex {
204	($($t:ty,)+) => {
205		$(
206			impl Hex for $t {
207				fn hex(self, prefix: &str) -> String {
208					bytes2hex(prefix, self)
209				}
210			}
211			impl Hex for &$t {
212				fn hex(self, prefix: &str) -> String {
213					bytes2hex(prefix, self)
214				}
215			}
216		)+
217	};
218}
219impl_array_hex! {
220	Vec<u8>,
221	[u8; 1],
222	[u8; 2],
223	[u8; 3],
224	[u8; 4],
225	[u8; 5],
226	[u8; 6],
227	[u8; 7],
228	[u8; 8],
229	[u8; 9],
230	[u8; 10],
231	[u8; 11],
232	[u8; 12],
233	[u8; 13],
234	[u8; 14],
235	[u8; 15],
236	[u8; 16],
237	[u8; 17],
238	[u8; 18],
239	[u8; 19],
240	[u8; 20],
241	[u8; 21],
242	[u8; 22],
243	[u8; 23],
244	[u8; 24],
245	[u8; 25],
246	[u8; 26],
247	[u8; 27],
248	[u8; 28],
249	[u8; 29],
250	[u8; 30],
251	[u8; 31],
252	[u8; 32],
253	[u8; 33],
254	[u8; 34],
255	[u8; 35],
256	[u8; 36],
257	[u8; 37],
258	[u8; 38],
259	[u8; 39],
260	[u8; 40],
261	[u8; 41],
262	[u8; 42],
263	[u8; 43],
264	[u8; 44],
265	[u8; 45],
266	[u8; 46],
267	[u8; 47],
268	[u8; 48],
269	[u8; 49],
270	[u8; 50],
271	[u8; 51],
272	[u8; 52],
273	[u8; 53],
274	[u8; 54],
275	[u8; 55],
276	[u8; 56],
277	[u8; 57],
278	[u8; 58],
279	[u8; 59],
280	[u8; 60],
281	[u8; 61],
282	[u8; 62],
283	[u8; 63],
284	[u8; 64],
285	[u8; 128],
286	[u8; 256],
287	[u8; 512],
288}
289impl Hex for &[u8] {
290	fn hex(self, prefix: &str) -> String {
291		bytes2hex(prefix, self)
292	}
293}
294
295/// The main error of array-bytes.
296#[derive(Debug, PartialEq, Eq)]
297pub enum Error {
298	/// The length must not be odd.
299	InvalidLength,
300	/// Found the invalid character at `index`.
301	InvalidCharacter {
302		/// The invalid character.
303		character: char,
304		/// The invalid character's index.
305		index: usize,
306	},
307	/// The data can not fit the array/slice length well.
308	MismatchedLength {
309		/// Expected length.
310		expect: usize,
311	},
312	/// Failed to parse the hex number from hex string.
313	Utf8Error(core::str::Utf8Error),
314	/// Failed to parse the hex number from hex string.
315	ParseIntError(core::num::ParseIntError),
316}
317
318/// `&[T]` to `[T; N]`.
319///
320/// # Examples
321/// ```
322/// assert_eq!(array_bytes::slice2array::<_, 8>(&[0; 8]), Ok([0; 8]));
323/// ```
324pub fn slice2array<T, const N: usize>(slice: &[T]) -> Result<[T; N]>
325where
326	T: Copy,
327{
328	slice.try_into().map_err(|_| Error::MismatchedLength { expect: N })
329}
330
331/// Just like [`slice2array`] but without the checking.
332///
333/// # Examples
334/// ```
335/// assert_eq!(array_bytes::slice2array_unchecked::<_, 8>(&[0; 8]), [0; 8]);
336/// ```
337pub fn slice2array_unchecked<T, const N: usize>(slice: &[T]) -> [T; N]
338where
339	T: Copy,
340{
341	slice2array(slice).unwrap()
342}
343
344/// `&[T]` to `&[T; N]`.
345///
346/// # Examples
347/// ```
348/// assert_eq!(array_bytes::slice2array::<_, 8>(&[0; 8]), Ok(&[0; 8]));
349/// ```
350pub fn slice2array_ref<T, const N: usize>(slice: &[T]) -> Result<&[T; N]>
351where
352	T: Copy,
353{
354	slice.try_into().map_err(|_| Error::MismatchedLength { expect: N })
355}
356
357/// Just like [`slice2array_ref`] but without the checking.
358///
359/// # Examples
360/// ```
361/// assert_eq!(array_bytes::slice2array_unchecked::<_, 8>(&[0; 8]), &[0; 8]);
362/// ```
363pub fn slice2array_ref_unchecked<T, const N: usize>(slice: &[T]) -> &[T; N]
364where
365	T: Copy,
366{
367	slice2array_ref(slice).unwrap()
368}
369
370/// Prefixes the given element to the given array/slice/vector to make it a fixed-size array of
371/// length `N`.
372///
373/// If the length of the array/slice/vector is already equal to `N`, it returns the
374/// array/slice/vector as a fixed-size array.
375/// If the length of the array/slice/vector is greater than `N`, it returns the first `N` elements
376/// of the array/slice/vector as a fixed-size array.
377/// If the length of the array/slice/vector is less than `N`, it creates a new fixed-size array of
378/// length `N` and copies the array/slice/vector into it, padding the remaining elements with the
379/// given element.
380///
381/// # Examples
382/// ```
383/// assert_eq!(array_bytes::prefix_with::<_, _, 4>([1, 2, 3, 4], 0), [1, 2, 3, 4]);
384/// assert_eq!(array_bytes::prefix_with::<_, _, 4>([1, 2, 3, 4, 5, 6], 0), [1, 2, 3, 4]);
385/// assert_eq!(array_bytes::prefix_with::<_, _, 5>([1, 2, 3], 0), [0, 0, 1, 2, 3]);
386/// ```
387pub fn prefix_with<A, T, const N: usize>(any: A, element: T) -> [T; N]
388where
389	A: AsRef<[T]>,
390	T: Copy,
391{
392	let a = any.as_ref();
393
394	match a.len().cmp(&N) {
395		Ordering::Equal => slice2array_unchecked(a),
396		Ordering::Greater => slice2array_unchecked(&a[..N]),
397		Ordering::Less => {
398			let mut padded = [element; N];
399
400			padded[N - a.len()..].copy_from_slice(a);
401
402			padded
403		},
404	}
405}
406
407/// Suffixes the given element to the given array/slice/vector to make it a fixed-size array of
408/// length `N`.
409///
410/// If the length of the array/slice/vector is already equal to `N`, it returns the
411/// array/slice/vector as a fixed-size array.
412/// If the length of the array/slice/vector is greater than `N`, it returns the first `N` elements
413/// of the array/slice/vector as a fixed-size array.
414/// If the length of the array/slice/vector is less than `N`, it creates a new fixed-size array of
415/// length `N` and copies the array/slice/vector into it, padding the remaining elements with the
416/// given element.
417///
418/// # Examples
419/// ```
420/// assert_eq!(array_bytes::suffix_with::<_, _, 4>([1, 2, 3, 4], 0), [1, 2, 3, 4]);
421/// assert_eq!(array_bytes::suffix_with::<_, _, 4>([1, 2, 3, 4, 5, 6], 0), [1, 2, 3, 4]);
422/// assert_eq!(array_bytes::suffix_with::<_, _, 5>([1, 2, 3], 0), [1, 2, 3, 0, 0]);
423/// ```
424pub fn suffix_with<A, T, const N: usize>(any: A, element: T) -> [T; N]
425where
426	A: AsRef<[T]>,
427	T: Copy,
428{
429	let a = any.as_ref();
430
431	match a.len().cmp(&N) {
432		Ordering::Equal => slice2array_unchecked(a),
433		Ordering::Greater => slice2array_unchecked(&a[..N]),
434		Ordering::Less => {
435			let mut padded = [element; N];
436
437			padded[..a.len()].copy_from_slice(a);
438
439			padded
440		},
441	}
442}
443
444/// Convert `&[T]` to a type directly.
445///
446/// # Examples
447/// ```
448/// #[derive(Debug, PartialEq)]
449/// struct LJF([u8; 17]);
450/// impl From<[u8; 17]> for LJF {
451/// 	fn from(array: [u8; 17]) -> Self {
452/// 		Self(array)
453/// 	}
454/// }
455///
456/// assert_eq!(
457/// 	array_bytes::slice_n_into::<u8, LJF, 17>(b"Love Jane Forever"),
458/// 	Ok(LJF(*b"Love Jane Forever"))
459/// );
460/// ```
461pub fn slice_n_into<T, V, const N: usize>(slice: &[T]) -> Result<V>
462where
463	T: Copy,
464	V: From<[T; N]>,
465{
466	Ok(slice2array(slice)?.into())
467}
468
469/// Just like [`slice_n_into`] but without the checking.
470///
471/// # Examples
472/// ```
473/// #[derive(Debug, PartialEq)]
474/// struct LJF([u8; 17]);
475/// impl From<[u8; 17]> for LJF {
476/// 	fn from(array: [u8; 17]) -> Self {
477/// 		Self(array)
478/// 	}
479/// }
480///
481/// assert_eq!(
482/// 	array_bytes::slice_n_into_unchecked::<u8, LJF, 17>(b"Love Jane Forever"),
483/// 	LJF(*b"Love Jane Forever")
484/// );
485/// ```
486pub fn slice_n_into_unchecked<T, V, const N: usize>(slice: &[T]) -> V
487where
488	T: Copy,
489	V: From<[T; N]>,
490{
491	slice2array_unchecked(slice).into()
492}
493
494/// [`Vec<T>`] to `[T; N]`.
495///
496/// # Examples
497/// ```
498/// assert_eq!(array_bytes::vec2array::<_, 8>(vec![0; 8]), Ok([0; 8]));
499/// ```
500pub fn vec2array<T, const N: usize>(vec: Vec<T>) -> Result<[T; N]> {
501	vec.try_into().map_err(|_| Error::MismatchedLength { expect: N })
502}
503
504/// Just like [`vec2array`] but without the checking.
505///
506/// # Examples
507/// ```
508/// assert_eq!(array_bytes::vec2array_unchecked::<_, 8>(vec![0; 8]), [0; 8]);
509/// ```
510pub fn vec2array_unchecked<T, const N: usize>(vec: Vec<T>) -> [T; N] {
511	vec2array(vec).unwrap()
512}
513
514/// Convert [`Vec<T>`] to a type directly.
515///
516/// # Examples
517///
518/// ```
519/// #[derive(Debug, PartialEq)]
520/// struct LJF([u8; 17]);
521/// impl From<[u8; 17]> for LJF {
522/// 	fn from(array: [u8; 17]) -> Self {
523/// 		Self(array)
524/// 	}
525/// }
526///
527/// assert_eq!(
528/// 	array_bytes::vec_n_into::<u8, LJF, 17>(b"Love Jane Forever".to_vec()),
529/// 	Ok(LJF(*b"Love Jane Forever"))
530/// );
531/// ```
532pub fn vec_n_into<T, V, const N: usize>(vec: Vec<T>) -> Result<V>
533where
534	V: From<[T; N]>,
535{
536	Ok(vec2array(vec)?.into())
537}
538
539/// Just like [`vec_n_into`] but without the checking.
540///
541/// # Examples
542/// ```
543/// #[derive(Debug, PartialEq)]
544/// struct LJF([u8; 17]);
545/// impl From<[u8; 17]> for LJF {
546/// 	fn from(array: [u8; 17]) -> Self {
547/// 		Self(array)
548/// 	}
549/// }
550///
551/// assert_eq!(
552/// 	array_bytes::vec_n_into_unchecked::<u8, LJF, 17>(b"Love Jane Forever".to_vec()),
553/// 	LJF(*b"Love Jane Forever")
554/// );
555/// ```
556pub fn vec_n_into_unchecked<T, V, const N: usize>(vec: Vec<T>) -> V
557where
558	V: From<[T; N]>,
559{
560	vec2array_unchecked(vec).into()
561}
562
563/// Convert hex bytes to hex string.
564///
565/// This is useful when you are interacting with the IO.
566///
567/// # Examples
568/// ```
569/// assert_eq!(
570/// 	array_bytes::hex_bytes2hex_str(b"0x4c6f7665204a616e6520466f7265766572"),
571/// 	Ok("0x4c6f7665204a616e6520466f7265766572"),
572/// );
573/// ```
574pub fn hex_bytes2hex_str(bytes: &[u8]) -> Result<&str> {
575	for (i, byte) in bytes.iter().enumerate().skip(if bytes.starts_with(b"0x") { 2 } else { 0 }) {
576		if !is_hex_ascii(byte) {
577			Err(Error::InvalidCharacter { character: *byte as _, index: i })?;
578		}
579	}
580
581	Ok(
582		// Validated in previous step, never fails here; qed.
583		unsafe { str::from_utf8_unchecked(bytes) },
584	)
585}
586
587/// Just like [`hex_bytes2hex_str`] but without the checking.
588///
589/// # Safety
590/// See the [`str::from_utf8_unchecked`].
591///
592/// # Examples
593/// ```
594/// unsafe {
595/// 	assert_eq!(
596/// 		array_bytes::hex_bytes2hex_str_unchecked(b"0x4c6f7665204a616e6520466f7265766572"),
597/// 		"0x4c6f7665204a616e6520466f7265766572",
598/// 	);
599/// }
600/// ```
601pub unsafe fn hex_bytes2hex_str_unchecked(bytes: &[u8]) -> &str {
602	str::from_utf8_unchecked(bytes)
603}
604
605/// `AsRef<[u8]>` to [`String`].
606///
607/// # Examples
608/// ```
609/// assert_eq!(
610/// 	array_bytes::bytes2hex("0x", b"Love Jane Forever"),
611/// 	String::from("0x4c6f7665204a616e6520466f7265766572")
612/// );
613/// ```
614pub fn bytes2hex<B>(prefix: &str, bytes: B) -> String
615where
616	B: AsRef<[u8]>,
617{
618	let bytes = bytes.as_ref();
619	let mut hex = String::with_capacity(prefix.len() + bytes.len() * 2);
620
621	prefix.chars().for_each(|byte| hex.push(byte));
622	bytes.iter().for_each(|byte| {
623		hex.push(char::from_digit((byte >> 4) as _, 16).unwrap());
624		hex.push(char::from_digit((byte & 0xf) as _, 16).unwrap());
625	});
626
627	hex
628}
629
630/// Just like [`hex2bytes`] but to a fixed length array.
631///
632/// # Examples
633/// ```
634/// assert_eq!(
635/// 	array_bytes::hex2array("0x4c6f7665204a616e6520466f7265766572"),
636/// 	Ok(*b"Love Jane Forever")
637/// );
638/// ```
639pub fn hex2array<H, const N: usize>(hex: H) -> Result<[u8; N]>
640where
641	H: AsRef<[u8]>,
642{
643	vec2array(hex2bytes(hex.as_ref())?)
644}
645
646/// Just like [`hex2array`] but without the checking.
647///
648/// # Examples
649/// ```
650/// assert_eq!(
651/// 	array_bytes::hex2array_unchecked("0x4c6f7665204a616e6520466f7265766572"),
652/// 	*b"Love Jane Forever"
653/// );
654/// ```
655pub fn hex2array_unchecked<H, const N: usize>(hex: H) -> [u8; N]
656where
657	H: AsRef<[u8]>,
658{
659	hex2bytes_unchecked(hex).try_into().unwrap()
660}
661
662/// `AsRef<[u8]>` to [`Vec<u8>`].
663///
664/// Return error if:
665/// - length is odd
666/// - encounter invalid hex ascii
667///
668/// # Examples
669/// ```
670/// assert_eq!(
671/// 	array_bytes::hex2bytes("0x4c6f7665204a616e6520466f7265766572"),
672/// 	Ok(b"Love Jane Forever".to_vec())
673/// );
674/// ```
675pub fn hex2bytes<H>(hex: H) -> Result<Vec<u8>>
676where
677	H: AsRef<[u8]>,
678{
679	let hex = strip_0x(hex.as_ref());
680
681	if hex.len() % 2 != 0 {
682		Err(Error::InvalidLength)?;
683	}
684
685	let mut bytes = Vec::new();
686
687	for i in (0..hex.len()).step_by(2) {
688		bytes.push(hex2byte((&hex[i], i), (&hex[i + 1], i + 1))?);
689	}
690
691	Ok(bytes)
692}
693
694/// Just like [`hex2bytes`] but without checking.
695///
696/// # Examples
697/// ```
698/// assert_eq!(
699/// 	array_bytes::hex2bytes_unchecked("0x4c6f7665204a616e6520466f7265766572"),
700/// 	*b"Love Jane Forever"
701/// );
702/// ```
703pub fn hex2bytes_unchecked<H>(hex: H) -> Vec<u8>
704where
705	H: AsRef<[u8]>,
706{
707	let hex = strip_0x(hex.as_ref());
708
709	(0..hex.len()).step_by(2).map(|i| hex2byte_unchecked(&hex[i], &hex[i + 1])).collect()
710}
711
712/// `AsRef<[u8]>` to `&[u8]`.
713///
714/// This function will modify the given slice's source and return the revised result.
715///
716/// Return error if:
717/// - length is odd
718/// - encounter invalid hex ascii
719/// - mismatched slice size
720///
721/// # Examples
722/// ```
723/// let mut bytes = [0; 17];
724///
725/// assert_eq!(
726/// 	array_bytes::hex2slice("0x4c6f7665204a616e6520466f7265766572", &mut bytes),
727/// 	Ok(b"Love Jane Forever".as_slice())
728/// );
729/// assert_eq!(bytes, *b"Love Jane Forever");
730/// ```
731pub fn hex2slice<H>(hex: H, slice: &mut [u8]) -> Result<&[u8]>
732where
733	H: AsRef<[u8]>,
734{
735	let hex = strip_0x(hex.as_ref());
736
737	if hex.len() % 2 != 0 {
738		Err(Error::InvalidLength)?;
739	}
740
741	let expected_len = hex.len() >> 1;
742
743	if expected_len != slice.len() {
744		Err(Error::MismatchedLength { expect: expected_len })?;
745	}
746
747	for (byte, i) in slice.iter_mut().zip((0..hex.len()).step_by(2)) {
748		*byte = hex2byte((&hex[i], i), (&hex[i + 1], i + 1))?;
749	}
750
751	Ok(slice)
752}
753
754/// Just like [`hex2slice`] but without checking.
755///
756/// # Examples
757/// ```
758/// let mut bytes = [0; 17];
759///
760/// assert_eq!(
761/// 	array_bytes::hex2slice_unchecked("0x4c6f7665204a616e6520466f7265766572", &mut bytes),
762/// 	b"Love Jane Forever"
763/// );
764/// assert_eq!(bytes, *b"Love Jane Forever");
765/// ```
766pub fn hex2slice_unchecked<H>(hex: H, slice: &mut [u8]) -> &[u8]
767where
768	H: AsRef<[u8]>,
769{
770	let hex = strip_0x(hex.as_ref());
771
772	slice
773		.iter_mut()
774		.zip((0..hex.len()).step_by(2))
775		.for_each(|(byte, i)| *byte = hex2byte_unchecked(&hex[i], &hex[i + 1]));
776
777	slice
778}
779
780/// Try to convert `AsRef<[u8]>` to `T` directly, where `T: From<Vec<u8>>`.
781///
782/// # Examples
783/// ```
784/// #[derive(Debug, PartialEq)]
785/// struct LJF(Vec<u8>);
786/// impl From<Vec<u8>> for LJF {
787/// 	fn from(vec: Vec<u8>) -> Self {
788/// 		Self(vec)
789/// 	}
790/// }
791///
792/// assert_eq!(
793/// 	array_bytes::hex_into::<_, LJF>("0x4c6f7665204a616e6520466f7265766572"),
794/// 	Ok(LJF(b"Love Jane Forever".to_vec()))
795/// );
796/// ```
797pub fn hex_into<H, T>(hex: H) -> Result<T>
798where
799	H: AsRef<[u8]>,
800	T: From<Vec<u8>>,
801{
802	Ok(hex2bytes(hex.as_ref())?.into())
803}
804
805/// Just like [`hex_into`] but without the checking.
806///
807/// # Examples
808/// ```
809/// #[derive(Debug, PartialEq)]
810/// struct LJF(Vec<u8>);
811/// impl From<Vec<u8>> for LJF {
812/// 	fn from(vec: Vec<u8>) -> Self {
813/// 		Self(vec)
814/// 	}
815/// }
816///
817/// assert_eq!(
818/// 	array_bytes::hex_into_unchecked::<_, LJF>("0x4c6f7665204a616e6520466f7265766572"),
819/// 	LJF(b"Love Jane Forever".to_vec())
820/// );
821/// ```
822pub fn hex_into_unchecked<H, T>(hex: H) -> T
823where
824	H: AsRef<[u8]>,
825	T: From<Vec<u8>>,
826{
827	hex2bytes_unchecked(hex).into()
828}
829
830/// Try to convert `AsRef<[u8]>` to `T` directly, where `T: From<[u8; N]>`.
831///
832/// # Examples
833/// ```
834/// #[derive(Debug, PartialEq)]
835/// struct LJF([u8; 17]);
836/// impl From<[u8; 17]> for LJF {
837/// 	fn from(array: [u8; 17]) -> Self {
838/// 		Self(array)
839/// 	}
840/// }
841///
842/// assert_eq!(
843/// 	array_bytes::hex_n_into::<_, LJF, 17>("0x4c6f7665204a616e6520466f7265766572"),
844/// 	Ok(LJF(*b"Love Jane Forever"))
845/// );
846/// ```
847pub fn hex_n_into<H, T, const N: usize>(hex: H) -> Result<T>
848where
849	H: AsRef<[u8]>,
850	T: From<[u8; N]>,
851{
852	Ok(hex2array(hex)?.into())
853}
854
855/// Just like [`hex_n_into`] but without the checking.
856///
857/// # Examples
858/// ```
859/// #[derive(Debug, PartialEq)]
860/// struct LJF([u8; 17]);
861/// impl From<[u8; 17]> for LJF {
862/// 	fn from(array: [u8; 17]) -> Self {
863/// 		Self(array)
864/// 	}
865/// }
866///
867/// assert_eq!(
868/// 	array_bytes::hex_n_into_unchecked::<_, LJF, 17>("0x4c6f7665204a616e6520466f7265766572"),
869/// 	LJF(*b"Love Jane Forever")
870/// );
871/// ```
872pub fn hex_n_into_unchecked<H, T, const N: usize>(hex: H) -> T
873where
874	H: AsRef<[u8]>,
875	T: From<[u8; N]>,
876{
877	hex2array_unchecked(hex).into()
878}
879
880/// Deserialize hex to `T`, where `T: From<Vec<u8>>`.
881///
882/// # Examples
883/// ```
884/// use serde::Deserialize;
885///
886/// #[derive(Debug, PartialEq)]
887/// struct LJF(Vec<u8>);
888/// impl From<Vec<u8>> for LJF {
889/// 	fn from(vec: Vec<u8>) -> Self {
890/// 		Self(vec)
891/// 	}
892/// }
893///
894/// #[derive(Debug, PartialEq, Deserialize)]
895/// struct WrappedLJF {
896/// 	#[serde(deserialize_with = "array_bytes::hex_deserialize_into")]
897/// 	ljf: LJF,
898/// }
899///
900/// assert_eq!(
901/// 	serde_json::from_str::<WrappedLJF>(r#"{
902/// 		"ljf": "0x4c6f7665204a616e6520466f7265766572"
903/// 	}"#).unwrap(),
904/// 	WrappedLJF {
905/// 		ljf: LJF(b"Love Jane Forever".to_vec())
906/// 	}
907/// );
908#[cfg(feature = "serde")]
909pub fn hex_deserialize_into<'de, D, T>(hex: D) -> CoreResult<T, D::Error>
910where
911	D: Deserializer<'de>,
912	T: From<Vec<u8>>,
913{
914	Ok(hex2bytes_unchecked(<&str>::deserialize(hex)?).into())
915}
916
917/// Deserialize hex to `T`, where `T: From<[u8; N]>`.
918///
919/// # Examples
920/// ```
921/// use serde::Deserialize;
922///
923/// #[derive(Debug, PartialEq)]
924/// struct LJF([u8; 17]);
925/// impl From<[u8; 17]> for LJF {
926/// 	fn from(array: [u8; 17]) -> Self {
927/// 		Self(array)
928/// 	}
929/// }
930///
931/// #[derive(Debug, PartialEq, Deserialize)]
932/// struct WrappedLJF {
933/// 	#[serde(deserialize_with = "array_bytes::hex_deserialize_n_into")]
934/// 	ljf: LJF,
935/// }
936///
937/// assert_eq!(
938/// 	serde_json::from_str::<WrappedLJF>(r#"{
939/// 		"ljf": "0x4c6f7665204a616e6520466f7265766572"
940/// 	}"#).unwrap(),
941/// 	WrappedLJF {
942/// 		ljf: LJF(*b"Love Jane Forever")
943/// 	}
944/// );
945#[cfg(feature = "serde")]
946pub fn hex_deserialize_n_into<'de, D, T, const N: usize>(hex: D) -> CoreResult<T, D::Error>
947where
948	D: Deserializer<'de>,
949	T: From<[u8; N]>,
950{
951	Ok(hex2array_unchecked(<&str>::deserialize(hex)?).into())
952}
953
954/// Deserialize hex to any Rust primitive num types.
955///
956/// # Examples
957/// ```
958/// use serde::Deserialize;
959///
960/// #[derive(Debug, PartialEq, Deserialize)]
961/// struct LJF {
962/// 	#[serde(deserialize_with = "array_bytes::de_hex2num")]
963/// 	_0: u8,
964/// 	#[serde(deserialize_with = "array_bytes::de_hex2num")]
965/// 	_1: u8,
966/// 	#[serde(deserialize_with = "array_bytes::de_hex2num")]
967/// 	_2: u8,
968/// 	#[serde(deserialize_with = "array_bytes::de_hex2num")]
969/// 	_3: u32,
970/// }
971///
972/// assert_eq!(
973/// 	serde_json::from_str::<LJF>(
974/// 		r#"{
975/// 		"_0": "0x5",
976/// 		"_1": "0x2",
977/// 		"_2": "0x0",
978/// 		"_3": "0x522"
979/// 	}"#
980/// 	)
981/// 	.unwrap(),
982/// 	LJF { _0: 5, _1: 2, _2: 0, _3: 1314 }
983/// );
984/// ```
985#[cfg(feature = "serde")]
986pub fn de_hex2num<'de, D, T>(hex: D) -> CoreResult<T, D::Error>
987where
988	D: Deserializer<'de>,
989	T: TryFromHex,
990{
991	let hex = <&str>::deserialize(hex)?;
992
993	T::try_from_hex(hex).map_err(|_| D::Error::custom(alloc::format!("Invalid hex str `{}`", hex)))
994}
995
996/// Deserialize hex to [`Vec<u8>`].
997///
998/// # Examples
999/// ```
1000/// use serde::Deserialize;
1001///
1002/// #[derive(Debug, PartialEq, Deserialize)]
1003/// struct LJF {
1004/// 	#[serde(deserialize_with = "array_bytes::de_hex2bytes")]
1005/// 	ljf: Vec<u8>,
1006/// }
1007///
1008/// assert_eq!(
1009/// 	serde_json::from_str::<LJF>(
1010/// 		r#"{
1011/// 		"ljf": "0x4c6f7665204a616e6520466f7265766572"
1012/// 	}"#
1013/// 	)
1014/// 	.unwrap(),
1015/// 	LJF { ljf: (*b"Love Jane Forever").to_vec() }
1016/// );
1017/// ```
1018#[cfg(feature = "serde")]
1019pub fn de_hex2bytes<'de, D>(hex: D) -> CoreResult<Vec<u8>, D::Error>
1020where
1021	D: Deserializer<'de>,
1022{
1023	let hex = <&str>::deserialize(hex)?;
1024
1025	hex2bytes(hex).map_err(|_| D::Error::custom(alloc::format!("Invalid hex str `{}`", hex)))
1026}
1027
1028fn strip_0x(hex: &[u8]) -> &[u8] {
1029	if let Some(hex) = hex.strip_prefix(b"0x") {
1030		hex
1031	} else {
1032		hex
1033	}
1034}
1035
1036fn is_hex_ascii(byte: &u8) -> bool {
1037	// Convert to lowercase.
1038	let byte = byte | 0b10_0000;
1039
1040	matches!(byte, b'0'..=b'9' | b'a'..=b'f')
1041}
1042
1043fn hex_ascii2digit(hex_ascii: &u8) -> Option<u8> {
1044	// Convert to lowercase.
1045	let hex_ascii = hex_ascii | 0b10_0000;
1046
1047	match hex_ascii {
1048		b'0'..=b'9' => Some(hex_ascii - b'0'),
1049		b'a'..=b'f' => Some(hex_ascii - b'a' + 10),
1050		_ => None,
1051	}
1052}
1053
1054fn hex2byte(hex_ascii_1: (&u8, usize), hex_ascii_2: (&u8, usize)) -> Result<u8> {
1055	let byte = hex_ascii2digit(hex_ascii_1.0)
1056		.ok_or(Error::InvalidCharacter { character: *hex_ascii_1.0 as _, index: hex_ascii_1.1 })?
1057		<< 4 | hex_ascii2digit(hex_ascii_2.0)
1058		.ok_or(Error::InvalidCharacter { character: *hex_ascii_2.0 as _, index: hex_ascii_2.1 })?;
1059
1060	Ok(byte)
1061}
1062
1063fn hex2byte_unchecked(hex_ascii_1: &u8, hex_ascii_2: &u8) -> u8 {
1064	hex_ascii2digit(hex_ascii_1).unwrap() << 4 | hex_ascii2digit(hex_ascii_2).unwrap()
1065}