use zerodds_idl::ast::types::EnumDef;
use crate::error::Result;
use crate::type_map::escape_keyword;
pub fn emit_enum(out: &mut String, e: &EnumDef) -> Result<()> {
out.push_str("/// Generated by `zerodds-idl-rust` from IDL enum.\n");
out.push_str("#[derive(Debug, Clone, Copy, PartialEq, Eq)]\n");
out.push_str("#[repr(i32)]\n");
out.push_str("pub enum ");
out.push_str(&escape_keyword(&e.name.text));
out.push_str(" {\n");
for (idx, enumerator) in e.enumerators.iter().enumerate() {
out.push_str(" ");
out.push_str(&escape_keyword(&enumerator.name.text));
out.push_str(&format!(" = {idx}"));
out.push_str(",\n");
}
out.push_str("}\n\n");
if let Some(first) = e.enumerators.first() {
out.push_str("impl Default for ");
out.push_str(&escape_keyword(&e.name.text));
out.push_str(" {\n");
out.push_str(" fn default() -> Self {\n");
out.push_str(&format!(
" Self::{}\n",
escape_keyword(&first.name.text)
));
out.push_str(" }\n");
out.push_str("}\n\n");
}
out.push_str("impl ");
out.push_str(&escape_keyword(&e.name.text));
out.push_str(" {\n");
out.push_str(" /// Versucht einen `i32`-Wire-Wert auf einen Enumerator zu mappen.\n");
out.push_str(" #[must_use]\n");
out.push_str(" pub fn from_wire(value: i32) -> Option<Self> {\n");
out.push_str(" match value {\n");
for (idx, enumerator) in e.enumerators.iter().enumerate() {
out.push_str(&format!(
" {idx} => Some(Self::{}),\n",
escape_keyword(&enumerator.name.text)
));
}
out.push_str(" _ => None,\n");
out.push_str(" }\n");
out.push_str(" }\n");
out.push_str("}\n\n");
out.push_str("impl zerodds_cdr::CdrEncode for ");
out.push_str(&escape_keyword(&e.name.text));
out.push_str(" {\n");
out.push_str(" fn encode(&self, w: &mut zerodds_cdr::BufferWriter) -> ::core::result::Result<(), zerodds_cdr::EncodeError> {\n");
out.push_str(" <i32 as zerodds_cdr::CdrEncode>::encode(&(*self as i32), w)\n");
out.push_str(" }\n");
out.push_str("}\n\n");
out.push_str("impl zerodds_cdr::CdrDecode for ");
out.push_str(&escape_keyword(&e.name.text));
out.push_str(" {\n");
out.push_str(" fn decode(r: &mut zerodds_cdr::BufferReader<'_>) -> ::core::result::Result<Self, zerodds_cdr::DecodeError> {\n");
out.push_str(" let v = <i32 as zerodds_cdr::CdrDecode>::decode(r)?;\n");
out.push_str(&format!(
" Self::from_wire(v).ok_or(zerodds_cdr::DecodeError::InvalidEnum {{ kind: \"{}\", value: v as u32 }})\n",
e.name.text
));
out.push_str(" }\n");
out.push_str("}\n");
Ok(())
}