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 /// Original Rust type before sanitization, stored when param.sanitized=true.
240 /// Allows codegen to reconstruct proper deserialization logic.
241 /// E.g. `"Vec<(PathBuf, Option<FileExtractionConfig>)>"` when sanitized to `Vec<String>`.
242 #[serde(default)]
243 pub original_type: Option<String>,
244}
245
246/// A public enum.
247#[derive(Debug, Clone, Serialize, Deserialize)]
248pub struct EnumDef {
249 pub name: String,
250 pub rust_path: String,
251 #[serde(default)]
252 pub original_rust_path: String,
253 pub variants: Vec<EnumVariant>,
254 pub doc: String,
255 #[serde(default)]
256 pub cfg: Option<String>,
257 /// Serde tag property name for internally tagged enums (from `#[serde(tag = "...")]`)
258 #[serde(default, skip_serializing_if = "Option::is_none")]
259 pub serde_tag: Option<String>,
260 /// Serde rename strategy for enum variants (from `#[serde(rename_all = "...")]`)
261 #[serde(default, skip_serializing_if = "Option::is_none")]
262 pub serde_rename_all: Option<String>,
263}
264
265/// An enum variant.
266#[derive(Debug, Clone, Serialize, Deserialize)]
267pub struct EnumVariant {
268 pub name: String,
269 pub fields: Vec<FieldDef>,
270 pub doc: String,
271 /// True if this variant has `#[default]` attribute (used by `#[derive(Default)]`).
272 #[serde(default)]
273 pub is_default: bool,
274 /// Explicit serde rename for this variant (from `#[serde(rename = "...")]`).
275 #[serde(default, skip_serializing_if = "Option::is_none")]
276 pub serde_rename: Option<String>,
277}
278
279/// An error type (enum used in Result<T, E>).
280#[derive(Debug, Clone, Serialize, Deserialize)]
281pub struct ErrorDef {
282 pub name: String,
283 pub rust_path: String,
284 #[serde(default)]
285 pub original_rust_path: String,
286 pub variants: Vec<ErrorVariant>,
287 pub doc: String,
288}
289
290/// An error variant.
291#[derive(Debug, Clone, Serialize, Deserialize)]
292pub struct ErrorVariant {
293 pub name: String,
294 /// The `#[error("...")]` message template string, e.g. `"I/O error: {0}"`.
295 pub message_template: Option<String>,
296 /// Fields on this variant (struct or tuple fields).
297 #[serde(default)]
298 pub fields: Vec<FieldDef>,
299 /// True if any field has `#[source]` or `#[from]`.
300 #[serde(default)]
301 pub has_source: bool,
302 /// True if any field has `#[from]` (auto From conversion).
303 #[serde(default)]
304 pub has_from: bool,
305 /// True if this is a unit variant (no fields).
306 #[serde(default)]
307 pub is_unit: bool,
308 pub doc: String,
309}
310
311/// Reference to a type, with enough info for codegen.
312#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
313pub enum TypeRef {
314 Primitive(PrimitiveType),
315 String,
316 /// Rust `char` — single Unicode character. Binding layer represents as single-char string.
317 Char,
318 Bytes,
319 Optional(Box<TypeRef>),
320 Vec(Box<TypeRef>),
321 Map(Box<TypeRef>, Box<TypeRef>),
322 Named(String),
323 Path,
324 Unit,
325 Json,
326 Duration,
327}
328
329impl TypeRef {
330 /// Returns true if this type reference contains `Named(name)` at any depth.
331 pub fn references_named(&self, name: &str) -> bool {
332 match self {
333 Self::Named(n) => n == name,
334 Self::Optional(inner) | Self::Vec(inner) => inner.references_named(name),
335 Self::Map(k, v) => k.references_named(name) || v.references_named(name),
336 _ => false,
337 }
338 }
339}
340
341/// Rust primitive types.
342#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
343pub enum PrimitiveType {
344 Bool,
345 U8,
346 U16,
347 U32,
348 U64,
349 I8,
350 I16,
351 I32,
352 I64,
353 F32,
354 F64,
355 Usize,
356 Isize,
357}