zerodds_dlrl_codegen/
csharp.rs1use alloc::format;
7use alloc::string::String;
8
9use crate::DlrlTypeInfo;
10
11#[allow(clippy::format_collect)]
13#[must_use]
14pub fn generate_csharp_partial(info: &DlrlTypeInfo) -> String {
15 let cls = simple_name(&info.name);
16 let ns = namespace(&info.name);
17 let key_attrs: String = info
18 .keys
19 .iter()
20 .map(|k| format!(" [DlrlKey] public long {k} {{ get; set; }}\n"))
21 .collect();
22 let rel_attrs: String = info
23 .relations
24 .iter()
25 .map(|(rel, target)| {
26 let t = simple_name(target);
27 format!(
28 " [DlrlRelation(typeof({t}))] public RefList<{t}> {rel} {{ get; }} = new RefList<{t}>();\n"
29 )
30 })
31 .collect();
32 let body = format!(
33 "[DlrlObject]\npublic partial class {cls} : ObjectRoot\n{{\n{key_attrs}{rel_attrs}}}\n"
34 );
35 if ns.is_empty() {
36 body
37 } else {
38 format!("namespace {ns}\n{{\n{body}}}\n")
39 }
40}
41
42#[allow(clippy::format_collect)]
45#[must_use]
46pub fn generate_csharp_object(info: &DlrlTypeInfo) -> String {
47 let cls = simple_name(&info.name);
48 let key_lines: String = info
49 .keys
50 .iter()
51 .map(|k| format!(" public long {k};\n"))
52 .collect();
53 format!(
54 "// Generated DLRL Object — Spec §B.6\n\
55[DlrlObject]\npublic class {cls} : ObjectRoot\n{{\n{key_lines}}}\n"
56 )
57}
58
59fn simple_name(scoped: &str) -> &str {
60 scoped.rsplit("::").next().unwrap_or(scoped)
61}
62
63fn namespace(scoped: &str) -> String {
64 let parts: alloc::vec::Vec<&str> = scoped.split("::").collect();
65 if parts.len() <= 1 {
66 return String::new();
67 }
68 parts[..parts.len() - 1].join(".")
69}
70
71#[cfg(test)]
72#[allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
73mod tests {
74 use super::*;
75
76 fn trade_info() -> DlrlTypeInfo {
77 DlrlTypeInfo {
78 name: "demo::Trade".into(),
79 keys: alloc::vec!["symbol".into()],
80 relations: alloc::vec![("quotes".into(), "demo::Quote".into())],
81 }
82 }
83
84 #[test]
85 fn csharp_partial_emits_namespace() {
86 let s = generate_csharp_partial(&trade_info());
87 assert!(s.contains("namespace demo"));
88 assert!(s.contains("[DlrlObject]"));
89 assert!(s.contains("partial class Trade : ObjectRoot"));
90 assert!(s.contains("[DlrlKey] public long symbol"));
91 assert!(s.contains("[DlrlRelation(typeof(Quote))]"));
92 assert!(s.contains("RefList<Quote> quotes"));
93 }
94
95 #[test]
96 fn csharp_partial_no_namespace_for_unscoped() {
97 let info = DlrlTypeInfo {
98 name: "Foo".into(),
99 ..DlrlTypeInfo::default()
100 };
101 let s = generate_csharp_partial(&info);
102 assert!(!s.contains("namespace"));
103 assert!(s.contains("class Foo : ObjectRoot"));
104 }
105
106 #[test]
107 fn csharp_object_emits_keys() {
108 let s = generate_csharp_object(&trade_info());
109 assert!(s.contains("public long symbol;"));
110 }
111
112 #[test]
113 fn namespace_for_multi_level() {
114 assert_eq!(namespace("a::b::C"), "a.b");
115 assert_eq!(namespace("X"), "");
116 }
117}