mirror of https://github.com/sunface/rust-course
				
				
				
			
			You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					123 lines
				
				3.3 KiB
			
		
		
			
		
	
	
					123 lines
				
				3.3 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								// from_str.rs
							 | 
						||
| 
								 | 
							
								// This is similar to from_into.rs, but this time we'll implement `FromStr`
							 | 
						||
| 
								 | 
							
								// and return errors instead of falling back to a default value.
							 | 
						||
| 
								 | 
							
								// Additionally, upon implementing FromStr, you can use the `parse` method
							 | 
						||
| 
								 | 
							
								// on strings to generate an object of the implementor type.
							 | 
						||
| 
								 | 
							
								// You can read more about it at https://doc.rust-lang.org/std/str/trait.FromStr.html
							 | 
						||
| 
								 | 
							
								use std::num::ParseIntError;
							 | 
						||
| 
								 | 
							
								use std::str::FromStr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#[derive(Debug, PartialEq)]
							 | 
						||
| 
								 | 
							
								struct Person {
							 | 
						||
| 
								 | 
							
								    name: String,
							 | 
						||
| 
								 | 
							
								    age: usize,
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// We will use this error type for the `FromStr` implementation.
							 | 
						||
| 
								 | 
							
								#[derive(Debug, PartialEq)]
							 | 
						||
| 
								 | 
							
								enum ParsePersonError {
							 | 
						||
| 
								 | 
							
								    // Empty input string
							 | 
						||
| 
								 | 
							
								    Empty,
							 | 
						||
| 
								 | 
							
								    // Incorrect number of fields
							 | 
						||
| 
								 | 
							
								    BadLen,
							 | 
						||
| 
								 | 
							
								    // Empty name field
							 | 
						||
| 
								 | 
							
								    NoName,
							 | 
						||
| 
								 | 
							
								    // Wrapped error from parse::<usize>()
							 | 
						||
| 
								 | 
							
								    ParseInt(ParseIntError),
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// I AM NOT DONE
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Steps:
							 | 
						||
| 
								 | 
							
								// 1. If the length of the provided string is 0, an error should be returned
							 | 
						||
| 
								 | 
							
								// 2. Split the given string on the commas present in it
							 | 
						||
| 
								 | 
							
								// 3. Only 2 elements should be returned from the split, otherwise return an error
							 | 
						||
| 
								 | 
							
								// 4. Extract the first element from the split operation and use it as the name
							 | 
						||
| 
								 | 
							
								// 5. Extract the other element from the split operation and parse it into a `usize` as the age
							 | 
						||
| 
								 | 
							
								//    with something like `"4".parse::<usize>()`
							 | 
						||
| 
								 | 
							
								// 6. If while extracting the name and the age something goes wrong, an error should be returned
							 | 
						||
| 
								 | 
							
								// If everything goes well, then return a Result of a Person object
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								impl FromStr for Person {
							 | 
						||
| 
								 | 
							
								    type Err = ParsePersonError;
							 | 
						||
| 
								 | 
							
								    fn from_str(s: &str) -> Result<Person, Self::Err> {
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								fn main() {
							 | 
						||
| 
								 | 
							
								    let p = "Mark,20".parse::<Person>().unwrap();
							 | 
						||
| 
								 | 
							
								    println!("{:?}", p);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#[cfg(test)]
							 | 
						||
| 
								 | 
							
								mod tests {
							 | 
						||
| 
								 | 
							
								    use super::*;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    #[test]
							 | 
						||
| 
								 | 
							
								    fn empty_input() {
							 | 
						||
| 
								 | 
							
								        assert_eq!("".parse::<Person>(), Err(ParsePersonError::Empty));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    #[test]
							 | 
						||
| 
								 | 
							
								    fn good_input() {
							 | 
						||
| 
								 | 
							
								        let p = "John,32".parse::<Person>();
							 | 
						||
| 
								 | 
							
								        assert!(p.is_ok());
							 | 
						||
| 
								 | 
							
								        let p = p.unwrap();
							 | 
						||
| 
								 | 
							
								        assert_eq!(p.name, "John");
							 | 
						||
| 
								 | 
							
								        assert_eq!(p.age, 32);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    #[test]
							 | 
						||
| 
								 | 
							
								    fn missing_age() {
							 | 
						||
| 
								 | 
							
								        assert!(matches!(
							 | 
						||
| 
								 | 
							
								            "John,".parse::<Person>(),
							 | 
						||
| 
								 | 
							
								            Err(ParsePersonError::ParseInt(_))
							 | 
						||
| 
								 | 
							
								        ));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    #[test]
							 | 
						||
| 
								 | 
							
								    fn invalid_age() {
							 | 
						||
| 
								 | 
							
								        assert!(matches!(
							 | 
						||
| 
								 | 
							
								            "John,twenty".parse::<Person>(),
							 | 
						||
| 
								 | 
							
								            Err(ParsePersonError::ParseInt(_))
							 | 
						||
| 
								 | 
							
								        ));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    #[test]
							 | 
						||
| 
								 | 
							
								    fn missing_comma_and_age() {
							 | 
						||
| 
								 | 
							
								        assert_eq!("John".parse::<Person>(), Err(ParsePersonError::BadLen));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    #[test]
							 | 
						||
| 
								 | 
							
								    fn missing_name() {
							 | 
						||
| 
								 | 
							
								        assert_eq!(",1".parse::<Person>(), Err(ParsePersonError::NoName));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    #[test]
							 | 
						||
| 
								 | 
							
								    fn missing_name_and_age() {
							 | 
						||
| 
								 | 
							
								        assert!(matches!(
							 | 
						||
| 
								 | 
							
								            ",".parse::<Person>(),
							 | 
						||
| 
								 | 
							
								            Err(ParsePersonError::NoName | ParsePersonError::ParseInt(_))
							 | 
						||
| 
								 | 
							
								        ));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    #[test]
							 | 
						||
| 
								 | 
							
								    fn missing_name_and_invalid_age() {
							 | 
						||
| 
								 | 
							
								        assert!(matches!(
							 | 
						||
| 
								 | 
							
								            ",one".parse::<Person>(),
							 | 
						||
| 
								 | 
							
								            Err(ParsePersonError::NoName | ParsePersonError::ParseInt(_))
							 | 
						||
| 
								 | 
							
								        ));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    #[test]
							 | 
						||
| 
								 | 
							
								    fn trailing_comma() {
							 | 
						||
| 
								 | 
							
								        assert_eq!("John,32,".parse::<Person>(), Err(ParsePersonError::BadLen));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    #[test]
							 | 
						||
| 
								 | 
							
								    fn trailing_comma_and_some_string() {
							 | 
						||
| 
								 | 
							
								        assert_eq!(
							 | 
						||
| 
								 | 
							
								            "John,32,man".parse::<Person>(),
							 | 
						||
| 
								 | 
							
								            Err(ParsePersonError::BadLen)
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 |