Skip to main content

zerodds_dlrl_codegen/
cpp.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 ZeroDDS Contributors
3
4//! C++-Codegen — DDS 1.4 §B.4 Annex C++ PSM.
5
6use alloc::format;
7use alloc::string::String;
8
9use crate::DlrlTypeInfo;
10
11/// Erzeugt einen C++ ObjectRoot-abgeleiteten Class-Header
12/// (`class T : public DLRL::ObjectRoot`). Spec §B.6.
13#[allow(clippy::format_collect)]
14#[must_use]
15pub fn generate_cpp_object(info: &DlrlTypeInfo) -> String {
16    let cls = simple_name(&info.name);
17    let mut out = format!(
18        "// Generated DLRL Object — Spec §B.6\n\
19class {cls} : public DLRL::ObjectRoot {{\npublic:\n"
20    );
21    for k in &info.keys {
22        out.push_str(&format!("    DDS::Long {k}_;\n"));
23        out.push_str(&format!(
24            "    DDS::Long get_{k}() const {{ return {k}_; }}\n"
25        ));
26    }
27    for (rel, target) in &info.relations {
28        let target_cls = simple_name(target);
29        out.push_str(&format!(
30            "    DLRL::RefList< {target_cls}* > {rel}_;\n\
31    DLRL::RefList< {target_cls}* >& {rel}() {{ return {rel}_; }}\n"
32        ));
33    }
34    out.push_str("};\n");
35    out
36}
37
38/// Erzeugt eine C++-Home-Class fuer einen DLRL-Type. Spec §B.3.
39#[must_use]
40pub fn generate_cpp_home(info: &DlrlTypeInfo) -> String {
41    let cls = simple_name(&info.name);
42    format!(
43        "// Generated DLRL Home — Spec §B.3\n\
44class {cls}Home : public DLRL::HomeBase {{\npublic:\n\
45    {cls}* create();\n\
46    void destroy({cls}* obj);\n\
47    {cls}* find_by_key(/* key fields */);\n\
48}};\n"
49    )
50}
51
52fn simple_name(scoped: &str) -> &str {
53    scoped.rsplit("::").next().unwrap_or(scoped)
54}
55
56#[cfg(test)]
57#[allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
58mod tests {
59    use super::*;
60
61    fn trade_info() -> DlrlTypeInfo {
62        DlrlTypeInfo {
63            name: "demo::Trade".into(),
64            keys: alloc::vec!["symbol".into()],
65            relations: alloc::vec![("quotes".into(), "demo::Quote".into())],
66        }
67    }
68
69    #[test]
70    fn cpp_object_inherits_object_root() {
71        let s = generate_cpp_object(&trade_info());
72        assert!(s.contains("class Trade : public DLRL::ObjectRoot"));
73        assert!(s.contains("symbol_"));
74        assert!(s.contains("get_symbol"));
75        assert!(s.contains("RefList< Quote* > quotes_"));
76    }
77
78    #[test]
79    fn cpp_home_inherits_home_base() {
80        let s = generate_cpp_home(&trade_info());
81        assert!(s.contains("class TradeHome : public DLRL::HomeBase"));
82        assert!(s.contains("Trade* create();"));
83        assert!(s.contains("void destroy(Trade* obj);"));
84    }
85
86    #[test]
87    fn simple_name_strips_scope() {
88        assert_eq!(simple_name("a::b::C"), "C");
89        assert_eq!(simple_name("Foo"), "Foo");
90    }
91}