From b609f0431c0031c8aa9113fea4de4b23db05cf77 Mon Sep 17 00:00:00 2001 From: mokou Date: Fri, 15 Jul 2022 12:51:12 +0200 Subject: [PATCH] feat: remove advanced_errs --- exercises/advanced_errors/advanced_errs1.rs | 98 ---------- exercises/advanced_errors/advanced_errs2.rs | 202 -------------------- info.toml | 52 ----- 3 files changed, 352 deletions(-) delete mode 100644 exercises/advanced_errors/advanced_errs1.rs delete mode 100644 exercises/advanced_errors/advanced_errs2.rs diff --git a/exercises/advanced_errors/advanced_errs1.rs b/exercises/advanced_errors/advanced_errs1.rs deleted file mode 100644 index 4bc7b63..0000000 --- a/exercises/advanced_errors/advanced_errs1.rs +++ /dev/null @@ -1,98 +0,0 @@ -// advanced_errs1.rs - -// Remember back in errors6, we had multiple mapping functions so that we -// could translate lower-level errors into our custom error type using -// `map_err()`? What if we could use the `?` operator directly instead? - -// Make this code compile! Execute `rustlings hint advanced_errs1` for -// hints :) - -// I AM NOT DONE - -use std::num::ParseIntError; -use std::str::FromStr; - -// This is a custom error type that we will be using in the `FromStr` -// implementation. -#[derive(PartialEq, Debug)] -enum ParsePosNonzeroError { - Creation(CreationError), - ParseInt(ParseIntError), -} - -impl From for ParsePosNonzeroError { - fn from(e: CreationError) -> Self { - // TODO: complete this implementation so that the `?` operator will - // work for `CreationError` - } -} - -// TODO: implement another instance of the `From` trait here so that the -// `?` operator will work in the other place in the `FromStr` -// implementation below. - -// Don't change anything below this line. - -impl FromStr for PositiveNonzeroInteger { - type Err = ParsePosNonzeroError; - fn from_str(s: &str) -> Result { - let x: i64 = s.parse()?; - Ok(PositiveNonzeroInteger::new(x)?) - } -} - -#[derive(PartialEq, Debug)] -struct PositiveNonzeroInteger(u64); - -#[derive(PartialEq, Debug)] -enum CreationError { - Negative, - Zero, -} - -impl PositiveNonzeroInteger { - fn new(value: i64) -> Result { - match value { - x if x < 0 => Err(CreationError::Negative), - x if x == 0 => Err(CreationError::Zero), - x => Ok(PositiveNonzeroInteger(x as u64)), - } - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn test_parse_error() { - // We can't construct a ParseIntError, so we have to pattern match. - assert!(matches!( - PositiveNonzeroInteger::from_str("not a number"), - Err(ParsePosNonzeroError::ParseInt(_)) - )); - } - - #[test] - fn test_negative() { - assert_eq!( - PositiveNonzeroInteger::from_str("-555"), - Err(ParsePosNonzeroError::Creation(CreationError::Negative)) - ); - } - - #[test] - fn test_zero() { - assert_eq!( - PositiveNonzeroInteger::from_str("0"), - Err(ParsePosNonzeroError::Creation(CreationError::Zero)) - ); - } - - #[test] - fn test_positive() { - let x = PositiveNonzeroInteger::new(42); - assert!(x.is_ok()); - assert_eq!(PositiveNonzeroInteger::from_str("42"), Ok(x.unwrap())); - } -} diff --git a/exercises/advanced_errors/advanced_errs2.rs b/exercises/advanced_errors/advanced_errs2.rs deleted file mode 100644 index 54e669f..0000000 --- a/exercises/advanced_errors/advanced_errs2.rs +++ /dev/null @@ -1,202 +0,0 @@ -// advanced_errs2.rs - -// This exercise demonstrates a few traits that are useful for custom error -// types to implement, especially so that other code can consume the custom -// error type more usefully. - -// Make this compile, and make the tests pass! -// Execute `rustlings hint advanced_errs2` for hints. - -// Steps: -// 1. Implement a missing trait so that `main()` will compile. -// 2. Complete the partial implementation of `From` for -// `ParseClimateError`. -// 3. Handle the missing error cases in the `FromStr` implementation for -// `Climate`. -// 4. Complete the partial implementation of `Display` for -// `ParseClimateError`. - -// I AM NOT DONE - -use std::error::Error; -use std::fmt::{self, Display, Formatter}; -use std::num::{ParseFloatError, ParseIntError}; -use std::str::FromStr; - -// This is the custom error type that we will be using for the parser for -// `Climate`. -#[derive(Debug, PartialEq)] -enum ParseClimateError { - Empty, - BadLen, - NoCity, - ParseInt(ParseIntError), - ParseFloat(ParseFloatError), -} - -// This `From` implementation allows the `?` operator to work on -// `ParseIntError` values. -impl From for ParseClimateError { - fn from(e: ParseIntError) -> Self { - Self::ParseInt(e) - } -} - -// This `From` implementation allows the `?` operator to work on -// `ParseFloatError` values. -impl From for ParseClimateError { - fn from(e: ParseFloatError) -> Self { - // TODO: Complete this function - } -} - -// TODO: Implement a missing trait so that `main()` below will compile. It -// is not necessary to implement any methods inside the missing trait. - -// The `Display` trait allows for other code to obtain the error formatted -// as a user-visible string. -impl Display for ParseClimateError { - // TODO: Complete this function so that it produces the correct strings - // for each error variant. - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - // Imports the variants to make the following code more compact. - use ParseClimateError::*; - match self { - NoCity => write!(f, "no city name"), - ParseFloat(e) => write!(f, "error parsing temperature: {}", e), - } - } -} - -#[derive(Debug, PartialEq)] -struct Climate { - city: String, - year: u32, - temp: f32, -} - -// Parser for `Climate`. -// 1. Split the input string into 3 fields: city, year, temp. -// 2. Return an error if the string is empty or has the wrong number of -// fields. -// 3. Return an error if the city name is empty. -// 4. Parse the year as a `u32` and return an error if that fails. -// 5. Parse the temp as a `f32` and return an error if that fails. -// 6. Return an `Ok` value containing the completed `Climate` value. -impl FromStr for Climate { - type Err = ParseClimateError; - // TODO: Complete this function by making it handle the missing error - // cases. - fn from_str(s: &str) -> Result { - let v: Vec<_> = s.split(',').collect(); - let (city, year, temp) = match &v[..] { - [city, year, temp] => (city.to_string(), year, temp), - _ => return Err(ParseClimateError::BadLen), - }; - let year: u32 = year.parse()?; - let temp: f32 = temp.parse()?; - Ok(Climate { city, year, temp }) - } -} - -// Don't change anything below this line (other than to enable ignored -// tests). - -fn main() -> Result<(), Box> { - println!("{:?}", "Hong Kong,1999,25.7".parse::()?); - println!("{:?}", "".parse::()?); - Ok(()) -} - -#[cfg(test)] -mod test { - use super::*; - #[test] - fn test_empty() { - let res = "".parse::(); - assert_eq!(res, Err(ParseClimateError::Empty)); - assert_eq!(res.unwrap_err().to_string(), "empty input"); - } - #[test] - fn test_short() { - let res = "Boston,1991".parse::(); - assert_eq!(res, Err(ParseClimateError::BadLen)); - assert_eq!(res.unwrap_err().to_string(), "incorrect number of fields"); - } - #[test] - fn test_long() { - let res = "Paris,1920,17.2,extra".parse::(); - assert_eq!(res, Err(ParseClimateError::BadLen)); - assert_eq!(res.unwrap_err().to_string(), "incorrect number of fields"); - } - #[test] - fn test_no_city() { - let res = ",1997,20.5".parse::(); - assert_eq!(res, Err(ParseClimateError::NoCity)); - assert_eq!(res.unwrap_err().to_string(), "no city name"); - } - #[test] - fn test_parse_int_neg() { - let res = "Barcelona,-25,22.3".parse::(); - assert!(matches!(res, Err(ParseClimateError::ParseInt(_)))); - let err = res.unwrap_err(); - if let ParseClimateError::ParseInt(ref inner) = err { - assert_eq!( - err.to_string(), - format!("error parsing year: {}", inner.to_string()) - ); - } else { - unreachable!(); - }; - } - #[test] - fn test_parse_int_bad() { - let res = "Beijing,foo,15.0".parse::(); - assert!(matches!(res, Err(ParseClimateError::ParseInt(_)))); - let err = res.unwrap_err(); - if let ParseClimateError::ParseInt(ref inner) = err { - assert_eq!( - err.to_string(), - format!("error parsing year: {}", inner.to_string()) - ); - } else { - unreachable!(); - }; - } - #[test] - fn test_parse_float() { - let res = "Manila,2001,bar".parse::(); - assert!(matches!(res, Err(ParseClimateError::ParseFloat(_)))); - let err = res.unwrap_err(); - if let ParseClimateError::ParseFloat(ref inner) = err { - assert_eq!( - err.to_string(), - format!("error parsing temperature: {}", inner.to_string()) - ); - } else { - unreachable!(); - }; - } - #[test] - fn test_parse_good() { - let res = "Munich,2015,23.1".parse::(); - assert_eq!( - res, - Ok(Climate { - city: "Munich".to_string(), - year: 2015, - temp: 23.1, - }) - ); - } - #[test] - #[ignore] - fn test_downcast() { - let res = "São Paulo,-21,28.5".parse::(); - assert!(matches!(res, Err(ParseClimateError::ParseInt(_)))); - let err = res.unwrap_err(); - let inner: Option<&(dyn Error + 'static)> = err.source(); - assert!(inner.is_some()); - assert!(inner.unwrap().is::()); - } -} diff --git a/info.toml b/info.toml index 3c37f95..c239121 100644 --- a/info.toml +++ b/info.toml @@ -1061,55 +1061,3 @@ path = "exercises/conversions/as_ref_mut.rs" mode = "test" hint = """ Add AsRef 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. -"""