133d722a9Sopenharmony_ciuse crate::gen::{CfgEvaluator, CfgResult}; 233d722a9Sopenharmony_ciuse std::collections::{BTreeMap as Map, BTreeSet as Set}; 333d722a9Sopenharmony_ciuse std::fmt::{self, Debug}; 433d722a9Sopenharmony_ciuse syn::parse::ParseStream; 533d722a9Sopenharmony_ciuse syn::{Ident, LitBool, LitStr, Token}; 633d722a9Sopenharmony_ci 733d722a9Sopenharmony_ci#[derive(Ord, PartialOrd, Eq, PartialEq)] 833d722a9Sopenharmony_cipub enum CfgValue { 933d722a9Sopenharmony_ci Bool(bool), 1033d722a9Sopenharmony_ci Str(String), 1133d722a9Sopenharmony_ci} 1233d722a9Sopenharmony_ci 1333d722a9Sopenharmony_ciimpl CfgValue { 1433d722a9Sopenharmony_ci const FALSE: Self = CfgValue::Bool(false); 1533d722a9Sopenharmony_ci const TRUE: Self = CfgValue::Bool(true); 1633d722a9Sopenharmony_ci} 1733d722a9Sopenharmony_ci 1833d722a9Sopenharmony_cipub struct FlagsCfgEvaluator { 1933d722a9Sopenharmony_ci map: Map<String, Set<CfgValue>>, 2033d722a9Sopenharmony_ci} 2133d722a9Sopenharmony_ci 2233d722a9Sopenharmony_ciimpl FlagsCfgEvaluator { 2333d722a9Sopenharmony_ci pub fn new(map: Map<String, Set<CfgValue>>) -> Self { 2433d722a9Sopenharmony_ci FlagsCfgEvaluator { map } 2533d722a9Sopenharmony_ci } 2633d722a9Sopenharmony_ci} 2733d722a9Sopenharmony_ci 2833d722a9Sopenharmony_ciimpl CfgEvaluator for FlagsCfgEvaluator { 2933d722a9Sopenharmony_ci fn eval(&self, name: &str, value: Option<&str>) -> CfgResult { 3033d722a9Sopenharmony_ci let set = self.map.get(name); 3133d722a9Sopenharmony_ci if let Some(value) = value { 3233d722a9Sopenharmony_ci if let Some(set) = set { 3333d722a9Sopenharmony_ci CfgResult::from(set.contains(&CfgValue::Str(value.to_owned()))) 3433d722a9Sopenharmony_ci } else if name == "feature" { 3533d722a9Sopenharmony_ci CfgResult::False 3633d722a9Sopenharmony_ci } else { 3733d722a9Sopenharmony_ci let msg = format!( 3833d722a9Sopenharmony_ci "pass `--cfg {}=\"...\"` to be able to use this attribute", 3933d722a9Sopenharmony_ci name, 4033d722a9Sopenharmony_ci ); 4133d722a9Sopenharmony_ci CfgResult::Undetermined { msg } 4233d722a9Sopenharmony_ci } 4333d722a9Sopenharmony_ci } else { 4433d722a9Sopenharmony_ci let (mut is_false, mut is_true) = (false, false); 4533d722a9Sopenharmony_ci if let Some(set) = set { 4633d722a9Sopenharmony_ci is_false = set.contains(&CfgValue::FALSE); 4733d722a9Sopenharmony_ci is_true = set.contains(&CfgValue::TRUE); 4833d722a9Sopenharmony_ci } 4933d722a9Sopenharmony_ci if is_false && is_true { 5033d722a9Sopenharmony_ci let msg = format!("the cxxbridge flags say both {0}=false and {0}=true", name); 5133d722a9Sopenharmony_ci CfgResult::Undetermined { msg } 5233d722a9Sopenharmony_ci } else if is_false { 5333d722a9Sopenharmony_ci CfgResult::False 5433d722a9Sopenharmony_ci } else if is_true { 5533d722a9Sopenharmony_ci CfgResult::True 5633d722a9Sopenharmony_ci } else { 5733d722a9Sopenharmony_ci let msg = format!( 5833d722a9Sopenharmony_ci "pass either `--cfg {0}=true` or `--cfg {0}=false` to be able to use this cfg attribute", 5933d722a9Sopenharmony_ci name, 6033d722a9Sopenharmony_ci ); 6133d722a9Sopenharmony_ci CfgResult::Undetermined { msg } 6233d722a9Sopenharmony_ci } 6333d722a9Sopenharmony_ci } 6433d722a9Sopenharmony_ci } 6533d722a9Sopenharmony_ci} 6633d722a9Sopenharmony_ci 6733d722a9Sopenharmony_ciimpl Debug for CfgValue { 6833d722a9Sopenharmony_ci fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 6933d722a9Sopenharmony_ci match self { 7033d722a9Sopenharmony_ci CfgValue::Bool(value) => Debug::fmt(value, formatter), 7133d722a9Sopenharmony_ci CfgValue::Str(value) => Debug::fmt(value, formatter), 7233d722a9Sopenharmony_ci } 7333d722a9Sopenharmony_ci } 7433d722a9Sopenharmony_ci} 7533d722a9Sopenharmony_ci 7633d722a9Sopenharmony_cipub fn parse(input: ParseStream) -> syn::Result<(String, CfgValue)> { 7733d722a9Sopenharmony_ci let ident: Ident = input.parse()?; 7833d722a9Sopenharmony_ci let name = ident.to_string(); 7933d722a9Sopenharmony_ci if input.is_empty() { 8033d722a9Sopenharmony_ci return Ok((name, CfgValue::TRUE)); 8133d722a9Sopenharmony_ci } 8233d722a9Sopenharmony_ci input.parse::<Token![=]>()?; 8333d722a9Sopenharmony_ci let lookahead = input.lookahead1(); 8433d722a9Sopenharmony_ci if lookahead.peek(LitBool) { 8533d722a9Sopenharmony_ci let lit: LitBool = input.parse()?; 8633d722a9Sopenharmony_ci Ok((name, CfgValue::Bool(lit.value))) 8733d722a9Sopenharmony_ci } else if lookahead.peek(LitStr) { 8833d722a9Sopenharmony_ci let lit: LitStr = input.parse()?; 8933d722a9Sopenharmony_ci Ok((name, CfgValue::Str(lit.value()))) 9033d722a9Sopenharmony_ci } else { 9133d722a9Sopenharmony_ci Err(lookahead.error()) 9233d722a9Sopenharmony_ci } 9333d722a9Sopenharmony_ci} 94