zerodds_corba_codegen/
skeleton.rs1use alloc::string::String;
11
12use crate::special_types::TargetLanguage;
13
14#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct SkeletonOp {
17 pub name: String,
19 pub method_name: String,
21}
22
23#[must_use]
30pub fn render_skeleton_dispatch(
31 class_name: &str,
32 ops: &[SkeletonOp],
33 lang: TargetLanguage,
34) -> String {
35 match lang {
36 TargetLanguage::Cpp => render_cpp(class_name, ops),
37 TargetLanguage::CSharp => render_csharp(class_name, ops),
38 TargetLanguage::Java => render_java(class_name, ops),
39 TargetLanguage::Rust => render_rust(class_name, ops),
40 }
41}
42
43fn render_rust(class_name: &str, ops: &[SkeletonOp]) -> String {
44 let mut s = alloc::format!(
45 "// Rust skeleton dispatch for {class_name} (used as template by zerodds-corba-rust)\nmatch op {{\n"
46 );
47 for op in ops {
48 s.push_str(&alloc::format!(
49 " \"{}\" => self.{}(req),\n",
50 op.name,
51 op.method_name,
52 ));
53 }
54 s.push_str(" _ => Err(CorbaException::BadOperation),\n}\n");
55 s
56}
57
58fn render_cpp(class_name: &str, ops: &[SkeletonOp]) -> String {
59 let mut s = alloc::format!("// C++ skeleton dispatch for {class_name}\n");
60 s.push_str("if (false) {}\n");
61 for op in ops {
62 s.push_str(&alloc::format!(
63 "else if (strcmp(op, \"{}\") == 0) return this->{}(req);\n",
64 op.name,
65 op.method_name,
66 ));
67 }
68 s.push_str("else throw CORBA::BAD_OPERATION();\n");
69 s
70}
71
72fn render_csharp(class_name: &str, ops: &[SkeletonOp]) -> String {
73 let mut s = alloc::format!("// C# skeleton dispatch for {class_name}\nswitch (op) {{\n");
74 for op in ops {
75 s.push_str(&alloc::format!(
76 " case \"{}\": return this.{}(req);\n",
77 op.name,
78 op.method_name,
79 ));
80 }
81 s.push_str(" default: throw new omg.org.CORBA.BAD_OPERATION();\n}\n");
82 s
83}
84
85fn render_java(class_name: &str, ops: &[SkeletonOp]) -> String {
86 let mut s = alloc::format!("// Java skeleton dispatch for {class_name}\nswitch (op) {{\n");
87 for op in ops {
88 s.push_str(&alloc::format!(
89 " case \"{}\": return this.{}(req);\n",
90 op.name,
91 op.method_name,
92 ));
93 }
94 s.push_str(" default: throw new org.omg.CORBA.BAD_OPERATION();\n}\n");
95 s
96}
97
98#[cfg(test)]
99#[allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
100mod tests {
101 use super::*;
102
103 fn ops() -> alloc::vec::Vec<SkeletonOp> {
104 alloc::vec![
105 SkeletonOp {
106 name: "echo".into(),
107 method_name: "echo".into(),
108 },
109 SkeletonOp {
110 name: "ping".into(),
111 method_name: "Ping".into(),
112 },
113 ]
114 }
115
116 #[test]
117 fn cpp_dispatch_uses_strcmp_and_bad_operation() {
118 let s = render_skeleton_dispatch("EchoImpl", &ops(), TargetLanguage::Cpp);
119 assert!(s.contains("strcmp(op, \"echo\")"));
120 assert!(s.contains("CORBA::BAD_OPERATION"));
121 }
122
123 #[test]
124 fn csharp_dispatch_uses_switch_and_omg_org_namespace() {
125 let s = render_skeleton_dispatch("EchoImpl", &ops(), TargetLanguage::CSharp);
126 assert!(s.contains("switch (op)"));
127 assert!(s.contains("omg.org.CORBA.BAD_OPERATION"));
128 }
129
130 #[test]
131 fn java_dispatch_uses_org_omg_namespace() {
132 let s = render_skeleton_dispatch("EchoImpl", &ops(), TargetLanguage::Java);
133 assert!(s.contains("org.omg.CORBA.BAD_OPERATION"));
134 }
135}