diceware_wordlists 1.2.3

Wordlists for the command line tool Rusty Diceware
Documentation
use std::env;
use std::fmt::Write as OtherWrite;
use std::fs::File;
use std::io::Read;
use std::io::Write;
use std::path::Path;
use std::string::String;

fn make_diceware_wordlist(array_name: String) -> impl Fn(&str) -> String {
    move |contents: &str| {
        // 7776 words = 6*6*6*6*6; five 6 faced dice throws.
        format!("pub static {}: [&str; 7776] = [\n", array_name)
            + &contents
                .split('\n')
                .skip(2)
                .take(6 * 6 * 6 * 6 * 6)
                .map(|s| s.split_once('\t').unwrap().1)
                .map(|s| {
                    s.chars()
                        .map(|c| {
                            if c == '"' {
                                "\\\"".to_owned()
                            } else {
                                c.to_string()
                            }
                        })
                        .collect::<String>()
                })
                .fold(String::new(), |mut output, s| {
                    writeln!(output, "    \"{}\",", s).unwrap();
                    output
                })
            + "];\n\n"
    }
}

fn make_minilock_wordlist(contents: &str) -> std::string::String {
    // 58110 words in the MiniLock wordlist.
    "pub static MINILOCK_WORDLIST: [&str; 58110] = [\n".to_owned()
        + &contents[1023..543718]
            .split(',')
            .fold(String::new(), |mut output, s| {
                writeln!(output, "    \"{}\",\n", s).unwrap();
                output
            })
        + "];\n"
}

fn make_eff_long_wordlist(contents: &str) -> String {
    // 7776 words = 6*6*6*6*6; five 6 faced dice throws.
    "pub static EFF_LONG_WORDLIST: [&str; 7776] = [\n".to_owned()
        + &contents
            .split('\n')
            .take(6 * 6 * 6 * 6 * 6)
            .map(|x| x.split('\t').nth(1).unwrap())
            .fold(String::new(), |mut output, s| {
                writeln!(output, "    \"{}\",", s).unwrap();
                output
            })
        + "];\n"
}

fn make_eff_short_wordlist(array_name: String) -> impl Fn(&str) -> String {
    move |contents: &str| {
        // 1296 words = 6*6*6*6; five 6 faced dice throws.
        format!("pub static {}: [&str; 1296] = [\n", array_name)
            + &contents
                .split('\n')
                .take(6 * 6 * 6 * 6)
                .map(|x| x.split('\t').nth(1).unwrap())
                .fold(String::new(), |mut output, x| {
                    writeln!(output, "    \"{}\",", x).unwrap();
                    output
                })
            + "];\n"
    }
}

fn build_wordlist(
    wordlist_file_path: &str,
    destination_file: &mut File,
    make_wordlist: &dyn Fn(&str) -> String,
) {
    let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    println!("{}", manifest_dir);
    let wordlist_file_path = Path::new(&manifest_dir).join(wordlist_file_path);

    let mut wordlist_file = File::open(&wordlist_file_path).unwrap();

    let mut wordlist_string = String::new();

    wordlist_file.read_to_string(&mut wordlist_string).unwrap();

    destination_file
        .write_all(make_wordlist(&wordlist_string).as_bytes())
        .unwrap();
}

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let dest_path = Path::new(&out_dir).join("diceware.rs");
    let mut destination_file = File::create(&dest_path).unwrap();

    build_wordlist(
        "wordlists/beale.wordlist.asc",
        &mut destination_file,
        &make_diceware_wordlist("BEALE_WORDLIST".to_string()),
    );
    build_wordlist(
        "wordlists/diceware.wordlist.asc",
        &mut destination_file,
        &make_diceware_wordlist("REINHOLD_WORDLIST".to_string()),
    );
    build_wordlist(
        "wordlists/phrase.js",
        &mut destination_file,
        &make_minilock_wordlist,
    );
    build_wordlist(
        // They call it "EFF's Long Wordlist" on https://www.eff.org/dice, not "EFF's Large
        // Wordlist", although the file name is different, so I will call it "long" rather than
        // "large".
        "wordlists/www.eff.org/files/2016/07/18/eff_large_wordlist.txt",
        &mut destination_file,
        &make_eff_long_wordlist,
    );
    build_wordlist(
        "wordlists/www.eff.org/files/2016/09/08/eff_short_wordlist_1.txt",
        &mut destination_file,
        &make_eff_short_wordlist("EFF_SHORT_WORDLIST_1".to_string()),
    );
    build_wordlist(
        "wordlists/www.eff.org/files/2016/09/08/eff_short_wordlist_2_0.txt",
        &mut destination_file,
        &make_eff_short_wordlist("EFF_SHORT_WORDLIST_2_0".to_string()),
    );
}