build.rs (4303B)
1 use std::env; 2 use std::fs::File; 3 use std::io::Read; 4 use std::io::Write; 5 use std::path::Path; 6 use std::string::String; 7 8 fn make_diceware_wordlist(array_name: String) -> impl Fn(&str) -> String { 9 move |contents: &str| { 10 // 7776 words = 6*6*6*6*6; five 6 faced dice throws. 11 format!("pub static {}: [&str; 7776] = [\n", array_name) 12 + &contents 13 .split('\n') 14 .skip(2) 15 .take(6 * 6 * 6 * 6 * 6) 16 .map(|s| s.split_once('\t').unwrap().1) 17 .map(|s| { 18 s.chars() 19 .map(|c| { 20 if c == '"' { 21 "\\\"".to_owned() 22 } else { 23 c.to_string() 24 } 25 }) 26 .collect::<String>() 27 }) 28 .map(|s| format!(" \"{}\",\n", s)) 29 .collect::<String>() 30 + "];\n\n" 31 } 32 } 33 34 fn make_minilock_wordlist(contents: &str) -> std::string::String { 35 // 58110 words in the MiniLock wordlist. 36 "pub static MINILOCK_WORDLIST: [&str; 58110] = [\n".to_owned() 37 + &contents[1023..543718] 38 .split(',') 39 .map(|x| format!(" \"{}\",\n", x)) 40 .collect::<String>() 41 + "];\n" 42 } 43 44 fn make_eff_long_wordlist(contents: &str) -> String { 45 // 7776 words = 6*6*6*6*6; five 6 faced dice throws. 46 "pub static EFF_LONG_WORDLIST: [&str; 7776] = [\n".to_owned() 47 + &contents 48 .split('\n') 49 .take(6 * 6 * 6 * 6 * 6) 50 .map(|x| x.split('\t').nth(1).unwrap()) 51 .map(|x| format!(" \"{}\",\n", x)) 52 .collect::<String>() 53 + "];\n" 54 } 55 56 fn make_eff_short_wordlist(array_name: String) -> impl Fn(&str) -> String { 57 move |contents: &str| { 58 // 1296 words = 6*6*6*6; five 6 faced dice throws. 59 format!("pub static {}: [&str; 1296] = [\n", array_name) 60 + &contents 61 .split('\n') 62 .take(6 * 6 * 6 * 6) 63 .map(|x| x.split('\t').nth(1).unwrap()) 64 .map(|x| format!(" \"{}\",\n", x)) 65 .collect::<String>() 66 + "];\n" 67 } 68 } 69 70 fn build_wordlist( 71 wordlist_file_path: &str, 72 destination_file: &mut File, 73 make_wordlist: &dyn Fn(&str) -> String, 74 ) { 75 let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); 76 println!("{}", manifest_dir); 77 let wordlist_file_path = Path::new(&manifest_dir).join(wordlist_file_path); 78 79 let mut wordlist_file = File::open(&wordlist_file_path).unwrap(); 80 81 let mut wordlist_string = String::new(); 82 83 wordlist_file.read_to_string(&mut wordlist_string).unwrap(); 84 85 destination_file 86 .write_all(make_wordlist(&wordlist_string).as_bytes()) 87 .unwrap(); 88 } 89 90 fn main() { 91 let out_dir = env::var("OUT_DIR").unwrap(); 92 let dest_path = Path::new(&out_dir).join("diceware.rs"); 93 let mut destination_file = File::create(&dest_path).unwrap(); 94 95 build_wordlist( 96 "wordlists/beale.wordlist.asc", 97 &mut destination_file, 98 &make_diceware_wordlist("BEALE_WORDLIST".to_string()), 99 ); 100 build_wordlist( 101 "wordlists/diceware.wordlist.asc", 102 &mut destination_file, 103 &make_diceware_wordlist("REINHOLD_WORDLIST".to_string()), 104 ); 105 build_wordlist( 106 "wordlists/phrase.js", 107 &mut destination_file, 108 &make_minilock_wordlist, 109 ); 110 build_wordlist( 111 // They call it "EFF's Long Wordlist" on https://www.eff.org/dice, not "EFF's Large 112 // Wordlist", although the file name is different, so I will call it "long" rather than 113 // "large". 114 "wordlists/www.eff.org/files/2016/07/18/eff_large_wordlist.txt", 115 &mut destination_file, 116 &make_eff_long_wordlist, 117 ); 118 build_wordlist( 119 "wordlists/www.eff.org/files/2016/09/08/eff_short_wordlist_1.txt", 120 &mut destination_file, 121 &make_eff_short_wordlist("EFF_SHORT_WORDLIST_1".to_string()), 122 ); 123 build_wordlist( 124 "wordlists/www.eff.org/files/2016/09/08/eff_short_wordlist_2_0.txt", 125 &mut destination_file, 126 &make_eff_short_wordlist("EFF_SHORT_WORDLIST_2_0".to_string()), 127 ); 128 }