rusty_bind_parser/
utils.rs1use std::collections::HashSet;
2
3use cfg_expr::targets::TargetInfo;
4use cfg_expr::{Expression, Predicate};
5use syn::Attribute;
6
7use crate::binding_module::CargoFeature;
8
9pub(crate) fn is_primitive(name: &str) -> bool {
10 name == "u8"
11 || name == "u16"
12 || name == "u32"
13 || name == "u64"
14 || name == "i8"
15 || name == "i16"
16 || name == "i32"
17 || name == "i64"
18 || name == "f32"
19 || name == "f64"
20 || name == "isize"
21 || name == "usize"
22 || name == "bool"
23}
24
25#[derive(Debug, Clone)]
26pub struct BuildContext {
27 current_target_info: &'static TargetInfo,
28 features: Vec<CargoFeature>,
29 target_features: Vec<String>,
30}
31
32impl BuildContext {
33 pub fn new(
34 current_target_info: &'static TargetInfo,
35 features: Vec<CargoFeature>,
36 target_features: Vec<String>,
37 ) -> Self {
38 Self {
39 current_target_info,
40 features,
41 target_features,
42 }
43 }
44
45 pub(crate) fn check_cfg_attrs<T>(&self, attrs: &T) -> bool
46 where
47 for<'a> &'a T: IntoIterator<Item = &'a Attribute>,
48 {
49 attrs
50 .into_iter()
51 .map(|attr| {
52 let cfg = match &attr.meta {
53 syn::Meta::List(val) => val.tokens.to_string(),
54 _ => panic!("Invalid cfg attribute"),
55 };
56
57 let required_cfg = Expression::parse(&cfg).expect("Invalid cfg attribute");
58
59 required_cfg.eval(|pred| match pred {
60 Predicate::Target(tp) => tp.matches(self.current_target_info),
61 Predicate::Feature(feature) => self
62 .features
63 .iter()
64 .any(|val| *val == CargoFeature::new(feature)),
65 Predicate::TargetFeature(target_feature) => {
66 self.target_features.iter().any(|val| val == target_feature)
67 }
68 _ => panic!("Unsupported cfg value"),
69 })
70 })
71 .all(|el| el)
72 }
73}
74
75#[derive(Debug, Default)]
76struct NameTracker {
77 known: HashSet<String>,
78 unknown: HashSet<String>,
79}
80
81impl NameTracker {
82 pub(crate) fn add_unknown(&mut self, name: String) {
83 if !self.known.iter().any(|v| v == &name) {
84 self.unknown.insert(name);
85 }
86 }
87
88 pub(crate) fn add_known(&mut self, name: String) {
89 self.unknown.retain(|v| v != &name);
90 self.known.insert(name);
91 }
92}
93
94#[derive(Debug, Default)]
95pub struct NamesTracker {
96 traits: NameTracker,
97 custom_types: NameTracker,
98}
99
100impl NamesTracker {
101 pub(crate) fn add_known_trait(&mut self, name: String) {
102 self.traits.add_known(name)
103 }
104
105 pub(crate) fn add_unknown_trait(&mut self, name: String) {
106 self.traits.add_unknown(name)
107 }
108
109 pub(crate) fn add_known_custom_type(&mut self, name: String) {
110 self.custom_types.add_known(name)
111 }
112
113 pub(crate) fn add_unknown_custom_type(&mut self, name: String) {
114 self.custom_types.add_unknown(name)
115 }
116
117 pub(crate) fn get_unknown(&self) -> Vec<String> {
118 let mut result = vec![];
119 result.extend(self.custom_types.unknown.iter().cloned());
120 result.extend(self.traits.unknown.iter().cloned());
121 result
122 }
123}
124
125#[cfg(test)]
126pub(crate) mod helpers {
127 use cfg_expr::targets::get_builtin_target_by_triple;
128 use syn::ItemEnum;
129
130 use crate::enum_helpers::get_enums_from_module;
131 use crate::utils::BuildContext;
132
133 pub fn get_context() -> BuildContext {
134 BuildContext {
135 current_target_info: get_builtin_target_by_triple("x86_64-apple-darwin").unwrap(),
136 features: vec![],
137 target_features: vec![],
138 }
139 }
140
141 pub fn get_enum_item() -> ItemEnum {
142 let rust_code = "
143mod ffi {
144 enum En1 {
145 V1,
146 V2,
147 }
148}
149 ";
150 let context = get_context();
151 let module = syn::parse_str(rust_code).unwrap();
152 get_enums_from_module(&module, &context).unwrap().remove(0)
153 }
154}