zlink_codegen/
lib.rs

1//! Code generation for Varlink interfaces.
2
3use anyhow::{Context, Result};
4use zlink::idl::Interface;
5
6mod codegen;
7pub use codegen::CodeGenerator;
8
9/// Generate Rust code from a Varlink interface.
10pub fn generate_interface(interface: &Interface<'_>) -> Result<String> {
11    let mut generator = CodeGenerator::new();
12    generator.generate_interface(interface, false)?;
13    Ok(generator.output())
14}
15
16/// Generate Rust code from multiple Varlink interfaces.
17pub fn generate_interfaces(interfaces: &[Interface<'_>]) -> Result<String> {
18    let mut generator = CodeGenerator::new();
19
20    // Add module-level header for multiple interfaces.
21    if interfaces.len() > 1 {
22        generator.write_module_header()?;
23    }
24
25    for interface in interfaces.iter() {
26        // Skip module header for all interfaces when generating multiple.
27        let skip_header = interfaces.len() > 1;
28        generator.generate_interface(interface, skip_header)?;
29    }
30    Ok(generator.output())
31}
32
33/// Format generated Rust code using rustfmt.
34pub fn format_code(code: &str) -> Result<String> {
35    use std::{
36        io::Write,
37        process::{Command, Stdio},
38    };
39
40    let mut child = Command::new("rustfmt")
41        .arg("--edition=2021")
42        .stdin(Stdio::piped())
43        .stdout(Stdio::piped())
44        .stderr(Stdio::piped())
45        .spawn()
46        .context("Failed to spawn rustfmt")?;
47
48    if let Some(mut stdin) = child.stdin.take() {
49        stdin
50            .write_all(code.as_bytes())
51            .context("Failed to write to rustfmt stdin")?;
52    }
53
54    let output = child
55        .wait_with_output()
56        .context("Failed to wait for rustfmt")?;
57
58    if !output.status.success() {
59        // If rustfmt fails, return the original code.
60        eprintln!(
61            "Warning: rustfmt failed: {}",
62            String::from_utf8_lossy(&output.stderr)
63        );
64        return Ok(code.to_string());
65    }
66
67    String::from_utf8(output.stdout).context("Failed to parse rustfmt output")
68}