First rough parsing of alias file to hashmap

This commit is contained in:
Gonne 2024-11-03 07:22:53 +01:00
parent 709cf20fa8
commit 184d8c543e
4 changed files with 90 additions and 0 deletions

4
.gitignore vendored
View file

@ -25,3 +25,7 @@ testdata/mathebau.aliases
# might contain private mailadresses as well # might contain private mailadresses as well
testdata/virt_aliases testdata/virt_aliases
# Added by cargo
/target

7
Cargo.lock generated Normal file
View file

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "alias_to_sieve"
version = "0.1.0"

10
Cargo.toml Normal file
View file

@ -0,0 +1,10 @@
[package]
name = "alias_to_sieve"
version = "0.1.0"
edition = "2021"
[dependencies]
[[bin]]
name = "alias_to_sieve"
path = "main.rs"

69
main.rs Normal file
View file

@ -0,0 +1,69 @@
use std::fs::File;
use std::io::{self, BufRead};
use std::path::Path;
use std::env;
use std::collections::HashMap;
fn main() {
let args: Vec<String> = env::args().collect();
let file_path = &args[1];
// File must exist in the current path
if let Ok(lines) = read_lines(file_path) {
// Consumes the iterator, returns an (Optional) String
let mut redirect_map : HashMap<String, Vec<String>> = HashMap::new();
let mut destinations : Vec<String> = Vec::new();
for line in lines.flatten() {
let line = String::from(line.split_at(line.find("#").unwrap_or(line.len())).0);
let destination = line.split_at(line.find(char::is_whitespace).unwrap_or(0)).0;
if destination == "" {
continue;
}
let redirects: Vec<String> = line.split_at(line.find(char::is_whitespace).unwrap_or(0)).1.split(", ")
.map(|address| to_mailaddress(address)).collect();
if redirects.len() == 0 {
continue;
}
destinations.push(to_mailaddress(destination));
redirect_map.insert(to_mailaddress(destination), redirects);
}
let mut changed = true;
while changed {
changed = false;
let mut all_new_redirects : HashMap<String, Vec<String>> = HashMap::new();
for destination in destinations.iter() {
for forward_to in redirect_map.get(destination).unwrap().iter() {
if let Some(new_redirects) = redirect_map.get(forward_to) {
changed = true;
all_new_redirects.entry(destination.clone()).or_insert(redirect_map.get(destination).unwrap().clone())
.retain(|dest| *dest != *forward_to);
all_new_redirects.entry(destination.clone()).and_modify(|d| d.extend(new_redirects.iter().map(|x| x.clone())));
}
}
}
for (destination, new_redirect) in all_new_redirects {
*redirect_map.get_mut(&destination).unwrap() = new_redirect;
}
}
println!("{:#?}", redirect_map);
}
}
fn to_mailaddress(local_part: &str) -> String {
let local_part = local_part.trim();
if local_part.contains("@") {
return String::from(local_part);
}
return local_part.to_string() + "@mathebau.de";
}
// The output is wrapped in a Result to allow matching on errors.
// Returns an Iterator to the Reader of the lines of the file.
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
where P: AsRef<Path>, {
let file = File::open(filename)?;
Ok(io::BufReader::new(file).lines())
}