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