use std::collections::HashMap;
use zerodds_idl::ast::types::{Definition, InterfaceDef, Specification};
use crate::error::Result;
pub(crate) type InterfaceRegistry<'a> = HashMap<String, &'a InterfaceDef>;
#[derive(Debug, Clone, Default)]
pub struct CorbaRustGenOptions {
pub header_comment: Option<String>,
}
pub fn generate_corba_rust_module(
spec: &Specification,
opts: &CorbaRustGenOptions,
) -> Result<String> {
let mut out = String::new();
out.push_str("// SPDX-License-Identifier: Apache-2.0\n");
if let Some(c) = &opts.header_comment {
for line in c.lines() {
out.push_str("// ");
out.push_str(line);
out.push('\n');
}
}
out.push_str("// Auto-generated by `zerodds-corba-rust`. Do not edit by hand.\n\n");
out.push_str("#![allow(clippy::too_many_lines)]\n");
out.push_str("#![allow(unused_imports, unused_variables)]\n\n");
let mut registry: InterfaceRegistry<'_> = HashMap::new();
collect_interfaces(spec, &mut registry);
for def in &spec.definitions {
emit_definition(&mut out, def, ®istry)?;
}
Ok(out)
}
fn collect_interfaces<'a>(spec: &'a Specification, reg: &mut InterfaceRegistry<'a>) {
for def in &spec.definitions {
collect_from_def(def, reg);
}
}
fn collect_from_def<'a>(def: &'a Definition, reg: &mut InterfaceRegistry<'a>) {
use zerodds_idl::ast::types::InterfaceDcl;
match def {
Definition::Interface(InterfaceDcl::Def(d)) => {
reg.insert(d.name.text.clone(), d);
}
Definition::Module(m) => {
for inner in &m.definitions {
collect_from_def(inner, reg);
}
}
_ => {}
}
}
fn emit_definition(
out: &mut String,
def: &Definition,
registry: &InterfaceRegistry<'_>,
) -> Result<()> {
match def {
Definition::Module(m) => emit_module(out, m, registry)?,
Definition::Interface(i_dcl) => {
use zerodds_idl::ast::types::InterfaceDcl;
match i_dcl {
InterfaceDcl::Def(def) => {
crate::interface_emit::emit_interface(out, def, registry)?;
out.push('\n');
}
InterfaceDcl::Forward(_) => {}
}
}
Definition::ValueDef(v) => {
crate::valuetype_emit::emit_valuetype(out, v)?;
out.push('\n');
}
Definition::Component(c) => {
crate::component_emit::emit_component(out, c)?;
out.push('\n');
}
Definition::Home(h) => {
crate::component_emit::emit_home(out, h)?;
out.push('\n');
}
_ => {}
}
Ok(())
}
fn emit_module(
out: &mut String,
m: &zerodds_idl::ast::types::ModuleDef,
registry: &InterfaceRegistry<'_>,
) -> Result<()> {
out.push_str("pub mod ");
out.push_str(&m.name.text);
out.push_str(" {\n");
for inner in &m.definitions {
let mut inner_out = String::new();
emit_definition(&mut inner_out, inner, registry)?;
for line in inner_out.lines() {
if line.is_empty() {
out.push('\n');
} else {
out.push_str(" ");
out.push_str(line);
out.push('\n');
}
}
}
out.push_str("}\n\n");
Ok(())
}