use rand::Rng;
#[derive(Eq, Debug)]
pub struct Guess {
val: i32, }
pub mod err {
use std::fmt;
#[derive(Debug, Clone)]
pub struct GuessRangeError;
impl fmt::Display for GuessRangeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "The guess value was out of 0-100 range")
}
}
impl std::error::Error for GuessRangeError {}
}
impl Guess {
pub fn new(val: i32) -> Result<Guess, err::GuessRangeError> {
if val < 0 || val > 100 {
return Err(err::GuessRangeError);
}
Ok(Guess { val })
}
pub fn parse(val: &str) -> Result<Guess, Box<dyn std::error::Error>> {
let parsed: i32 = match val.trim().parse() {
Ok(val) => val,
Err(err) => return Err(err)?,
};
match Guess::new(parsed) {
Ok(val) => Ok(val),
Err(err) => Err(err)?
}
}
pub fn value(&self) -> &i32 {
&self.val
}
}
impl Ord for Guess {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.value().cmp(other.value())
}
}
impl PartialOrd for Guess {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for Guess {
fn eq(&self, other: &Self) -> bool {
self.value() == other.value()
}
}
pub fn gen_random() -> Guess {
Guess::new(rand::thread_rng().gen_range(0..101)).unwrap()
}
#[cfg(test)]
mod tests {
use super::*;
use std::cmp::Ordering;
#[test]
fn eq_test() {
let guess1 = Guess::new(13).unwrap();
let guess2 = Guess::new(13).unwrap();
assert_eq!(guess1, guess2);
}
#[test]
fn cmp_test() {
let guess1 = Guess::new(50).unwrap();
let guess2 = Guess::new(13).unwrap();
assert_eq!(guess1.cmp(&guess2), Ordering::Greater);
}
#[test]
fn parse_test() {
match Guess::parse("16") {
Ok(_) => (),
Err(err) => panic!("Should had no errors, got: {}", err),
}
match Guess::parse("val") {
Ok(_) => panic!("Should have panicked but didn't."),
Err(_) => (),
}
}
}