mod matcher;
pub use matcher::*;
use thiserror::Error;
pub fn fizzbuzz(from: usize, to: usize, matchers: &Vec<Matcher>) -> Result<(), FizzBuzzError> {
if from > to {
return Err(FizzBuzzError::FromBiggerThanTo { from, to });
}
for i in from..(to + 1) {
println!("{}", line(i, matchers));
}
Ok(())
}
pub fn line(number: usize, matchers: &Vec<Matcher>) -> String {
let mut out = String::new();
for m in matchers.iter() {
out += m.text(number);
}
if out.is_empty() {
out += &number.to_string();
}
out
}
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum FizzBuzzError {
#[error("`from` value ({from}) is bigger than `to` value({to})")]
FromBiggerThanTo { from: usize, to: usize },
}
#[cfg(test)]
mod tests {
use super::*;
use rand::random;
#[test]
fn line_normal() {
let text1 = "Fizz";
let text2 = "Buzz";
let mut number1: u8 = 0;
let mut number2 = 0;
while number1 == 0 || number1 == 1 || number1 >= (u8::MAX / 2) {
number1 = random();
}
while number2 < number1 || number2 % number1 == 0 {
number2 = random();
}
let number1 = number1.into();
let number2 = number2.into();
let matchers = vec![
Matcher::new(number1, text1).unwrap(),
Matcher::new(number2, text2).unwrap(),
];
assert_eq!(line(1, &matchers), "1");
assert_eq!(line(number1, &matchers), text1.to_string());
assert_eq!(line(number2, &matchers), text2.to_string());
assert_eq!(
line(number1 * number2, &matchers),
format!("{}{}", text1, text2)
);
assert_eq!(
line((number1 * number2) + 1, &matchers),
((number1 * number2) + 1).to_string()
);
}
#[test]
fn line_one() {
let text1 = "Fizz";
let text2 = "Buzz";
let number1 = 1;
let mut number2: u8 = 0;
while number2 < number1 {
number2 = random();
}
let number1 = number1.into();
let number2 = number2.into();
let matchers = vec![
Matcher::new(number1, text1).unwrap(),
Matcher::new(number2, text2).unwrap(),
];
assert_eq!(line(1, &matchers), text1.to_string());
assert_eq!(line(number2, &matchers), format!("{}{}", text1, text2));
assert_eq!(line((number1 * number2) + 1, &matchers), text1.to_string());
}
}