rusty-diceware

Commandline diceware, with or without dice, written in Rustlang.
git clone https://kaka.farm/~git/rusty-diceware
Log | Files | Refs | README | LICENSE

commit 3b3649c7c38e680335af1f3f190bbdd309701b3f
parent 5e124728c690569cf45213179d8cdf6a29dd9890
Author: Yuval Langer <yuval.langer@gmail.com>
Date:   Mon,  4 Nov 2024 19:58:06 +0200

Add generic type definitions and a test.

Diffstat:
Msrc/main.rs | 43++++++++++++++++++++++---------------------
1 file changed, 22 insertions(+), 21 deletions(-)

diff --git a/src/main.rs b/src/main.rs @@ -27,7 +27,6 @@ use std::str::FromStr; use diceware_wordlists::Wordlist; use getopts::Options; -// use rand::prelude::SliceRandom; use rand::rngs::ThreadRng; use rand::thread_rng; use crate::rand::Rng; @@ -79,12 +78,10 @@ fn print_words( println!(); } -fn read_single_word(bytes_iter: &mut std::iter::Peekable<std::io::Bytes<std::io::Stdin>>, wordlist: &Vec<&str>) -> Option<String> { - eprintln!("##### wordlist length: {}", wordlist.len()); +fn read_single_word<T: std::iter::Iterator<Item = Result<u8, std::io::Error>>, U: std::fmt::Display + ?Sized>(bytes_iter: &mut std::iter::Peekable<T>, wordlist: &Vec<&str>) -> Result<String, Error> { let die_cast_per_word = die_cast_per_word(wordlist.len()); - eprintln!("##### die cast per word: {}", die_cast_per_word); let mut word_index = 0; - + for die_significance in 0..=die_cast_per_word { if die_significance == die_cast_per_word { let current_byte_result = match bytes_iter.next() { @@ -118,7 +115,6 @@ fn read_single_word(bytes_iter: &mut std::iter::Peekable<std::io::Bytes<std::io: } else { let current_byte_result = match bytes_iter.next() { Some(x) => { - eprintln!("##### {:?}", x); x }, None => { @@ -151,17 +147,17 @@ fn read_single_word(bytes_iter: &mut std::iter::Peekable<std::io::Bytes<std::io: }; }; }; - + return Some(wordlist[word_index].to_string()); } -fn read_words_from_rolls(wordlist: &Vec<&str>) -> Vec<String> { +fn read_words_from_rolls<U: std::fmt::Display + ?Sized>(wordlist: &Vec<&str>) -> Vec<String> { let stdin = std::io::stdin(); let mut words: Vec<String> = Vec::new(); let mut bytes_iter = stdin.bytes().peekable(); loop { - match read_single_word(&mut bytes_iter, wordlist) { + match read_single_word::<std::io::Bytes<std::io::Stdin>, U>(&mut bytes_iter, wordlist) { Some(word) => words.push(word), None => break, }; @@ -188,23 +184,18 @@ fn read_rng_rolls( wordlist: &Vec<&str>, word_num: u64, ) -> Vec<String> { - let die_cast_per_word = die_cast_per_word(wordlist.len()); - /* From base 6 conversion: (0..6).pow(1) = (0, 1, ..6) (0..6).pow(2) = (0, 6, ..36) (0..6).pow(3) = (0, 36, ..216) */ + return (0..word_num) .collect::<Vec<_>>() - .iter().map(|_| { - let current_word_index: usize = (0..die_cast_per_word).collect::<Vec<_>>() - .into_iter() - .map(|die_significance| (rng.gen_range(0..6_usize)) * ((6_usize).pow(die_significance))) - .sum(); - wordlist[current_word_index].to_string() - }).collect(); + .iter() + .map(|_| wordlist[rng.gen_range(0..wordlist.len())].to_string()) + .collect(); } fn load_wordlist_file(filepath: &str) -> String { @@ -265,7 +256,7 @@ fn main() { }; let wordlist_string; - + let wordlist = if let Some(wordlist_filepath) = matches.opt_str("f") { wordlist_string = load_wordlist_file(&wordlist_filepath); wordlist_string @@ -278,7 +269,7 @@ fn main() { }; let words = if is_physical_rolls { - read_words_from_rolls(&wordlist) + read_words_from_rolls::<dyn std::fmt::Display>(&wordlist) } else if word_num != 0 { let mut rng = thread_rng(); read_rng_rolls(&mut rng, &wordlist, word_num) @@ -290,7 +281,7 @@ fn main() { if words.len() > 0 { print_words(&words, delimiter); } - + if is_entropy_printed { println!("{}", entropyn(wordlist, words.len() as u64)); } @@ -300,9 +291,19 @@ fn main() { mod tests { use super::*; + /* #[test] fn test_rolls_to_word_index_01() { assert_eq!(0, rolls_to_word_index(3, &[1, 1, 1])); assert_eq!(1, rolls_to_word_index(3, &[1, 1, 2])); } + */ + + #[test] + fn test_read_single_word() { + let wordlist = Wordlist::default().get_list().to_vec(); + let input = &b"11111\n"[..]; + let mut reader = std::io::BufReader::with_capacity(input.len(), input).bytes().peekable(); + assert_eq!("abacus", read_single_word::<std::io::Bytes<std::io::BufReader<&[u8]>>, u8>(&mut reader, &wordlist).unwrap()); + } }