From da69086e9f17cded994222ba343e39b42775a6e9 Mon Sep 17 00:00:00 2001 From: Chirantan Ekbote Date: Tue, 23 Jun 2020 16:27:43 +0900 Subject: [PATCH] rand_ish: Generate random string from SimpleRng Devices may not have access to /dev/urandom so refactor the random string generation code so that it can also be used by SimpleRng. Also implement Iterator for SimpleRng to make the string generator implementation easier. BUG=b:152806644,b:159285544 TEST=unit tests Change-Id: I245c90dc44cfa53a7e12343925b1e04a5df55255 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2260252 Auto-Submit: Chirantan Ekbote Tested-by: kokoro Reviewed-by: Zach Reizner Reviewed-by: Stephen Barber Commit-Queue: Chirantan Ekbote --- rand_ish/src/lib.rs | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/rand_ish/src/lib.rs b/rand_ish/src/lib.rs index 84d1a16a29..c7b0ff4947 100644 --- a/rand_ish/src/lib.rs +++ b/rand_ish/src/lib.rs @@ -25,27 +25,37 @@ impl SimpleRng { self.seed = a.wrapping_mul(self.seed).wrapping_add(c); self.seed } + + /// Generate a random alphanumeric string. + pub fn str(&mut self, len: usize) -> String { + self.filter_map(|v| uniform_sample_ascii_alphanumeric(v as u8)) + .take(len) + .collect() + } +} + +impl Iterator for SimpleRng { + type Item = u64; + + fn next(&mut self) -> Option { + Some(self.rng()) + } } // Uniformly samples the ASCII alphanumeric characters given a random variable. If an `Err` is // passed in, the error is returned as `Some(Err(...))`. If the the random variable can not be used // to uniformly sample, `None` is returned. -fn uniform_sample_ascii_alphanumeric( - b: Result, -) -> Option> { +fn uniform_sample_ascii_alphanumeric(b: u8) -> Option { const ASCII_CHARS: &[u8] = b"\ ABCDEFGHIJKLMNOPQRSTUVWXYZ\ abcdefghijklmnopqrstuvwxyz\ 0123456789"; - let char_index = match b { - Ok(c) => c as usize, - Err(e) => return Some(Err(e)), - }; + let char_index = b as usize; // Throw away numbers that would cause sampling bias. if char_index >= ASCII_CHARS.len() * 4 { None } else { - Some(Ok(ASCII_CHARS[char_index % ASCII_CHARS.len()] as char)) + Some(ASCII_CHARS[char_index % ASCII_CHARS.len()] as char) } } @@ -53,7 +63,7 @@ fn uniform_sample_ascii_alphanumeric( pub fn urandom_str(len: usize) -> io::Result { File::open("/dev/urandom")? .bytes() - .filter_map(uniform_sample_ascii_alphanumeric) + .filter_map(|b| b.map(uniform_sample_ascii_alphanumeric).transpose()) .take(len) .collect::>() }