Skip to main content

weaveffi_core/
config.rs

1//! Per-target generator configuration.
2
3use serde::{Deserialize, Serialize};
4
5/// Configuration knobs that generators consult at code-generation time.
6///
7/// Every field falls back to a sensible default when `None`.
8#[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}
30
31impl GeneratorConfig {
32    pub fn swift_module_name(&self) -> &str {
33        self.swift_module_name.as_deref().unwrap_or("WeaveFFI")
34    }
35
36    pub fn android_package(&self) -> &str {
37        self.android_package.as_deref().unwrap_or("com.weaveffi")
38    }
39
40    pub fn node_package_name(&self) -> &str {
41        self.node_package_name.as_deref().unwrap_or("weaveffi")
42    }
43
44    pub fn wasm_module_name(&self) -> &str {
45        self.wasm_module_name.as_deref().unwrap_or("weaveffi_wasm")
46    }
47
48    pub fn c_prefix(&self) -> &str {
49        self.c_prefix.as_deref().unwrap_or("weaveffi")
50    }
51
52    pub fn python_package_name(&self) -> &str {
53        self.python_package_name.as_deref().unwrap_or("weaveffi")
54    }
55
56    pub fn dotnet_namespace(&self) -> &str {
57        self.dotnet_namespace.as_deref().unwrap_or("WeaveFFI")
58    }
59
60    pub fn cpp_namespace(&self) -> &str {
61        self.cpp_namespace.as_deref().unwrap_or("weaveffi")
62    }
63
64    pub fn cpp_header_name(&self) -> &str {
65        self.cpp_header_name.as_deref().unwrap_or("weaveffi.hpp")
66    }
67
68    pub fn cpp_standard(&self) -> &str {
69        self.cpp_standard.as_deref().unwrap_or("17")
70    }
71
72    pub fn dart_package_name(&self) -> &str {
73        self.dart_package_name.as_deref().unwrap_or("weaveffi")
74    }
75
76    pub fn go_module_path(&self) -> &str {
77        self.go_module_path.as_deref().unwrap_or("weaveffi")
78    }
79
80    pub fn ruby_module_name(&self) -> &str {
81        self.ruby_module_name.as_deref().unwrap_or("WeaveFFI")
82    }
83
84    pub fn ruby_gem_name(&self) -> &str {
85        self.ruby_gem_name.as_deref().unwrap_or("weaveffi")
86    }
87}
88
89#[cfg(test)]
90mod tests {
91    use super::*;
92
93    #[test]
94    fn defaults_are_applied() {
95        let cfg = GeneratorConfig::default();
96
97        assert_eq!(cfg.swift_module_name(), "WeaveFFI");
98        assert_eq!(cfg.android_package(), "com.weaveffi");
99        assert_eq!(cfg.node_package_name(), "weaveffi");
100        assert_eq!(cfg.wasm_module_name(), "weaveffi_wasm");
101        assert_eq!(cfg.c_prefix(), "weaveffi");
102        assert_eq!(cfg.python_package_name(), "weaveffi");
103        assert_eq!(cfg.dotnet_namespace(), "WeaveFFI");
104        assert_eq!(cfg.cpp_namespace(), "weaveffi");
105        assert_eq!(cfg.cpp_header_name(), "weaveffi.hpp");
106        assert_eq!(cfg.cpp_standard(), "17");
107        assert_eq!(cfg.dart_package_name(), "weaveffi");
108        assert_eq!(cfg.go_module_path(), "weaveffi");
109        assert_eq!(cfg.ruby_module_name(), "WeaveFFI");
110        assert_eq!(cfg.ruby_gem_name(), "weaveffi");
111        assert!(!cfg.strip_module_prefix);
112    }
113
114    #[test]
115    fn custom_values_override_defaults() {
116        let cfg = GeneratorConfig {
117            swift_module_name: Some("MySwift".into()),
118            android_package: Some("org.example".into()),
119            node_package_name: Some("my-node-pkg".into()),
120            wasm_module_name: Some("my_wasm".into()),
121            c_prefix: Some("myffi".into()),
122            python_package_name: Some("my_python_pkg".into()),
123            dotnet_namespace: Some("MyCompany.Bindings".into()),
124            cpp_namespace: Some("mylib".into()),
125            cpp_header_name: Some("mylib.hpp".into()),
126            cpp_standard: Some("20".into()),
127            dart_package_name: Some("my_dart_pkg".into()),
128            go_module_path: Some("github.com/myorg/mylib".into()),
129            ruby_module_name: Some("MyRubyMod".into()),
130            ruby_gem_name: Some("my_ruby_gem".into()),
131            strip_module_prefix: true,
132            template_dir: None,
133            pre_generate: None,
134            post_generate: None,
135        };
136
137        assert_eq!(cfg.swift_module_name(), "MySwift");
138        assert_eq!(cfg.android_package(), "org.example");
139        assert_eq!(cfg.node_package_name(), "my-node-pkg");
140        assert_eq!(cfg.wasm_module_name(), "my_wasm");
141        assert_eq!(cfg.c_prefix(), "myffi");
142        assert_eq!(cfg.python_package_name(), "my_python_pkg");
143        assert_eq!(cfg.dotnet_namespace(), "MyCompany.Bindings");
144        assert_eq!(cfg.cpp_namespace(), "mylib");
145        assert_eq!(cfg.cpp_header_name(), "mylib.hpp");
146        assert_eq!(cfg.cpp_standard(), "20");
147        assert_eq!(cfg.dart_package_name(), "my_dart_pkg");
148        assert_eq!(cfg.go_module_path(), "github.com/myorg/mylib");
149        assert_eq!(cfg.ruby_module_name(), "MyRubyMod");
150        assert_eq!(cfg.ruby_gem_name(), "my_ruby_gem");
151        assert!(cfg.strip_module_prefix);
152    }
153
154    #[test]
155    fn roundtrip_json() {
156        let cfg = GeneratorConfig {
157            swift_module_name: Some("S".into()),
158            android_package: None,
159            node_package_name: None,
160            wasm_module_name: None,
161            c_prefix: None,
162            python_package_name: Some("mypkg".into()),
163            dotnet_namespace: None,
164            cpp_namespace: Some("myns".into()),
165            cpp_header_name: None,
166            cpp_standard: None,
167            dart_package_name: None,
168            go_module_path: None,
169            ruby_module_name: None,
170            ruby_gem_name: None,
171            strip_module_prefix: true,
172            template_dir: None,
173            pre_generate: None,
174            post_generate: None,
175        };
176
177        let json = serde_json::to_string(&cfg).unwrap();
178        let back: GeneratorConfig = serde_json::from_str(&json).unwrap();
179
180        assert_eq!(back.swift_module_name(), "S");
181        assert_eq!(back.android_package(), "com.weaveffi");
182        assert_eq!(back.python_package_name(), "mypkg");
183        assert_eq!(back.dotnet_namespace(), "WeaveFFI");
184        assert_eq!(back.cpp_namespace(), "myns");
185        assert_eq!(back.cpp_header_name(), "weaveffi.hpp");
186        assert_eq!(back.cpp_standard(), "17");
187        assert_eq!(back.dart_package_name(), "weaveffi");
188        assert_eq!(back.go_module_path(), "weaveffi");
189        assert_eq!(back.ruby_module_name(), "WeaveFFI");
190        assert_eq!(back.ruby_gem_name(), "weaveffi");
191        assert!(back.strip_module_prefix);
192    }
193
194    #[test]
195    fn deserialize_empty_object_gives_defaults() {
196        let cfg: GeneratorConfig = serde_json::from_str("{}").unwrap();
197
198        assert_eq!(cfg.swift_module_name(), "WeaveFFI");
199        assert!(!cfg.strip_module_prefix);
200    }
201}