mirror of
https://github.com/rust-lang/rustlings.git
synced 2026-01-10 20:59:19 +00:00
Add new exercises errors5 and errors6, to introduce boxed errors and custom error enums more gently. Delete errorsn, because it tried to do too much too soon.
117 lines
3.1 KiB
Rust
117 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?
|
|
//
|
|
// Execute `rustlings hint errorsn` for hints :)
|
|
|
|
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, Box<dyn error::Error>> {
|
|
let mut line = String::new();
|
|
b.read_line(&mut line)?;
|
|
let num: i64 = line.trim().parse()?;
|
|
let answer = PositiveNonzeroInteger::new(num)?;
|
|
|
|
Ok(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 {}
|