diff options
Diffstat (limited to 'exercises/error_handling')
| -rw-r--r-- | exercises/error_handling/errors1.rs | 1 | ||||
| -rw-r--r-- | exercises/error_handling/errors4.rs (renamed from exercises/error_handling/result1.rs) | 4 | ||||
| -rw-r--r-- | exercises/error_handling/errors5.rs | 53 | ||||
| -rw-r--r-- | exercises/error_handling/errors6.rs | 95 | ||||
| -rw-r--r-- | exercises/error_handling/errorsn.rs | 117 |
5 files changed, 151 insertions, 119 deletions
diff --git a/exercises/error_handling/errors1.rs b/exercises/error_handling/errors1.rs index 9c24d85..5844a49 100644 --- a/exercises/error_handling/errors1.rs +++ b/exercises/error_handling/errors1.rs @@ -36,6 +36,7 @@ mod tests { fn explains_why_generating_nametag_text_fails() { assert_eq!( generate_nametag_text("".into()), + // Don't change this line Err("`name` was empty; it must be nonempty.".into()) ); } diff --git a/exercises/error_handling/result1.rs b/exercises/error_handling/errors4.rs index b978001..0685c37 100644 --- a/exercises/error_handling/result1.rs +++ b/exercises/error_handling/errors4.rs @@ -1,5 +1,5 @@ -// result1.rs -// Make this test pass! Execute `rustlings hint result1` for hints :) +// errors4.rs +// Make this test pass! Execute `rustlings hint errors4` for hints :) // I AM NOT DONE diff --git a/exercises/error_handling/errors5.rs b/exercises/error_handling/errors5.rs new file mode 100644 index 0000000..365a869 --- /dev/null +++ b/exercises/error_handling/errors5.rs @@ -0,0 +1,53 @@ +// errors5.rs + +// This program uses a completed version of the code from errors4. +// It won't compile right now! Why? +// Execute `rustlings hint errors5` for hints! + +// I AM NOT DONE + +use std::error; +use std::fmt; +use std::num::ParseIntError; + +// TODO: update the return type of `main()` to make this compile. +fn main() -> Result<(), ParseIntError> { + let pretend_user_input = "42"; + let x: i64 = pretend_user_input.parse()?; + println!("output={:?}", PositiveNonzeroInteger::new(x)?); + Ok(()) +} + +// Don't change anything below this line. + +#[derive(PartialEq, Debug)] +struct PositiveNonzeroInteger(u64); + +#[derive(PartialEq, Debug)] +enum CreationError { + Negative, + Zero, +} + +impl PositiveNonzeroInteger { + fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> { + match value { + x if x < 0 => Err(CreationError::Negative), + x if x == 0 => Err(CreationError::Zero), + x => Ok(PositiveNonzeroInteger(x as u64)) + } + } +} + +// This is required so that `CreationError` can implement `error::Error`. +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 {} diff --git a/exercises/error_handling/errors6.rs b/exercises/error_handling/errors6.rs new file mode 100644 index 0000000..0f6b27a --- /dev/null +++ b/exercises/error_handling/errors6.rs @@ -0,0 +1,95 @@ +// errors6.rs + +// Using catch-all error types like `Box<dyn error::Error>` isn't recommended +// for library code, where callers might want to make decisions based on the +// error content, instead of printing it out or propagating it further. Here, +// we define a custom error type to make it possible for callers to decide +// what to do next when our function returns an error. + +// Make these tests pass! Execute `rustlings hint errors6` for hints :) + +// I AM NOT DONE + +use std::num::ParseIntError; + +// This is a custom error type that we will be using in `parse_pos_nonzero()`. +#[derive(PartialEq, Debug)] +enum ParsePosNonzeroError { + Creation(CreationError), + ParseInt(ParseIntError) +} + +impl ParsePosNonzeroError { + fn from_creation(err: CreationError) -> ParsePosNonzeroError { + ParsePosNonzeroError::Creation(err) + } + // TODO: add another error conversion function here. +} + +fn parse_pos_nonzero(s: &str) + -> Result<PositiveNonzeroInteger, ParsePosNonzeroError> +{ + // TODO: change this to return an appropriate error instead of panicking + // when `parse()` returns an error. + let x: i64 = s.parse().unwrap(); + PositiveNonzeroInteger::new(x) + .map_err(ParsePosNonzeroError::from_creation) +} + +// Don't change anything below this line. + +#[derive(PartialEq, Debug)] +struct PositiveNonzeroInteger(u64); + +#[derive(PartialEq, Debug)] +enum CreationError { + Negative, + Zero, +} + +impl PositiveNonzeroInteger { + fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> { + match value { + x if x < 0 => Err(CreationError::Negative), + x if x == 0 => Err(CreationError::Zero), + x => Ok(PositiveNonzeroInteger(x as u64)) + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_parse_error() { + // We can't construct a ParseIntError, so we have to pattern match. + assert!(matches!( + parse_pos_nonzero("not a number"), + Err(ParsePosNonzeroError::ParseInt(_)) + )); + } + + #[test] + fn test_negative() { + assert_eq!( + parse_pos_nonzero("-555"), + Err(ParsePosNonzeroError::Creation(CreationError::Negative)) + ); + } + + #[test] + fn test_zero() { + assert_eq!( + parse_pos_nonzero("0"), + Err(ParsePosNonzeroError::Creation(CreationError::Zero)) + ); + } + + #[test] + fn test_positive() { + let x = PositiveNonzeroInteger::new(42); + assert!(x.is_ok()); + assert_eq!(parse_pos_nonzero("42"), Ok(x.unwrap())); + } +} diff --git a/exercises/error_handling/errorsn.rs b/exercises/error_handling/errorsn.rs deleted file mode 100644 index 5fe212b..0000000 --- a/exercises/error_handling/errorsn.rs +++ /dev/null @@ -1,117 +0,0 @@ -// 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 :) - -// 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 {} |
