use std::{env, fs::read};
use anyhow::Context;
use base64::{engine::general_purpose::STANDARD, Engine};
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, LitStr};
#[proc_macro]
pub fn include_data_uri(input: TokenStream) -> TokenStream {
let path_str = parse_macro_input!(input as LitStr).value();
#[allow(clippy::expect_used)]
let uri = inner(path_str).expect("macro runtime error");
TokenStream::from(quote!(#uri))
}
fn inner(path_str: impl Into<String>) -> anyhow::Result<String> {
let path_str = path_str.into();
let cwd = env::current_dir()?;
let path = cwd
.join(&path_str)
.canonicalize()
.with_context(|| format!("canonicalize path {path_str}"))?;
let mimetype = mime_guess::from_path(&path);
if mimetype.is_empty() {
anyhow::bail!("Unknown mime type")
}
let raw = read(path).with_context(|| "reading file")?;
let data = STANDARD.encode(raw);
let uri = format!(
"data:{};base64,{}",
mimetype.first().unwrap_or_else(|| unreachable!()),
data
);
Ok(uri)
}