Skip to content

Commit 882d535

Browse files
tlyuana
authored andcommitted
feat: add advanced_errs1
New section and exercise to demonstrate the `From` trait for errors and its usefulness with the `?` operator.
1 parent 2dc93ca commit 882d535

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// advanced_errs1.rs
2+
3+
// Remember back in errors6, we had multiple mapping functions so that we
4+
// could translate lower-level errors into our custom error type using
5+
// `map_err()`? What if we could use the `?` operator directly instead?
6+
7+
// Make this code compile! Execute `rustlings hint advanced_errs1` for
8+
// hints :)
9+
10+
// I AM NOT DONE
11+
12+
use std::num::ParseIntError;
13+
use std::str::FromStr;
14+
15+
// This is a custom error type that we will be using in the `FromStr`
16+
// implementation.
17+
#[derive(PartialEq, Debug)]
18+
enum ParsePosNonzeroError {
19+
Creation(CreationError),
20+
ParseInt(ParseIntError),
21+
}
22+
23+
impl From<CreationError> for ParsePosNonzeroError {
24+
fn from(e: CreationError) -> Self {
25+
// TODO: complete this implementation so that the `?` operator will
26+
// work for `CreationError`
27+
}
28+
}
29+
30+
// TODO: implement another instance of the `From` trait here so that the
31+
// `?` operator will work in the other place in the `FromStr`
32+
// implementation below.
33+
34+
// Don't change anything below this line.
35+
36+
impl FromStr for PositiveNonzeroInteger {
37+
type Err = ParsePosNonzeroError;
38+
fn from_str(s: &str) -> Result<PositiveNonzeroInteger, Self::Err> {
39+
let x: i64 = s.parse()?;
40+
Ok(PositiveNonzeroInteger::new(x)?)
41+
}
42+
}
43+
44+
#[derive(PartialEq, Debug)]
45+
struct PositiveNonzeroInteger(u64);
46+
47+
#[derive(PartialEq, Debug)]
48+
enum CreationError {
49+
Negative,
50+
Zero,
51+
}
52+
53+
impl PositiveNonzeroInteger {
54+
fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> {
55+
match value {
56+
x if x < 0 => Err(CreationError::Negative),
57+
x if x == 0 => Err(CreationError::Zero),
58+
x => Ok(PositiveNonzeroInteger(x as u64)),
59+
}
60+
}
61+
}
62+
63+
#[cfg(test)]
64+
mod test {
65+
use super::*;
66+
67+
#[test]
68+
fn test_parse_error() {
69+
// We can't construct a ParseIntError, so we have to pattern match.
70+
assert!(matches!(
71+
PositiveNonzeroInteger::from_str("not a number"),
72+
Err(ParsePosNonzeroError::ParseInt(_))
73+
));
74+
}
75+
76+
#[test]
77+
fn test_negative() {
78+
assert_eq!(
79+
PositiveNonzeroInteger::from_str("-555"),
80+
Err(ParsePosNonzeroError::Creation(CreationError::Negative))
81+
);
82+
}
83+
84+
#[test]
85+
fn test_zero() {
86+
assert_eq!(
87+
PositiveNonzeroInteger::from_str("0"),
88+
Err(ParsePosNonzeroError::Creation(CreationError::Zero))
89+
);
90+
}
91+
92+
#[test]
93+
fn test_positive() {
94+
let x = PositiveNonzeroInteger::new(42);
95+
assert!(x.is_ok());
96+
assert_eq!(PositiveNonzeroInteger::from_str("42"), Ok(x.unwrap()));
97+
}
98+
}

info.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,3 +974,23 @@ path = "exercises/conversions/as_ref_mut.rs"
974974
mode = "test"
975975
hint = """
976976
Add AsRef<str> as a trait bound to the functions."""
977+
978+
# ADVANCED ERRORS
979+
980+
[[exercises]]
981+
name = "advanced_errs1"
982+
path = "exercises/advanced_errors/advanced_errs1.rs"
983+
mode = "test"
984+
hint = """
985+
This exercise uses an updated version of the code in errors6. The parsing
986+
code is now in an implementation of the `FromStr` trait. Note that the
987+
parsing code uses `?` directly, without any calls to `map_err()`. There is
988+
one partial implementation of the `From` trait example that you should
989+
complete.
990+
991+
Details: The `?` operator calls `From::from()` on the error type to convert
992+
it to the error type of the return type of the surrounding function.
993+
994+
Hint: You will need to write another implementation of `From` that has a
995+
different input type.
996+
"""

0 commit comments

Comments
 (0)