1extern crate proc_macro;
18
19use proc_macro_hack::proc_macro_hack;
20use quote::quote;
21use syn::parse_macro_input;
22
23struct Bytes(Vec<u8>);
24
25impl ::std::fmt::Debug for Bytes {
26 #[inline]
27 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
28 let data = &self.0;
29 write!(f, "&[")?;
30 if data.len() != 0 {
31 write!(f, "{:#04x}u8", data[0])?;
32 for unit in data.iter().skip(1) {
33 write!(f, ", {:#04x}", unit)?;
34 }
35 }
36 write!(f, "]")
37 }
38}
39
40#[proc_macro_hack]
41pub fn u8_slice(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
42 let input = parse_macro_input!(input as syn::LitStr);
43 let expanded = {
44 let input = input.value().replace("_", "");
45 if input.len() < 2 || &input[..2] != "0x" || input.len() % 2 != 0 {
46 panic!("Input has to be a hexadecimal string with 0x-prefix.");
47 };
48 let input_str = &input[2..];
49 let buffer_len = input_str.len() / 2;
50 let buffer = if buffer_len != 0 {
51 let mut buffer = vec![0u8; buffer_len];
52 faster_hex::hex_decode(input_str.as_bytes(), &mut buffer).unwrap_or_else(|err| {
53 panic!("Failed to parse the input hexadecimal string: {}", err);
54 });
55 buffer
56 } else {
57 vec![]
58 };
59 let bytes = Bytes(buffer);
60 let eval_str = format!("{:?}", bytes);
61 let eval_ts: proc_macro2::TokenStream = eval_str.parse().unwrap_or_else(|_| {
62 panic!(
63 "Failed to parse the string \"{}\" to TokenStream.",
64 eval_str
65 );
66 });
67 quote!(#eval_ts)
68 };
69 expanded.into()
70}