nicknamer 0.1.0

A tool for generating alternate names.
Documentation
use std::collections::{HashMap, HashSet};
use std::env;
use std::fs;
use std::io::{BufRead, BufReader, Write};
use std::path::Path;

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("generated.rs");
    let csv_path = Path::new("names.csv");
    let file = fs::File::open(csv_path).expect("names.csv not found");
    let reader = BufReader::new(file);

    let mut adj: HashMap<String, HashSet<String>> = HashMap::new();
    for (idx, line) in reader.lines().enumerate() {
        let line = line.expect("read line");
        if idx == 0 { continue; } // skip header
        let mut parts = line.splitn(3, ',');
        let a = match parts.next() { Some(s) => s.trim(), None => continue };
        let rel = match parts.next() { Some(s) => s.trim(), None => continue };
        let b = match parts.next() { Some(s) => s.trim(), None => continue };
        if rel != "has_nickname" || a.is_empty() || b.is_empty() { continue; }
        let an = a.to_lowercase();
        let bn = b.to_lowercase();
        if an.is_empty() || bn.is_empty() { continue; }
        adj.entry(an.clone()).or_default().insert(bn.clone());
        adj.entry(bn.clone()).or_default().insert(an.clone());
    }

    let mut out = fs::File::create(&dest_path).unwrap();
    writeln!(out, "// This file is @generated by build.rs. Do not edit manually.").unwrap();
    writeln!(out, "use std::collections::HashMap;").unwrap();
    writeln!(out, "pub fn nickname_map() -> HashMap<&'static str, &'static [&'static str]> {{").unwrap();
    writeln!(out, "    let mut m = HashMap::new();").unwrap();
    for (k, v) in &adj {
        let mut vs: Vec<_> = v.iter().collect();
        vs.sort();
        let vals = vs.iter().map(|s| format!("\"{}\"", s)).collect::<Vec<_>>().join(", ");
        writeln!(out, "    m.insert(\"{}\", &[{}][..]);", k, vals).unwrap();
    }
    writeln!(out, "    m").unwrap();
    writeln!(out, "}}").unwrap();
}