oxiforge 0.3.0

YAML-to-Rust code generator for oxivgl LVGL UIs
Documentation
// SPDX-License-Identifier: GPL-3.0-only
//! **oxiforge** — YAML-to-Rust code generator for [oxivgl](https://github.com/emobotics-dev/oxivgl) LVGL UIs.
//!
//! Three-stage pipeline: **parse** → **validate** → **codegen**.
//! Use [`generate_from_str`] for in-memory generation or [`generate`] from
//! `build.rs`.
pub mod codegen;
/// Error types returned by all pipeline stages.
pub mod error;
/// Fuzzy "did you mean?" hints for unknown YAML keys.
pub mod hints;
/// IR model types — the YAML schema as Rust structs/enums.
pub mod model;
/// YAML parsing into the IR model.
pub mod parse;
/// Semantic validation (duplicate IDs, undefined style/gradient refs).
pub mod validate;

pub use error::OxiforgeError;
/// LvglBuffers, display initialisation.
#[cfg(feature = "runtime")]
pub use oxivgl::display;
/// LvglDriver, tick source, log bridge.
#[cfg(feature = "runtime")]
pub use oxivgl::driver;
/// Built-in MONTSERRAT_* fonts, Font type.
#[cfg(feature = "runtime")]
pub use oxivgl::fonts;
// ── Runtime re-exports (behind `runtime` feature) ───────────────────
// Consumers depend only on oxiforge; these replace direct oxivgl deps.
/// All widget types, enums, style helpers.
#[cfg(feature = "runtime")]
pub use oxivgl::prelude;
/// Screen capture (host-only).
#[cfg(feature = "runtime")]
pub use oxivgl::snapshot;
/// View trait, run_lvgl render loop.
#[cfg(feature = "runtime")]
pub use oxivgl::view;

/// Parse + validate + generate Rust code from YAML string.
pub fn generate_from_str(yaml: &str) -> Result<String, OxiforgeError> {
    // Pre-pass: check for unknown keys with fuzzy suggestions
    let hint_errors = hints::check_unknown_keys(yaml);
    if let Some(e) = hint_errors.into_iter().next() {
        return Err(e);
    }

    let doc = parse::parse_str(yaml)?;
    let errors = validate::validate(&doc);
    if let Some(e) = errors.into_iter().next() {
        return Err(e);
    }
    codegen::generate(&doc).map_err(|e| OxiforgeError::Other(e.to_string()))
}

/// Parse + validate + generate from YAML file, write .rs to out_dir.
/// Intended for use in build.rs.
pub fn generate(yaml_path: &std::path::Path, out_dir: &std::path::Path) -> Result<(), OxiforgeError> {
    let content = std::fs::read_to_string(yaml_path)?;

    let hint_errors = hints::check_unknown_keys(&content);
    if let Some(e) = hint_errors.into_iter().next() {
        return Err(e);
    }

    let doc = parse::parse_str(&content)?;
    let errors = validate::validate(&doc);
    if let Some(e) = errors.into_iter().next() {
        return Err(e);
    }
    let code = codegen::generate(&doc).map_err(|e| OxiforgeError::Other(e.to_string()))?;

    let stem = yaml_path.file_stem().unwrap().to_str().unwrap();
    let out_file = out_dir.join(format!("{stem}.rs"));
    std::fs::write(&out_file, code)?;

    println!("cargo::rerun-if-changed={}", yaml_path.display());
    Ok(())
}