alef_codegen/generators/mod.rs
1use ahash::AHashMap;
2
3pub mod binding_helpers;
4pub mod enums;
5pub mod functions;
6pub mod methods;
7pub mod structs;
8pub mod trait_bridge;
9pub mod type_paths;
10
11/// Map of adapter-generated method/function bodies.
12/// Key: "TypeName.method_name" for methods, "function_name" for free functions.
13pub type AdapterBodies = AHashMap<String, String>;
14
15/// Async support pattern for the backend.
16#[derive(Clone, Copy, Debug, PartialEq, Eq)]
17pub enum AsyncPattern {
18 /// No async support
19 None,
20 /// PyO3: pyo3_async_runtimes::tokio::future_into_py
21 Pyo3FutureIntoPy,
22 /// NAPI-RS: native async fn → auto-Promise
23 NapiNativeAsync,
24 /// wasm-bindgen: native async fn → auto-Promise
25 WasmNativeAsync,
26 /// Block on Tokio runtime (Ruby, PHP)
27 TokioBlockOn,
28}
29
30/// Configuration for Rust binding code generation.
31pub struct RustBindingConfig<'a> {
32 /// Attrs applied to generated structs, e.g. `["pyclass(frozen)"]`.
33 pub struct_attrs: &'a [&'a str],
34 /// Attrs applied to each field, e.g. `["pyo3(get)"]`.
35 pub field_attrs: &'a [&'a str],
36 /// Derives applied to generated structs, e.g. `["Clone"]`.
37 pub struct_derives: &'a [&'a str],
38 /// Attr wrapping the impl block, e.g. `Some("pymethods")`.
39 pub method_block_attr: Option<&'a str>,
40 /// Attr placed on the constructor, e.g. `"#[new]"`.
41 pub constructor_attr: &'a str,
42 /// Attr placed on static methods, e.g. `Some("staticmethod")`.
43 pub static_attr: Option<&'a str>,
44 /// Attr placed on free functions, e.g. `"#[pyfunction]"`.
45 pub function_attr: &'a str,
46 /// Attrs applied to generated enums, e.g. `["pyclass(eq, eq_int)"]`.
47 pub enum_attrs: &'a [&'a str],
48 /// Derives applied to generated enums, e.g. `["Clone", "PartialEq"]`.
49 pub enum_derives: &'a [&'a str],
50 /// Whether the backend requires `#[pyo3(signature = (...))]`-style annotations.
51 pub needs_signature: bool,
52 /// Prefix for the signature annotation, e.g. `"#[pyo3(signature = ("`.
53 pub signature_prefix: &'a str,
54 /// Suffix for the signature annotation, e.g. `"))]"`.
55 pub signature_suffix: &'a str,
56 /// Core crate import path, e.g. `"liter_llm"`. Used to generate calls into core.
57 pub core_import: &'a str,
58 /// Async pattern supported by this backend.
59 pub async_pattern: AsyncPattern,
60 /// Whether serde/serde_json are available in the output crate's dependencies.
61 /// When true, the generator can use serde-based param conversion and add `serde::Serialize` derives.
62 /// When false, non-convertible Named params fall back to `gen_unimplemented_body`.
63 pub has_serde: bool,
64 /// Prefix for binding type names (e.g. "Js" for NAPI/WASM, "" for PyO3/PHP).
65 /// Used in impl block targets: `impl {prefix}{TypeName}`.
66 pub type_name_prefix: &'a str,
67 /// When true, non-optional Duration fields on `has_default` types are emitted as
68 /// `Option<u64>` in the binding struct so that unset fields fall back to the core
69 /// type's `Default` implementation rather than `Duration::ZERO`.
70 /// Used by PyO3 to prevent validation failures when `request_timeout` is unset.
71 pub option_duration_on_defaults: bool,
72 /// Opaque type names. Structs with non-optional fields of these types
73 /// skip `Default`/`Serialize`/`Deserialize` derives since opaque wrappers don't impl them.
74 pub opaque_type_names: &'a [String],
75 /// When true, the impl block constructor (`fn new(...)`) is suppressed regardless of
76 /// whether the type has fields. Useful for backends (e.g. extendr) that generate a
77 /// separate kwargs-style free-function constructor instead of an in-class `new()`.
78 pub skip_impl_constructor: bool,
79 /// When true, small unsigned/signed ints (u8, u16, u32, i8, i16) are cast from i32 in
80 /// `gen_lossy_binding_to_core_fields`. Used by the extendr backend where R maps small
81 /// ints to i32.
82 pub cast_uints_to_i32: bool,
83 /// When true, large int/size types (u64, usize, isize) are cast from f64 in
84 /// `gen_lossy_binding_to_core_fields`. Used by the extendr backend where R maps large
85 /// ints to f64.
86 pub cast_large_ints_to_f64: bool,
87 /// When true, Named non-opaque struct parameters in free function signatures are emitted
88 /// as `&T` (reference) instead of `T` (owned). Required for the extendr backend because
89 /// `#[extendr]` only generates `TryFrom<&Robj> for &T`, not `for T`, so owned struct
90 /// params cannot be passed through the FFI layer.
91 pub named_non_opaque_params_by_ref: bool,
92 /// Types that have no `From<BindingType>` impl (e.g. output-only flat data enums).
93 /// When `gen_lossy_binding_to_core_fields` encounters a field whose `TypeRef::Named` type
94 /// is in this slice, it emits `Default::default()` instead of `.clone().into()`.
95 pub lossy_skip_types: &'a [String],
96}
97
98/// Method names that conflict with standard trait methods.
99/// When a generated method has one of these names, we add
100/// `#[allow(clippy::should_implement_trait)]` to suppress the lint.
101pub(super) const TRAIT_METHOD_NAMES: &[&str] = &[
102 "default", "from", "from_str", "into", "eq", "ne", "lt", "le", "gt", "ge", "add", "sub", "mul", "div", "rem",
103 "neg", "not", "index", "deref",
104];
105
106// Re-exports for backwards compatibility — callers use `crate::generators::*`.
107pub use binding_helpers::{
108 gen_async_body, gen_call_args, gen_call_args_with_let_bindings, gen_lossy_binding_to_core_fields,
109 gen_lossy_binding_to_core_fields_mut, gen_named_let_bindings_no_promote, gen_named_let_bindings_pub,
110 gen_serde_let_bindings, gen_unimplemented_body, has_named_params, is_simple_non_opaque_param, wrap_return,
111 wrap_return_with_mutex,
112};
113pub use enums::{enum_has_data_variants, gen_enum, gen_pyo3_data_enum};
114pub use functions::{collect_explicit_core_imports, collect_trait_imports, gen_function, has_unresolved_trait_methods};
115pub use methods::{
116 gen_constructor, gen_constructor_with_renames, gen_impl_block, gen_impl_block_with_renames, gen_method,
117 gen_opaque_impl_block, gen_static_method, is_trait_method_name,
118};
119pub use structs::{
120 can_generate_default_impl, gen_opaque_struct, gen_opaque_struct_prefixed, gen_struct, gen_struct_default_impl,
121 gen_struct_with_per_field_attrs, gen_struct_with_rename, type_needs_mutex, type_needs_tokio_mutex,
122};