From 184d8c543e120885f028ead6013d7dfb41a3b3d2 Mon Sep 17 00:00:00 2001 From: Gonne Date: Sun, 3 Nov 2024 07:22:53 +0100 Subject: [PATCH] First rough parsing of alias file to hashmap --- .gitignore | 4 ++++ Cargo.lock | 7 ++++++ Cargo.toml | 10 ++++++++ main.rs | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+) create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 main.rs diff --git a/.gitignore b/.gitignore index 56c8728..fcac908 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,7 @@ testdata/mathebau.aliases # might contain private mailadresses as well testdata/virt_aliases + + +# Added by cargo +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..2c0fdae --- /dev/null +++ b/Cargo.lock @@ -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" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..b1cbd25 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "alias_to_sieve" +version = "0.1.0" +edition = "2021" + +[dependencies] + +[[bin]] +name = "alias_to_sieve" +path = "main.rs" diff --git a/main.rs b/main.rs new file mode 100644 index 0000000..f4279ee --- /dev/null +++ b/main.rs @@ -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 = 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> = HashMap::new(); + let mut destinations : Vec = 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 = 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> = 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

(filename: P) -> io::Result>> +where P: AsRef, { + let file = File::open(filename)?; + Ok(io::BufReader::new(file).lines()) +} \ No newline at end of file