zerodds_dlrl_codegen/
lib.rs1#![cfg_attr(not(feature = "std"), no_std)]
27#![forbid(unsafe_code)]
28#![warn(missing_docs)]
29
30extern crate alloc;
31
32pub mod cpp;
33pub mod csharp;
34pub mod java;
35pub mod ts;
36
37pub use cpp::{generate_cpp_home, generate_cpp_object};
38pub use csharp::{generate_csharp_object, generate_csharp_partial};
39pub use java::{generate_java_object, generate_java_object_listener};
40pub use ts::{generate_ts_class, generate_ts_interface};
41
42use alloc::string::String;
43use alloc::vec::Vec;
44use zerodds_dlrl::pragma::DlrlPragma;
45
46#[derive(Debug, Clone, PartialEq, Eq, Default)]
48pub struct DlrlTypeInfo {
49 pub name: String,
51 pub keys: Vec<String>,
53 pub relations: Vec<(String, String)>,
55}
56
57#[must_use]
60pub fn collect_type_infos(
61 pragmas: &[DlrlPragma],
62) -> alloc::collections::BTreeMap<String, DlrlTypeInfo> {
63 use alloc::collections::BTreeMap;
64 let mut out: BTreeMap<String, DlrlTypeInfo> = BTreeMap::new();
65 for p in pragmas {
66 match p {
67 DlrlPragma::DataType { name } => {
68 out.entry(name.clone()).or_insert_with(|| DlrlTypeInfo {
69 name: name.clone(),
70 ..DlrlTypeInfo::default()
71 });
72 }
73 DlrlPragma::DataKey { type_name, field } => {
74 out.entry(type_name.clone())
75 .or_insert_with(|| DlrlTypeInfo {
76 name: type_name.clone(),
77 ..DlrlTypeInfo::default()
78 })
79 .keys
80 .push(field.clone());
81 }
82 DlrlPragma::DlrlRelation {
83 type_name,
84 relation,
85 target,
86 } => {
87 out.entry(type_name.clone())
88 .or_insert_with(|| DlrlTypeInfo {
89 name: type_name.clone(),
90 ..DlrlTypeInfo::default()
91 })
92 .relations
93 .push((relation.clone(), target.clone()));
94 }
95 }
96 }
97 out
98}
99
100#[cfg(test)]
101#[allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
102mod tests {
103 use super::*;
104
105 #[test]
106 fn collect_groups_by_type_name() {
107 let pragmas = alloc::vec![
108 DlrlPragma::DataType {
109 name: "demo::Trade".into()
110 },
111 DlrlPragma::DataKey {
112 type_name: "demo::Trade".into(),
113 field: "symbol".into(),
114 },
115 DlrlPragma::DataKey {
116 type_name: "demo::Trade".into(),
117 field: "venue".into(),
118 },
119 DlrlPragma::DlrlRelation {
120 type_name: "demo::Trade".into(),
121 relation: "quotes".into(),
122 target: "demo::Quote".into(),
123 },
124 ];
125 let infos = collect_type_infos(&pragmas);
126 assert_eq!(infos.len(), 1);
127 let trade = infos.get("demo::Trade").unwrap();
128 assert_eq!(
129 trade.keys,
130 alloc::vec!["symbol".to_string(), "venue".into()]
131 );
132 assert_eq!(trade.relations.len(), 1);
133 assert_eq!(trade.relations[0].0, "quotes");
134 }
135
136 #[test]
137 fn data_type_without_keys_yields_empty_lists() {
138 let pragmas = alloc::vec![DlrlPragma::DataType { name: "Foo".into() }];
139 let infos = collect_type_infos(&pragmas);
140 assert!(infos.get("Foo").unwrap().keys.is_empty());
141 assert!(infos.get("Foo").unwrap().relations.is_empty());
142 }
143
144 #[test]
145 fn keys_without_data_type_still_create_info() {
146 let pragmas = alloc::vec![DlrlPragma::DataKey {
147 type_name: "Bar".into(),
148 field: "k".into(),
149 }];
150 let infos = collect_type_infos(&pragmas);
151 assert!(infos.contains_key("Bar"));
152 assert_eq!(infos["Bar"].keys, alloc::vec!["k".to_string()]);
153 }
154}