mirror of
https://github.com/rust-lang/rustlings.git
synced 2024-12-25 23:10:30 +00:00
errors5 solution
This commit is contained in:
parent
720b280bc1
commit
129884aff7
3 changed files with 96 additions and 52 deletions
|
@ -1,38 +1,18 @@
|
||||||
// This program uses an altered version of the code from errors4.
|
// This exercise is an altered version of the `errors4` exercise. It uses some
|
||||||
//
|
// concepts that we won't get to until later in the course, like `Box` and the
|
||||||
// This exercise uses some concepts that we won't get to until later in the
|
// `From` trait. It's not important to understand them in detail right now, but
|
||||||
// course, like `Box` and the `From` trait. It's not important to understand
|
// you can read ahead if you like. For now, think of the `Box<dyn ???>` type as
|
||||||
// them in detail right now, but you can read ahead if you like. For now, think
|
// an "I want anything that does ???" type.
|
||||||
// of the `Box<dyn ???>` type as an "I want anything that does ???" type, which,
|
|
||||||
// given Rust's usual standards for runtime safety, should strike you as
|
|
||||||
// somewhat lenient!
|
|
||||||
//
|
//
|
||||||
// In short, this particular use case for boxes is for when you want to own a
|
// In short, this particular use case for boxes is for when you want to own a
|
||||||
// value and you care only that it is a type which implements a particular
|
// value and you care only that it is a type which implements a particular
|
||||||
// trait. To do so, The Box is declared as of type Box<dyn Trait> where Trait is
|
// trait. To do so, The `Box` is declared as of type `Box<dyn Trait>` where
|
||||||
// the trait the compiler looks for on any value used in that context. For this
|
// `Trait` is the trait the compiler looks for on any value used in that
|
||||||
// exercise, that context is the potential errors which can be returned in a
|
// context. For this exercise, that context is the potential errors which
|
||||||
// Result.
|
// can be returned in a `Result`.
|
||||||
//
|
|
||||||
// What can we use to describe both errors? In other words, is there a trait
|
|
||||||
// which both errors implement?
|
|
||||||
|
|
||||||
use std::error;
|
use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::num::ParseIntError;
|
|
||||||
|
|
||||||
// TODO: update the return type of `main()` to make this compile.
|
|
||||||
fn main() -> Result<(), Box<dyn ???>> {
|
|
||||||
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)]
|
#[derive(PartialEq, Debug)]
|
||||||
enum CreationError {
|
enum CreationError {
|
||||||
|
@ -40,17 +20,7 @@ enum CreationError {
|
||||||
Zero,
|
Zero,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PositiveNonzeroInteger {
|
// This is required so that `CreationError` can implement `Error`.
|
||||||
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 {
|
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 {
|
||||||
|
@ -61,4 +31,26 @@ impl fmt::Display for CreationError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl error::Error for CreationError {}
|
impl Error for CreationError {}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug)]
|
||||||
|
struct PositiveNonzeroInteger(u64);
|
||||||
|
|
||||||
|
impl PositiveNonzeroInteger {
|
||||||
|
fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> {
|
||||||
|
match value {
|
||||||
|
0 => Err(CreationError::Zero),
|
||||||
|
x if x < 0 => Err(CreationError::Negative),
|
||||||
|
x => Ok(PositiveNonzeroInteger(x as u64)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Add the correct return type `Result<(), Box<dyn ???>>`. What can we
|
||||||
|
// use to describe both errors? Is there a trait which both errors implement?
|
||||||
|
fn main() {
|
||||||
|
let pretend_user_input = "42";
|
||||||
|
let x: i64 = pretend_user_input.parse()?;
|
||||||
|
println!("output={:?}", PositiveNonzeroInteger::new(x)?);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
@ -692,24 +692,23 @@ name = "errors5"
|
||||||
dir = "13_error_handling"
|
dir = "13_error_handling"
|
||||||
test = false
|
test = false
|
||||||
hint = """
|
hint = """
|
||||||
There are two different possible `Result` types produced within `main()`, which
|
There are two different possible `Result` types produced within the `main`
|
||||||
are propagated using `?` operators. How do we declare a return type from
|
function, which are propagated using the `?` operators. How do we declare a
|
||||||
`main()` that allows both?
|
return type for the `main` function that allows both?
|
||||||
|
|
||||||
Under the hood, the `?` operator calls `From::from` on the error value to
|
Under the hood, the `?` operator calls `From::from` on the error value to
|
||||||
convert it to a boxed trait object, a `Box<dyn error::Error>`. This boxed trait
|
convert it to a boxed trait object, a `Box<dyn Error>`. This boxed trait object
|
||||||
object is polymorphic, and since all errors implement the `error::Error` trait,
|
is polymorphic, and since all errors implement the `Error` trait, we can capture
|
||||||
we can capture lots of different errors in one "Box" object.
|
lots of different errors in one `Box` object.
|
||||||
|
|
||||||
Check out this section of the book:
|
Check out this section of The Book:
|
||||||
https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html#a-shortcut-for-propagating-errors-the--operator
|
https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html#a-shortcut-for-propagating-errors-the--operator
|
||||||
|
|
||||||
Read more about boxing errors:
|
Read more about boxing errors:
|
||||||
https://doc.rust-lang.org/stable/rust-by-example/error/multiple_error_types/boxing_errors.html
|
https://doc.rust-lang.org/stable/rust-by-example/error/multiple_error_types/boxing_errors.html
|
||||||
|
|
||||||
Read more about using the `?` operator with boxed errors:
|
Read more about using the `?` operator with boxed errors:
|
||||||
https://doc.rust-lang.org/stable/rust-by-example/error/multiple_error_types/reenter_question_mark.html
|
https://doc.rust-lang.org/stable/rust-by-example/error/multiple_error_types/reenter_question_mark.html"""
|
||||||
"""
|
|
||||||
|
|
||||||
[[exercises]]
|
[[exercises]]
|
||||||
name = "errors6"
|
name = "errors6"
|
||||||
|
|
|
@ -1 +1,54 @@
|
||||||
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰
|
// This exercise is an altered version of the `errors4` exercise. It uses some
|
||||||
|
// concepts that we won't get to until later in the course, like `Box` and the
|
||||||
|
// `From` trait. It's not important to understand them in detail right now, but
|
||||||
|
// you can read ahead if you like. For now, think of the `Box<dyn ???>` type as
|
||||||
|
// an "I want anything that does ???" type.
|
||||||
|
//
|
||||||
|
// In short, this particular use case for boxes is for when you want to own a
|
||||||
|
// value and you care only that it is a type which implements a particular
|
||||||
|
// trait. To do so, The `Box` is declared as of type `Box<dyn Trait>` where
|
||||||
|
// `Trait` is the trait the compiler looks for on any value used in that
|
||||||
|
// context. For this exercise, that context is the potential errors which
|
||||||
|
// can be returned in a `Result`.
|
||||||
|
|
||||||
|
use std::error::Error;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug)]
|
||||||
|
enum CreationError {
|
||||||
|
Negative,
|
||||||
|
Zero,
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is required so that `CreationError` can implement `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 for CreationError {}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug)]
|
||||||
|
struct PositiveNonzeroInteger(u64);
|
||||||
|
|
||||||
|
impl PositiveNonzeroInteger {
|
||||||
|
fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> {
|
||||||
|
match value {
|
||||||
|
x if x < 0 => Err(CreationError::Negative),
|
||||||
|
0 => Err(CreationError::Zero),
|
||||||
|
x => Ok(PositiveNonzeroInteger(x as u64)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
let pretend_user_input = "42";
|
||||||
|
let x: i64 = pretend_user_input.parse()?;
|
||||||
|
println!("output={:?}", PositiveNonzeroInteger::new(x)?);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue