Skip to main content

alef_core/config/
languages.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3use std::path::PathBuf;
4
5use super::extras::Language;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct PythonConfig {
9    pub module_name: Option<String>,
10    pub async_runtime: Option<String>,
11    pub stubs: Option<StubsConfig>,
12    /// PyPI package name (e.g. `"html-to-markdown"`). Used as the `[project] name` in
13    /// `pyproject.toml` and to derive the `python-packages` list for maturin.
14    /// Defaults to the crate name.
15    #[serde(default)]
16    pub pip_name: Option<String>,
17    /// Per-language feature override. When set, these features are used instead of
18    /// `[crate] features` for this language's binding crate.
19    #[serde(default)]
20    pub features: Option<Vec<String>>,
21    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
22    /// When set, this takes priority over the IR type-level serde_rename_all.
23    #[serde(default)]
24    pub serde_rename_all: Option<String>,
25    /// Map of type name -> PyCapsule name for raw pointer wrapping.
26    /// When a function returns one of these types, alef generates PyCapsule_New instead of Arc wrapping.
27    // TODO: Wire into gen_bindings.rs to emit PyCapsule_New / PyCapsule_GetPointer at call sites.
28    #[serde(default)]
29    pub capsule_types: HashMap<String, String>,
30    /// When true, wrap blocking function bodies in py.allow_threads() to release the GIL.
31    // TODO: Wire into gen_bindings.rs to emit py.allow_threads(|| { ... }) for non-async functions.
32    #[serde(default)]
33    pub release_gil: bool,
34    /// Functions to exclude from Python binding generation.
35    #[serde(default)]
36    pub exclude_functions: Vec<String>,
37    /// Types to exclude from Python binding generation.
38    #[serde(default)]
39    pub exclude_types: Vec<String>,
40    /// Additional Cargo dependencies for this language's binding crate only.
41    #[serde(default)]
42    pub extra_dependencies: HashMap<String, toml::Value>,
43    /// Override the scaffold output directory for this language's Cargo.toml and package files.
44    #[serde(default)]
45    pub scaffold_output: Option<PathBuf>,
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct StubsConfig {
50    pub output: PathBuf,
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct NodeConfig {
55    pub package_name: Option<String>,
56    /// Per-language feature override. When set, these features are used instead of
57    /// `[crate] features` for this language's binding crate.
58    #[serde(default)]
59    pub features: Option<Vec<String>>,
60    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
61    /// When set, this takes priority over the IR type-level serde_rename_all.
62    #[serde(default)]
63    pub serde_rename_all: Option<String>,
64    /// Prefix for generated type names (e.g. "Js" produces `JsConversionOptions`).
65    /// Defaults to `"Js"`.
66    #[serde(default)]
67    pub type_prefix: Option<String>,
68    /// Functions to exclude from Node binding generation.
69    #[serde(default)]
70    pub exclude_functions: Vec<String>,
71    /// Types to exclude from Node binding generation.
72    #[serde(default)]
73    pub exclude_types: Vec<String>,
74    /// Additional Cargo dependencies for this language's binding crate only.
75    #[serde(default)]
76    pub extra_dependencies: HashMap<String, toml::Value>,
77    /// Override the scaffold output directory for this language's Cargo.toml and package files.
78    #[serde(default)]
79    pub scaffold_output: Option<PathBuf>,
80}
81
82#[derive(Debug, Clone, Serialize, Deserialize)]
83pub struct RubyConfig {
84    pub gem_name: Option<String>,
85    pub stubs: Option<StubsConfig>,
86    /// Per-language feature override. When set, these features are used instead of
87    /// `[crate] features` for this language's binding crate.
88    #[serde(default)]
89    pub features: Option<Vec<String>>,
90    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
91    /// When set, this takes priority over the IR type-level serde_rename_all.
92    #[serde(default)]
93    pub serde_rename_all: Option<String>,
94    /// Functions to exclude from Ruby binding generation.
95    #[serde(default)]
96    pub exclude_functions: Vec<String>,
97    /// Types to exclude from Ruby binding generation.
98    #[serde(default)]
99    pub exclude_types: Vec<String>,
100    /// Additional Cargo dependencies for this language's binding crate only.
101    #[serde(default)]
102    pub extra_dependencies: HashMap<String, toml::Value>,
103    /// Override the scaffold output directory for this language's Cargo.toml and package files.
104    #[serde(default)]
105    pub scaffold_output: Option<PathBuf>,
106}
107
108#[derive(Debug, Clone, Serialize, Deserialize)]
109pub struct PhpConfig {
110    pub extension_name: Option<String>,
111    /// Feature gate for ext-php-rs (default: "extension-module").
112    /// All generated code is wrapped in `#[cfg(feature = "...")]`.
113    #[serde(default)]
114    pub feature_gate: Option<String>,
115    /// Output directory for generated PHP facade / stubs (e.g., `packages/php/src/`).
116    #[serde(default)]
117    pub stubs: Option<StubsConfig>,
118    #[serde(default)]
119    pub features: Option<Vec<String>>,
120    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
121    /// When set, this takes priority over the IR type-level serde_rename_all.
122    #[serde(default)]
123    pub serde_rename_all: Option<String>,
124    /// Functions to exclude from PHP binding generation.
125    #[serde(default)]
126    pub exclude_functions: Vec<String>,
127    /// Types to exclude from PHP binding generation.
128    #[serde(default)]
129    pub exclude_types: Vec<String>,
130    /// Additional Cargo dependencies for this language's binding crate only.
131    #[serde(default)]
132    pub extra_dependencies: HashMap<String, toml::Value>,
133    /// Override the scaffold output directory for this language's Cargo.toml and package files.
134    #[serde(default)]
135    pub scaffold_output: Option<PathBuf>,
136}
137
138#[derive(Debug, Clone, Serialize, Deserialize)]
139pub struct ElixirConfig {
140    pub app_name: Option<String>,
141    #[serde(default)]
142    pub features: Option<Vec<String>>,
143    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
144    /// When set, this takes priority over the IR type-level serde_rename_all.
145    #[serde(default)]
146    pub serde_rename_all: Option<String>,
147    /// Functions to exclude from Elixir NIF generation.
148    #[serde(default)]
149    pub exclude_functions: Vec<String>,
150    /// Types to exclude from Elixir NIF generation.
151    #[serde(default)]
152    pub exclude_types: Vec<String>,
153    /// Additional Cargo dependencies for this language's binding crate only.
154    #[serde(default)]
155    pub extra_dependencies: HashMap<String, toml::Value>,
156    /// Override the scaffold output directory for this language's Cargo.toml and package files.
157    #[serde(default)]
158    pub scaffold_output: Option<PathBuf>,
159}
160
161#[derive(Debug, Clone, Serialize, Deserialize)]
162pub struct WasmConfig {
163    #[serde(default)]
164    pub exclude_functions: Vec<String>,
165    #[serde(default)]
166    pub exclude_types: Vec<String>,
167    #[serde(default)]
168    pub type_overrides: HashMap<String, String>,
169    #[serde(default)]
170    pub features: Option<Vec<String>>,
171    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
172    /// When set, this takes priority over the IR type-level serde_rename_all.
173    #[serde(default)]
174    pub serde_rename_all: Option<String>,
175    /// Prefix for generated type names (e.g. "Wasm" produces `WasmConversionOptions`).
176    /// Defaults to `"Wasm"`.
177    #[serde(default)]
178    pub type_prefix: Option<String>,
179    /// Functions to exclude from the public TypeScript re-export (index.ts) while still
180    /// generating the Rust binding. Use this when a custom module provides a wrapper.
181    #[serde(default)]
182    pub exclude_reexports: Vec<String>,
183    /// Wide-character C functions to shim for WASM external scanner interop.
184    #[serde(default)]
185    pub env_shims: Vec<String>,
186    /// Additional Cargo dependencies for the WASM binding crate only.
187    #[serde(default)]
188    pub extra_dependencies: HashMap<String, toml::Value>,
189}
190
191#[derive(Debug, Clone, Serialize, Deserialize)]
192pub struct FfiConfig {
193    pub prefix: Option<String>,
194    #[serde(default = "default_error_style")]
195    pub error_style: String,
196    pub header_name: Option<String>,
197    /// Native library name for Go cgo/Java Panama/C# P/Invoke (e.g., "ts_pack_ffi").
198    /// Defaults to `{prefix}_ffi`.
199    #[serde(default)]
200    pub lib_name: Option<String>,
201    /// If true, generate visitor/callback FFI support.
202    #[serde(default)]
203    pub visitor_callbacks: bool,
204    #[serde(default)]
205    pub features: Option<Vec<String>>,
206    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
207    /// When set, this takes priority over the IR type-level serde_rename_all.
208    #[serde(default)]
209    pub serde_rename_all: Option<String>,
210    /// Functions to exclude from FFI binding generation.
211    #[serde(default)]
212    pub exclude_functions: Vec<String>,
213    /// Types to exclude from FFI binding generation.
214    #[serde(default)]
215    pub exclude_types: Vec<String>,
216}
217
218fn default_error_style() -> String {
219    "last_error".to_string()
220}
221
222#[derive(Debug, Clone, Serialize, Deserialize)]
223pub struct GoConfig {
224    pub module: Option<String>,
225    /// Override the Go package name (default: derived from module path)
226    pub package_name: Option<String>,
227    #[serde(default)]
228    pub features: Option<Vec<String>>,
229    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
230    /// When set, this takes priority over the IR type-level serde_rename_all.
231    #[serde(default)]
232    pub serde_rename_all: Option<String>,
233}
234
235#[derive(Debug, Clone, Serialize, Deserialize)]
236pub struct JavaConfig {
237    pub package: Option<String>,
238    #[serde(default = "default_java_ffi_style")]
239    pub ffi_style: String,
240    #[serde(default)]
241    pub features: Option<Vec<String>>,
242    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
243    /// When set, this takes priority over the IR type-level serde_rename_all.
244    #[serde(default)]
245    pub serde_rename_all: Option<String>,
246}
247
248fn default_java_ffi_style() -> String {
249    "panama".to_string()
250}
251
252#[derive(Debug, Clone, Serialize, Deserialize)]
253pub struct CSharpConfig {
254    pub namespace: Option<String>,
255    pub target_framework: Option<String>,
256    #[serde(default)]
257    pub features: Option<Vec<String>>,
258    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
259    /// When set, this takes priority over the IR type-level serde_rename_all.
260    #[serde(default)]
261    pub serde_rename_all: Option<String>,
262}
263
264#[derive(Debug, Clone, Serialize, Deserialize)]
265pub struct RConfig {
266    pub package_name: Option<String>,
267    #[serde(default)]
268    pub features: Option<Vec<String>>,
269    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
270    /// When set, this takes priority over the IR type-level serde_rename_all.
271    #[serde(default)]
272    pub serde_rename_all: Option<String>,
273}
274
275/// Custom modules that alef should declare (mod X;) but not generate.
276/// These are hand-written modules imported by the generated lib.rs.
277#[derive(Debug, Clone, Default, Serialize, Deserialize)]
278pub struct CustomModulesConfig {
279    #[serde(default)]
280    pub python: Vec<String>,
281    #[serde(default)]
282    pub node: Vec<String>,
283    #[serde(default)]
284    pub ruby: Vec<String>,
285    #[serde(default)]
286    pub php: Vec<String>,
287    #[serde(default)]
288    pub elixir: Vec<String>,
289    #[serde(default)]
290    pub wasm: Vec<String>,
291    #[serde(default)]
292    pub ffi: Vec<String>,
293    #[serde(default)]
294    pub go: Vec<String>,
295    #[serde(default)]
296    pub java: Vec<String>,
297    #[serde(default)]
298    pub csharp: Vec<String>,
299    #[serde(default)]
300    pub r: Vec<String>,
301}
302
303impl CustomModulesConfig {
304    pub fn for_language(&self, lang: Language) -> &[String] {
305        match lang {
306            Language::Python => &self.python,
307            Language::Node => &self.node,
308            Language::Ruby => &self.ruby,
309            Language::Php => &self.php,
310            Language::Elixir => &self.elixir,
311            Language::Wasm => &self.wasm,
312            Language::Ffi => &self.ffi,
313            Language::Go => &self.go,
314            Language::Java => &self.java,
315            Language::Csharp => &self.csharp,
316            Language::R => &self.r,
317            Language::Rust => &[], // Rust doesn't need custom modules (no binding crate)
318        }
319    }
320}
321
322/// Custom classes/functions from hand-written modules to register in module init.
323#[derive(Debug, Clone, Default, Serialize, Deserialize)]
324pub struct CustomRegistration {
325    #[serde(default)]
326    pub classes: Vec<String>,
327    #[serde(default)]
328    pub functions: Vec<String>,
329    #[serde(default)]
330    pub init_calls: Vec<String>,
331}
332
333/// Per-language custom registrations.
334#[derive(Debug, Clone, Default, Serialize, Deserialize)]
335pub struct CustomRegistrationsConfig {
336    #[serde(default)]
337    pub python: Option<CustomRegistration>,
338    #[serde(default)]
339    pub node: Option<CustomRegistration>,
340    #[serde(default)]
341    pub ruby: Option<CustomRegistration>,
342    #[serde(default)]
343    pub php: Option<CustomRegistration>,
344    #[serde(default)]
345    pub elixir: Option<CustomRegistration>,
346    #[serde(default)]
347    pub wasm: Option<CustomRegistration>,
348}
349
350impl CustomRegistrationsConfig {
351    pub fn for_language(&self, lang: Language) -> Option<&CustomRegistration> {
352        match lang {
353            Language::Python => self.python.as_ref(),
354            Language::Node => self.node.as_ref(),
355            Language::Ruby => self.ruby.as_ref(),
356            Language::Php => self.php.as_ref(),
357            Language::Elixir => self.elixir.as_ref(),
358            Language::Wasm => self.wasm.as_ref(),
359            _ => None,
360        }
361    }
362}