133d722a9Sopenharmony_ciuse crate::gen::{CfgEvaluator, CfgResult}; 233d722a9Sopenharmony_ciuse once_cell::sync::OnceCell; 333d722a9Sopenharmony_ciuse std::borrow::Borrow; 433d722a9Sopenharmony_ciuse std::cmp::Ordering; 533d722a9Sopenharmony_ciuse std::collections::{BTreeMap as Map, BTreeSet as Set}; 633d722a9Sopenharmony_ciuse std::env; 733d722a9Sopenharmony_ci 833d722a9Sopenharmony_cistatic ENV: OnceCell<CargoEnv> = OnceCell::new(); 933d722a9Sopenharmony_ci 1033d722a9Sopenharmony_cistruct CargoEnv { 1133d722a9Sopenharmony_ci features: Set<Name>, 1233d722a9Sopenharmony_ci cfgs: Map<Name, String>, 1333d722a9Sopenharmony_ci} 1433d722a9Sopenharmony_ci 1533d722a9Sopenharmony_cipub(super) struct CargoEnvCfgEvaluator; 1633d722a9Sopenharmony_ci 1733d722a9Sopenharmony_ciimpl CfgEvaluator for CargoEnvCfgEvaluator { 1833d722a9Sopenharmony_ci fn eval(&self, name: &str, query_value: Option<&str>) -> CfgResult { 1933d722a9Sopenharmony_ci let env = ENV.get_or_init(CargoEnv::load); 2033d722a9Sopenharmony_ci if name == "feature" { 2133d722a9Sopenharmony_ci return if let Some(query_value) = query_value { 2233d722a9Sopenharmony_ci CfgResult::from(env.features.contains(Lookup::new(query_value))) 2333d722a9Sopenharmony_ci } else { 2433d722a9Sopenharmony_ci let msg = "expected `feature = \"...\"`".to_owned(); 2533d722a9Sopenharmony_ci CfgResult::Undetermined { msg } 2633d722a9Sopenharmony_ci }; 2733d722a9Sopenharmony_ci } 2833d722a9Sopenharmony_ci if name == "test" && query_value.is_none() { 2933d722a9Sopenharmony_ci let msg = "cfg(test) is not supported because Cargo runs your build script only once across the lib and test build of the same crate".to_owned(); 3033d722a9Sopenharmony_ci return CfgResult::Undetermined { msg }; 3133d722a9Sopenharmony_ci } 3233d722a9Sopenharmony_ci if let Some(cargo_value) = env.cfgs.get(Lookup::new(name)) { 3333d722a9Sopenharmony_ci return if let Some(query_value) = query_value { 3433d722a9Sopenharmony_ci CfgResult::from(cargo_value.split(',').any(|value| value == query_value)) 3533d722a9Sopenharmony_ci } else { 3633d722a9Sopenharmony_ci CfgResult::True 3733d722a9Sopenharmony_ci }; 3833d722a9Sopenharmony_ci } 3933d722a9Sopenharmony_ci if name == "debug_assertions" && query_value.is_none() { 4033d722a9Sopenharmony_ci return CfgResult::from(cfg!(debug_assertions)); 4133d722a9Sopenharmony_ci } 4233d722a9Sopenharmony_ci CfgResult::False 4333d722a9Sopenharmony_ci } 4433d722a9Sopenharmony_ci} 4533d722a9Sopenharmony_ci 4633d722a9Sopenharmony_ciimpl CargoEnv { 4733d722a9Sopenharmony_ci fn load() -> Self { 4833d722a9Sopenharmony_ci const CARGO_FEATURE_PREFIX: &str = "CARGO_FEATURE_"; 4933d722a9Sopenharmony_ci const CARGO_CFG_PREFIX: &str = "CARGO_CFG_"; 5033d722a9Sopenharmony_ci 5133d722a9Sopenharmony_ci let mut features = Set::new(); 5233d722a9Sopenharmony_ci let mut cfgs = Map::new(); 5333d722a9Sopenharmony_ci for (k, v) in env::vars_os() { 5433d722a9Sopenharmony_ci let k = match k.to_str() { 5533d722a9Sopenharmony_ci Some(k) => k, 5633d722a9Sopenharmony_ci None => continue, 5733d722a9Sopenharmony_ci }; 5833d722a9Sopenharmony_ci let v = match v.into_string() { 5933d722a9Sopenharmony_ci Ok(v) => v, 6033d722a9Sopenharmony_ci Err(_) => continue, 6133d722a9Sopenharmony_ci }; 6233d722a9Sopenharmony_ci if let Some(feature_name) = k.strip_prefix(CARGO_FEATURE_PREFIX) { 6333d722a9Sopenharmony_ci let feature_name = Name(feature_name.to_owned()); 6433d722a9Sopenharmony_ci features.insert(feature_name); 6533d722a9Sopenharmony_ci } else if let Some(cfg_name) = k.strip_prefix(CARGO_CFG_PREFIX) { 6633d722a9Sopenharmony_ci let cfg_name = Name(cfg_name.to_owned()); 6733d722a9Sopenharmony_ci cfgs.insert(cfg_name, v); 6833d722a9Sopenharmony_ci } 6933d722a9Sopenharmony_ci } 7033d722a9Sopenharmony_ci CargoEnv { features, cfgs } 7133d722a9Sopenharmony_ci } 7233d722a9Sopenharmony_ci} 7333d722a9Sopenharmony_ci 7433d722a9Sopenharmony_cistruct Name(String); 7533d722a9Sopenharmony_ci 7633d722a9Sopenharmony_ciimpl Ord for Name { 7733d722a9Sopenharmony_ci fn cmp(&self, rhs: &Self) -> Ordering { 7833d722a9Sopenharmony_ci Lookup::new(&self.0).cmp(Lookup::new(&rhs.0)) 7933d722a9Sopenharmony_ci } 8033d722a9Sopenharmony_ci} 8133d722a9Sopenharmony_ci 8233d722a9Sopenharmony_ciimpl PartialOrd for Name { 8333d722a9Sopenharmony_ci fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> { 8433d722a9Sopenharmony_ci Some(self.cmp(rhs)) 8533d722a9Sopenharmony_ci } 8633d722a9Sopenharmony_ci} 8733d722a9Sopenharmony_ci 8833d722a9Sopenharmony_ciimpl Eq for Name {} 8933d722a9Sopenharmony_ci 9033d722a9Sopenharmony_ciimpl PartialEq for Name { 9133d722a9Sopenharmony_ci fn eq(&self, rhs: &Self) -> bool { 9233d722a9Sopenharmony_ci Lookup::new(&self.0).eq(Lookup::new(&rhs.0)) 9333d722a9Sopenharmony_ci } 9433d722a9Sopenharmony_ci} 9533d722a9Sopenharmony_ci 9633d722a9Sopenharmony_ci#[repr(transparent)] 9733d722a9Sopenharmony_cistruct Lookup(str); 9833d722a9Sopenharmony_ci 9933d722a9Sopenharmony_ciimpl Lookup { 10033d722a9Sopenharmony_ci fn new(name: &str) -> &Self { 10133d722a9Sopenharmony_ci unsafe { &*(name as *const str as *const Self) } 10233d722a9Sopenharmony_ci } 10333d722a9Sopenharmony_ci} 10433d722a9Sopenharmony_ci 10533d722a9Sopenharmony_ciimpl Borrow<Lookup> for Name { 10633d722a9Sopenharmony_ci fn borrow(&self) -> &Lookup { 10733d722a9Sopenharmony_ci Lookup::new(&self.0) 10833d722a9Sopenharmony_ci } 10933d722a9Sopenharmony_ci} 11033d722a9Sopenharmony_ci 11133d722a9Sopenharmony_ciimpl Ord for Lookup { 11233d722a9Sopenharmony_ci fn cmp(&self, rhs: &Self) -> Ordering { 11333d722a9Sopenharmony_ci self.0 11433d722a9Sopenharmony_ci .bytes() 11533d722a9Sopenharmony_ci .map(CaseAgnosticByte) 11633d722a9Sopenharmony_ci .cmp(rhs.0.bytes().map(CaseAgnosticByte)) 11733d722a9Sopenharmony_ci } 11833d722a9Sopenharmony_ci} 11933d722a9Sopenharmony_ci 12033d722a9Sopenharmony_ciimpl PartialOrd for Lookup { 12133d722a9Sopenharmony_ci fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> { 12233d722a9Sopenharmony_ci Some(self.cmp(rhs)) 12333d722a9Sopenharmony_ci } 12433d722a9Sopenharmony_ci} 12533d722a9Sopenharmony_ci 12633d722a9Sopenharmony_ciimpl Eq for Lookup {} 12733d722a9Sopenharmony_ci 12833d722a9Sopenharmony_ciimpl PartialEq for Lookup { 12933d722a9Sopenharmony_ci fn eq(&self, rhs: &Self) -> bool { 13033d722a9Sopenharmony_ci self.0 13133d722a9Sopenharmony_ci .bytes() 13233d722a9Sopenharmony_ci .map(CaseAgnosticByte) 13333d722a9Sopenharmony_ci .eq(rhs.0.bytes().map(CaseAgnosticByte)) 13433d722a9Sopenharmony_ci } 13533d722a9Sopenharmony_ci} 13633d722a9Sopenharmony_ci 13733d722a9Sopenharmony_cistruct CaseAgnosticByte(u8); 13833d722a9Sopenharmony_ci 13933d722a9Sopenharmony_ciimpl Ord for CaseAgnosticByte { 14033d722a9Sopenharmony_ci fn cmp(&self, rhs: &Self) -> Ordering { 14133d722a9Sopenharmony_ci self.0.to_ascii_lowercase().cmp(&rhs.0.to_ascii_lowercase()) 14233d722a9Sopenharmony_ci } 14333d722a9Sopenharmony_ci} 14433d722a9Sopenharmony_ci 14533d722a9Sopenharmony_ciimpl PartialOrd for CaseAgnosticByte { 14633d722a9Sopenharmony_ci fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> { 14733d722a9Sopenharmony_ci Some(self.cmp(rhs)) 14833d722a9Sopenharmony_ci } 14933d722a9Sopenharmony_ci} 15033d722a9Sopenharmony_ci 15133d722a9Sopenharmony_ciimpl Eq for CaseAgnosticByte {} 15233d722a9Sopenharmony_ci 15333d722a9Sopenharmony_ciimpl PartialEq for CaseAgnosticByte { 15433d722a9Sopenharmony_ci fn eq(&self, rhs: &Self) -> bool { 15533d722a9Sopenharmony_ci self.cmp(rhs) == Ordering::Equal 15633d722a9Sopenharmony_ci } 15733d722a9Sopenharmony_ci} 158