86dccc4ca7
a description starts with the filename, has an optional description and ends with help information
119 lines
3.1 KiB
Rust
119 lines
3.1 KiB
Rust
// errorsn.rs
|
|
//
|
|
// This is a bigger error exercise than the previous ones!
|
|
// You can do it! :)
|
|
//
|
|
// Edit the `read_and_validate` function ONLY. Don't create any Errors
|
|
// that do not already exist.
|
|
//
|
|
// So many things could go wrong!
|
|
//
|
|
// - Reading from stdin could produce an io::Error
|
|
// - Parsing the input could produce a num::ParseIntError
|
|
// - Validating the input could produce a CreationError (defined below)
|
|
//
|
|
// How can we lump these errors into one general error? That is, what
|
|
// type goes where the question marks are, and how do we return
|
|
// that type from the body of read_and_validate?
|
|
//
|
|
// If you need help, open the corresponding README.md or run: rustlings hint errorsn
|
|
|
|
// I AM NOT DONE
|
|
|
|
use std::error;
|
|
use std::fmt;
|
|
use std::io;
|
|
|
|
// PositiveNonzeroInteger is a struct defined below the tests.
|
|
fn read_and_validate(b: &mut dyn io::BufRead) -> Result<PositiveNonzeroInteger, ???> {
|
|
let mut line = String::new();
|
|
b.read_line(&mut line);
|
|
let num: i64 = line.trim().parse();
|
|
let answer = PositiveNonzeroInteger::new(num);
|
|
answer
|
|
}
|
|
|
|
//
|
|
// Nothing below this needs to be modified
|
|
//
|
|
|
|
// This is a test helper function that turns a &str into a BufReader.
|
|
fn test_with_str(s: &str) -> Result<PositiveNonzeroInteger, Box<dyn error::Error>> {
|
|
let mut b = io::BufReader::new(s.as_bytes());
|
|
read_and_validate(&mut b)
|
|
}
|
|
|
|
#[test]
|
|
fn test_success() {
|
|
let x = test_with_str("42\n");
|
|
assert_eq!(PositiveNonzeroInteger(42), x.unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn test_not_num() {
|
|
let x = test_with_str("eleven billion\n");
|
|
assert!(x.is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn test_non_positive() {
|
|
let x = test_with_str("-40\n");
|
|
assert!(x.is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn test_ioerror() {
|
|
struct Broken;
|
|
impl io::Read for Broken {
|
|
fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
|
|
Err(io::Error::new(io::ErrorKind::BrokenPipe, "uh-oh!"))
|
|
}
|
|
}
|
|
let mut b = io::BufReader::new(Broken);
|
|
assert!(read_and_validate(&mut b).is_err());
|
|
assert_eq!("uh-oh!", read_and_validate(&mut b).unwrap_err().to_string());
|
|
}
|
|
|
|
#[derive(PartialEq, Debug)]
|
|
struct PositiveNonzeroInteger(u64);
|
|
|
|
impl PositiveNonzeroInteger {
|
|
fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> {
|
|
if value == 0 {
|
|
Err(CreationError::Zero)
|
|
} else if value < 0 {
|
|
Err(CreationError::Negative)
|
|
} else {
|
|
Ok(PositiveNonzeroInteger(value as u64))
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_positive_nonzero_integer_creation() {
|
|
assert!(PositiveNonzeroInteger::new(10).is_ok());
|
|
assert_eq!(
|
|
Err(CreationError::Negative),
|
|
PositiveNonzeroInteger::new(-10)
|
|
);
|
|
assert_eq!(Err(CreationError::Zero), PositiveNonzeroInteger::new(0));
|
|
}
|
|
|
|
#[derive(PartialEq, Debug)]
|
|
enum CreationError {
|
|
Negative,
|
|
Zero,
|
|
}
|
|
|
|
impl fmt::Display for CreationError {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
let description = match *self {
|
|
CreationError::Negative => "Number is negative",
|
|
CreationError::Zero => "Number is zero",
|
|
};
|
|
f.write_str(description)
|
|
}
|
|
}
|
|
|
|
impl error::Error for CreationError {}
|