try_from_into.rs (4615B)
1 // `TryFrom` is a simple and safe type conversion that may fail in a controlled 2 // way under some circumstances. Basically, this is the same as `From`. The main 3 // difference is that this should return a `Result` type instead of the target 4 // type itself. You can read more about it in the documentation: 5 // https://doc.rust-lang.org/std/convert/trait.TryFrom.html 6 7 #![allow(clippy::useless_vec)] 8 use std::convert::{TryFrom, TryInto}; 9 10 #[derive(Debug, PartialEq)] 11 struct Color { 12 red: u8, 13 green: u8, 14 blue: u8, 15 } 16 17 // We will use this error type for the `TryFrom` conversions. 18 #[derive(Debug, PartialEq)] 19 enum IntoColorError { 20 // Incorrect length of slice 21 BadLen, 22 // Integer conversion error 23 IntConversion, 24 } 25 26 // TODO: Tuple implementation. 27 // Correct RGB color values must be integers in the 0..=255 range. 28 impl TryFrom<(i16, i16, i16)> for Color { 29 type Error = IntoColorError; 30 31 fn try_from(tuple: (i16, i16, i16)) -> Result<Self, Self::Error> {} 32 } 33 34 // TODO: Array implementation. 35 impl TryFrom<[i16; 3]> for Color { 36 type Error = IntoColorError; 37 38 fn try_from(arr: [i16; 3]) -> Result<Self, Self::Error> {} 39 } 40 41 // TODO: Slice implementation. 42 // This implementation needs to check the slice length. 43 impl TryFrom<&[i16]> for Color { 44 type Error = IntoColorError; 45 46 fn try_from(slice: &[i16]) -> Result<Self, Self::Error> {} 47 } 48 49 fn main() { 50 // Using the `try_from` function. 51 let c1 = Color::try_from((183, 65, 14)); 52 println!("{c1:?}"); 53 54 // Since `TryFrom` is implemented for `Color`, we can use `TryInto`. 55 let c2: Result<Color, _> = [183, 65, 14].try_into(); 56 println!("{c2:?}"); 57 58 let v = vec![183, 65, 14]; 59 // With slice we should use the `try_from` function 60 let c3 = Color::try_from(&v[..]); 61 println!("{c3:?}"); 62 // or put the slice within round brackets and use `try_into`. 63 let c4: Result<Color, _> = (&v[..]).try_into(); 64 println!("{c4:?}"); 65 } 66 67 #[cfg(test)] 68 mod tests { 69 use super::*; 70 use IntoColorError::*; 71 72 #[test] 73 fn test_tuple_out_of_range_positive() { 74 assert_eq!(Color::try_from((256, 1000, 10000)), Err(IntConversion)); 75 } 76 77 #[test] 78 fn test_tuple_out_of_range_negative() { 79 assert_eq!(Color::try_from((-1, -10, -256)), Err(IntConversion)); 80 } 81 82 #[test] 83 fn test_tuple_sum() { 84 assert_eq!(Color::try_from((-1, 255, 255)), Err(IntConversion)); 85 } 86 87 #[test] 88 fn test_tuple_correct() { 89 let c: Result<Color, _> = (183, 65, 14).try_into(); 90 assert!(c.is_ok()); 91 assert_eq!( 92 c.unwrap(), 93 Color { 94 red: 183, 95 green: 65, 96 blue: 14, 97 } 98 ); 99 } 100 101 #[test] 102 fn test_array_out_of_range_positive() { 103 let c: Result<Color, _> = [1000, 10000, 256].try_into(); 104 assert_eq!(c, Err(IntConversion)); 105 } 106 107 #[test] 108 fn test_array_out_of_range_negative() { 109 let c: Result<Color, _> = [-10, -256, -1].try_into(); 110 assert_eq!(c, Err(IntConversion)); 111 } 112 113 #[test] 114 fn test_array_sum() { 115 let c: Result<Color, _> = [-1, 255, 255].try_into(); 116 assert_eq!(c, Err(IntConversion)); 117 } 118 119 #[test] 120 fn test_array_correct() { 121 let c: Result<Color, _> = [183, 65, 14].try_into(); 122 assert!(c.is_ok()); 123 assert_eq!( 124 c.unwrap(), 125 Color { 126 red: 183, 127 green: 65, 128 blue: 14 129 } 130 ); 131 } 132 133 #[test] 134 fn test_slice_out_of_range_positive() { 135 let arr = [10000, 256, 1000]; 136 assert_eq!(Color::try_from(&arr[..]), Err(IntConversion)); 137 } 138 139 #[test] 140 fn test_slice_out_of_range_negative() { 141 let arr = [-256, -1, -10]; 142 assert_eq!(Color::try_from(&arr[..]), Err(IntConversion)); 143 } 144 145 #[test] 146 fn test_slice_sum() { 147 let arr = [-1, 255, 255]; 148 assert_eq!(Color::try_from(&arr[..]), Err(IntConversion)); 149 } 150 151 #[test] 152 fn test_slice_correct() { 153 let v = vec![183, 65, 14]; 154 let c: Result<Color, _> = Color::try_from(&v[..]); 155 assert!(c.is_ok()); 156 assert_eq!( 157 c.unwrap(), 158 Color { 159 red: 183, 160 green: 65, 161 blue: 14, 162 } 163 ); 164 } 165 166 #[test] 167 fn test_slice_excess_length() { 168 let v = vec![0, 0, 0, 0]; 169 assert_eq!(Color::try_from(&v[..]), Err(BadLen)); 170 } 171 172 #[test] 173 fn test_slice_insufficient_length() { 174 let v = vec![0, 0]; 175 assert_eq!(Color::try_from(&v[..]), Err(BadLen)); 176 } 177 }