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