alef_core/backend.rs
1use crate::config::{Language, ResolvedCrateConfig};
2use crate::ir::ApiSurface;
3use std::path::PathBuf;
4
5/// Build-time dependency for a language backend.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
7pub enum BuildDependency {
8 /// Backend has no external build dependencies.
9 #[default]
10 None,
11 /// Backend depends on the C FFI base being built first (Go, Java, C#, Zig).
12 Ffi,
13 /// Backend depends on the Rustler NIF being built first (Gleam).
14 Rustler,
15}
16
17/// Build configuration for a language backend.
18#[derive(Debug, Clone)]
19pub struct BuildConfig {
20 /// Build tool name (e.g., "napi", "maturin", "wasm-pack", "cargo", "mvn", "dotnet", "mix").
21 pub tool: &'static str,
22 /// Crate suffix for Rust binding crate (e.g., "-node", "-py", "-wasm", "-ffi").
23 pub crate_suffix: &'static str,
24 /// Build-time dependency for this backend.
25 pub build_dep: BuildDependency,
26 /// Post-processing steps to run after build.
27 pub post_build: Vec<PostBuildStep>,
28}
29
30impl BuildConfig {
31 /// Returns whether this backend depends on the C FFI base (backwards compatibility).
32 pub fn depends_on_ffi(&self) -> bool {
33 matches!(self.build_dep, BuildDependency::Ffi)
34 }
35}
36
37/// In-process post-processor applied to a generated file after external build tools run.
38#[derive(Debug, Clone, Copy, PartialEq, Eq)]
39pub enum PostProcessor {
40 /// Rewrite frb-generated Dart sealed-class factory params from positional names (`field0`)
41 /// to payload-derived names (e.g. `metadata` for a `PdfMetadata` payload).
42 FrbDartSealedVariants,
43}
44
45/// A post-build processing step.
46#[derive(Debug, Clone)]
47pub enum PostBuildStep {
48 /// Replace all occurrences of `find` with `replace` in `path` (relative to crate dir).
49 PatchFile {
50 /// File path relative to the binding crate directory.
51 path: &'static str,
52 /// Text to find.
53 find: &'static str,
54 /// Text to replace with.
55 replace: &'static str,
56 },
57 /// Run an external command (e.g., for generated code post-processing via flutter_rust_bridge).
58 RunCommand {
59 /// Command to execute.
60 cmd: &'static str,
61 /// Command arguments.
62 args: Vec<&'static str>,
63 },
64 /// Apply an in-process [`PostProcessor`] to the file at `path` (relative to crate dir).
65 PostProcessFile {
66 /// File path relative to the binding crate directory.
67 path: PathBuf,
68 /// In-process processor to apply.
69 processor: PostProcessor,
70 },
71}
72
73/// A generated file to write to disk.
74#[derive(Debug, Clone)]
75pub struct GeneratedFile {
76 /// Path relative to the output root.
77 pub path: PathBuf,
78 /// File content.
79 pub content: String,
80 /// Whether to prepend a "DO NOT EDIT" header.
81 pub generated_header: bool,
82}
83
84/// Capabilities supported by a backend.
85#[derive(Debug, Clone, Default)]
86pub struct Capabilities {
87 pub supports_async: bool,
88 pub supports_classes: bool,
89 pub supports_enums: bool,
90 pub supports_option: bool,
91 pub supports_result: bool,
92 pub supports_callbacks: bool,
93 pub supports_streaming: bool,
94}
95
96/// Trait that all language backends implement.
97pub trait Backend: Send + Sync {
98 /// Backend identifier (e.g., "pyo3", "napi", "ffi").
99 fn name(&self) -> &str;
100
101 /// Target language.
102 fn language(&self) -> Language;
103
104 /// What this backend supports.
105 fn capabilities(&self) -> Capabilities;
106
107 /// Generate binding source code.
108 fn generate_bindings(&self, api: &ApiSurface, config: &ResolvedCrateConfig) -> anyhow::Result<Vec<GeneratedFile>>;
109
110 /// Generate type stubs (.pyi, .rbs, .d.ts). Optional — default returns empty.
111 fn generate_type_stubs(
112 &self,
113 _api: &ApiSurface,
114 _config: &ResolvedCrateConfig,
115 ) -> anyhow::Result<Vec<GeneratedFile>> {
116 Ok(vec![])
117 }
118
119 /// Generate package scaffolding. Optional — default returns empty.
120 fn generate_scaffold(
121 &self,
122 _api: &ApiSurface,
123 _config: &ResolvedCrateConfig,
124 ) -> anyhow::Result<Vec<GeneratedFile>> {
125 Ok(vec![])
126 }
127
128 /// Generate language-native public API wrappers. Optional — default returns empty.
129 fn generate_public_api(
130 &self,
131 _api: &ApiSurface,
132 _config: &ResolvedCrateConfig,
133 ) -> anyhow::Result<Vec<GeneratedFile>> {
134 Ok(vec![])
135 }
136
137 /// Build configuration for this backend. Returns `None` if build is not supported.
138 fn build_config(&self) -> Option<BuildConfig> {
139 None
140 }
141}