use dotenv::dotenv;
use std::env;
use std::fs::{self, File};
use std::io::{self, Write};
use std::path::Path;
use toml::Value;
struct AppMetadata {
file: std::fs::File,
}
impl AppMetadata {
pub fn new() -> io::Result<Self> {
let out_dir = env::var("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("app_metadata.rs");
let file = File::create(&dest_path).unwrap();
Ok(Self { file })
}
pub fn write(&mut self, key: &str, value: &str) -> io::Result<()> {
write!(
self.file,
"#[allow(unused)]\npub const APP_METADATA_{}: &str = \"{}\";\n",
key.to_uppercase(),
value
)
}
pub fn write_bytes(&mut self, key: &str, value: &[u8]) -> io::Result<()> {
write!(
self.file,
"#[allow(unused)]\npub const APP_METADATA_{}: &[u8; {}] = &[",
key.to_uppercase(),
value.len()
)?;
for (i, byte) in value.iter().enumerate() {
if i > 0 {
write!(self.file, ", ")?;
}
write!(self.file, "{}", byte)?;
}
writeln!(self.file, "];")
}
}
fn main() -> io::Result<()> {
#[cfg(windows)]
{
let mut res = winres::WindowsResource::new();
res.set_icon("icon.ico");
res.compile().unwrap();
}
let _ = dotenv();
let cargo_toml = fs::read_to_string("Cargo.toml").expect("Failed to read Cargo.toml");
let cargo_toml: Value = toml::from_str(&cargo_toml).expect("Failed to parse Cargo.toml");
let bin_name = cargo_toml
.get("bin")
.and_then(|bins| bins.as_array())
.and_then(|bins| bins.first())
.and_then(|bin| bin.get("name"))
.and_then(|name| name.as_str())
.map(str::to_string)
.unwrap_or_else(|| env::var("CARGO_PKG_NAME").unwrap());
let mut app_metadata = AppMetadata::new()?;
app_metadata.write("NAME", &bin_name)?;
app_metadata.write("VERSION", &env::var("CARGO_PKG_VERSION").unwrap())?;
if let Some(metadata) = cargo_toml.get("package").and_then(|pkg| pkg.get("metadata")).and_then(|meta| meta.as_table()) {
for (key, value) in metadata {
if let Some(value) = value.as_str() {
app_metadata.write(key, value)?;
}
}
}
let mut legacy_key = format!("{}_default_encryption_key_32b", bin_name);
let mut legacy_iv = format!("{}_iv_16b", bin_name);
legacy_key.truncate(32);
while legacy_key.len() < 32 {
legacy_key.push('!');
}
legacy_iv.truncate(16);
while legacy_iv.len() < 16 {
legacy_iv.push('!');
}
app_metadata.write_bytes("ENCRYPTION_KEY", legacy_key.as_bytes())?;
app_metadata.write_bytes("ENCRYPTION_IV", legacy_iv.as_bytes())?;
Ok(())
}