xkcd-password 0.1.1

Generate passwords
Documentation
use std::fs;
use std::env;
use std::collections::HashSet;

fn convert(filename: &str) {
    println!("Processing: dictionary/{}", filename);
    let out_dir = env::var("OUT_DIR").unwrap();
    let in_data = fs::read_to_string(format!("dictionary/{}", filename)).expect("Failed to read dictionary");
    let mut out_dict: Vec<HashSet<&str>> = Vec::new();
    for line in in_data.lines() {
        for (pos, line_part) in line.split_whitespace().enumerate() {
            if line_part.is_empty() || line_part.starts_with('#') {
                break;
            }
            if pos != 0 {
                panic!("More than one word per line");
            }
            if out_dict.len() < line_part.len() {
                let count = line_part.len() - out_dict.len();
                out_dict.reserve(count);
                while out_dict.len() < line_part.len() {
                    out_dict.push(HashSet::default());
                }
            }
            if !out_dict[line_part.len() - 1].insert(line_part) {
                panic!("Duplicate word {}", line_part);
            }
        }
    }
    let out_data: String = out_dict.into_iter().flat_map(|x| x.into_iter().chain(std::iter::once("\n"))).collect();
    fs::write(format!("{}/dictionary/{}", out_dir, filename), out_data).expect("Failed to write converted dictionary");
}

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    fs::create_dir_all(format!("{}/dictionary/", out_dir)).expect("failed to create dictionary output dir");
    convert("en_US");
}