You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1001 lines
36 KiB

# VARIABLES
[[exercises]]
name = "variables1"
path = "exercises/variables/variables1.rs"
mode = "compile"
hint = """
: 12 Rust
"""
[[exercises]]
name = "variables2"
path = "exercises/variables/variables2.rs"
mode = "compile"
hint = """
Rust `x` .
3 years ago
7
x
x
x 10 """
[[exercises]]
name = "variables3"
path = "exercises/variables/variables3.rs"
mode = "compile"
hint = """
Rust
x 使使"""
[[exercises]]
name = "variables4"
path = "exercises/variables/variables4.rs"
mode = "compile"
hint = """
7 8
使 x
Bug Rust """
[[exercises]]
name = "variables5"
path = "exercises/variables/variables5.rs"
mode = "compile"
hint = """
variables3 使使
使
Rust Shadowing
'Variables and Mutability'* :
https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html#shadowing
使
Variables and Mutability"""
[[exercises]]
name = "variables6"
path = "exercises/variables/variables6.rs"
mode = "compile"
hint = """
Constant
3 years ago
'const' 'let'
'Differences Between Variables and Constants'* 'Variables and Mutability':
https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants
Differences Between Variables and Constants
"""
# FUNCTIONS
[[exercises]]
name = "functions1"
path = "exercises/functions/functions1.rs"
mode = "compile"
hint = """
3 years ago
`call_me`
`main` """
[[exercises]]
name = "functions2"
path = "exercises/functions/functions2.rs"
mode = "compile"
hint = """
3 years ago
Rust signature `call_me` `num` """
[[exercises]]
name = "functions3"
path = "exercises/functions/functions3.rs"
mode = "compile"
hint = """
3 years ago
, *declaration* """
[[exercises]]
name = "functions4"
path = "exercises/functions/functions4.rs"
mode = "compile"
hint = """
3 years ago
15 `->`
`is_even` """
[[exercises]]
name = "functions5"
path = "exercises/functions/functions5.rs"
mode = "compile"
hint = """
3 years ago
Rust operand,
`()` C/C++ `void`
`square` `i32` `()` ...
1. `num * num;` `return`
2. `;` `num * num`"""
# IF
[[exercises]]
name = "if1"
path = "exercises/if/if1.rs"
mode = "test"
hint = """
3 years ago
!
:
- C(++) : `a > b ? a : b`
- Python : `a if a > b else b`
Rust
- `if`
- `if`/`else`
- `{}` """
[[exercises]]
name = "if2"
path = "exercises/if/if2.rs"
mode = "test"
hint = """
3 years ago
Rust
conditional block
"""
# TEST 1
[[exercises]]
name = "quiz1"
path = "exercises/quiz1.rs"
mode = "test"
hint = "No hints this time ;)"
# MOVE SEMANTICS
[[exercises]]
name = "move_semantics1"
path = "exercises/move_semantics/move_semantics1.rs"
mode = "compile"
hint = """
13 "cannot borrow immutable local variable `vec1` as mutable"*
13
`vec1` """
[[exercises]]
name = "move_semantics2"
path = "exercises/move_semantics/move_semantics2.rs"
mode = "compile"
hint = """
10 `fill_vec` `vec0' *moved*
`fill_vec` `fill_vec`
13 使 `vec0` `main` `fill_vec`
1. `vec0` `fill_vec`
2. `fill_vec` 便
`Vec<i32>`
3. `fill_vec` 西
`vec1` `println!` """
[[exercises]]
name = "move_semantics3"
path = "exercises/move_semantics/move_semantics3.rs"
mode = "compile"
hint = """
`fn fill_vec` `let mut vec = vec;`
`mut` 使 :)"""
[[exercises]]
name = "move_semantics4"
path = "exercises/move_semantics/move_semantics4.rs"
mode = "compile"
hint = """
:)
- main vector
3 years ago
- `vec0` `fill_vec`
3 years ago
- `fill_vec` 西*
- `main` vector `fill_vec` vector
`main`
fill_vec """
[[exercises]]
name = "move_semantics5"
path = "exercises/move_semantics/move_semantics5.rs"
mode = "compile"
hint = """
使
x
'References and Borrowing' 'Mutable References'
https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#mutable-references.
"""
# PRIMITIVE TYPES
[[exercises]]
name = "primitive_types1"
path = "exercises/primitive_types/primitive_types1.rs"
mode = "compile"
hint = "这次没有提示 ;)"
[[exercises]]
name = "primitive_types2"
path = "exercises/primitive_types/primitive_types2.rs"
mode = "compile"
hint = "这次没有提示 ;)"
[[exercises]]
name = "primitive_types3"
path = "exercises/primitive_types/primitive_types3.rs"
mode = "compile"
hint = """
便 100
let array = ["Are we there yet?"; 10];
: 西 `a.len()>=100` true """
[[exercises]]
name = "primitive_types4"
path = "exercises/primitive_types/primitive_types4.rs"
mode = "test"
hint = """
Understanding Ownership -> Slices -> Other Slices
https://doc.rust-lang.org/book/ch04-03-slices.html
`assert_eq!`
使 & Deref
https://doc.rust-lang.org/book/ch15-02-deref.html"""
[[exercises]]
name = "primitive_types5"
path = "exercises/primitive_types/primitive_types5.rs"
mode = "compile"
hint = """
Data Types -> The Tuple Type
https://doc.rust-lang.org/book/ch03-02-data-types.html#the-tuple-type
`name` `age` """
[[exercises]]
name = "primitive_types6"
path = "exercises/primitive_types/primitive_types6.rs"
mode = "test"
hint = """
使 `let`
Data Types -> The Tuple Type
https://doc.rust-lang.org/book/ch03-02-data-types.html#the-tuple-type
"""
# STRUCTS
[[exercises]]
name = "structs1"
path = "exercises/structs/structs1.rs"
mode = "test"
hint = """
Rust
https://doc.rust-lang.org/book/ch05-01-defining-structs.html"""
[[exercises]]
name = "structs2"
path = "exercises/structs/structs2.rs"
mode = "test"
hint = """
https://doc.rust-lang.org/stable/book/ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax"""
[[exercises]]
name = "structs3"
path = "exercises/structs/structs3.rs"
mode = "test"
hint = """
Package new weight_in_grams panic :) Rust
is_international
calculate_transport_fees Package 西 :)
https://doc.rust-lang.org/book/ch05-03-method-syntax.html"""
# ENUMS
[[exercises]]
name = "enums1"
path = "exercises/enums/enums1.rs"
mode = "compile"
hint = """
"""
[[exercises]]
name = "enums2"
path = "exercises/enums/enums2.rs"
mode = "compile"
hint = """
*
"""
[[exercises]]
name = "enums3"
path = "exercises/enums/enums3.rs"
mode = "test"
hint = "这次没有提示 ;)"
# MODULES
[[exercises]]
name = "modules1"
path = "exercises/modules/modules1.rs"
mode = "compile"
hint = """
Rust 西private西public
西访"""
[[exercises]]
name = "modules2"
path = "exercises/modules/modules2.rs"
mode = "compile"
hint = """
delicious_snacks `fruits` `veggies`
main 使 `use` """
[[exercises]]
name = "modules3"
path = "exercises/modules/modules3.rs"
mode = "compile"
hint = """
UNIX_EPOCH SystemTime std::time `use`
使nested paths
glob operator
{x,y,z} * """
# COLLECTIONS
[[exercises]]
name = "vec1"
path = "exercises/collections/vec1.rs"
mode = "test"
hint = """
Rust vector
1. 使 `Vec::new()` vector
使 `push()`
2. 使 `vec![]`
https://doc.rust-lang.org/stable/book/ch08-01-vectors.html
"""
[[exercises]]
name = "vec2"
path = "exercises/collections/vec2.rs"
mode = "test"
hint = """
1 `i` Vec
2 : ;)
"""
[[exercises]]
name = "hashmap1"
path = "exercises/collections/hashmap1.rs"
mode = "test"
hint = """
1 `basket`
2 5
"""
[[exercises]]
name = "hashmap2"
path = "exercises/collections/hashmap2.rs"
mode = "test"
hint = """
使 `HashMap` `entry()` `or_insert()`
https://doc.rust-lang.org/stable/book/ch08-03-hash-maps.html#only-inserting-a-value-if-the-key-has-no-value
"""
# STRINGS
[[exercises]]
name = "strings1"
path = "exercises/strings/strings1.rs"
mode = "compile"
hint = """
`current_favorite_color` `'static`
`String` Strings
使 `From` """
[[exercises]]
name = "strings2"
path = "exercises/strings/strings2.rs"
mode = "compile"
hint = """
`word` `String`
9 `String` """
# TEST 2
[[exercises]]
name = "quiz2"
path = "exercises/quiz2.rs"
mode = "compile"
hint = "No hints this time ;)"
# ERROR HANDLING
[[exercises]]
name = "errors1"
path = "exercises/error_handling/errors1.rs"
mode = "test"
hint = """
`Err` `Result` `generate_nametag_text`
`Result` `Option`
- Result<String, String>便 `Ok(String)` `Err(String)`
- `Some(stuff)` `Ok(stuff)`
- `None` `Err(error message)`
- `Some(stuff)` `Ok(stuff)`"""
[[exercises]]
name = "errors2"
path = "exercises/error_handling/errors2.rs"
mode = "test"
hint = """
`item_quantity.parse::<i32>()` 使 match
`Ok(something)` `Err(something)`
Rust `?`
Error Handling :
https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html#a-shortcut-for-propagating-errors-the--operator
"""
[[exercises]]
name = "errors3"
path = "exercises/error_handling/errors3.rs"
mode = "compile"
hint = """
`Result` `main` """
[[exercises]]
name = "errors4"
path = "exercises/error_handling/errors4.rs"
mode = "test"
hint = """
`PositiveNonzeroInteger::new` `Ok`
`Err` `Ok` :)"""
[[exercises]]
name = "errors5"
path = "exercises/error_handling/errors5.rs"
mode = "compile"
hint = """
`main()` `Result` `?`
`main()`
`?` `From::from`
`Box<dyn error::Error>`
`error::Error`
https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html#a-shortcut-for-propagating-errors-the--operator
使 `Box` `From`
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/reenter_question_mark.html
"""
[[exercises]]
name = "errors6"
path = "exercises/error_handling/errors6.rs"
mode = "test"
hint = """
使 error 4 `PositiveNonzeroInteger`
TODO `Result` 使 `map_err()`
`parse()` `Result` 使西
使 `?` 使 `match`
`impl ParsePosNonzeroError` `map_err()` 使
`std::result` `map_err()`
https://doc.rust-lang.org/std/result/enum.Result.html#method.map_err"""
# Generics
[[exercises]]
name = "generics1"
path = "exercises/generics/generics1.rs"
mode = "compile"
hint = """
Rust Vector
"""
[[exercises]]
name = "generics2"
path = "exercises/generics/generics2.rs"
mode = "test"
hint = """
'u32'
https://doc.rust-lang.org/stable/book/ch10-01-syntax.html#in-method-definitions
"""
[[exercises]]
name = "generics3"
path = "exercises/generics/generics3.rs"
mode = "test"
hint = """
trait trait
"use std::fmt::Display;"
使 ReportCard
💪
"""
# OPTIONS
[[exercises]]
name = "option1"
path = "exercises/option/option1.rs"
mode = "compile"
hint = """
1 Option
is_some
is_none
unwrap
2使
"""
[[exercises]]
name = "option2"
path = "exercises/option/option2.rs"
mode = "compile"
hint = """
https://doc.rust-lang.org/rust-by-example/flow_control/if_let.html
https://doc.rust-lang.org/rust-by-example/flow_control/while_let.html
Options 使 if let while let
: Some(Some(variable)) = variable2
Option::flatten
"""
[[exercises]]
name = "option3"
path = "exercises/option/option3.rs"
mode = "compile"
hint = """
`match`
https://doc.rust-lang.org/std/keyword.ref.html"""
# TRAITS
[[exercises]]
name = "traits1"
path = "exercises/traits/traits1.rs"
mode = "test"
hint = """
A discussion about Traits in Rust can be found at:
https://doc.rust-lang.org/book/ch10-02-traits.html
"""
[[exercises]]
name = "traits2"
path = "exercises/traits/traits2.rs"
mode = "test"
hint = """
Notice how the trait takes ownership of 'self',and returns `Self'.
Try mutating the incoming string vector.
Vectors provide suitable methods for adding an element at the end. See
the documentation at: https://doc.rust-lang.org/std/vec/struct.Vec.html"""
# TESTS
[[exercises]]
name = "tests1"
path = "exercises/tests/tests1.rs"
mode = "test"
hint = """
You don't even need to write any code to test -- you can just test values and run that, even
though you wouldn't do that in real life :) `assert!` is a macro that needs an argument.
Depending on the value of the argument, `assert!` will do nothing (in which case the test will
pass) or `assert!` will panic (in which case the test will fail). So try giving different values
to `assert!` and see which ones compile, which ones pass, and which ones fail :)"""
[[exercises]]
name = "tests2"
path = "exercises/tests/tests2.rs"
mode = "test"
hint = """
Like the previous exercise, you don't need to write any code to get this test to compile and
run. `assert_eq!` is a macro that takes two arguments and compares them. Try giving it two
values that are equal! Try giving it two arguments that are different! Try giving it two values
that are of different types! Try switching which argument comes first and which comes second!"""
[[exercises]]
name = "tests3"
path = "exercises/tests/tests3.rs"
mode = "test"
hint = """
You can call a function right where you're passing arguments to `assert!` -- so you could do
something like `assert!(having_fun())`. If you want to check that you indeed get false, you
can negate the result of what you're doing using `!`, like `assert!(!having_fun())`."""
# TEST 3
[[exercises]]
name = "quiz3"
path = "exercises/quiz3.rs"
mode = "test"
hint = "No hints this time ;)"
# STANDARD LIBRARY TYPES
[[exercises]]
name = "box1"
path = "exercises/standard_library_types/box1.rs"
mode = "test"
hint = """
Step 1
The compiler's message should help: since we cannot store the value of the actual type
when working with recursive types, we need to store a reference (pointer) to its value.
We should, therefore, place our `List` inside a `Box`. More details in the book here:
https://doc.rust-lang.org/book/ch15-01-box.html#enabling-recursive-types-with-boxes
Step 2
Creating an empty list should be fairly straightforward (hint: peek at the assertions).
For a non-empty list keep in mind that we want to use our Cons "list builder".
Although the current list is one of integers (i32), feel free to change the definition
and try other types!
"""
[[exercises]]
name = "arc1"
path = "exercises/standard_library_types/arc1.rs"
mode = "compile"
hint = """
Make `shared_numbers` be an `Arc` from the numbers vector. Then, in order
to avoid creating a copy of `numbers`, you'll need to create `child_numbers`
inside the loop but still in the main thread.
`child_numbers` should be a clone of the Arc of the numbers instead of a
thread-local copy of the numbers.
This is a simple exercise if you understand the underlying concepts, but if this
is too much of a struggle, consider reading through all of Chapter 16 in the book:
https://doc.rust-lang.org/stable/book/ch16-00-concurrency.html
"""
[[exercises]]
name = "iterators1"
path = "exercises/standard_library_types/iterators1.rs"
mode = "compile"
hint = """
Step 1:
We need to apply something to the collection `my_fav_fruits` before we start to go through
it. What could that be? Take a look at the struct definition for a vector for inspiration:
https://doc.rust-lang.org/std/vec/struct.Vec.html.
Step 2 & step 2.1:
Very similar to the lines above and below. You've got this!
Step 3:
An iterator goes through all elements in a collection, but what if we've run out of
elements? What should we expect here? If you're stuck, take a look at
https://doc.rust-lang.org/std/iter/trait.Iterator.html for some ideas.
"""
[[exercises]]
name = "iterators2"
path = "exercises/standard_library_types/iterators2.rs"
mode = "test"
hint = """
Step 1
The variable `first` is a `char`. It needs to be capitalized and added to the
remaining characters in `c` in order to return the correct `String`.
The remaining characters in `c` can be viewed as a string slice using the
`as_str` method.
The documentation for `char` contains many useful methods.
https://doc.rust-lang.org/std/primitive.char.html
Step 2
Create an iterator from the slice. Transform the iterated values by applying
the `capitalize_first` function. Remember to collect the iterator.
Step 3.
This is surprising similar to the previous solution. Collect is very powerful
and very general. Rust just needs to know the desired type."""
[[exercises]]
name = "iterators3"
path = "exercises/standard_library_types/iterators3.rs"
mode = "test"
hint = """
The divide function needs to return the correct error when even division is not
possible.
The division_results variable needs to be collected into a collection type.
The result_with_list function needs to return a single Result where the success
case is a vector of integers and the failure case is a DivisionError.
The list_of_results function needs to return a vector of results.
See https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.collect for how
the `FromIterator` trait is used in `collect()`."""
[[exercises]]
name = "iterators4"
path = "exercises/standard_library_types/iterators4.rs"
mode = "test"
hint = """
In an imperative language, you might write a for loop that updates
a mutable variable. Or, you might write code utilizing recursion
and a match clause. In Rust you can take another functional
approach, computing the factorial elegantly with ranges and iterators."""
[[exercises]]
name = "iterators5"
path = "exercises/standard_library_types/iterators5.rs"
mode = "test"
hint = """
The documentation for the std::iter::Iterator trait contains numerous methods
that would be helpful here.
Return 0 from count_collection_iterator to make the code compile in order to
test count_iterator.
The collection variable in count_collection_iterator is a slice of HashMaps. It
needs to be converted into an iterator in order to use the iterator methods.
The fold method can be useful in the count_collection_iterator function.
For a further challenge, consult the documentation for Iterator to find
a different method that could make your code more compact than using fold."""
# THREADS
[[exercises]]
name = "threads1"
path = "exercises/threads/threads1.rs"
mode = "compile"
hint = """
`Arc` is an Atomic Reference Counted pointer that allows safe, shared access
to **immutable** data. But we want to *change* the number of `jobs_completed`
so we'll need to also use another type that will only allow one thread to
mutate the data at a time. Take a look at this section of the book:
https://doc.rust-lang.org/book/ch16-03-shared-state.html#atomic-reference-counting-with-arct
and keep reading if you'd like more hints :)
Do you now have an `Arc` `Mutex` `JobStatus` at the beginning of main? Like:
`let status = Arc::new(Mutex::new(JobStatus { jobs_completed: 0 }));`
Similar to the code in the example in the book that happens after the text
that says "We can use Arc<T> to fix this.". If not, give that a try! If you
do and would like more hints, keep reading!!
Make sure neither of your threads are holding onto the lock of the mutex
while they are sleeping, since this will prevent the other thread from
being allowed to get the lock. Locks are automatically released when
they go out of scope.
Ok, so, real talk, this was actually tricky for *me* to do too. And
I could see a lot of different problems you might run into, so at this
point I'm not sure which one you've hit :)
Please open an issue if you're still running into a problem that
these hints are not helping you with, or if you've looked at the sample
answers and don't understand why they work and yours doesn't.
If you've learned from the sample solutions, I encourage you to come
back to this exercise and try it again in a few days to reinforce
what you've learned :)"""
# MACROS
[[exercises]]
name = "macros1"
path = "exercises/macros/macros1.rs"
mode = "compile"
hint = """
When you call a macro, you need to add something special compared to a
regular function call. If you're stuck, take a look at what's inside
`my_macro`."""
[[exercises]]
name = "macros2"
path = "exercises/macros/macros2.rs"
mode = "compile"
hint = """
Macros don't quite play by the same rules as the rest of Rust, in terms of
what's available where.
Unlike other things in Rust, the order of "where you define a macro" versus
"where you use it" actually matters."""
[[exercises]]
name = "macros3"
path = "exercises/macros/macros3.rs"
mode = "compile"
hint = """
In order to use a macro outside of its module, you need to do something
special to the module to lift the macro out into its parent.
The same trick also works on "extern crate" statements for crates that have
exported macros, if you've seen any of those around."""
[[exercises]]
name = "macros4"
path = "exercises/macros/macros4.rs"
mode = "compile"
hint = """
You only need to add a single character to make this compile.
The way macros are written, it wants to see something between each
"macro arm", so it can separate them."""
# TEST 4
[[exercises]]
name = "quiz4"
path = "exercises/quiz4.rs"
mode = "test"
hint = "No hints this time ;)"
# CLIPPY
[[exercises]]
name = "clippy1"
path = "exercises/clippy/clippy1.rs"
mode = "clippy"
hint = """
Not every floating point value can be represented exactly in binary values in
memory. Take a look at the description of
https://doc.rust-lang.org/stable/std/primitive.f32.html
When using the binary compare operators with floating points you won't compare
the floating point values but the binary representation in memory. This is
usually not what you would like to do.
See the suggestions of the clippy warning in compile output and use the
machine epsilon value...
https://doc.rust-lang.org/stable/std/primitive.f32.html#associatedconstant.EPSILON"""
[[exercises]]
name = "clippy2"
path = "exercises/clippy/clippy2.rs"
mode = "clippy"
hint = """
`for` loops over Option values are more clearly expressed as an `if let`"""
# TYPE CONVERSIONS
[[exercises]]
name = "using_as"
path = "exercises/conversions/using_as.rs"
mode = "test"
hint = """
Use the `as` operator to cast one of the operands in the last line of the
`average` function into the expected return type."""
[[exercises]]
name = "from_into"
path = "exercises/conversions/from_into.rs"
mode = "test"
hint = """
Follow the steps provided right before the `From` implementation"""
[[exercises]]
name = "from_str"
path = "exercises/conversions/from_str.rs"
mode = "test"
hint = """
The implementation of FromStr should return an Ok with a Person object,
or an Err with an error if the string is not valid.
This is almost like the `from_into` exercise, but returning errors instead
of falling back to a default value.
Hint: Look at the test cases to see which error variants to return.
Another hint: You can use the `map_err` method of `Result` with a function
or a closure to wrap the error from `parse::<usize>`.
Yet another hint: If you would like to propagate errors by using the `?`
operator in your solution, you might want to look at
https://doc.rust-lang.org/stable/rust-by-example/error/multiple_error_types/reenter_question_mark.html
"""
[[exercises]]
name = "try_from_into"
path = "exercises/conversions/try_from_into.rs"
mode = "test"
hint = """
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
Hint: Is there an implementation of `TryFrom` in the standard library that
can both do the required integer conversion and check the range of the input?
Another hint: Look at the test cases to see which error variants to return.
Yet another hint: You can use the `map_err` or `or` methods of `Result` to
convert errors.
Yet another hint: If you would like to propagate errors by using the `?`
operator in your solution, you might want to look at
https://doc.rust-lang.org/stable/rust-by-example/error/multiple_error_types/reenter_question_mark.html
Challenge: Can you make the `TryFrom` implementations generic over many integer types?"""
[[exercises]]
name = "as_ref_mut"
path = "exercises/conversions/as_ref_mut.rs"
mode = "test"
hint = """
Add AsRef<str> as a trait bound to the functions."""
# ADVANCED ERRORS
[[exercises]]
name = "advanced_errs1"
path = "exercises/advanced_errors/advanced_errs1.rs"
mode = "test"
hint = """
This exercise uses an updated version of the code in errors6. The parsing
code is now in an implementation of the `FromStr` trait. Note that the
parsing code uses `?` directly, without any calls to `map_err()`. There is
one partial implementation of the `From` trait example that you should
complete.
Details: The `?` operator calls `From::from()` on the error type to convert
it to the error type of the return type of the surrounding function.
Hint: You will need to write another implementation of `From` that has a
different input type.
"""
[[exercises]]
name = "advanced_errs2"
path = "exercises/advanced_errors/advanced_errs2.rs"
mode = "test"
hint = """
This exercise demonstrates a few traits that are useful for custom error
types to implement. These traits make it easier for other code to consume
the custom error type.
Follow the steps in the comment near the top of the file. You will have to
supply a missing trait implementation, and complete a few incomplete ones.
You may find these pages to be helpful references:
https://doc.rust-lang.org/stable/rust-by-example/error/multiple_error_types/define_error_type.html
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/wrap_error.html
Hint: What trait must our error type have for `main()` to return the return
type that it returns?
Another hint: It's not necessary to implement any methods inside the missing
trait. (Some methods have default implementations that are supplied by the
trait.)
Another hint: Consult the tests to determine which error variants (and which
error message text) to produce for certain error conditions.
Challenge: There is one test that is marked `#[ignore]`. Can you supply the
missing code that will make it pass? You may want to consult the standard
library documentation for a certain trait for more hints.
"""