rustlings

solving rustlings ft. dracuxan
git clone [email protected]:dracuxan/rustlings.git
Log | Files | Refs

errors6.rs (2468B)


      1 // Using catch-all error types like `Box<dyn Error>` isn't recommended for
      2 // library code where callers might want to make decisions based on the error
      3 // content instead of printing it out or propagating it further. Here, we define
      4 // a custom error type to make it possible for callers to decide what to do next
      5 // when our function returns an error.
      6 
      7 use std::num::ParseIntError;
      8 
      9 #[derive(PartialEq, Debug)]
     10 enum CreationError {
     11     Negative,
     12     Zero,
     13 }
     14 
     15 // A custom error type that we will be using in `PositiveNonzeroInteger::parse`.
     16 #[derive(PartialEq, Debug)]
     17 enum ParsePosNonzeroError {
     18     Creation(CreationError),
     19     ParseInt(ParseIntError),
     20 }
     21 
     22 impl ParsePosNonzeroError {
     23     fn from_creation(err: CreationError) -> Self {
     24         Self::Creation(err)
     25     }
     26 
     27     // TODO: Add another error conversion function here.
     28     fn from_parse_int(err: ParseIntError) -> Self {
     29         Self::ParseInt(err)
     30     }
     31 }
     32 
     33 #[derive(PartialEq, Debug)]
     34 struct PositiveNonzeroInteger(u64);
     35 
     36 impl PositiveNonzeroInteger {
     37     fn new(value: i64) -> Result<Self, CreationError> {
     38         match value {
     39             x if x < 0 => Err(CreationError::Negative),
     40             0 => Err(CreationError::Zero),
     41             x => Ok(Self(x as u64)),
     42         }
     43     }
     44 
     45     fn parse(s: &str) -> Result<Self, ParsePosNonzeroError> {
     46         // TODO: change this to return an appropriate error instead of panicking
     47         // when `parse()` returns an error.
     48         let x: i64 = s.parse().map_err(ParsePosNonzeroError::from_parse_int)?;
     49         Self::new(x).map_err(ParsePosNonzeroError::from_creation)
     50     }
     51 }
     52 
     53 fn main() {
     54     // You can optionally experiment here.
     55 }
     56 
     57 #[cfg(test)]
     58 mod test {
     59     use super::*;
     60 
     61     #[test]
     62     fn test_parse_error() {
     63         assert!(matches!(
     64             PositiveNonzeroInteger::parse("not a number"),
     65             Err(ParsePosNonzeroError::ParseInt(_)),
     66         ));
     67     }
     68 
     69     #[test]
     70     fn test_negative() {
     71         assert_eq!(
     72             PositiveNonzeroInteger::parse("-555"),
     73             Err(ParsePosNonzeroError::Creation(CreationError::Negative)),
     74         );
     75     }
     76 
     77     #[test]
     78     fn test_zero() {
     79         assert_eq!(
     80             PositiveNonzeroInteger::parse("0"),
     81             Err(ParsePosNonzeroError::Creation(CreationError::Zero)),
     82         );
     83     }
     84 
     85     #[test]
     86     fn test_positive() {
     87         let x = PositiveNonzeroInteger::new(42).unwrap();
     88         assert_eq!(x.0, 42);
     89         assert_eq!(PositiveNonzeroInteger::parse("42"), Ok(x));
     90     }
     91 }