use std::collections::HashSet;
use cfg_expr::targets::TargetInfo;
use cfg_expr::{Expression, Predicate};
use syn::Attribute;
use crate::binding_module::CargoFeature;
pub(crate) fn is_primitive(name: &str) -> bool {
name == "u8"
|| name == "u16"
|| name == "u32"
|| name == "u64"
|| name == "i8"
|| name == "i16"
|| name == "i32"
|| name == "i64"
|| name == "f32"
|| name == "f64"
|| name == "isize"
|| name == "usize"
|| name == "bool"
}
#[derive(Debug, Clone)]
pub struct BuildContext {
current_target_info: &'static TargetInfo,
features: Vec<CargoFeature>,
target_features: Vec<String>,
}
impl BuildContext {
pub fn new(
current_target_info: &'static TargetInfo,
features: Vec<CargoFeature>,
target_features: Vec<String>,
) -> Self {
Self {
current_target_info,
features,
target_features,
}
}
pub(crate) fn check_cfg_attrs<T>(&self, attrs: &T) -> bool
where
for<'a> &'a T: IntoIterator<Item = &'a Attribute>,
{
attrs
.into_iter()
.map(|attr| {
let cfg = match &attr.meta {
syn::Meta::List(val) => val.tokens.to_string(),
_ => panic!("Invalid cfg attribute"),
};
let required_cfg = Expression::parse(&cfg).expect("Invalid cfg attribute");
required_cfg.eval(|pred| match pred {
Predicate::Target(tp) => tp.matches(self.current_target_info),
Predicate::Feature(feature) => self
.features
.iter()
.any(|val| *val == CargoFeature::new(feature)),
Predicate::TargetFeature(target_feature) => {
self.target_features.iter().any(|val| val == target_feature)
}
_ => panic!("Unsupported cfg value"),
})
})
.all(|el| el)
}
}
#[derive(Debug, Default)]
struct NameTracker {
known: HashSet<String>,
unknown: HashSet<String>,
}
impl NameTracker {
pub(crate) fn add_unknown(&mut self, name: String) {
if !self.known.iter().any(|v| v == &name) {
self.unknown.insert(name);
}
}
pub(crate) fn add_known(&mut self, name: String) {
self.unknown.retain(|v| v != &name);
self.known.insert(name);
}
}
#[derive(Debug, Default)]
pub struct NamesTracker {
traits: NameTracker,
custom_types: NameTracker,
}
impl NamesTracker {
pub(crate) fn add_known_trait(&mut self, name: String) {
self.traits.add_known(name)
}
pub(crate) fn add_unknown_trait(&mut self, name: String) {
self.traits.add_unknown(name)
}
pub(crate) fn add_known_custom_type(&mut self, name: String) {
self.custom_types.add_known(name)
}
pub(crate) fn add_unknown_custom_type(&mut self, name: String) {
self.custom_types.add_unknown(name)
}
pub(crate) fn get_unknown(&self) -> Vec<String> {
let mut result = vec![];
result.extend(self.custom_types.unknown.iter().cloned());
result.extend(self.traits.unknown.iter().cloned());
result
}
}
#[cfg(test)]
pub(crate) mod helpers {
use cfg_expr::targets::get_builtin_target_by_triple;
use syn::ItemEnum;
use crate::enum_helpers::get_enums_from_module;
use crate::utils::BuildContext;
pub fn get_context() -> BuildContext {
BuildContext {
current_target_info: get_builtin_target_by_triple("x86_64-apple-darwin").unwrap(),
features: vec![],
target_features: vec![],
}
}
pub fn get_enum_item() -> ItemEnum {
let rust_code = "
mod ffi {
enum En1 {
V1,
V2,
}
}
";
let context = get_context();
let module = syn::parse_str(rust_code).unwrap();
get_enums_from_module(&module, &context).unwrap().remove(0)
}
}