hex_macro/
lib.rs

1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, LitStr};
4
5/// Decodes a hex string into a byte array at compile time
6///
7/// # Examples
8///
9/// ```rust
10/// use hex_macro::hex;
11/// const DATA: [u8; 11] = hex!("48656c6c6f20776f726c64");
12/// assert_eq!(DATA, *b"Hello world");
13/// ```
14///
15/// ```rust
16/// use hex_macro::hex;
17/// // With a '0x' prefix
18/// const DATA: [u8; 11] = hex!("0x48656c6c6f20776f726c64");
19/// assert_eq!(DATA, *b"Hello world");
20/// ```
21///
22/// ```compile_fail
23/// use hex_macro::hex;
24/// const DATA: [u8; 10] = hex!("48656c6c6f20776f726c64"); // Wrong length byte array
25/// ```
26///
27/// ```compile_fail
28/// hex!("notvalidhexstring!"); // not a valid hex string
29/// ```
30#[proc_macro]
31pub fn hex(input: TokenStream) -> TokenStream {
32    let input = parse_macro_input!(input as LitStr).value();
33
34    // Trim '0x' from start
35    let input = input.trim_start_matches("0x");
36
37    match hex::decode(input) {
38        Ok(decoded) => {
39            let len = decoded.len();
40            let byte_array = quote! {
41                {
42                    const DATA: [u8; #len] = [#(#decoded),*];
43                    DATA
44                }
45            };
46            byte_array.into()
47        }
48        Err(_) => panic!("Invalid hex string"),
49    }
50}