Going through rustlings for the first time
at main 91 lines 2.5 kB view raw
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 7use std::num::ParseIntError; 8 9#[derive(PartialEq, Debug)] 10enum CreationError { 11 Negative, 12 Zero, 13} 14 15// A custom error type that we will be using in `PositiveNonzeroInteger::parse`. 16#[derive(PartialEq, Debug)] 17enum ParsePosNonzeroError { 18 Creation(CreationError), 19 ParseInt(ParseIntError), 20} 21 22impl ParsePosNonzeroError { 23 fn from_creation(err: CreationError) -> Self { 24 Self::Creation(err) 25 } 26 27 fn from_parse_int(err: ParseIntError) -> Self { 28 Self::ParseInt(err) 29 } 30} 31 32#[derive(PartialEq, Debug)] 33struct PositiveNonzeroInteger(u64); 34 35impl PositiveNonzeroInteger { 36 fn new(value: i64) -> Result<Self, CreationError> { 37 match value { 38 x if x < 0 => Err(CreationError::Negative), 39 0 => Err(CreationError::Zero), 40 x => Ok(Self(x as u64)), 41 } 42 } 43 44 fn parse(s: &str) -> Result<Self, ParsePosNonzeroError> { 45 // Return an appropriate error instead of panicking when `parse()` 46 // returns an error. 47 let x: i64 = s.parse().map_err(ParsePosNonzeroError::from_parse_int)?; 48 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 49 Self::new(x).map_err(ParsePosNonzeroError::from_creation) 50 } 51} 52 53fn main() { 54 // You can optionally experiment here. 55} 56 57#[cfg(test)] 58mod 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}