diff options
| author | Hunter Kvalevog <hunter@kvog.sh> | 2026-10-02 21:53:51 -0500 |
|---|---|---|
| committer | Hunter Kvalevog <hunter@kvog.sh> | 2026-10-02 21:53:51 -0500 |
| commit | 4dfc11d74ab02ac5765ae5d08fb750c91f4744b4 (patch) | |
| tree | 17ba62056d6b691dd0217b0e8f1b3a5826dce0f6 /rustlings/solutions/13_error_handling | |
| parent | 02d8f1c62896576e1266553a56980eddbc2a88d7 (diff) | |
rustlings: move to rust/
Diffstat (limited to 'rustlings/solutions/13_error_handling')
| -rw-r--r-- | rustlings/solutions/13_error_handling/errors1.rs | 37 | ||||
| -rw-r--r-- | rustlings/solutions/13_error_handling/errors2.rs | 58 | ||||
| -rw-r--r-- | rustlings/solutions/13_error_handling/errors3.rs | 32 | ||||
| -rw-r--r-- | rustlings/solutions/13_error_handling/errors4.rs | 42 | ||||
| -rw-r--r-- | rustlings/solutions/13_error_handling/errors5.rs | 54 | ||||
| -rw-r--r-- | rustlings/solutions/13_error_handling/errors6.rs | 106 |
6 files changed, 0 insertions, 329 deletions
diff --git a/rustlings/solutions/13_error_handling/errors1.rs b/rustlings/solutions/13_error_handling/errors1.rs deleted file mode 100644 index f552ca7..0000000 --- a/rustlings/solutions/13_error_handling/errors1.rs +++ /dev/null @@ -1,37 +0,0 @@ -fn generate_nametag_text(name: String) -> Result<String, String> { - // ^^^^^^ ^^^^^^ - if name.is_empty() { - // `Err(String)` instead of `None`. - Err("Empty names aren't allowed".to_string()) - } else { - // `Ok` instead of `Some`. - Ok(format!("Hi! My name is {name}")) - } -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn generates_nametag_text_for_a_nonempty_name() { - assert_eq!( - generate_nametag_text("Beyoncé".to_string()).as_deref(), - Ok("Hi! My name is Beyoncé"), - ); - } - - #[test] - fn explains_why_generating_nametag_text_fails() { - assert_eq!( - generate_nametag_text(String::new()) - .as_ref() - .map_err(|e| e.as_str()), - Err("Empty names aren't allowed"), - ); - } -} diff --git a/rustlings/solutions/13_error_handling/errors2.rs b/rustlings/solutions/13_error_handling/errors2.rs deleted file mode 100644 index f0e144e..0000000 --- a/rustlings/solutions/13_error_handling/errors2.rs +++ /dev/null @@ -1,58 +0,0 @@ -// Say we're writing a game where you can buy items with tokens. All items cost -// 5 tokens, and whenever you purchase items there is a processing fee of 1 -// token. A player of the game will type in how many items they want to buy, and -// the `total_cost` function will calculate the total cost of the items. Since -// the player typed in the quantity, we get it as a string. They might have -// typed anything, not just numbers! -// -// Right now, this function isn't handling the error case at all. What we want -// to do is: If we call the `total_cost` function on a string that is not a -// number, that function will return a `ParseIntError`. In that case, we want to -// immediately return that error from our function and not try to multiply and -// add. -// -// There are at least two ways to implement this that are both correct. But one -// is a lot shorter! - -use std::num::ParseIntError; - -#[allow(unused_variables, clippy::question_mark)] -fn total_cost(item_quantity: &str) -> Result<i32, ParseIntError> { - let processing_fee = 1; - let cost_per_item = 5; - - // Added `?` to propagate the error. - let qty = item_quantity.parse::<i32>()?; - // ^ added - - // Equivalent to this verbose version: - let qty = match item_quantity.parse::<i32>() { - Ok(v) => v, - Err(e) => return Err(e), - }; - - Ok(qty * cost_per_item + processing_fee) -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - use std::num::IntErrorKind; - - #[test] - fn item_quantity_is_a_valid_number() { - assert_eq!(total_cost("34"), Ok(171)); - } - - #[test] - fn item_quantity_is_an_invalid_number() { - assert_eq!( - total_cost("beep boop").unwrap_err().kind(), - &IntErrorKind::InvalidDigit, - ); - } -} diff --git a/rustlings/solutions/13_error_handling/errors3.rs b/rustlings/solutions/13_error_handling/errors3.rs deleted file mode 100644 index 63f4aba..0000000 --- a/rustlings/solutions/13_error_handling/errors3.rs +++ /dev/null @@ -1,32 +0,0 @@ -// This is a program that is trying to use a completed version of the -// `total_cost` function from the previous exercise. It's not working though! -// Why not? What should we do to fix it? - -use std::num::ParseIntError; - -// Don't change this function. -fn total_cost(item_quantity: &str) -> Result<i32, ParseIntError> { - let processing_fee = 1; - let cost_per_item = 5; - let qty = item_quantity.parse::<i32>()?; - - Ok(qty * cost_per_item + processing_fee) -} - -fn main() -> Result<(), ParseIntError> { - // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ added - let mut tokens = 100; - let pretend_user_input = "8"; - - let cost = total_cost(pretend_user_input)?; - - if cost > tokens { - println!("You can't afford that many!"); - } else { - tokens -= cost; - println!("You now have {tokens} tokens."); - } - - // Added this line to return the `Ok` variant of the expected `Result`. - Ok(()) -} diff --git a/rustlings/solutions/13_error_handling/errors4.rs b/rustlings/solutions/13_error_handling/errors4.rs deleted file mode 100644 index 70c5f1c..0000000 --- a/rustlings/solutions/13_error_handling/errors4.rs +++ /dev/null @@ -1,42 +0,0 @@ -use std::cmp::Ordering; - -#[derive(PartialEq, Debug)] -enum CreationError { - Negative, - Zero, -} - -#[derive(PartialEq, Debug)] -struct PositiveNonzeroInteger(u64); - -impl PositiveNonzeroInteger { - fn new(value: i64) -> Result<Self, CreationError> { - match value.cmp(&0) { - Ordering::Less => Err(CreationError::Negative), - Ordering::Equal => Err(CreationError::Zero), - Ordering::Greater => Ok(Self(value as u64)), - } - } -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_creation() { - assert_eq!( - PositiveNonzeroInteger::new(10), - Ok(PositiveNonzeroInteger(10)), - ); - assert_eq!( - PositiveNonzeroInteger::new(-10), - Err(CreationError::Negative), - ); - assert_eq!(PositiveNonzeroInteger::new(0), Err(CreationError::Zero)); - } -} diff --git a/rustlings/solutions/13_error_handling/errors5.rs b/rustlings/solutions/13_error_handling/errors5.rs deleted file mode 100644 index c1424ee..0000000 --- a/rustlings/solutions/13_error_handling/errors5.rs +++ /dev/null @@ -1,54 +0,0 @@ -// 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(()) -} diff --git a/rustlings/solutions/13_error_handling/errors6.rs b/rustlings/solutions/13_error_handling/errors6.rs deleted file mode 100644 index ce18073..0000000 --- a/rustlings/solutions/13_error_handling/errors6.rs +++ /dev/null @@ -1,106 +0,0 @@ -// Using catch-all error types like `Box<dyn Error>` isn't recommended for -// library code where callers might want to make decisions based on the error -// content instead of printing it out or propagating it further. Here, we define -// a custom error type to make it possible for callers to decide what to do next -// when our function returns an error. - -use std::num::ParseIntError; - -#[derive(PartialEq, Debug)] -enum CreationError { - Negative, - Zero, -} - -// A custom error type that we will be using in `PositiveNonzeroInteger::parse`. -#[derive(PartialEq, Debug)] -enum ParsePosNonzeroError { - Creation(CreationError), - ParseInt(ParseIntError), -} - -impl ParsePosNonzeroError { - fn from_creation(err: CreationError) -> Self { - Self::Creation(err) - } - - fn from_parse_int(err: ParseIntError) -> Self { - Self::ParseInt(err) - } -} - -// As an alternative solution, implementing the `From` trait allows for the -// automatic conversion from a `ParseIntError` into a `ParsePosNonzeroError` -// using the `?` operator, without the need to call `map_err`. -// -// ``` -// let x: i64 = s.parse()?; -// ``` -// -// Traits like `From` will be dealt with in later exercises. -impl From<ParseIntError> for ParsePosNonzeroError { - fn from(err: ParseIntError) -> Self { - ParsePosNonzeroError::ParseInt(err) - } -} - -#[derive(PartialEq, Debug)] -struct PositiveNonzeroInteger(u64); - -impl PositiveNonzeroInteger { - fn new(value: i64) -> Result<Self, CreationError> { - match value { - x if x < 0 => Err(CreationError::Negative), - 0 => Err(CreationError::Zero), - x => Ok(Self(x as u64)), - } - } - - fn parse(s: &str) -> Result<Self, ParsePosNonzeroError> { - // Return an appropriate error instead of panicking when `parse()` - // returns an error. - let x: i64 = s.parse().map_err(ParsePosNonzeroError::from_parse_int)?; - // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Self::new(x).map_err(ParsePosNonzeroError::from_creation) - } -} - -fn main() { - // You can optionally experiment here. -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn test_parse_error() { - assert!(matches!( - PositiveNonzeroInteger::parse("not a number"), - Err(ParsePosNonzeroError::ParseInt(_)), - )); - } - - #[test] - fn test_negative() { - assert_eq!( - PositiveNonzeroInteger::parse("-555"), - Err(ParsePosNonzeroError::Creation(CreationError::Negative)), - ); - } - - #[test] - fn test_zero() { - assert_eq!( - PositiveNonzeroInteger::parse("0"), - Err(ParsePosNonzeroError::Creation(CreationError::Zero)), - ); - } - - #[test] - fn test_positive() { - let x = PositiveNonzeroInteger::new(42).unwrap(); - assert_eq!(x.0, 42); - assert_eq!(PositiveNonzeroInteger::parse("42"), Ok(x)); - } -} |