use pest::iterators::Pairs;
use target::{arch, endian, os, os_family, pointer_width};
use crate::parse::Rule;
use crate::vm::RunOpts;
fn check_feature_val(val: &str, p: Pairs<Rule>, neg: bool) -> bool {
let mut found = false;
for fv in p {
let val_low = fv.as_str().to_lowercase();
if val == val_low.as_str() {
found = true;
break;
}
}
if neg {
found = !found;
}
found
}
fn check_feature_list(vals: &[String], p: Pairs<Rule>, neg: bool, feats: &mut Vec<String>) -> bool {
for fv in p.clone() {
let val_low = fv.as_str().to_lowercase();
feats.push(val_low);
}
if vals.is_empty() {
return false;
}
let mut found = false;
for fv in p {
let val_low = fv.as_str().to_lowercase();
for val in vals {
let val = val.to_lowercase();
if val == val_low {
found = true;
break;
}
}
if found {
break;
}
}
if neg {
found = !found;
}
found
}
pub fn process_feature(p: Pairs<Rule>, opts: &RunOpts, feats: &mut Vec<String>) -> Result<bool, String> {
let mut ok = true;
for ss in p {
let mut inverse = false;
let mut f_name: String = String::new();
for sss in ss.into_inner() {
match sss.as_rule() {
Rule::not_op => {
inverse = true;
}
Rule::feature_name => {
f_name = sss.as_str().to_lowercase();
}
Rule::feature_val => {
let pass = match f_name.as_str() {
"os" => check_feature_val(os(), sss.into_inner(), inverse),
"bit" => check_feature_val(pointer_width(), sss.into_inner(), inverse),
"family" | "platform" => check_feature_val(os_family(), sss.into_inner(), inverse),
"arch" => check_feature_val(arch(), sss.into_inner(), inverse),
"endian" => check_feature_val(endian(), sss.into_inner(), inverse),
"feature" | "feat" => check_feature_list(&opts.feats, sss.into_inner(), inverse, feats),
_ => return Err(f_name),
};
ok &= pass;
}
_ => unreachable!(),
}
}
}
Ok(ok)
}