use std::collections::BTreeMap;
use super::{Term, VersionMap};
fn fmt_f(v: f64) -> String {
if (v - v.round()).abs() < 1e-15 {
format!("{v:.1}")
} else {
format!("{v:.14}")
}
}
#[derive(Debug, Clone, Default)]
pub struct DatasetProvenance {
pub source_url: String,
pub sha256_hex: String,
pub retrieved_at: String,
pub byte_count: u64,
}
pub fn generate_modules_with_provenance(
versions: &VersionMap,
prov: &DatasetProvenance,
) -> anyhow::Result<BTreeMap<char, String>> {
let mut modules = BTreeMap::new();
for (version, planets) in versions {
let code = generate_one(*version, planets, Some(prov));
modules.insert(*version, code);
}
Ok(modules)
}
pub fn generate_modules(versions: &VersionMap) -> anyhow::Result<BTreeMap<char, String>> {
let mut modules = BTreeMap::new();
for (version, planets) in versions {
let code = generate_one(*version, planets, None);
modules.insert(*version, code);
}
Ok(modules)
}
fn generate_one(
_version: char,
planets: &super::PlanetMap,
prov: Option<&DatasetProvenance>,
) -> String {
let coord_letter = |c| match c {
1 => 'X',
2 => 'Y',
3 => 'Z',
_ => '?',
};
let mut code = String::new();
code.push_str("// ───────────────────────────────────────────────────────────────────\n");
code.push_str("// **AUTOGENERATED** by build.rs – DO NOT EDIT BY HAND\n");
if let Some(p) = prov {
code.push_str(&format!("// Source URL : {}\n", p.source_url));
code.push_str(&format!("// Source bytes: {}\n", p.byte_count));
code.push_str(&format!("// Source SHA256: {}\n", p.sha256_hex));
code.push_str(&format!("// Retrieved at : {}\n", p.retrieved_at));
code.push_str("// Generator : siderust scripts/vsop87/codegen.rs\n");
}
code.push_str("// ───────────────────────────────────────────────────────────────────\n");
code.push_str("use crate::calculus::vsop87::vsop87_impl::Vsop87;\n\n");
for (planet, coords) in planets {
let planet_up = planet.to_uppercase();
for (coord, t_powers) in coords {
let letter = coord_letter(*coord);
for (t, terms) in t_powers {
let array_name = format!("{planet_up}_{letter}{t}");
code.push_str("#[allow(dead_code)]\n");
code.push_str(&format!(
"pub static {array_name}: [Vsop87; {}] = [\n",
terms.len()
));
for Term { a, b, c } in terms {
code.push_str(&format!(
" Vsop87 {{ a: {}, b: {}, c: {} }},\n",
fmt_f(*a),
fmt_f(*b),
fmt_f(*c)
));
}
code.push_str("]\n;\n\n");
}
}
}
code
}