include_blob_macros/
lib.rs1use std::{
6 collections::hash_map::DefaultHasher,
7 env, fs,
8 hash::{Hash, Hasher},
9 path::PathBuf,
10 str::FromStr,
11};
12
13use proc_macro::TokenStream;
14
15#[proc_macro]
23pub fn include_blob(args: TokenStream) -> TokenStream {
24 let lit: syn::LitStr = syn::parse(args).unwrap();
25 let lit = lit.value();
26
27 let mut path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
28 path.push(lit);
29
30 let path = path.canonicalize().unwrap_or_else(|_| {
31 panic!("could not find file '{}'", path.display(),);
32 });
33 let metadata = fs::metadata(&path).unwrap();
34 assert!(metadata.is_file());
35 let len = metadata.len();
36
37 let mut hasher = DefaultHasher::new();
38 path.hash(&mut hasher);
39 metadata.modified().unwrap().hash(&mut hasher);
40 let unique_name = format!("include_blob_{:016x}", hasher.finish());
41
42 TokenStream::from_str(&format!(
43 r#"
44 {{
45 extern "C" {{
46 #[link_name = "{unique_name}"]
47 static STATIC: [u8; {len}];
48 }}
49 unsafe {{ &STATIC }}
50 }}
51 "#
52 ))
53 .unwrap()
54}