From 763aa6e378a586caae2d8d63755a85eeba227933 Mon Sep 17 00:00:00 2001 From: IkaR49 Date: Sat, 16 May 2020 00:02:57 +0300 Subject: [PATCH] feat: Rewrite try_from_into (#393) --- exercises/conversions/from_str.rs | 3 +- exercises/conversions/try_from_into.rs | 144 +++++++++++++++---------- info.toml | 5 +- 3 files changed, 91 insertions(+), 61 deletions(-) diff --git a/exercises/conversions/from_str.rs b/exercises/conversions/from_str.rs index 14e9e09..014d054 100644 --- a/exercises/conversions/from_str.rs +++ b/exercises/conversions/from_str.rs @@ -17,6 +17,7 @@ struct Person { // 3. Extract the first element from the split operation and use it as the name // 4. If the name is empty, then return an error // 5. Extract the other element from the split operation and parse it into a `usize` as the age +// with something like `"4".parse::()`. // If while parsing the age, something goes wrong, then return an error // Otherwise, then return a Result of a Person object impl FromStr for Person { @@ -82,4 +83,4 @@ mod tests { ",one".parse::().unwrap(); } -} \ No newline at end of file +} diff --git a/exercises/conversions/try_from_into.rs b/exercises/conversions/try_from_into.rs index 9968075..dbdbe00 100644 --- a/exercises/conversions/try_from_into.rs +++ b/exercises/conversions/try_from_into.rs @@ -5,98 +5,126 @@ use std::convert::{TryInto, TryFrom}; #[derive(Debug)] -struct Person { - name: String, - age: usize, +struct Color { + red: u8, + green: u8, + blue: u8, } // I AM NOT DONE + // Your task is to complete this implementation -// in order for the line `let p = Person::try_from("Mark,20")` to compile -// and return an Ok result of inner type Person. -// Please note that you'll need to parse the age component into a `usize` -// with something like `"4".parse::()`. The outcome of this needs to -// be handled appropriately. +// and return an Ok result of inner type Color. +// You need create implementation for a tuple of three integer, +// an array of three integer and slice of integer. // -// Steps: -// 1. If the length of the provided string is 0, then return an error -// 2. Split the given string on the commas present in it -// 3. Extract the first element from the split operation and use it as the name -// 4. If the name is empty, then return an error. -// 5. Extract the other element from the split operation and parse it into a `usize` as the age -// If while parsing the age, something goes wrong, then return an error -// Otherwise, then return a Result of a Person object -impl TryFrom<&str> for Person { +// Note, that implementation for tuple and array will be checked at compile-time, +// but slice implementation need check slice length! +// Also note, that chunk of correct rgb color must be integer in range 0..=255. + +// Tuple implementation +impl TryFrom<(i16, i16, i16)> for Color { type Error = String; - fn try_from(s: &str) -> Result { + fn try_from(tuple: (i16, i16, i16)) -> Result { + } +} + +// Array implementation +impl TryFrom<[i16; 3]> for Color { + type Error = String; + fn try_from(arr: [i16; 3]) -> Result { + } +} + +// Slice implementation +impl TryFrom<&[i16]> for Color { + type Error = String; + fn try_from(slice: &[i16]) -> Result { } } fn main() { // Use the `from` function - let p1 = Person::try_from("Mark,20"); - // Since From is implemented for Person, we should be able to use Into - let p2: Result = "Gerald,70".try_into(); - println!("{:?}", p1); - println!("{:?}", p2); + let c1 = Color::try_from((183, 65, 14)); + println!("{:?}", c1); + + // Since From is implemented for Color, we should be able to use Into + let c2: Result = [183, 65, 14].try_into(); + println!("{:?}", c2); + + let v = vec![183, 65, 14]; + // With slice we should use `from` function + let c3 = Color::try_from(&v[..]); + println!("{:?}", c3); + // or take slice within round brackets and use Into + let c4: Result = (&v[..]).try_into(); + println!("{:?}", c4); } #[cfg(test)] mod tests { use super::*; + #[test] - fn test_bad_convert() { - // Test that error is returned when bad string is provided - let p = Person::try_from(""); - assert!(p.is_err()); - } - #[test] - fn test_good_convert() { - // Test that "Mark,20" works - let p = Person::try_from("Mark,20"); - assert!(p.is_ok()); - let p = p.unwrap(); - assert_eq!(p.name, "Mark"); - assert_eq!(p.age, 20); + #[should_panic] + fn test_tuple_out_of_range_positive() { + let _ = Color::try_from((256, 1000, 10000)).unwrap(); } #[test] #[should_panic] - fn test_panic_empty_input() { - let p: Person = "".try_into().unwrap(); + fn test_tuple_out_of_range_negative() { + let _ = Color::try_from((-1, -10, -256)).unwrap(); } #[test] - #[should_panic] - fn test_panic_bad_age() { - let p = Person::try_from("Mark,twenty").unwrap(); + fn test_tuple_correct() { + let c: Color = (183, 65, 14).try_into().unwrap(); + assert_eq!(c.red, 183); + assert_eq!(c.green, 65); + assert_eq!(c.blue, 14); } #[test] #[should_panic] - fn test_missing_comma_and_age() { - let _: Person = "Mark".try_into().unwrap(); + fn test_array_out_of_range_positive() { + let _: Color = [1000, 10000, 256].try_into().unwrap(); + } + #[test] + #[should_panic] + fn test_array_out_of_range_negative() { + let _: Color = [-10, -256, -1].try_into().unwrap(); + } + #[test] + fn test_array_correct() { + let c: Color = [183, 65, 14].try_into().unwrap(); + assert_eq!(c.red, 183); + assert_eq!(c.green, 65); + assert_eq!(c.blue, 14); } #[test] #[should_panic] - fn test_missing_age() { - let _: Person = "Mark,".try_into().unwrap(); + fn test_slice_out_of_range_positive() { + let arr = [10000, 256, 1000]; + let _ = Color::try_from(&arr[..]).unwrap(); } - #[test] #[should_panic] - fn test_missing_name() { - let _ : Person = ",1".try_into().unwrap(); + fn test_slice_out_of_range_negative() { + let arr = [-256, -1, -10]; + let _ = Color::try_from(&arr[..]).unwrap(); + } + #[test] + fn test_slice_correct() { + let v = vec![183, 65, 14]; + let c = Color::try_from(&v[..]).unwrap(); + assert_eq!(c.red, 183); + assert_eq!(c.green, 65); + assert_eq!(c.blue, 14); } - #[test] #[should_panic] - fn test_missing_name_and_age() { - let _: Person = ",".try_into().unwrap(); + fn test_slice_excess_length() { + let v = vec![0, 0, 0, 0]; + let _ = Color::try_from(&v[..]).unwrap(); } - - #[test] - #[should_panic] - fn test_missing_name_and_invalid_age() { - let _: Person = ",one".try_into().unwrap(); - } -} \ No newline at end of file +} diff --git a/info.toml b/info.toml index c47041b..7858d7c 100644 --- a/info.toml +++ b/info.toml @@ -799,5 +799,6 @@ name = "from_str" path = "exercises/conversions/from_str.rs" mode = "test" hint = """ -If you've already solved try_from_into.rs, then this is almost a copy-paste. -Otherwise, go ahead and solve try_from_into.rs first.""" +The implementation of FromStr should return an Ok with a Person object, +or an Err with a string if the string is not valid. +This is a some like an `try_from_into` exercise."""