Add some type safety
This commit is contained in:
parent
eef3728818
commit
bbd936cf88
5 changed files with 336 additions and 21 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -22,11 +22,11 @@ target/
|
|||
|
||||
# Testdata with private mailadresses
|
||||
testdata/mathebau.aliases
|
||||
testdata/koma.aliases
|
||||
|
||||
# might contain private mailadresses as well
|
||||
testdata/virt_aliases
|
||||
|
||||
|
||||
# Added by cargo
|
||||
/target
|
||||
|
||||
|
|
310
Cargo.lock
generated
310
Cargo.lock
generated
|
@ -5,3 +5,313 @@ version = 3
|
|||
[[package]]
|
||||
name = "alias_to_sieve"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"email-address-parser",
|
||||
"fqdn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "console_error_panic_hook"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "email-address-parser"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fe19a4967eca30062be4abaf813d929ba48b3bfb21830367f7e1baae37f213a"
|
||||
dependencies = [
|
||||
"console_error_panic_hook",
|
||||
"pest",
|
||||
"pest_derive",
|
||||
"quick-xml",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fqdn"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28d649848b92394c9e1357f6574e48ba9b073a20ceac342f7fbfd0ab5f12524d"
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.164"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.20.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "2.7.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"thiserror",
|
||||
"ucd-trie",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_derive"
|
||||
version = "2.7.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_generator"
|
||||
version = "2.7.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_meta"
|
||||
version = "2.7.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"pest",
|
||||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.18.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3cc440ee4802a86e357165021e3e255a9143724da31db1e2ea540214c96a0f82"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||
|
||||
[[package]]
|
||||
name = "ucd-trie"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"
|
||||
|
|
|
@ -4,3 +4,7 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
|
||||
rust-version = "1.68.2"
|
||||
|
||||
[dependencies]
|
||||
fqdn = {version = "0.4.2", features = ["domain-label-length-limited-to-63", "domain-name-without-special-chars"]}
|
||||
email-address-parser = "2.0.0"
|
|
@ -74,11 +74,11 @@
|
|||
"nixpkgs": "nixpkgs_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1732242723,
|
||||
"narHash": "sha256-NWI8csIK0ujFlFuEXKnoc+7hWoCiEtINK9r48LUUMeU=",
|
||||
"lastModified": 1732328983,
|
||||
"narHash": "sha256-RHt12f/slrzDpSL7SSkydh8wUE4Nr4r23HlpWywed9E=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "a229311fcb45b88a95fdfa5cecd8349c809a272a",
|
||||
"rev": "ed8aa5b64f7d36d9338eb1d0a3bb60cf52069a72",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
33
src/main.rs
33
src/main.rs
|
@ -1,15 +1,19 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::{self, BufRead};
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
use fqdn::*;
|
||||
use email_address_parser::EmailAddress;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct AliasFile {
|
||||
content: io::Lines<io::BufReader<File>>,
|
||||
default_domain: String,
|
||||
default_domain: FQDN,
|
||||
}
|
||||
|
||||
type AliasMap = HashMap<EmailAddress, Vec<EmailAddress>>;
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
|
@ -20,7 +24,7 @@ fn main() {
|
|||
let mut alias_files : Vec<AliasFile> = Vec::new();
|
||||
for i in (1..args.len()).step_by(2) {
|
||||
if let Ok(lines) = read_lines(&args[i]) {
|
||||
alias_files.push(AliasFile{content: lines, default_domain: args[i+1].to_string()})
|
||||
alias_files.push(AliasFile{content: lines, default_domain: FQDN::from_str(&args[i+1]).unwrap()})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,13 +33,12 @@ fn main() {
|
|||
println!("{}", sieve_script);
|
||||
}
|
||||
|
||||
fn generate_sieve_script(redirects: BTreeMap<String, Vec<String>>) -> String {
|
||||
fn generate_sieve_script(redirects: AliasMap) -> String {
|
||||
let mut script : String = "require [\"envelope\", \"copy\"];\n\n".to_string();
|
||||
for (redirect, mut destinations) in redirects {
|
||||
for (redirect, destinations) in redirects {
|
||||
script += format!("if envelope :is \"to\" \"{}\" {{\n{}}}\n", redirect,
|
||||
{
|
||||
let mut subscript : String = "".to_string();
|
||||
destinations.sort();
|
||||
for destination in destinations.iter().rev().skip(1).rev() {
|
||||
subscript += format!(" redirect :copy \"{}\";\n", destination).as_str();
|
||||
}
|
||||
|
@ -46,10 +49,10 @@ fn generate_sieve_script(redirects: BTreeMap<String, Vec<String>>) -> String {
|
|||
script
|
||||
}
|
||||
|
||||
fn parse_alias_to_map(alias_files: Vec<AliasFile>) -> BTreeMap<String, Vec<String>> {
|
||||
fn parse_alias_to_map(alias_files: Vec<AliasFile>) -> AliasMap {
|
||||
// File must exist in the current path
|
||||
let mut redirect_map : BTreeMap<String, Vec<String>> = BTreeMap::new();
|
||||
let mut destinations : Vec<String> = Vec::new();
|
||||
let mut redirect_map : AliasMap = AliasMap::new();
|
||||
let mut destinations : Vec<EmailAddress> = Vec::new();
|
||||
for alias_file in alias_files.into_iter() {
|
||||
for line in alias_file.content {
|
||||
let line = line.unwrap();
|
||||
|
@ -58,7 +61,7 @@ fn parse_alias_to_map(alias_files: Vec<AliasFile>) -> BTreeMap<String, Vec<Strin
|
|||
if destination.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let redirects: Vec<String> = line.split_at(line.find(char::is_whitespace).unwrap_or(0)).1.split(" ")
|
||||
let redirects: Vec<EmailAddress> = line.split_at(line.find(char::is_whitespace).unwrap_or(0)).1.split(" ")
|
||||
.filter(|address| address.trim().to_string().replace(",","") != "").map(|addr| to_mailaddress(addr, &alias_file.default_domain)).collect();
|
||||
if redirects.is_empty() {
|
||||
continue;
|
||||
|
@ -70,7 +73,7 @@ fn parse_alias_to_map(alias_files: Vec<AliasFile>) -> BTreeMap<String, Vec<Strin
|
|||
let mut changed = true;
|
||||
while changed {
|
||||
changed = false;
|
||||
let mut all_new_redirects : BTreeMap<String, Vec<String>> = BTreeMap::new();
|
||||
let mut all_new_redirects : AliasMap = AliasMap::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) {
|
||||
|
@ -88,16 +91,15 @@ fn parse_alias_to_map(alias_files: Vec<AliasFile>) -> BTreeMap<String, Vec<Strin
|
|||
redirect_map
|
||||
}
|
||||
|
||||
fn to_mailaddress(local_part: &str, default_domain : &String) -> String {
|
||||
fn to_mailaddress(local_part: &str, default_domain : &FQDN) -> EmailAddress {
|
||||
let mut addr = local_part.trim().to_string();
|
||||
addr = addr.replace(",", "");
|
||||
if addr.contains("@") {
|
||||
return addr;
|
||||
return EmailAddress::parse(&addr, None).unwrap();
|
||||
}
|
||||
addr + "@" + default_domain
|
||||
EmailAddress::new(&addr, &default_domain.to_string(), None).unwrap()
|
||||
}
|
||||
|
||||
|
||||
// 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>>>
|
||||
|
@ -106,7 +108,6 @@ where P: AsRef<Path>, {
|
|||
Ok(io::BufReader::new(file).lines())
|
||||
}
|
||||
|
||||
|
||||
fn print_help(){
|
||||
print!("Reads a virtual alias file and needs a default domain to append to local paths, e.g.
|
||||
./alias_to_sieve example.com.txt example.com");
|
||||
|
|
Loading…
Reference in a new issue