nsb 0.1.1

Night-sky background evaluation and observation planning for ground-based astronomy.
Documentation
// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Vallés Puig, Ramon
//! Deterministic Rust source generation for verified bundled scientific assets.

use super::types::Asset;
use std::fmt::Write as _;

/// Emit the generated Rust module consumed by `src/data/bundled.rs` and Starlight.
///
/// `verified_embedded` must contain only assets that passed existence + SHA-256
/// verification (`runtime_embedded = true`). Candidate/external registry entries
/// must not be passed here.
pub fn generate_bundled_assets_rs(
    schema_version: u32,
    verified_embedded: &[&Asset],
    starlight: Option<(&Asset, &Asset)>,
) -> String {
    let mut out = String::from("// @generated by build.rs; do not edit.\n");
    writeln!(
        out,
        "/// Manifest `schema_version` from `crates/nsb/data/manifest.toml`."
    )
    .unwrap();
    writeln!(
        out,
        "pub const ASSET_MANIFEST_SCHEMA_VERSION: u32 = {schema_version};"
    )
    .unwrap();
    out.push('\n');
    writeln!(
        out,
        "/// Build-verified `runtime_embedded` assets (existence + SHA-256 checked)."
    )
    .unwrap();
    writeln!(
        out,
        "pub static BUNDLED_ASSETS: &[BundledAssetMetadata] = &["
    )
    .unwrap();
    for asset in verified_embedded {
        debug_assert!(
            asset.runtime_embedded,
            "codegen must only emit verified runtime_embedded assets"
        );
        write_asset_literal(&mut out, asset);
    }
    writeln!(out, "];").unwrap();
    out.push('\n');
    match starlight {
        None => {
            out.push_str(
                "pub(crate) const BUNDLED_PRODUCTION_STARLIGHT_AVAILABLE: bool = false;\n",
            );
        }
        Some((map, sidecar)) => {
            writeln!(
                out,
                "pub(crate) const BUNDLED_PRODUCTION_STARLIGHT_AVAILABLE: bool = true;"
            )
            .unwrap();
            writeln!(
                out,
                "pub(crate) const BUNDLED_PRODUCTION_STARLIGHT_MAP: &[u8] = include_bytes!(concat!(env!(\"CARGO_MANIFEST_DIR\"), {:?}));",
                format!("/data/{}", map.path)
            )
            .unwrap();
            writeln!(
                out,
                "pub(crate) const BUNDLED_PRODUCTION_STARLIGHT_MANIFEST: &str = include_str!(concat!(env!(\"CARGO_MANIFEST_DIR\"), {:?}));",
                format!("/data/{}", sidecar.path)
            )
            .unwrap();
        }
    }
    out
}

fn write_asset_literal(out: &mut String, asset: &Asset) {
    writeln!(out, "    BundledAssetMetadata {{").unwrap();
    writeln!(out, "        path: {:?},", asset.path).unwrap();
    writeln!(out, "        schema: {:?},", asset.schema).unwrap();
    writeln!(out, "        sha256: {:?},", asset.sha256).unwrap();
    writeln!(out, "        source: {:?},", asset.source).unwrap();
    writeln!(out, "        license: {:?},", asset.license).unwrap();
    writeln!(out, "        generator: {:?},", asset.generator).unwrap();
    writeln!(
        out,
        "        generation_command: {:?},",
        asset.generation_command
    )
    .unwrap();
    writeln!(
        out,
        "        validation_report: {:?},",
        asset.validation_report
    )
    .unwrap();
    writeln!(
        out,
        "        calibration_status: {:?},",
        asset.calibration_status
    )
    .unwrap();
    writeln!(out, "    }},").unwrap();
}