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 a0e2eb496e425865322875462c4cd8be5b31c0c5
parent fc7ec7a5988530b59b03d018cd2761612d651c47
Author: Yuval Langer <yuval.langer@gmail.com>
Date:   Wed,  6 Nov 2024 17:45:47 +0200

Fix significance order and some typing.  Add comments.

Diffstat:
MCargo.lock | 70++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Msrc/main.rs | 119++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
2 files changed, 119 insertions(+), 70 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -3,6 +3,12 @@ version = 3 [[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -36,9 +42,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -47,30 +53,33 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.137" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "ppv-lite86" -version = "0.2.16" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.21" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -107,18 +116,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.147" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" +checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.147" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" +checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", @@ -127,9 +136,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.103" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -138,18 +147,39 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.5" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/src/main.rs b/src/main.rs @@ -78,37 +78,50 @@ fn print_words( println!(); } -struct ReadWords<'a, T: std::iter::Iterator> { - bytes_iter: &'a mut std::iter::Peekable<T>, - wordlist: &'a Vec<&'a str> -} - -impl<'a, T: std::iter::Iterator> ReadWords<'a, T> { - fn new( - bytes_iter: &'a mut std::iter::Peekable<T>, - wordlist: &'a Vec<&'a str> - ) -> ReadWords<'a, T> { - ReadWords { - bytes_iter, - wordlist, - } - } -} - -impl<'a, T: std::iter::Iterator<Item = Result<u8, std::io::Error>> + std::fmt::Display> Iterator for ReadWords<'a, T> { - type Item = String; - - fn next(&mut self) -> Option<<Self as Iterator>::Item> { - return read_single_word::<T, T>(self.bytes_iter, self.wordlist); - } -} - -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>) -> Option<String> { +// struct ReadWords<'a, T: std::iter::Iterator> { +// bytes_iter: &'a mut std::io::Bytes<T>, +// wordlist: &'a Vec<&'a str> +// } + +// impl<'a, T: std::iter::Iterator> ReadWords<'a, T> { +// fn new( +// bytes_iter: &'a mut std::io::Bytes<T>, +// wordlist: &'a Vec<&'a str> +// ) -> ReadWords<'a, T> { +// ReadWords { +// bytes_iter, +// wordlist, +// } +// } +// } + +// impl<'a, T: std::iter::Iterator<Item = Result<u8, std::io::Error>> + std::fmt::Display + std::io::Read> Iterator for ReadWords<'a, T> { +// type Item = String; + +// fn next(&mut self) -> Option<<Self as Iterator>::Item> { +// return read_single_word::<T, T>(self.bytes_iter, self.wordlist); +// } +// } + +fn read_single_word<T>( + bytes_iter: &mut std::io::Bytes<T>, + wordlist: &Vec<&str>, +) -> Option<String> where T: std::io::Read { let die_cast_per_word = die_cast_per_word(wordlist.len()); let mut word_index = 0; - for die_significance in 0..=die_cast_per_word { - if die_significance == die_cast_per_word { + for die_index in 0..=die_cast_per_word { + // for die_cast_per_word == 5 we have: + // + // die_significance = die_cast_per_word - die_index + // 5 = 5 - 0 : just starting, may be an EOF, so next() == None and we then return None + // 4 = 5 - 1 . + // 3 = 5 - 2 . + // 2 = 5 - 3 . + // 1 = 5 - 4 . + // 0 = 5 - 5 : should be an end of line byte. + + if die_index == die_cast_per_word { let current_byte_result = match bytes_iter.next() { Some(x) => x, None => { @@ -138,26 +151,27 @@ fn read_single_word<T: std::iter::Iterator<Item = Result<u8, std::io::Error>>, U } }; } else { - if die_significance == 0 { - match bytes_iter.peek() { - None => return None, - Some(_) => {}, - } - } let current_byte_result = match bytes_iter.next() { Some(x) => { x }, None => { - eprintln!("Bad number of rolls. Each word must have exactly {} die rolls.", - die_cast_per_word); - exit(-1); + if die_index == 0 { + // We are at a legal EOF state, right before a single word die casting sequence. + return None; + } else { + // We are in the middle of die casting and somehow stdin ended. + eprintln!("Bad number of rolls. Each word must have exactly {} die rolls.", + die_cast_per_word); + exit(-1); + } }, }; + let die_significance = die_cast_per_word - die_index - 1; word_index += match current_byte_result { - Ok(b'1') => 0 * 6_usize.pow(die_significance), - Ok(b'2') => 1 * 6_usize.pow(die_significance), + Ok(b'1') => 0, + Ok(b'2') => 6_usize.pow(die_significance), Ok(b'3') => 2 * 6_usize.pow(die_significance), Ok(b'4') => 3 * 6_usize.pow(die_significance), Ok(b'5') => 4 * 6_usize.pow(die_significance), @@ -182,21 +196,18 @@ fn read_single_word<T: std::iter::Iterator<Item = Result<u8, std::io::Error>>, U return Some(wordlist[word_index].to_string()); } -fn read_words_from_rolls<U: std::fmt::Display + ?Sized>(wordlist: &Vec<&str>) -> Vec<String> { +fn read_words_from_rolls( + wordlist: &Vec<&str>, +) -> Vec<String> { let stdin = std::io::stdin(); let mut words = Vec::new(); - let mut bytes_iter = stdin.bytes().peekable(); + let mut bytes_iter = stdin.bytes(); loop { - match read_single_word::<std::io::Bytes<std::io::Stdin>, U>(&mut bytes_iter, wordlist) { + match read_single_word(&mut bytes_iter, wordlist) { Some(word) => words.push(word), None => break, }; - - match bytes_iter.peek() { - None => break, - Some(_) => continue, - } }; // TODO: Maybe use an iterator? @@ -305,7 +316,7 @@ fn main() { }; let words = if is_physical_rolls { - read_words_from_rolls::<dyn std::fmt::Display>(&wordlist) + read_words_from_rolls(&wordlist) } else if word_num != 0 { let mut rng = thread_rng(); read_rng_rolls(&mut rng, &wordlist, word_num) @@ -331,7 +342,15 @@ mod tests { 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()); + let mut reader = std::io::BufReader::with_capacity(input.len(), input).bytes(); + assert_eq!("abacus", read_single_word(&mut reader, &wordlist).unwrap()); } + + // #[test] + // fn test_read_words_from_rolls() { + // let wordlist = Wordlist::default().get_list().to_vec(); + // let input = &b"11111\n11111\n"[..]; + // let mut reader = std::io::BufReader::with_capacity(input.len(), input).bytes(); + // assert_eq!("abacus", read_words_from_rolls::<std::io::Bytes<std::io::BufReader<&[u8]>>, u8>(reader, &wordlist).unwrap()); + // } }