use autocxx_parser::TypeConfig;
use syn::{Item, Type, TypePath};
use crate::{
conversion::{
api::{ApiDetail, UnanalyzedApi},
ConvertError,
},
known_types::KNOWN_TYPES,
types::TypeName,
};
use super::ByValueChecker;
pub(crate) fn identify_byvalue_safe_types(
apis: &[UnanalyzedApi],
type_config: &TypeConfig,
) -> Result<ByValueChecker, ConvertError> {
let mut byvalue_checker = ByValueChecker::new();
byvalue_checker.ingest_blocklist(type_config.get_blocklist());
for api in apis {
match &api.detail {
ApiDetail::Typedef { type_item } => {
let name = api.typename();
let typedef_type = analyze_typedef_target(type_item.ty.as_ref());
match &typedef_type {
Some(typ) => {
byvalue_checker.ingest_simple_typedef(name, TypeName::from_type_path(&typ))
}
None => byvalue_checker.ingest_nonpod_type(name),
}
}
ApiDetail::Type {
ty_details: _,
for_extern_c_ts: _,
is_forward_declaration: _,
bindgen_mod_item,
analysis: _,
} => match bindgen_mod_item {
None => {}
Some(Item::Struct(s)) => byvalue_checker.ingest_struct(&s, &api.ns),
Some(Item::Enum(_)) => byvalue_checker.ingest_pod_type(api.typename()),
_ => {}
},
_ => {}
}
}
let pod_requests = type_config
.get_pod_requests()
.iter()
.map(|ty| TypeName::new_from_user_input(ty))
.collect();
byvalue_checker
.satisfy_requests(pod_requests)
.map_err(ConvertError::UnsafePodType)?;
Ok(byvalue_checker)
}
fn analyze_typedef_target(ty: &Type) -> Option<TypePath> {
match ty {
Type::Path(typ) => KNOWN_TYPES.known_type_substitute_path(&typ),
_ => None,
}
}