Skip to main content

zerodds_corba_codegen/
stub.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 ZeroDDS Contributors
3
4//! Stub-Code-Generation-Helper โ€” Spec Annex-A.1 Operation-Mapping.
5//!
6//! Ein **Stub** ist der Client-Side-Proxy, der eine IDL-Operation
7//! in einen GIOP-Request marshalt, ueber IIOP sendet und die Reply
8//! demarshalt. Wir liefern eine Sprache-agnostische Datenstruktur,
9//! die das Codegen pro Ziel-Sprache verarbeitet.
10
11use alloc::string::String;
12use alloc::vec::Vec;
13
14use crate::special_types::TargetLanguage;
15
16/// Parameter-Direction.
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum ParamDirection {
19    /// `in`.
20    In,
21    /// `out`.
22    Out,
23    /// `inout`.
24    InOut,
25}
26
27/// Operation-Parameter.
28#[derive(Debug, Clone, PartialEq, Eq)]
29pub struct StubParam {
30    /// IDL-Name.
31    pub name: String,
32    /// IDL-Type-Spec (Caller-Repraesentation).
33    pub type_spec: String,
34    /// Direction.
35    pub direction: ParamDirection,
36}
37
38/// Operation-Definition fuer Stub-Generation.
39#[derive(Debug, Clone, PartialEq, Eq)]
40pub struct StubOp {
41    /// Operation-Name.
42    pub name: String,
43    /// Return-Type-Spec (`void` wenn keine).
44    pub return_type: String,
45    /// Parameter.
46    pub params: Vec<StubParam>,
47    /// `oneway` (Spec ยง7.4.16) โ€” keine Reply erwartet.
48    pub oneway: bool,
49}
50
51/// Rendert eine textuelle Stub-Skeleton-Praeambel mit den
52/// konkreten Sprach-Namen. Das ist ein **Helper** fuer Tests
53/// und Dokumentation; das richtige Codegen passiert in
54/// `crates/idl-cpp/`/etc., das diese Datenstruktur konsumiert.
55#[must_use]
56pub fn render_stub_op(op: &StubOp, lang: TargetLanguage) -> String {
57    let lang_label = match lang {
58        TargetLanguage::Cpp => "C++",
59        TargetLanguage::CSharp => "C#",
60        TargetLanguage::Java => "Java",
61        TargetLanguage::Rust => "Rust",
62    };
63    let oneway_marker = if op.oneway { "[oneway]" } else { "" };
64    let mut s = alloc::format!("// {lang_label} stub for {oneway_marker}{}", op.name);
65    s.push_str(&alloc::format!("\n//   return: {}", op.return_type));
66    for p in &op.params {
67        let dir = match p.direction {
68            ParamDirection::In => "in",
69            ParamDirection::Out => "out",
70            ParamDirection::InOut => "inout",
71        };
72        s.push_str(&alloc::format!("\n//   {dir} {} {}", p.type_spec, p.name));
73    }
74    s
75}
76
77#[cfg(test)]
78#[allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
79mod tests {
80    use super::*;
81
82    fn echo_op() -> StubOp {
83        StubOp {
84            name: "echo".into(),
85            return_type: "string".into(),
86            params: alloc::vec![StubParam {
87                name: "msg".into(),
88                type_spec: "string".into(),
89                direction: ParamDirection::In,
90            }],
91            oneway: false,
92        }
93    }
94
95    #[test]
96    fn render_stub_lists_params_per_language() {
97        let s = render_stub_op(&echo_op(), TargetLanguage::Cpp);
98        assert!(s.contains("C++ stub"));
99        assert!(s.contains("in string msg"));
100    }
101
102    #[test]
103    fn oneway_marker_present_for_oneway_ops() {
104        let mut op = echo_op();
105        op.oneway = true;
106        op.return_type = "void".into();
107        let s = render_stub_op(&op, TargetLanguage::Java);
108        assert!(s.contains("[oneway]"));
109    }
110
111    #[test]
112    fn out_and_inout_params_render() {
113        let op = StubOp {
114            name: "swap".into(),
115            return_type: "void".into(),
116            params: alloc::vec![
117                StubParam {
118                    name: "a".into(),
119                    type_spec: "long".into(),
120                    direction: ParamDirection::InOut,
121                },
122                StubParam {
123                    name: "b".into(),
124                    type_spec: "long".into(),
125                    direction: ParamDirection::Out,
126                },
127            ],
128            oneway: false,
129        };
130        let s = render_stub_op(&op, TargetLanguage::CSharp);
131        assert!(s.contains("inout long a"));
132        assert!(s.contains("out long b"));
133    }
134}