address review feedback

Adjust error text and naming to conform with best practices.
Use `map_err()` instead of `or()`. Wrap lower-level errors instead of
ignoring their details.

Also, don't "cheat" by bypassing the `new()` function in tests.

Fix a dangling reference in the try_from_into hints.
This commit is contained in:
Taylor Yu 2021-06-09 18:13:57 -05:00
parent 68d3ac567c
commit b7ddd09fab
3 changed files with 35 additions and 23 deletions

View File

@ -43,8 +43,8 @@ impl PositiveNonzeroInteger {
impl fmt::Display for CreationError { impl fmt::Display for CreationError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let description = match *self { let description = match *self {
CreationError::Negative => "Number is negative", CreationError::Negative => "number is negative",
CreationError::Zero => "Number is zero", CreationError::Zero => "number is zero",
}; };
f.write_str(description) f.write_str(description)
} }

View File

@ -10,11 +10,20 @@
// I AM NOT DONE // I AM NOT DONE
use std::num::ParseIntError;
// This is a custom error type that we will be using in `parse_pos_nonzero()`. // This is a custom error type that we will be using in `parse_pos_nonzero()`.
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
enum ParsePosNonzeroError { enum ParsePosNonzeroError {
CreationError, Creation(CreationError),
ParseIntError 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) fn parse_pos_nonzero(s: &str)
@ -24,7 +33,7 @@ fn parse_pos_nonzero(s: &str)
// when `parse()` returns an error. // when `parse()` returns an error.
let x: i64 = s.parse().unwrap(); let x: i64 = s.parse().unwrap();
PositiveNonzeroInteger::new(x) PositiveNonzeroInteger::new(x)
.or(Err(ParsePosNonzeroError::CreationError)) .map_err(ParsePosNonzeroError::from_creation)
} }
// Don't change anything below this line. // Don't change anything below this line.
@ -54,17 +63,18 @@ mod test {
#[test] #[test]
fn test_parse_error() { fn test_parse_error() {
assert_eq!( // We can't construct a ParseIntError, so we have to pattern match.
assert!(matches!(
parse_pos_nonzero("not a number"), parse_pos_nonzero("not a number"),
Err(ParsePosNonzeroError::ParseIntError) Err(ParsePosNonzeroError::ParseInt(_))
); ));
} }
#[test] #[test]
fn test_negative() { fn test_negative() {
assert_eq!( assert_eq!(
parse_pos_nonzero("-555"), parse_pos_nonzero("-555"),
Err(ParsePosNonzeroError::CreationError) Err(ParsePosNonzeroError::Creation(CreationError::Negative))
); );
} }
@ -72,15 +82,14 @@ mod test {
fn test_zero() { fn test_zero() {
assert_eq!( assert_eq!(
parse_pos_nonzero("0"), parse_pos_nonzero("0"),
Err(ParsePosNonzeroError::CreationError) Err(ParsePosNonzeroError::Creation(CreationError::Zero))
); );
} }
#[test] #[test]
fn test_positive() { fn test_positive() {
assert_eq!( let x = PositiveNonzeroInteger::new(42);
parse_pos_nonzero("42"), assert!(x.is_ok());
Ok(PositiveNonzeroInteger(42)) assert_eq!(parse_pos_nonzero("42"), Ok(x.unwrap()));
);
} }
} }

View File

@ -532,16 +532,19 @@ path = "exercises/error_handling/errors6.rs"
mode = "test" mode = "test"
hint = """ hint = """
This exercise uses a completed version of `PositiveNonzeroInteger` from This exercise uses a completed version of `PositiveNonzeroInteger` from
the errors4. errors4.
Below the TODO line, there is an example of using the `.or()` method Below the line that TODO asks you to change, there is an example of using
on a `Result` to transform one type of error into another. Try using the `map_err()` method on a `Result` to transform one type of error into
something similar on the `Result` from `parse()`. You might use the `?` another. Try using something similar on the `Result` from `parse()`. You
operator to return early from the function, or you might use a `match` might use the `?` operator to return early from the function, or you might
expression, or maybe there's another way! use a `match` expression, or maybe there's another way!
Read more about `.or()` in the `std::result` documentation: You can create another function inside `impl ParsePosNonzeroError` to use
https://doc.rust-lang.org/std/result/enum.Result.html#method.or""" with `map_err()`.
Read more about `map_err()` in the `std::result` documentation:
https://doc.rust-lang.org/std/result/enum.Result.html#method.map_err"""
# Generics # Generics
@ -927,7 +930,7 @@ hint = """
Follow the steps provided right before the `TryFrom` implementation. Follow the steps provided right before the `TryFrom` implementation.
You can also use the example at https://doc.rust-lang.org/std/convert/trait.TryFrom.html You can also use the example at https://doc.rust-lang.org/std/convert/trait.TryFrom.html
You might want to look back at the exercise errorsn (or its hints) to remind You might want to look back at the exercise errors5 (or its hints) to remind
yourself about how `Box<dyn Error>` works. yourself about how `Box<dyn Error>` works.
If you're trying to return a string as an error, note that neither `str` If you're trying to return a string as an error, note that neither `str`