use super::visitor_bridge::{VisitorBridgeCtx, gen_visitor_bridge};
use crate::codegen::generators::trait_bridge::{BridgeOutput, TraitBridgeSpec, gen_bridge_all};
use crate::core::config::TraitBridgeConfig;
use crate::core::ir::{ApiSurface, TypeDef};
use std::collections::HashMap;
pub struct RustlerBridgeGenerator {
pub core_import: String,
pub type_paths: HashMap<String, String>,
pub error_type: String,
}
pub fn gen_trait_bridge(
trait_type: &TypeDef,
bridge_cfg: &TraitBridgeConfig,
core_import: &str,
error_type: &str,
error_constructor: &str,
api: &ApiSurface,
) -> anyhow::Result<BridgeOutput> {
let type_paths: HashMap<String, String> = api
.types
.iter()
.map(|t| (t.name.clone(), t.rust_path.replace('-', "_")))
.chain(
api.enums
.iter()
.map(|e| (e.name.clone(), e.rust_path.replace('-', "_"))),
)
.chain(
api.excluded_type_paths
.iter()
.map(|(name, path)| (name.clone(), path.replace('-', "_"))),
)
.collect();
let is_visitor_bridge = bridge_cfg.type_alias.is_some()
&& bridge_cfg.register_fn.is_none()
&& bridge_cfg.super_trait.is_none()
&& trait_type.methods.iter().all(|m| m.has_default_impl);
if is_visitor_bridge {
let mut out = String::with_capacity(8192);
let struct_name = format!("Elixir{}Bridge", bridge_cfg.trait_name);
let trait_path = trait_type.rust_path.replace('-', "_");
gen_visitor_bridge(
&mut out,
&VisitorBridgeCtx {
trait_type,
struct_name: &struct_name,
trait_path: &trait_path,
core_crate: core_import,
type_paths: &type_paths,
bridge_cfg,
api,
},
)?;
Ok(BridgeOutput {
imports: vec![],
code: out,
})
} else {
let generator = super::generator::RustlerBridgeGenerator {
core_import: core_import.to_string(),
type_paths: type_paths.clone(),
error_type: error_type.to_string(),
};
let lifetime_type_names: std::collections::HashSet<String> = api
.types
.iter()
.filter(|typ| typ.has_lifetime_params)
.map(|typ| typ.name.clone())
.collect();
let spec = TraitBridgeSpec {
trait_def: trait_type,
bridge_config: bridge_cfg,
core_import,
wrapper_prefix: "Rustler",
type_paths,
lifetime_type_names,
error_type: error_type.to_string(),
error_constructor: error_constructor.to_string(),
};
let output = gen_bridge_all(&spec, &generator);
Ok(output)
}
}