rusty-diceware

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit aa03cb6dfc0299e75ee223137786234784e70ec3
parent e7a5f63a2da5414958e8d0cc03dee483e22639b7
Author: Yuval Langer <yuvallangerontheroad@gmail.com>
Date:   Tue,  6 Sep 2022 22:57:45 +0000

Merge branch 'feature/macros' into 'master'

Implement generators using a macro

See merge request yuvallanger/rusty-diceware!3
Diffstat:
Msrc/lib.rs | 121++++++++++++++++++++++---------------------------------------------------------
Mtests/tests.rs | 78+++++++++++++++++++++++++++++++++---------------------------------------------
2 files changed, 66 insertions(+), 133 deletions(-)

diff --git a/src/lib.rs b/src/lib.rs @@ -3,19 +3,9 @@ extern crate rand; use rand::rngs::ThreadRng; use rand::seq::SliceRandom; use rand::Rng; -use std::fmt; include!(concat!(env!("OUT_DIR"), "/diceware.rs")); -#[derive(Debug, Clone, Eq, PartialEq, Copy)] -pub struct BealeWord(&'static str); - -#[derive(Debug, Clone, Eq, PartialEq, Copy)] -pub struct ReinholdWord(&'static str); - -#[derive(Debug, Clone, Eq, PartialEq, Copy)] -pub struct MiniLockWord(&'static str); - pub trait Word { fn new(word: &'static str) -> Self; @@ -26,86 +16,41 @@ pub trait Word { } } -impl Word for BealeWord { - fn new(word: &'static str) -> Self { - Self(word) - } - - fn entropy() -> f64 { - (BEALE_WORDLIST.len() as f64).log2() - } - - fn entropyn(n: u64) -> f64 { - Self::entropy() * (n as f64) - } +macro_rules! create_generator { + ( $gen_name:ident, $wordlist: expr ) => { + #[derive(Debug, Clone, Eq, PartialEq, Copy)] + pub struct $gen_name(&'static str); + impl Word for $gen_name { + fn new(word: &'static str) -> Self { + $gen_name(word) + } + + fn entropy() -> f64 { + ($wordlist.len() as f64).log2() + } + + fn entropyn(n: u64) -> f64 { + Self::entropy() * (n as f64) + } + } + + impl std::fmt::Display for $gen_name { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.0) + } + } + + impl rand::distributions::Distribution<$gen_name> for rand::distributions::Standard { + fn sample<R: rand::Rng + ?Sized>(&self, mut rng: &mut R) -> $gen_name { + *$wordlist.choose(&mut rng).unwrap() + } + } + }; } -impl Word for ReinholdWord { - fn new(word: &'static str) -> Self { - Self(word) - } - - fn entropy() -> f64 { - (REINHOLD_WORDLIST.len() as f64).log2() - } - - fn entropyn(n: u64) -> f64 { - Self::entropy() * (n as f64) - } -} - -impl Word for MiniLockWord { - fn new(word: &'static str) -> Self { - Self(word) - } - - fn entropy() -> f64 { - (MINILOCK_WORDLIST.len() as f64).log2() - } - - fn entropyn(n: u64) -> f64 { - Self::entropy() * (n as f64) - } -} - -impl rand::distributions::Distribution<BealeWord> for rand::distributions::Standard { - fn sample<R: rand::Rng + ?Sized>(&self, mut rng: &mut R) -> BealeWord { - *BEALE_WORDLIST.choose(&mut rng).unwrap() - } -} - -impl fmt::Display for BealeWord { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let Self(w) = self; - write!(f, "{}", w) - } -} - -impl rand::distributions::Distribution<ReinholdWord> for rand::distributions::Standard { - fn sample<R: rand::Rng + ?Sized>(&self, mut rng: &mut R) -> ReinholdWord { - *REINHOLD_WORDLIST.choose(&mut rng).unwrap() - } -} - -impl fmt::Display for ReinholdWord { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let Self(w) = self; - write!(f, "{}", w) - } -} - -impl rand::distributions::Distribution<MiniLockWord> for rand::distributions::Standard { - fn sample<R: rand::Rng + ?Sized>(&self, mut rng: &mut R) -> MiniLockWord { - *MINILOCK_WORDLIST.choose(&mut rng).unwrap() - } -} - -impl fmt::Display for MiniLockWord { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let Self(w) = self; - write!(f, "{}", w) - } -} +create_generator!(BealeWord, BEALE_WORDLIST); +create_generator!(ReinholdWord, REINHOLD_WORDLIST); +create_generator!(MiniLockWord, MINILOCK_WORDLIST); pub fn print_words<T: Word + std::fmt::Display>( word_num: &u64, diff --git a/tests/tests.rs b/tests/tests.rs @@ -8,50 +8,38 @@ use diceware::BealeWord; use diceware::ReinholdWord; use diceware::Word; -fn make_beale_vector() -> Vec<BealeWord> { - let seed: [u8; 32] = [0; 32]; - let mut rng: StdRng = SeedableRng::from_seed(seed); - - let mut beale_vector: Vec<BealeWord> = vec![]; - for _ in 0..4 { - let word: BealeWord = rng.gen(); - beale_vector.push(word); - } - beale_vector +macro_rules! create_test { + ( $gen_name: ident, $test_name: ident, $expected: expr ) => { + #[test] + fn $test_name() { + fn make_vektor() -> Vec<$gen_name> { + let seed: [u8; 32] = [0; 32]; + let mut rng: StdRng = SeedableRng::from_seed(seed); + + let mut vector: Vec<$gen_name> = vec![]; + for _ in 0..4 { + let word: $gen_name = rng.gen(); + vector.push(word); + } + vector + } + let wanted: Vec<$gen_name> = $expected.into_iter().map($gen_name::new).collect(); + + let got = make_vektor(); + + assert_eq!(got, wanted); + } + }; } -fn make_reinhold_vector() -> Vec<ReinholdWord> { - let seed: [u8; 32] = [0; 32]; - let mut rng: StdRng = SeedableRng::from_seed(seed); - - let mut reinhold_vector: Vec<ReinholdWord> = vec![]; - for _ in 0..4 { - let word: ReinholdWord = rng.gen(); - reinhold_vector.push(word); - } - reinhold_vector -} - -#[test] -fn beale_rng_test() { - let wanted: Vec<BealeWord> = vec!["io", "gavel", "beam", "time"] - .into_iter() - .map(BealeWord::new) - .collect(); - - let got = make_beale_vector(); - - assert_eq!(got, wanted); -} - -#[test] -fn reinhold_rng_test() { - let wanted: Vec<ReinholdWord> = vec!["india", "gamma", "bcd", "theme"] - .into_iter() - .map(ReinholdWord::new) - .collect(); - - let got = make_reinhold_vector(); - - assert_eq!(got, wanted); -} +create_test!( + BealeWord, + beale_rng_test, + vec!["io", "gavel", "beam", "time"] +); + +create_test!( + ReinholdWord, + reinhold_rng_test, + vec!["india", "gamma", "bcd", "theme"] +);