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    /// Additional Cargo dependencies for this language's binding crate only.
95    #[serde(default)]
96    pub extra_dependencies: HashMap<String, toml::Value>,
97    /// Override the scaffold output directory for this language's Cargo.toml and package files.
98    #[serde(default)]
99    pub scaffold_output: Option<PathBuf>,
100}
101
102#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct PhpConfig {
104    pub extension_name: Option<String>,
105    /// Feature gate for ext-php-rs (default: "extension-module").
106    /// All generated code is wrapped in `#[cfg(feature = "...")]`.
107    #[serde(default)]
108    pub feature_gate: Option<String>,
109    /// Output directory for generated PHP facade / stubs (e.g., `packages/php/src/`).
110    #[serde(default)]
111    pub stubs: Option<StubsConfig>,
112    #[serde(default)]
113    pub features: Option<Vec<String>>,
114    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
115    /// When set, this takes priority over the IR type-level serde_rename_all.
116    #[serde(default)]
117    pub serde_rename_all: Option<String>,
118    /// Functions to exclude from PHP binding generation.
119    #[serde(default)]
120    pub exclude_functions: Vec<String>,
121    /// Types to exclude from PHP binding generation.
122    #[serde(default)]
123    pub exclude_types: Vec<String>,
124    /// Additional Cargo dependencies for this language's binding crate only.
125    #[serde(default)]
126    pub extra_dependencies: HashMap<String, toml::Value>,
127    /// Override the scaffold output directory for this language's Cargo.toml and package files.
128    #[serde(default)]
129    pub scaffold_output: Option<PathBuf>,
130}
131
132#[derive(Debug, Clone, Serialize, Deserialize)]
133pub struct ElixirConfig {
134    pub app_name: Option<String>,
135    #[serde(default)]
136    pub features: Option<Vec<String>>,
137    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
138    /// When set, this takes priority over the IR type-level serde_rename_all.
139    #[serde(default)]
140    pub serde_rename_all: Option<String>,
141    /// Functions to exclude from Elixir NIF generation.
142    #[serde(default)]
143    pub exclude_functions: Vec<String>,
144    /// Types to exclude from Elixir NIF generation.
145    #[serde(default)]
146    pub exclude_types: Vec<String>,
147    /// Additional Cargo dependencies for this language's binding crate only.
148    #[serde(default)]
149    pub extra_dependencies: HashMap<String, toml::Value>,
150    /// Override the scaffold output directory for this language's Cargo.toml and package files.
151    #[serde(default)]
152    pub scaffold_output: Option<PathBuf>,
153}
154
155#[derive(Debug, Clone, Serialize, Deserialize)]
156pub struct WasmConfig {
157    #[serde(default)]
158    pub exclude_functions: Vec<String>,
159    #[serde(default)]
160    pub exclude_types: Vec<String>,
161    #[serde(default)]
162    pub type_overrides: HashMap<String, String>,
163    #[serde(default)]
164    pub features: Option<Vec<String>>,
165    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
166    /// When set, this takes priority over the IR type-level serde_rename_all.
167    #[serde(default)]
168    pub serde_rename_all: Option<String>,
169    /// Prefix for generated type names (e.g. "Wasm" produces `WasmConversionOptions`).
170    /// Defaults to `"Wasm"`.
171    #[serde(default)]
172    pub type_prefix: Option<String>,
173    /// Functions to exclude from the public TypeScript re-export (index.ts) while still
174    /// generating the Rust binding. Use this when a custom module provides a wrapper.
175    #[serde(default)]
176    pub exclude_reexports: Vec<String>,
177    /// Wide-character C functions to shim for WASM external scanner interop.
178    #[serde(default)]
179    pub env_shims: Vec<String>,
180    /// Additional Cargo dependencies for the WASM binding crate only.
181    #[serde(default)]
182    pub extra_dependencies: HashMap<String, toml::Value>,
183}
184
185#[derive(Debug, Clone, Serialize, Deserialize)]
186pub struct FfiConfig {
187    pub prefix: Option<String>,
188    #[serde(default = "default_error_style")]
189    pub error_style: String,
190    pub header_name: Option<String>,
191    /// Native library name for Go cgo/Java Panama/C# P/Invoke (e.g., "ts_pack_ffi").
192    /// Defaults to `{prefix}_ffi`.
193    #[serde(default)]
194    pub lib_name: Option<String>,
195    /// If true, generate visitor/callback FFI support.
196    #[serde(default)]
197    pub visitor_callbacks: bool,
198    #[serde(default)]
199    pub features: Option<Vec<String>>,
200    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
201    /// When set, this takes priority over the IR type-level serde_rename_all.
202    #[serde(default)]
203    pub serde_rename_all: Option<String>,
204    /// Functions to exclude from FFI binding generation.
205    #[serde(default)]
206    pub exclude_functions: Vec<String>,
207    /// Types to exclude from FFI binding generation.
208    #[serde(default)]
209    pub exclude_types: Vec<String>,
210}
211
212fn default_error_style() -> String {
213    "last_error".to_string()
214}
215
216#[derive(Debug, Clone, Serialize, Deserialize)]
217pub struct GoConfig {
218    pub module: Option<String>,
219    /// Override the Go package name (default: derived from module path)
220    pub package_name: Option<String>,
221    #[serde(default)]
222    pub features: Option<Vec<String>>,
223    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
224    /// When set, this takes priority over the IR type-level serde_rename_all.
225    #[serde(default)]
226    pub serde_rename_all: Option<String>,
227}
228
229#[derive(Debug, Clone, Serialize, Deserialize)]
230pub struct JavaConfig {
231    pub package: Option<String>,
232    #[serde(default = "default_java_ffi_style")]
233    pub ffi_style: String,
234    #[serde(default)]
235    pub features: Option<Vec<String>>,
236    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
237    /// When set, this takes priority over the IR type-level serde_rename_all.
238    #[serde(default)]
239    pub serde_rename_all: Option<String>,
240}
241
242fn default_java_ffi_style() -> String {
243    "panama".to_string()
244}
245
246#[derive(Debug, Clone, Serialize, Deserialize)]
247pub struct CSharpConfig {
248    pub namespace: Option<String>,
249    pub target_framework: Option<String>,
250    #[serde(default)]
251    pub features: Option<Vec<String>>,
252    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
253    /// When set, this takes priority over the IR type-level serde_rename_all.
254    #[serde(default)]
255    pub serde_rename_all: Option<String>,
256}
257
258#[derive(Debug, Clone, Serialize, Deserialize)]
259pub struct RConfig {
260    pub package_name: Option<String>,
261    #[serde(default)]
262    pub features: Option<Vec<String>>,
263    /// Override the serde rename_all strategy for JSON field names (e.g. "camelCase", "snake_case").
264    /// When set, this takes priority over the IR type-level serde_rename_all.
265    #[serde(default)]
266    pub serde_rename_all: Option<String>,
267}
268
269/// Custom modules that alef should declare (mod X;) but not generate.
270/// These are hand-written modules imported by the generated lib.rs.
271#[derive(Debug, Clone, Default, Serialize, Deserialize)]
272pub struct CustomModulesConfig {
273    #[serde(default)]
274    pub python: Vec<String>,
275    #[serde(default)]
276    pub node: Vec<String>,
277    #[serde(default)]
278    pub ruby: Vec<String>,
279    #[serde(default)]
280    pub php: Vec<String>,
281    #[serde(default)]
282    pub elixir: Vec<String>,
283    #[serde(default)]
284    pub wasm: Vec<String>,
285    #[serde(default)]
286    pub ffi: Vec<String>,
287    #[serde(default)]
288    pub go: Vec<String>,
289    #[serde(default)]
290    pub java: Vec<String>,
291    #[serde(default)]
292    pub csharp: Vec<String>,
293    #[serde(default)]
294    pub r: Vec<String>,
295}
296
297impl CustomModulesConfig {
298    pub fn for_language(&self, lang: Language) -> &[String] {
299        match lang {
300            Language::Python => &self.python,
301            Language::Node => &self.node,
302            Language::Ruby => &self.ruby,
303            Language::Php => &self.php,
304            Language::Elixir => &self.elixir,
305            Language::Wasm => &self.wasm,
306            Language::Ffi => &self.ffi,
307            Language::Go => &self.go,
308            Language::Java => &self.java,
309            Language::Csharp => &self.csharp,
310            Language::R => &self.r,
311            Language::Rust => &[], // Rust doesn't need custom modules (no binding crate)
312        }
313    }
314}
315
316/// Custom classes/functions from hand-written modules to register in module init.
317#[derive(Debug, Clone, Default, Serialize, Deserialize)]
318pub struct CustomRegistration {
319    #[serde(default)]
320    pub classes: Vec<String>,
321    #[serde(default)]
322    pub functions: Vec<String>,
323    #[serde(default)]
324    pub init_calls: Vec<String>,
325}
326
327/// Per-language custom registrations.
328#[derive(Debug, Clone, Default, Serialize, Deserialize)]
329pub struct CustomRegistrationsConfig {
330    #[serde(default)]
331    pub python: Option<CustomRegistration>,
332    #[serde(default)]
333    pub node: Option<CustomRegistration>,
334    #[serde(default)]
335    pub ruby: Option<CustomRegistration>,
336    #[serde(default)]
337    pub php: Option<CustomRegistration>,
338    #[serde(default)]
339    pub elixir: Option<CustomRegistration>,
340    #[serde(default)]
341    pub wasm: Option<CustomRegistration>,
342}
343
344impl CustomRegistrationsConfig {
345    pub fn for_language(&self, lang: Language) -> Option<&CustomRegistration> {
346        match lang {
347            Language::Python => self.python.as_ref(),
348            Language::Node => self.node.as_ref(),
349            Language::Ruby => self.ruby.as_ref(),
350            Language::Php => self.php.as_ref(),
351            Language::Elixir => self.elixir.as_ref(),
352            Language::Wasm => self.wasm.as_ref(),
353            _ => None,
354        }
355    }
356}