tuwunel_core/info/
rustc.rs1use std::{
8 collections::BTreeMap,
9 mem::replace,
10 sync::{Mutex, OnceLock},
11};
12
13tuwunel_macros::rustc_version! {}
15
16pub static FLAGS: Mutex<BTreeMap<&str, &[&str]>> = Mutex::new(BTreeMap::new());
22
23static FEATURES: OnceLock<Vec<&'static str>> = OnceLock::new();
26
27pub fn features() -> &'static Vec<&'static str> { FEATURES.get_or_init(init_features) }
29
30#[inline]
32#[must_use]
33pub fn version() -> Option<&'static str> {
34 RUSTC_VERSION
35 .len()
36 .gt(&0)
37 .then_some(RUSTC_VERSION)
38}
39
40fn init_features() -> Vec<&'static str> {
41 let mut features = Vec::new();
42 FLAGS
43 .lock()
44 .expect("locked")
45 .iter()
46 .for_each(|(_, flags)| append_features(&mut features, flags));
47
48 features.sort_unstable();
49 features.dedup();
50 features
51}
52
53fn append_features(features: &mut Vec<&'static str>, flags: &[&'static str]) {
54 let mut next_is_cfg = false;
55 for flag in flags {
56 let is_cfg = *flag == "--cfg";
57 let is_feature = flag.starts_with("feature=");
58 if replace(&mut next_is_cfg, is_cfg)
59 && is_feature
60 && let Some(feature) = flag
61 .split_once('=')
62 .map(|(_, feature)| feature.trim_matches('"'))
63 {
64 features.push(feature);
65 }
66 }
67}