zerodds-idl-rust 1.0.0-rc.1

IDL4 → Rust code generator for ZeroDDS DataTypes (impl DdsType from zerodds-dcps).
Documentation
// SPDX-License-Identifier: Apache-2.0
// Copyright 2026 ZeroDDS Contributors
//! Emittiert IDL `enum` → Rust `enum`.
//!
//! XTypes 1.3 §7.4.5.1 Enum-Wire-Format: 32-bit signed integer (`i32`)
//! mit dem Wert des Enumerators. Default-Mapping: 0..N-1 in
//! deklarations-Reihenfolge.

use zerodds_idl::ast::types::EnumDef;

use crate::error::Result;
use crate::type_map::escape_keyword;

/// Emittiert ein vollstaendiges Rust-Enum + DdsType-Impl.
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");

    // CdrEncode/CdrDecode-Impls — wir delegieren an i32 (Wire-Format
    // §7.4.5.1) und nutzen die existing `impl CdrEncode for i32` aus
    // zerodds_cdr::encode (das macht intern den u32-cast + write_u32).
    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(())
}