1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9pub struct GeneratorConfig {
10 pub swift_module_name: Option<String>,
11 pub android_package: Option<String>,
12 pub node_package_name: Option<String>,
13 pub wasm_module_name: Option<String>,
14 pub c_prefix: Option<String>,
15 pub python_package_name: Option<String>,
16 pub dotnet_namespace: Option<String>,
17 pub cpp_namespace: Option<String>,
18 pub cpp_header_name: Option<String>,
19 pub cpp_standard: Option<String>,
20 pub dart_package_name: Option<String>,
21 pub go_module_path: Option<String>,
22 pub ruby_module_name: Option<String>,
23 pub ruby_gem_name: Option<String>,
24 #[serde(default)]
25 pub strip_module_prefix: bool,
26 pub template_dir: Option<String>,
27 pub pre_generate: Option<String>,
28 pub post_generate: Option<String>,
29 #[serde(skip)]
33 pub input_basename: Option<String>,
34}
35
36impl GeneratorConfig {
37 pub fn swift_module_name(&self) -> &str {
38 self.swift_module_name.as_deref().unwrap_or("WeaveFFI")
39 }
40
41 pub fn android_package(&self) -> &str {
42 self.android_package.as_deref().unwrap_or("com.weaveffi")
43 }
44
45 pub fn node_package_name(&self) -> &str {
46 self.node_package_name.as_deref().unwrap_or("weaveffi")
47 }
48
49 pub fn wasm_module_name(&self) -> &str {
50 self.wasm_module_name.as_deref().unwrap_or("weaveffi_wasm")
51 }
52
53 pub fn c_prefix(&self) -> &str {
54 self.c_prefix.as_deref().unwrap_or("weaveffi")
55 }
56
57 pub fn python_package_name(&self) -> &str {
58 self.python_package_name.as_deref().unwrap_or("weaveffi")
59 }
60
61 pub fn dotnet_namespace(&self) -> &str {
62 self.dotnet_namespace.as_deref().unwrap_or("WeaveFFI")
63 }
64
65 pub fn cpp_namespace(&self) -> &str {
66 self.cpp_namespace.as_deref().unwrap_or("weaveffi")
67 }
68
69 pub fn cpp_header_name(&self) -> &str {
70 self.cpp_header_name.as_deref().unwrap_or("weaveffi.hpp")
71 }
72
73 pub fn cpp_standard(&self) -> &str {
74 self.cpp_standard.as_deref().unwrap_or("17")
75 }
76
77 pub fn dart_package_name(&self) -> &str {
78 self.dart_package_name.as_deref().unwrap_or("weaveffi")
79 }
80
81 pub fn go_module_path(&self) -> &str {
82 self.go_module_path.as_deref().unwrap_or("weaveffi")
83 }
84
85 pub fn ruby_module_name(&self) -> &str {
86 self.ruby_module_name.as_deref().unwrap_or("WeaveFFI")
87 }
88
89 pub fn ruby_gem_name(&self) -> &str {
90 self.ruby_gem_name.as_deref().unwrap_or("weaveffi")
91 }
92
93 pub fn input_basename(&self) -> &str {
94 self.input_basename.as_deref().unwrap_or("weaveffi.yml")
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 #[test]
103 fn defaults_are_applied() {
104 let cfg = GeneratorConfig::default();
105
106 assert_eq!(cfg.swift_module_name(), "WeaveFFI");
107 assert_eq!(cfg.android_package(), "com.weaveffi");
108 assert_eq!(cfg.node_package_name(), "weaveffi");
109 assert_eq!(cfg.wasm_module_name(), "weaveffi_wasm");
110 assert_eq!(cfg.c_prefix(), "weaveffi");
111 assert_eq!(cfg.python_package_name(), "weaveffi");
112 assert_eq!(cfg.dotnet_namespace(), "WeaveFFI");
113 assert_eq!(cfg.cpp_namespace(), "weaveffi");
114 assert_eq!(cfg.cpp_header_name(), "weaveffi.hpp");
115 assert_eq!(cfg.cpp_standard(), "17");
116 assert_eq!(cfg.dart_package_name(), "weaveffi");
117 assert_eq!(cfg.go_module_path(), "weaveffi");
118 assert_eq!(cfg.ruby_module_name(), "WeaveFFI");
119 assert_eq!(cfg.ruby_gem_name(), "weaveffi");
120 assert!(!cfg.strip_module_prefix);
121 }
122
123 #[test]
124 fn custom_values_override_defaults() {
125 let cfg = GeneratorConfig {
126 swift_module_name: Some("MySwift".into()),
127 android_package: Some("org.example".into()),
128 node_package_name: Some("my-node-pkg".into()),
129 wasm_module_name: Some("my_wasm".into()),
130 c_prefix: Some("myffi".into()),
131 python_package_name: Some("my_python_pkg".into()),
132 dotnet_namespace: Some("MyCompany.Bindings".into()),
133 cpp_namespace: Some("mylib".into()),
134 cpp_header_name: Some("mylib.hpp".into()),
135 cpp_standard: Some("20".into()),
136 dart_package_name: Some("my_dart_pkg".into()),
137 go_module_path: Some("github.com/myorg/mylib".into()),
138 ruby_module_name: Some("MyRubyMod".into()),
139 ruby_gem_name: Some("my_ruby_gem".into()),
140 strip_module_prefix: true,
141 template_dir: None,
142 pre_generate: None,
143 post_generate: None,
144 input_basename: None,
145 };
146
147 assert_eq!(cfg.swift_module_name(), "MySwift");
148 assert_eq!(cfg.android_package(), "org.example");
149 assert_eq!(cfg.node_package_name(), "my-node-pkg");
150 assert_eq!(cfg.wasm_module_name(), "my_wasm");
151 assert_eq!(cfg.c_prefix(), "myffi");
152 assert_eq!(cfg.python_package_name(), "my_python_pkg");
153 assert_eq!(cfg.dotnet_namespace(), "MyCompany.Bindings");
154 assert_eq!(cfg.cpp_namespace(), "mylib");
155 assert_eq!(cfg.cpp_header_name(), "mylib.hpp");
156 assert_eq!(cfg.cpp_standard(), "20");
157 assert_eq!(cfg.dart_package_name(), "my_dart_pkg");
158 assert_eq!(cfg.go_module_path(), "github.com/myorg/mylib");
159 assert_eq!(cfg.ruby_module_name(), "MyRubyMod");
160 assert_eq!(cfg.ruby_gem_name(), "my_ruby_gem");
161 assert!(cfg.strip_module_prefix);
162 }
163
164 #[test]
165 fn roundtrip_json() {
166 let cfg = GeneratorConfig {
167 swift_module_name: Some("S".into()),
168 android_package: None,
169 node_package_name: None,
170 wasm_module_name: None,
171 c_prefix: None,
172 python_package_name: Some("mypkg".into()),
173 dotnet_namespace: None,
174 cpp_namespace: Some("myns".into()),
175 cpp_header_name: None,
176 cpp_standard: None,
177 dart_package_name: None,
178 go_module_path: None,
179 ruby_module_name: None,
180 ruby_gem_name: None,
181 strip_module_prefix: true,
182 template_dir: None,
183 pre_generate: None,
184 post_generate: None,
185 input_basename: Some("ignored.yml".into()),
186 };
187
188 let json = serde_json::to_string(&cfg).unwrap();
189 let back: GeneratorConfig = serde_json::from_str(&json).unwrap();
190
191 assert_eq!(back.swift_module_name(), "S");
192 assert_eq!(back.android_package(), "com.weaveffi");
193 assert_eq!(back.python_package_name(), "mypkg");
194 assert_eq!(back.dotnet_namespace(), "WeaveFFI");
195 assert_eq!(back.cpp_namespace(), "myns");
196 assert_eq!(back.cpp_header_name(), "weaveffi.hpp");
197 assert_eq!(back.cpp_standard(), "17");
198 assert_eq!(back.dart_package_name(), "weaveffi");
199 assert_eq!(back.go_module_path(), "weaveffi");
200 assert_eq!(back.ruby_module_name(), "WeaveFFI");
201 assert_eq!(back.ruby_gem_name(), "weaveffi");
202 assert!(back.strip_module_prefix);
203 }
204
205 #[test]
206 fn deserialize_empty_object_gives_defaults() {
207 let cfg: GeneratorConfig = serde_json::from_str("{}").unwrap();
208
209 assert_eq!(cfg.swift_module_name(), "WeaveFFI");
210 assert!(!cfg.strip_module_prefix);
211 assert_eq!(cfg.input_basename(), "weaveffi.yml");
212 }
213
214 #[test]
215 fn input_basename_is_skipped_during_serde() {
216 let cfg = GeneratorConfig {
217 input_basename: Some("calc.yml".into()),
218 ..GeneratorConfig::default()
219 };
220 let json = serde_json::to_string(&cfg).unwrap();
221 assert!(!json.contains("input_basename"));
222 assert!(!json.contains("calc.yml"));
223 let back: GeneratorConfig = serde_json::from_str(&json).unwrap();
224 assert_eq!(back.input_basename(), "weaveffi.yml");
225 }
226}