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