use zerodds_idl::ast::types::{Case, SwitchTypeSpec, UnionDef};
use crate::error::{Result, RustGenError};
use crate::type_map::escape_keyword;
use crate::type_map::rust_type_for;
pub fn emit_union(out: &mut String, u: &UnionDef) -> Result<()> {
out.push_str("/// Generated by `zerodds-idl-rust` from IDL union.\n");
out.push_str("#[derive(Debug, Clone, PartialEq)]\n");
out.push_str("pub enum ");
out.push_str(&escape_keyword(&u.name.text));
out.push_str(" {\n");
for case in &u.cases {
emit_case_variant(out, case)?;
}
out.push_str("}\n\n");
if let Some(first) = u.cases.first() {
let variant_name = &first.element.declarator.name().text;
out.push_str("impl Default for ");
out.push_str(&escape_keyword(&u.name.text));
out.push_str(" {\n");
out.push_str(" fn default() -> Self {\n");
let elem_type = rust_type_for(&first.element.type_spec)?;
out.push_str(&format!(
" Self::{} (<{}>::default())\n",
capitalize(variant_name),
elem_type
));
out.push_str(" }\n");
out.push_str("}\n\n");
}
let _ = &u.switch_type; Ok(())
}
fn emit_case_variant(out: &mut String, case: &Case) -> Result<()> {
let variant_name = case.element.declarator.name();
let elem_type = rust_type_for(&case.element.type_spec)?;
out.push_str(" ");
out.push_str(&capitalize(&variant_name.text));
out.push('(');
out.push_str(&elem_type);
out.push_str("),\n");
Ok(())
}
fn capitalize(s: &str) -> String {
let mut c = s.chars();
match c.next() {
None => String::new(),
Some(first) => first.to_uppercase().chain(c).collect(),
}
}
#[allow(dead_code)]
fn switch_repr(spec: &SwitchTypeSpec) -> Result<&'static str> {
use zerodds_idl::ast::types::IntegerType;
match spec {
SwitchTypeSpec::Integer(IntegerType::Int8) => Ok("i8"),
SwitchTypeSpec::Integer(IntegerType::UInt8) => Ok("u8"),
SwitchTypeSpec::Integer(IntegerType::Short | IntegerType::Int16) => Ok("i16"),
SwitchTypeSpec::Integer(IntegerType::UShort | IntegerType::UInt16) => Ok("u16"),
SwitchTypeSpec::Integer(IntegerType::Long | IntegerType::Int32) => Ok("i32"),
SwitchTypeSpec::Integer(IntegerType::ULong | IntegerType::UInt32) => Ok("u32"),
SwitchTypeSpec::Integer(IntegerType::LongLong | IntegerType::Int64) => Ok("i64"),
SwitchTypeSpec::Integer(IntegerType::ULongLong | IntegerType::UInt64) => Ok("u64"),
SwitchTypeSpec::Char | SwitchTypeSpec::Octet => Ok("u8"),
SwitchTypeSpec::Boolean => Ok("u8"),
SwitchTypeSpec::Scoped(_) => Err(RustGenError::Unsupported {
what: "union discriminator scoped",
at: 0,
}),
}
}