zerodds_idl_rust/
emitter.rs1use zerodds_idl::ast::types::{
6 ConstrTypeDecl, Declarator, Definition, ExceptDecl, ModuleDef, Specification, TypeDecl,
7};
8
9use crate::error::Result;
10use crate::struct_emit::emit_struct;
11use crate::type_map::{escape_keyword, rust_type_for};
12
13#[derive(Debug, Clone, Default)]
15pub struct RustGenOptions {
16 pub header_comment: Option<String>,
19}
20
21pub fn generate_rust_module(spec: &Specification, opts: &RustGenOptions) -> Result<String> {
26 let mut out = String::new();
27 out.push_str("// SPDX-License-Identifier: Apache-2.0\n");
28 if let Some(c) = &opts.header_comment {
29 for line in c.lines() {
30 out.push_str("// ");
31 out.push_str(line);
32 out.push('\n');
33 }
34 }
35 out.push_str("// Auto-generated by `zerodds-idl-rust`. Do not edit by hand.\n");
36 out.push('\n');
37 out.push_str("#![allow(clippy::too_many_lines)]\n");
38 out.push_str("#![allow(unused_imports)]\n");
39 out.push('\n');
40 out.push_str("use zerodds_cdr::{BufferReader, BufferWriter, CdrDecode, CdrEncode, DecodeError, EncodeError, Endianness};\n");
41 out.push('\n');
42
43 let mut path: Vec<String> = Vec::new();
44 for def in &spec.definitions {
45 emit_definition(&mut out, def, &mut path)?;
46 }
47
48 Ok(out)
49}
50
51fn emit_definition(out: &mut String, def: &Definition, path: &mut Vec<String>) -> Result<()> {
55 match def {
56 Definition::Module(m) => emit_module(out, m, path),
57 Definition::Type(t) => emit_type_decl(out, t, path),
58 Definition::Except(e) => {
59 emit_exception(out, e)?;
60 out.push('\n');
61 Ok(())
62 }
63 Definition::Const(_) => Ok(()),
67 _ => Ok(()),
70 }
71}
72
73fn emit_module(out: &mut String, m: &ModuleDef, path: &mut Vec<String>) -> Result<()> {
75 out.push_str("pub mod ");
76 out.push_str(&escape_keyword(&m.name.text));
77 out.push_str(" {\n");
78 out.push_str(" use zerodds_cdr::{BufferReader, BufferWriter, CdrDecode, CdrEncode, DecodeError, EncodeError, Endianness};\n\n");
79 path.push(m.name.text.clone());
82 for inner in &m.definitions {
83 let mut inner_out = String::new();
84 emit_definition(&mut inner_out, inner, path)?;
85 for line in inner_out.lines() {
87 if line.is_empty() {
88 out.push('\n');
89 } else {
90 out.push_str(" ");
91 out.push_str(line);
92 out.push('\n');
93 }
94 }
95 }
96 path.pop();
97 out.push_str("}\n\n");
98 Ok(())
99}
100
101fn emit_type_decl(out: &mut String, td: &TypeDecl, path: &[String]) -> Result<()> {
102 match td {
103 TypeDecl::Constr(ConstrTypeDecl::Struct(struct_dcl)) => {
104 use zerodds_idl::ast::types::StructDcl;
106 match struct_dcl {
107 StructDcl::Def(s) => {
108 emit_struct(out, s, path)?;
109 out.push('\n');
110 }
111 StructDcl::Forward(_) => {
112 }
115 }
116 }
117 TypeDecl::Constr(ConstrTypeDecl::Enum(e)) => {
118 crate::enum_emit::emit_enum(out, e)?;
119 out.push('\n');
120 }
121 TypeDecl::Constr(ConstrTypeDecl::Union(u)) => {
122 use zerodds_idl::ast::types::UnionDcl;
123 match u {
124 UnionDcl::Def(def) => {
125 crate::union_emit::emit_union(out, def)?;
126 out.push('\n');
127 }
128 UnionDcl::Forward(_) => {}
129 }
130 }
131 TypeDecl::Typedef(td) => {
132 crate::typedef_emit::emit_typedef(out, td)?;
133 }
134 TypeDecl::Constr(ConstrTypeDecl::Bitset(b)) => {
135 crate::bitset_emit::emit_bitset(out, b)?;
136 out.push('\n');
137 }
138 TypeDecl::Constr(ConstrTypeDecl::Bitmask(m)) => {
139 crate::bitset_emit::emit_bitmask(out, m)?;
140 out.push('\n');
141 }
142 }
143 Ok(())
144}
145
146fn emit_exception(out: &mut String, e: &ExceptDecl) -> Result<()> {
154 out.push_str("/// Generated by `zerodds-idl-rust` from IDL exception (CORBA 3.3 §7.4.10).\n");
155 out.push_str("#[derive(Debug, Clone, PartialEq, Default)]\n");
156 out.push_str("pub struct ");
157 out.push_str(&escape_keyword(&e.name.text));
158 out.push_str(" {\n");
159 for member in &e.members {
160 let rust_ty = rust_type_for(&member.type_spec)?;
161 for declarator in &member.declarators {
162 let raw = match declarator {
163 Declarator::Simple(n) => &n.text,
164 Declarator::Array(a) => &a.name.text,
165 };
166 let name = escape_keyword(raw);
167 out.push_str(&format!(" pub {name}: {rust_ty},\n"));
168 }
169 }
170 out.push_str("}\n");
171 Ok(())
172}