use serde::Deserialize;
use std::{collections::HashMap, env, fs, path::Path};
static VERSION: &str = env!("CARGO_PKG_VERSION");
fn main() {
let out_dir = env::var_os("OUT_DIR").unwrap();
let platform = rustc_host::from_cli().unwrap_or_else(|_| {
let arch = str_or_unknown(env::var("CARGO_CFG_TARGET_ARCH").unwrap());
let vendor = str_or_unknown(env::var("CARGO_CFG_TARGET_VENDOR").unwrap());
let os = str_or_unknown(env::var("CARGO_CFG_TARGET_OS").unwrap());
let env_abi = str_or_unknown(env::var("CARGO_CFG_TARGET_ENV").unwrap());
[arch, vendor, os, env_abi].join("-")
});
let changelog = include_str!("CHANGELOG.gmi");
let release_date = {
let version_line_start = format!("## {VERSION} - ");
let date_maybe = changelog
.lines()
.find_map(|l| l.strip_prefix(&version_line_start));
if let Some(date) = date_maybe
&& date.contains("-")
{
date
} else {
"Unreleased"
}
};
let cargo_toml: CargoToml = toml::from_str(include_str!("Cargo.toml")).unwrap();
let rustls = cargo_toml.get_dep("rustls").unwrap().version();
let rustls_native_certs = cargo_toml.get_dep("rustls-native-certs").unwrap().version();
let tokio = cargo_toml.get_dep("tokio").unwrap().version();
let webpki_roots = cargo_toml.get_dep("webpki-roots").unwrap().version();
let x509_parser = cargo_toml.get_dep("x509-parser").unwrap().version();
let full_version = format!(
r"{VERSION} ({platform}) rustls/{rustls} rustls-native-certs/{rustls_native_certs} tokio/{tokio} webpki-roots/{webpki_roots} x509-parser/{x509_parser}
Release-Date: {release_date}
Protocols: gemini"
);
let full_version_txt = Path::new(&out_dir).join("full_version.txt");
fs::write(full_version_txt, full_version).unwrap();
println!("cargo::rerun-if-changed=Cargo.toml,build.rs");
}
fn str_or_unknown(value: String) -> String {
if value.is_empty() {
String::from("unknown")
} else {
value
}
}
#[derive(Deserialize)]
struct CargoToml {
dependencies: HashMap<String, Package>,
}
impl CargoToml {
fn get_dep(&self, name: &'static str) -> Option<&Package> {
self.dependencies.get(name)
}
}
#[derive(Deserialize)]
#[serde(untagged)]
enum Package {
Version(String),
Manifest { version: String },
}
impl Package {
const fn version(&self) -> &str {
match self {
Self::Version(version) => version.as_str(),
Self::Manifest { version } => version.as_str(),
}
}
}