Skip to main content

alef_core/
ir.rs

1use serde::{Deserialize, Serialize};
2
3/// Indicates the core Rust type wraps the resolved type in a smart pointer or cow.
4/// Used by codegen to generate correct From/Into conversions.
5#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
6pub enum CoreWrapper {
7    #[default]
8    None,
9    /// `Cow<'static, str>` — binding uses String, core needs `.into()`
10    Cow,
11    /// `Arc<T>` — binding unwraps, core wraps with `Arc::new()`
12    Arc,
13    /// `bytes::Bytes` — binding uses `Vec<u8>`, core needs `Bytes::from()`
14    Bytes,
15    /// `Arc<Mutex<T>>` — binding wraps with `Arc::new(Mutex::new())`, methods call `.lock()`
16    ArcMutex,
17}
18
19/// Typed default value for a field, enabling backends to emit language-native defaults.
20#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
21pub enum DefaultValue {
22    BoolLiteral(bool),
23    StringLiteral(String),
24    IntLiteral(i64),
25    FloatLiteral(f64),
26    EnumVariant(String),
27    /// Empty collection or Default::default()
28    Empty,
29    /// None / null
30    None,
31}
32
33/// Complete API surface extracted from a Rust crate's public interface.
34#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct ApiSurface {
36    pub crate_name: String,
37    pub version: String,
38    pub types: Vec<TypeDef>,
39    pub functions: Vec<FunctionDef>,
40    pub enums: Vec<EnumDef>,
41    pub errors: Vec<ErrorDef>,
42}
43
44/// A public struct exposed to bindings.
45#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct TypeDef {
47    pub name: String,
48    pub rust_path: String,
49    pub fields: Vec<FieldDef>,
50    pub methods: Vec<MethodDef>,
51    pub is_opaque: bool,
52    pub is_clone: bool,
53    pub doc: String,
54    #[serde(default)]
55    pub cfg: Option<String>,
56    /// True if this type was extracted from a trait definition.
57    /// Trait types need `dyn` keyword when used as opaque inner types.
58    #[serde(default)]
59    pub is_trait: bool,
60    /// True if the type implements Default (via derive or manual impl).
61    /// Used by backends like NAPI to make all fields optional with defaults.
62    #[serde(default)]
63    pub has_default: bool,
64    /// True if some fields were stripped due to `#[cfg]` conditions.
65    /// When true, struct literal initializers need `..Default::default()` to fill
66    /// the missing fields that may exist when the core crate is compiled with features.
67    #[serde(default)]
68    pub has_stripped_cfg_fields: bool,
69    /// True if this type appears as a function return type.
70    /// Used to select output DTO style (e.g., TypedDict for Python return types).
71    #[serde(default)]
72    pub is_return_type: bool,
73    /// Serde `rename_all` strategy for this type (e.g., `"camelCase"`, `"snake_case"`).
74    /// Used by Go/Java/C# backends to emit correct JSON tags matching Rust serde config.
75    #[serde(default)]
76    pub serde_rename_all: Option<String>,
77    /// True if the type derives `serde::Serialize` and `serde::Deserialize`.
78    /// Used by FFI backend to gate `from_json`/`to_json` generation — types
79    /// without serde derives cannot be (de)serialized.
80    #[serde(default)]
81    pub has_serde: bool,
82    /// Super-traits of this trait (e.g., `["Plugin"]` for `OcrBackend: Plugin`).
83    /// Only populated when `is_trait` is true. Used by trait bridge codegen
84    /// to determine which super-trait impls to generate.
85    #[serde(default)]
86    pub super_traits: Vec<String>,
87}
88
89/// A field on a public struct.
90#[derive(Debug, Clone, Serialize, Deserialize)]
91pub struct FieldDef {
92    pub name: String,
93    pub ty: TypeRef,
94    pub optional: bool,
95    pub default: Option<String>,
96    pub doc: String,
97    /// True if this field's type was sanitized (e.g., Duration→u64, trait object→String).
98    /// Fields marked sanitized cannot participate in auto-generated From/Into conversions.
99    #[serde(default)]
100    pub sanitized: bool,
101    /// True if the core field type is `Box<T>` (or `Option<Box<T>>`).
102    /// Used by FFI backends to insert proper deref when cloning field values.
103    #[serde(default)]
104    pub is_boxed: bool,
105    /// Fully qualified Rust path for the field's type (e.g. `my_crate::types::OutputFormat`).
106    /// Used by backends to disambiguate types with the same short name.
107    #[serde(default)]
108    pub type_rust_path: Option<String>,
109    /// `#[cfg(...)]` condition string on this field, if any.
110    /// Used by backends to conditionally include fields in struct literals.
111    #[serde(default)]
112    pub cfg: Option<String>,
113    /// Typed default value for language-native default emission.
114    #[serde(default)]
115    pub typed_default: Option<DefaultValue>,
116    /// Core wrapper on this field (Cow, Arc, Bytes). Affects From/Into codegen.
117    #[serde(default)]
118    pub core_wrapper: CoreWrapper,
119    /// Core wrapper on Vec inner elements (e.g., `Vec<Arc<T>>`).
120    #[serde(default)]
121    pub vec_inner_core_wrapper: CoreWrapper,
122    /// Full Rust path of the newtype wrapper that was resolved away for this field,
123    /// e.g. `"my_crate::NodeIndex"` when `NodeIndex(u32)` was resolved to `u32`.
124    /// When set, binding→core codegen must wrap values into the newtype
125    /// (e.g. `my_crate::NodeIndex(val.field)`) and core→binding codegen must unwrap (`.0`).
126    #[serde(default)]
127    pub newtype_wrapper: Option<String>,
128}
129
130/// A method on a public struct.
131#[derive(Debug, Clone, Serialize, Deserialize)]
132pub struct MethodDef {
133    pub name: String,
134    pub params: Vec<ParamDef>,
135    pub return_type: TypeRef,
136    pub is_async: bool,
137    pub is_static: bool,
138    pub error_type: Option<String>,
139    pub doc: String,
140    pub receiver: Option<ReceiverKind>,
141    /// True if any param or return type was sanitized during unknown type resolution.
142    /// Methods with sanitized signatures cannot be auto-delegated.
143    #[serde(default)]
144    pub sanitized: bool,
145    /// Fully qualified trait path if this method comes from a trait impl
146    /// (e.g. "liter_llm::LlmClient"). None for inherent methods.
147    #[serde(default)]
148    pub trait_source: Option<String>,
149    /// True if the core function returns a reference (`&T`, `Option<&T>`, etc.).
150    /// Used by code generators to insert `.clone()` before type conversion.
151    #[serde(default)]
152    pub returns_ref: bool,
153    /// True if the core function returns `Cow<'_, T>` where T is a named type (not str/bytes).
154    /// Used by code generators to emit `.into_owned()` before type conversion.
155    #[serde(default)]
156    pub returns_cow: bool,
157    /// Full Rust path of the newtype wrapper that was resolved away for the return type,
158    /// e.g. `"my_crate::NodeIndex"` when the return type `NodeIndex(u32)` was resolved to `u32`.
159    /// When set, codegen must unwrap the returned newtype value (e.g. `result.0`) before returning.
160    #[serde(default)]
161    pub return_newtype_wrapper: Option<String>,
162    /// True if this method has a default implementation in the trait definition.
163    /// Methods with defaults can be optionally implemented by the foreign object
164    /// in trait bridge codegen.
165    #[serde(default)]
166    pub has_default_impl: bool,
167}
168
169/// How `self` is received.
170#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
171pub enum ReceiverKind {
172    Ref,
173    RefMut,
174    Owned,
175}
176
177/// A free function exposed to bindings.
178#[derive(Debug, Clone, Serialize, Deserialize)]
179pub struct FunctionDef {
180    pub name: String,
181    pub rust_path: String,
182    pub params: Vec<ParamDef>,
183    pub return_type: TypeRef,
184    pub is_async: bool,
185    pub error_type: Option<String>,
186    pub doc: String,
187    #[serde(default)]
188    pub cfg: Option<String>,
189    /// True if any param or return type was sanitized during unknown type resolution.
190    #[serde(default)]
191    pub sanitized: bool,
192    /// True if the core function returns a reference (`&T`, `Option<&T>`, etc.).
193    /// Used by code generators to insert `.clone()` before type conversion.
194    #[serde(default)]
195    pub returns_ref: bool,
196    /// True if the core function returns `Cow<'_, T>` where T is a named type (not str/bytes).
197    /// Used by code generators to emit `.into_owned()` before type conversion.
198    #[serde(default)]
199    pub returns_cow: bool,
200    /// Full Rust path of the newtype wrapper that was resolved away for the return type.
201    /// When set, codegen must unwrap the returned newtype value (e.g. `result.0`).
202    #[serde(default)]
203    pub return_newtype_wrapper: Option<String>,
204}
205
206/// A function/method parameter.
207#[derive(Debug, Clone, Serialize, Deserialize)]
208pub struct ParamDef {
209    pub name: String,
210    pub ty: TypeRef,
211    pub optional: bool,
212    pub default: Option<String>,
213    /// True if this param's type was sanitized during unknown type resolution.
214    #[serde(default)]
215    pub sanitized: bool,
216    /// Typed default value for language-native default emission.
217    #[serde(default)]
218    pub typed_default: Option<DefaultValue>,
219    /// True if the original Rust parameter was a reference (`&T`).
220    /// Used by codegen to generate owned intermediates and pass refs.
221    #[serde(default)]
222    pub is_ref: bool,
223    /// True if the original Rust parameter was a mutable reference (`&mut T`).
224    /// Used by codegen to generate `&mut` refs when calling core functions.
225    #[serde(default)]
226    pub is_mut: bool,
227    /// Full Rust path of the newtype wrapper that was resolved away for this param,
228    /// e.g. `"my_crate::NodeIndex"` when `NodeIndex(u32)` was resolved to `u32`.
229    /// When set, codegen must wrap the raw value back into the newtype when calling core:
230    /// `my_crate::NodeIndex(param)` instead of just `param`.
231    #[serde(default)]
232    pub newtype_wrapper: Option<String>,
233}
234
235/// A public enum.
236#[derive(Debug, Clone, Serialize, Deserialize)]
237pub struct EnumDef {
238    pub name: String,
239    pub rust_path: String,
240    pub variants: Vec<EnumVariant>,
241    pub doc: String,
242    #[serde(default)]
243    pub cfg: Option<String>,
244    /// Serde tag property name for internally tagged enums (from `#[serde(tag = "...")]`)
245    #[serde(default, skip_serializing_if = "Option::is_none")]
246    pub serde_tag: Option<String>,
247    /// Serde rename strategy for enum variants (from `#[serde(rename_all = "...")]`)
248    #[serde(default, skip_serializing_if = "Option::is_none")]
249    pub serde_rename_all: Option<String>,
250}
251
252/// An enum variant.
253#[derive(Debug, Clone, Serialize, Deserialize)]
254pub struct EnumVariant {
255    pub name: String,
256    pub fields: Vec<FieldDef>,
257    pub doc: String,
258    /// True if this variant has `#[default]` attribute (used by `#[derive(Default)]`).
259    #[serde(default)]
260    pub is_default: bool,
261    /// Explicit serde rename for this variant (from `#[serde(rename = "...")]`).
262    #[serde(default, skip_serializing_if = "Option::is_none")]
263    pub serde_rename: Option<String>,
264}
265
266/// An error type (enum used in Result<T, E>).
267#[derive(Debug, Clone, Serialize, Deserialize)]
268pub struct ErrorDef {
269    pub name: String,
270    pub rust_path: String,
271    pub variants: Vec<ErrorVariant>,
272    pub doc: String,
273}
274
275/// An error variant.
276#[derive(Debug, Clone, Serialize, Deserialize)]
277pub struct ErrorVariant {
278    pub name: String,
279    /// The `#[error("...")]` message template string, e.g. `"I/O error: {0}"`.
280    pub message_template: Option<String>,
281    /// Fields on this variant (struct or tuple fields).
282    #[serde(default)]
283    pub fields: Vec<FieldDef>,
284    /// True if any field has `#[source]` or `#[from]`.
285    #[serde(default)]
286    pub has_source: bool,
287    /// True if any field has `#[from]` (auto From conversion).
288    #[serde(default)]
289    pub has_from: bool,
290    /// True if this is a unit variant (no fields).
291    #[serde(default)]
292    pub is_unit: bool,
293    pub doc: String,
294}
295
296/// Reference to a type, with enough info for codegen.
297#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
298pub enum TypeRef {
299    Primitive(PrimitiveType),
300    String,
301    /// Rust `char` — single Unicode character. Binding layer represents as single-char string.
302    Char,
303    Bytes,
304    Optional(Box<TypeRef>),
305    Vec(Box<TypeRef>),
306    Map(Box<TypeRef>, Box<TypeRef>),
307    Named(String),
308    Path,
309    Unit,
310    Json,
311    Duration,
312}
313
314/// Rust primitive types.
315#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
316pub enum PrimitiveType {
317    Bool,
318    U8,
319    U16,
320    U32,
321    U64,
322    I8,
323    I16,
324    I32,
325    I64,
326    F32,
327    F64,
328    Usize,
329    Isize,
330}