use log::error; use std::collections::BTreeSet as Set; use std::sync::LazyLock; static CMDLINE: LazyLock = LazyLock::new(|| { std::fs::read("/proc/cmdline") .map(|c| String::from_utf8_lossy(&c).to_string()) .unwrap_or_default() }); pub fn param<'t>(name: &'t str, default: &'t str) -> &'t str { let prefix1 = &format!("dkl.{name}="); let prefix2 = &format!("direktil.{name}="); CMDLINE .split_ascii_whitespace() .find_map(|part| { part.strip_prefix(prefix1) .or_else(|| part.strip_prefix(prefix2)) }) .unwrap_or(default) } pub struct NameAliases { name: String, aliases: Set, } impl NameAliases { pub fn new(name: String) -> Self { Self { name, aliases: Set::new(), } } pub fn name(&self) -> &str { self.name.as_str() } pub fn aliases(&self) -> impl Iterator { self.aliases.iter().map(|s| s.as_str()) } pub fn iter(&self) -> impl Iterator { std::iter::once(self.name()).chain(self.aliases()) } pub fn push(&mut self, alias: String) { if self.name == alias { return; } self.aliases.insert(alias); } } pub fn select_n_by_regex<'t>( n: i16, regexs: &Vec, nas: impl Iterator, ) -> Vec { // compile regexs let regexs: Vec<_> = (regexs.iter()) .filter_map(|re| { regex::Regex::new(re) .inspect_err(|e| error!("invalid regex ignored: {re:?}: {e}")) .ok() }) .collect(); let matching = |name| regexs.iter().any(|re| re.is_match(name)); let nas = nas .filter(|na| na.iter().any(matching)) .map(|na| na.name().to_string()); if n == -1 { nas.collect() } else { nas.take(n as usize).collect() } }