use crate::core::config::TraitBridgeConfig;
use crate::core::ir::{ApiSurface, FieldDef};
use super::bridge_targets_language;
fn inactive_carriers<'a>(trait_bridges: &'a [TraitBridgeConfig], target_spellings: &[&str]) -> Vec<(&'a str, &'a str)> {
trait_bridges
.iter()
.filter(|bridge| !bridge_targets_language(bridge, target_spellings))
.filter_map(|bridge| {
let options_type = bridge.options_type.as_deref()?;
let field = bridge.resolved_options_field()?;
Some((options_type, field))
})
.collect()
}
fn is_matching_carrier(candidate: &FieldDef, carrier: &FieldDef) -> bool {
candidate.name == carrier.name && candidate.ty == carrier.ty && candidate.type_rust_path == carrier.type_rust_path
}
fn carrier_fields<'a>(api: &'a ApiSurface, carriers: &[(&str, &str)]) -> Vec<&'a FieldDef> {
carriers
.iter()
.filter_map(|(options_type, field_name)| {
api.types
.iter()
.find(|typ| typ.name == *options_type)?
.fields
.iter()
.find(|field| field.name == *field_name)
})
.collect()
}
pub fn prune_inactive_bridge_carriers(
api: &ApiSurface,
trait_bridges: &[TraitBridgeConfig],
target_spellings: &[&str],
) -> Option<ApiSurface> {
let carriers = inactive_carriers(trait_bridges, target_spellings);
if carriers.is_empty() {
return None;
}
let carrier_fields = carrier_fields(api, &carriers);
let mut pruned = api.clone();
let mut marked = false;
for typ in &mut pruned.types {
for field in &mut typ.fields {
if !field.binding_excluded && carrier_fields.iter().any(|carrier| is_matching_carrier(field, carrier)) {
field.binding_excluded = true;
field.binding_exclusion_reason =
Some("trait bridge excluded for this language via exclude_languages".to_string());
marked = true;
}
}
}
marked.then_some(pruned)
}
pub fn language_surface(
api: &ApiSurface,
trait_bridges: &[TraitBridgeConfig],
language: crate::core::config::Language,
) -> Option<ApiSurface> {
prune_inactive_bridge_carriers(api, trait_bridges, language.bridge_spellings())
}
pub fn validated_language_surface<'a>(
pruned: &'a Option<ApiSurface>,
whole: crate::core::validation::ValidatedApiSurface<'a>,
) -> crate::core::validation::ValidatedApiSurface<'a> {
pruned.as_ref().map_or(
whole,
crate::core::validation::ValidatedApiSurface::from_subtractive_projection,
)
}