use anyhow::Result; use log::*; use std::collections::HashSet; #[derive(PartialEq, Eq, Hash)] pub enum Item { Ending(String), Exact(String), } pub enum List { Allow(HashSet), } impl List { pub async fn from_opt(list: &Vec) -> Result { let mut this = HashSet::new(); for i in list { for line in if i.contains("://") { reqwest::get(i).await?.text().await? } else { std::fs::read_to_string(i)? } .lines() { if line.starts_with("/") || line.starts_with("#") || line.is_empty() { continue; } if !this.insert(if let Some(item) = line.strip_prefix(".") { debug!("Add `{line}` to the whitelist"); Item::Ending(item.to_string()) } else { debug!("Add `{line}` exact match to the whitelist"); Item::Exact(line.to_string()) }) { warn!("Duplicated whitelist record: `{line}`") } } } info!("Total whitelist entries parsed: {}", this.len()); Ok(Self::Allow(this)) } pub fn has(&self, value: &str) -> bool { match self { Self::Allow(list) => list.iter().any(|item| match item { Item::Exact(s) => s == value, Item::Ending(s) => value.ends_with(s), }), } } pub fn entries(&self) -> usize { match self { Self::Allow(list) => list.len(), } } }