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 }