include_bytes_zstd_macro/
lib.rs

1//! Macro definition of the include-bytes-zstd crate.
2
3extern crate proc_macro;
4
5use std::io::Write;
6use std::path::PathBuf;
7
8use proc_macro::TokenStream;
9use proc_macro_crate::FoundCrate;
10use syn::{parse::Parse, parse_macro_input, LitInt, LitStr, Token};
11
12struct Arguments {
13    filename: LitStr,
14    _comma: Token![,],
15    level: LitInt,
16}
17
18impl Parse for Arguments {
19    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
20        Ok(Self {
21            filename: input.parse()?,
22            _comma: input.parse()?,
23            level: input.parse()?,
24        })
25    }
26}
27
28#[doc(hidden)]
29#[proc_macro]
30pub fn include_bytes_zstd(input: TokenStream) -> TokenStream {
31    // parses arguments
32    let args = parse_macro_input!(input as Arguments);
33    let filename = PathBuf::from(args.filename.value());
34    let level = args.level.base10_parse::<i32>().unwrap();
35
36    // resolves file path
37    let manifest_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
38    let filename = if filename.is_relative() {
39        manifest_dir.join(filename)
40    } else {
41        filename
42    };
43
44    // compression
45    let bytes = std::fs::read(filename).unwrap();
46    let mut compressed = vec![];
47    let mut encoder = zstd::Encoder::new(&mut compressed, level).unwrap();
48    encoder.write_all(&bytes).unwrap();
49    encoder.finish().unwrap();
50
51    // generates code
52    let crate_name = proc_macro_crate::crate_name("include-bytes-zstd").unwrap();
53    let crate_name = match crate_name {
54        FoundCrate::Itself => "include_bytes_zstd".to_string(),
55        FoundCrate::Name(crate_name) => crate_name,
56    };
57    format!("{{ {crate_name}::decode(&{:?}) }}", compressed.as_slice())
58        .parse()
59        .unwrap()
60}