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