Skip to content

Commit de7eda9

Browse files
JulienBerkaneDana Binkley
authored andcommitted
Resolve "Create Lab for Module: Error Handling"
1 parent ecb892d commit de7eda9

5 files changed

Lines changed: 199 additions & 10 deletions

File tree

courses/rust_essentials/200_error_handling/88-error_handling.lab.rst

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,16 @@
22
Lab
33
=====
44

5-
-----
6-
TBD
7-
-----
5+
------------------
6+
Lab Instructions
7+
------------------
88

9-
TBD
9+
- Solve for compilation errors
10+
11+
- Follow the hints!
12+
13+
- Success is
14+
15+
- Code that compiles
16+
17+
- ...and that follows any behavior indicated within the hints!
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
[package]
2-
name = "lab"
2+
name = "answer"
33
version = "1.0.0"
44
edition = "2024"
55

66
[dependencies]
7-
# Leave this empty for now
7+
anyhow = "*"
8+
thiserror = "*"
Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,99 @@
1+
//! Lab (answer)
2+
//! Error Handling
3+
//!
4+
5+
#![allow(unused_assignments)]
6+
#![allow(unused_variables)]
7+
#![allow(dead_code)]
8+
19
fn main() {
2-
println!("TBD");
10+
// TASK 1 - Error Result
11+
// Hint: You can return an error using a 'Result' enum variant 'Err'
12+
enum Reason { TooYoung, TooOld, }
13+
fn check_age(age: i32) -> Result<i32, Reason> {
14+
if age < 18 {
15+
Err(Reason::TooYoung)
16+
} else {
17+
Ok(age)
18+
}
19+
}
20+
let my_age = 17;
21+
22+
// TASK 2 - Handling Results
23+
// Hint: Replace the 'unwrap()' function by a pattern matching to 'handle check_age' return
24+
match check_age(my_age) {
25+
Ok(age) => println!("Access granted! You are {} years old.", age),
26+
Err(Reason::TooYoung) => println!("Sorry, you're not old enough yet."),
27+
Err(Reason::TooOld) => println!("System error: User exceeds maximum age limit."),
28+
}
29+
30+
// TASK 3 - The Try Operator
31+
// Hint: Use the try operator to return an error automatically to the caller of 'register'
32+
// if check_age returns an error
33+
// The try operator tries to convert 'reason' to the return type of 'register' 'string'
34+
// From trait should be implemented
35+
impl From<Reason> for String {
36+
fn from(reason: Reason) -> Self {
37+
match reason {
38+
Reason::TooYoung => "User is under the required age limit".to_string(),
39+
Reason::TooOld => "User is above the maximum age limit".to_string(),
40+
}
41+
}
42+
}
43+
fn register() -> Result<(), String> {
44+
check_age(10)?;
45+
Ok(())
46+
}
47+
48+
// TASK 4 - Handling Propagation
49+
// Hint: Error has been propagated from 'check_age' to 'register' to 'main'
50+
// Use pattern matching to handle return from 'register' instead of 'unwrap()'
51+
// Print a message for each possible result
52+
match register() {
53+
Ok(_) => println!("Registration successful!"),
54+
Err(e) => println!("Registration failed: {}", e),
55+
}
56+
57+
// TASK 5 - thiserror
58+
// Hint: Convert the comments over the two variants into error text using 'thiserror'
59+
// Then make sure withdraw returns an 'AccountError' of 'InsufficientFunds'
60+
// Display the 'balance' and the 'amount'
61+
use thiserror::Error;
62+
#[derive(Error, Debug)]
63+
pub enum AccountError {
64+
#[error("insufficient funds: available {available}, requested {requested}")]
65+
InsufficientFunds { available: u64, requested: u64 },
66+
#[error("account is inactive")]
67+
InactiveAccount,
68+
}
69+
fn withdraw(balance: u64, amount: u64) -> Result<u64, AccountError> {
70+
if amount > balance {
71+
return Err(AccountError::InsufficientFunds {
72+
available: balance,
73+
requested: amount
74+
});
75+
}
76+
Ok(balance - amount)
77+
}
78+
79+
// Task 6 - Anyhow
80+
// Hint: Turn the 'println' in 'process_transaction' into an additional context of information
81+
// Attached to the withdraw function
82+
// You have to use the correct library to be able to use the 'with_context' method
83+
use anyhow::Context;
84+
fn process_transaction(balance: u64, amount: u64) -> anyhow::Result<()> {
85+
withdraw(balance, amount)
86+
.with_context(|| format!("Failed to process withdrawal of ${}", amount))?;
87+
Ok(())
88+
}
89+
let result = process_transaction(50, 100);
90+
if let Err(e) = result {
91+
// This will print a message that looks like an actual run-time error
92+
println!("Error: {}", e);
93+
// This next line will print the following :
94+
// Debug Trace: Failed to process withdrawal of $100
95+
// Caused by:
96+
// insufficient funds: available 50, requested 100
97+
println!("\nDebug Trace: {:?}", e);
98+
}
399
}
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
[package]
2-
name = "lab"
2+
name = "prompt"
33
version = "1.0.0"
44
edition = "2024"
55

66
[dependencies]
7-
# Leave this empty for now
7+
anyhow = "*"
8+
thiserror = "*"
Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,86 @@
1+
//! Lab (prompt)
2+
//! Error Handling
3+
//!
4+
//! Fix all the compile errors below and/or follow the hints provided
5+
//!
6+
7+
#![allow(unused_assignments)]
8+
#![allow(unused_variables)]
9+
#![allow(dead_code)]
10+
111
fn main() {
2-
println!("TBD");
12+
// TASK 1 - Error Result
13+
// Hint: You can return an error using a 'Result' enum variant 'Err'
14+
enum Reason { TooYoung, TooOld, }
15+
fn check_age(age: i32) -> Result<i32, Reason> {
16+
todo!("Replace me with a proper error result");
17+
}
18+
let my_age = 17;
19+
20+
// TASK 2 - Handling Results
21+
// Hint: Replace the 'unwrap()' function by a pattern matching to 'handle check_age' return
22+
check_age(my_age).unwrap();
23+
24+
// TASK 3 - the Try Operator
25+
// Hint: Use the try operator to return an error automatically to the caller of 'register'
26+
// if check_age returns an error
27+
// The try operator tries to convert 'reason' to the return type of 'register' 'string'
28+
// From trait should be implemented
29+
impl From<Reason> for String {
30+
fn from(reason: Reason) -> Self {
31+
match reason {
32+
Reason::TooYoung => "User is under the required age limit".to_string(),
33+
Reason::TooOld => "User is above the maximum age limit".to_string(),
34+
}
35+
}
36+
}
37+
fn register() -> Result<(), String> {
38+
check_age(10);
39+
Ok(())
40+
}
41+
42+
// TASK 4 - Handling Propagation
43+
// Hint: Error has been propagated from 'check_age' to 'register' to 'main'
44+
// Use pattern matching to handle return from 'register' instead of 'unwrap()'
45+
// Print a message for each possible result
46+
register().unwrap();
47+
48+
// TASK 5 - thiserror
49+
// Hint: Convert the comments over the two variants into error text using 'thiserror'
50+
// Then make sure withdraw returns an 'AccountError' of 'InsufficientFunds'
51+
// Display the 'balance' and the 'amount'
52+
use thiserror::Error;
53+
#[derive(Error, Debug)]
54+
pub enum AccountError {
55+
// Insufficient funds: available {available}, requested {requested}
56+
InsufficientFunds { available: u64, requested: u64 },
57+
// Account is inactive
58+
InactiveAccount,
59+
}
60+
fn withdraw(balance: u64, amount: u64) -> Result<u64, AccountError> {
61+
if amount > balance {
62+
return Err(AccountError{});
63+
}
64+
Ok(balance - amount)
65+
}
66+
67+
// Task 6 - Anyhow
68+
// Hint: Turn the 'println' in 'process_transaction' into an additional context of information
69+
// Attached to the 'withdraw' function
70+
// You have to use the correct library to be able to use the 'with_context' method
71+
fn process_transaction(balance: u64, amount: u64) -> anyhow::Result<()> {
72+
withdraw(balance, amount)
73+
println!("Failed to process withdrawal of ${}", amount);
74+
Ok(())
75+
}
76+
let result = process_transaction(50, 100);
77+
if let Err(e) = result {
78+
// This will print a message that looks like an actual run-time error
79+
println!("Error: {}", e);
80+
// This next line will print the following :
81+
// Debug Trace: Failed to process withdrawal of $100
82+
// Caused by:
83+
// insufficient funds: available 50, requested 100
84+
println!("\nDebug Trace: {:?}", e);
85+
}
386
}

0 commit comments

Comments
 (0)