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)]
49pub struct DlrlTypeInfo {
50 pub name: String,
52 pub keys: Vec<String>,
54 pub relations: Vec<(String, String)>,
56}
57
58#[must_use]
61pub fn collect_type_infos(
62 pragmas: &[DlrlPragma],
63) -> alloc::collections::BTreeMap<String, DlrlTypeInfo> {
64 use alloc::collections::BTreeMap;
65 let mut out: BTreeMap<String, DlrlTypeInfo> = BTreeMap::new();
66 for p in pragmas {
67 match p {
68 DlrlPragma::DataType { name } => {
69 out.entry(name.clone()).or_insert_with(|| DlrlTypeInfo {
70 name: name.clone(),
71 ..DlrlTypeInfo::default()
72 });
73 }
74 DlrlPragma::DataKey { type_name, field } => {
75 out.entry(type_name.clone())
76 .or_insert_with(|| DlrlTypeInfo {
77 name: type_name.clone(),
78 ..DlrlTypeInfo::default()
79 })
80 .keys
81 .push(field.clone());
82 }
83 DlrlPragma::DlrlRelation {
84 type_name,
85 relation,
86 target,
87 } => {
88 out.entry(type_name.clone())
89 .or_insert_with(|| DlrlTypeInfo {
90 name: type_name.clone(),
91 ..DlrlTypeInfo::default()
92 })
93 .relations
94 .push((relation.clone(), target.clone()));
95 }
96 }
97 }
98 out
99}
100
101#[cfg(test)]
102#[allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
103mod tests {
104 use super::*;
105
106 #[test]
107 fn collect_groups_by_type_name() {
108 let pragmas = alloc::vec![
109 DlrlPragma::DataType {
110 name: "demo::Trade".into()
111 },
112 DlrlPragma::DataKey {
113 type_name: "demo::Trade".into(),
114 field: "symbol".into(),
115 },
116 DlrlPragma::DataKey {
117 type_name: "demo::Trade".into(),
118 field: "venue".into(),
119 },
120 DlrlPragma::DlrlRelation {
121 type_name: "demo::Trade".into(),
122 relation: "quotes".into(),
123 target: "demo::Quote".into(),
124 },
125 ];
126 let infos = collect_type_infos(&pragmas);
127 assert_eq!(infos.len(), 1);
128 let trade = infos.get("demo::Trade").unwrap();
129 assert_eq!(
130 trade.keys,
131 alloc::vec!["symbol".to_string(), "venue".into()]
132 );
133 assert_eq!(trade.relations.len(), 1);
134 assert_eq!(trade.relations[0].0, "quotes");
135 }
136
137 #[test]
138 fn data_type_without_keys_yields_empty_lists() {
139 let pragmas = alloc::vec![DlrlPragma::DataType { name: "Foo".into() }];
140 let infos = collect_type_infos(&pragmas);
141 assert!(infos.get("Foo").unwrap().keys.is_empty());
142 assert!(infos.get("Foo").unwrap().relations.is_empty());
143 }
144
145 #[test]
146 fn keys_without_data_type_still_create_info() {
147 let pragmas = alloc::vec![DlrlPragma::DataKey {
148 type_name: "Bar".into(),
149 field: "k".into(),
150 }];
151 let infos = collect_type_infos(&pragmas);
152 assert!(infos.contains_key("Bar"));
153 assert_eq!(infos["Bar"].keys, alloc::vec!["k".to_string()]);
154 }
155}