1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#![doc = include_str!("../README.md")]
#![no_std]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
)]
const fn next_hex_char(string: &[u8], mut pos: usize) -> Option<(u8, usize)> {
while pos < string.len() {
let raw_val = string[pos];
pos += 1;
let val = match raw_val {
b'0'..=b'9' => raw_val - 48,
b'A'..=b'F' => raw_val - 55,
b'a'..=b'f' => raw_val - 87,
b' ' | b'\r' | b'\n' | b'\t' => continue,
0..=127 => panic!("Encountered invalid ASCII character"),
_ => panic!("Encountered non-ASCII character"),
};
return Some((val, pos));
}
None
}
const fn next_byte(string: &[u8], pos: usize) -> Option<(u8, usize)> {
let (half1, pos) = match next_hex_char(string, pos) {
Some(v) => v,
None => return None,
};
let (half2, pos) = match next_hex_char(string, pos) {
Some(v) => v,
None => panic!("Odd number of hex characters"),
};
Some(((half1 << 4) + half2, pos))
}
#[doc(hidden)]
pub const fn len(strings: &[&[u8]]) -> usize {
let mut i = 0;
let mut len = 0;
while i < strings.len() {
let mut pos = 0;
while let Some((_, new_pos)) = next_byte(strings[i], pos) {
len += 1;
pos = new_pos;
}
i += 1;
}
len
}
#[doc(hidden)]
pub const fn decode<const LEN: usize>(strings: &[&[u8]]) -> [u8; LEN] {
let mut i = 0;
let mut buf = [0u8; LEN];
let mut buf_pos = 0;
while i < strings.len() {
let mut pos = 0;
while let Some((byte, new_pos)) = next_byte(strings[i], pos) {
buf[buf_pos] = byte;
buf_pos += 1;
pos = new_pos;
}
i += 1;
}
if LEN != buf_pos {
panic!("Length mismatch. Please report this bug.");
}
buf
}
#[macro_export]
macro_rules! hex {
($($s:literal)*) => {{
const STRINGS: &[&'static [u8]] = &[$($s.as_bytes(),)*];
const LEN: usize = $crate::len(STRINGS);
const RES: [u8; LEN] = $crate::decode(STRINGS);
RES
}};
}