summaryrefslogtreecommitdiff
path: root/exercises/conversions/try_from_into.rs
diff options
context:
space:
mode:
authorTaylor Yu <tlyu@mit.edu>2021-06-24 21:33:41 -0500
committerTaylor Yu <tlyu@mit.edu>2021-06-24 21:33:41 -0500
commit2dc93caddad43821743e4903d89b355df58d7a49 (patch)
tree050edd4010df3358e7a50087ed4aa9b49cca7911 /exercises/conversions/try_from_into.rs
parentde6c45ad244528562889138757f3c8c7f089bbec (diff)
fix(from_str, try_from_into): custom error types
Remove the use of trait objects as errors from `from_str` and `try_from_into`; they seem to have caused a lot of confusion in practice. (Also, it's considered best practice to use custom error types instead of boxed errors in library code.) Instead, use custom error enums, and update hints accordingly. Hints also provide some guidance about converting errors, which could be covered more completely in a future advanced errors section. Also move from_str to directly after the similar exercise `from_into`, for the sake of familiarity when solving.
Diffstat (limited to 'exercises/conversions/try_from_into.rs')
-rw-r--r--exercises/conversions/try_from_into.rs74
1 files changed, 52 insertions, 22 deletions
diff --git a/exercises/conversions/try_from_into.rs b/exercises/conversions/try_from_into.rs
index c0b5d98..b8ec445 100644
--- a/exercises/conversions/try_from_into.rs
+++ b/exercises/conversions/try_from_into.rs
@@ -1,9 +1,9 @@
+// try_from_into.rs
// TryFrom is a simple and safe type conversion that may fail in a controlled way under some circumstances.
// Basically, this is the same as From. The main difference is that this should return a Result type
// instead of the target type itself.
// You can read more about it at https://doc.rust-lang.org/std/convert/trait.TryFrom.html
use std::convert::{TryFrom, TryInto};
-use std::error;
#[derive(Debug, PartialEq)]
struct Color {
@@ -12,12 +12,21 @@ struct Color {
blue: u8,
}
+// We will use this error type for these `TryFrom` conversions.
+#[derive(Debug, PartialEq)]
+enum IntoColorError {
+ // Incorrect length of slice
+ BadLen,
+ // Integer conversion error
+ IntConversion,
+}
+
// I AM NOT DONE
// Your task is to complete this implementation
// and return an Ok result of inner type Color.
// You need to create an implementation for a tuple of three integers,
-// an array of three integers and a slice of integers.
+// an array of three integers, and a slice of integers.
//
// Note that the implementation for tuple and array will be checked at compile time,
// but the slice implementation needs to check the slice length!
@@ -25,20 +34,23 @@ struct Color {
// Tuple implementation
impl TryFrom<(i16, i16, i16)> for Color {
- type Error = Box<dyn error::Error>;
- fn try_from(tuple: (i16, i16, i16)) -> Result<Self, Self::Error> {}
+ type Error = IntoColorError;
+ fn try_from(tuple: (i16, i16, i16)) -> Result<Self, Self::Error> {
+ }
}
// Array implementation
impl TryFrom<[i16; 3]> for Color {
- type Error = Box<dyn error::Error>;
- fn try_from(arr: [i16; 3]) -> Result<Self, Self::Error> {}
+ type Error = IntoColorError;
+ fn try_from(arr: [i16; 3]) -> Result<Self, Self::Error> {
+ }
}
// Slice implementation
impl TryFrom<&[i16]> for Color {
- type Error = Box<dyn error::Error>;
- fn try_from(slice: &[i16]) -> Result<Self, Self::Error> {}
+ type Error = IntoColorError;
+ fn try_from(slice: &[i16]) -> Result<Self, Self::Error> {
+ }
}
fn main() {
@@ -46,15 +58,15 @@ fn main() {
let c1 = Color::try_from((183, 65, 14));
println!("{:?}", c1);
- // Since From is implemented for Color, we should be able to use Into
+ // Since TryFrom is implemented for Color, we should be able to use TryInto
let c2: Result<Color, _> = [183, 65, 14].try_into();
println!("{:?}", c2);
let v = vec![183, 65, 14];
- // With slice we should use `from` function
+ // With slice we should use `try_from` function
let c3 = Color::try_from(&v[..]);
println!("{:?}", c3);
- // or take slice within round brackets and use Into
+ // or take slice within round brackets and use TryInto
let c4: Result<Color, _> = (&v[..]).try_into();
println!("{:?}", c4);
}
@@ -65,15 +77,24 @@ mod tests {
#[test]
fn test_tuple_out_of_range_positive() {
- assert!(Color::try_from((256, 1000, 10000)).is_err());
+ assert_eq!(
+ Color::try_from((256, 1000, 10000)),
+ Err(IntoColorError::IntConversion)
+ );
}
#[test]
fn test_tuple_out_of_range_negative() {
- assert!(Color::try_from((-1, -10, -256)).is_err());
+ assert_eq!(
+ Color::try_from((-1, -10, -256)),
+ Err(IntoColorError::IntConversion)
+ );
}
#[test]
fn test_tuple_sum() {
- assert!(Color::try_from((-1, 255, 255)).is_err());
+ assert_eq!(
+ Color::try_from((-1, 255, 255)),
+ Err(IntoColorError::IntConversion)
+ );
}
#[test]
fn test_tuple_correct() {
@@ -91,17 +112,17 @@ mod tests {
#[test]
fn test_array_out_of_range_positive() {
let c: Result<Color, _> = [1000, 10000, 256].try_into();
- assert!(c.is_err());
+ assert_eq!(c, Err(IntoColorError::IntConversion));
}
#[test]
fn test_array_out_of_range_negative() {
let c: Result<Color, _> = [-10, -256, -1].try_into();
- assert!(c.is_err());
+ assert_eq!(c, Err(IntoColorError::IntConversion));
}
#[test]
fn test_array_sum() {
let c: Result<Color, _> = [-1, 255, 255].try_into();
- assert!(c.is_err());
+ assert_eq!(c, Err(IntoColorError::IntConversion));
}
#[test]
fn test_array_correct() {
@@ -119,17 +140,26 @@ mod tests {
#[test]
fn test_slice_out_of_range_positive() {
let arr = [10000, 256, 1000];
- assert!(Color::try_from(&arr[..]).is_err());
+ assert_eq!(
+ Color::try_from(&arr[..]),
+ Err(IntoColorError::IntConversion)
+ );
}
#[test]
fn test_slice_out_of_range_negative() {
let arr = [-256, -1, -10];
- assert!(Color::try_from(&arr[..]).is_err());
+ assert_eq!(
+ Color::try_from(&arr[..]),
+ Err(IntoColorError::IntConversion)
+ );
}
#[test]
fn test_slice_sum() {
let arr = [-1, 255, 255];
- assert!(Color::try_from(&arr[..]).is_err());
+ assert_eq!(
+ Color::try_from(&arr[..]),
+ Err(IntoColorError::IntConversion)
+ );
}
#[test]
fn test_slice_correct() {
@@ -148,11 +178,11 @@ mod tests {
#[test]
fn test_slice_excess_length() {
let v = vec![0, 0, 0, 0];
- assert!(Color::try_from(&v[..]).is_err());
+ assert_eq!(Color::try_from(&v[..]), Err(IntoColorError::BadLen));
}
#[test]
fn test_slice_insufficient_length() {
let v = vec![0, 0];
- assert!(Color::try_from(&v[..]).is_err());
+ assert_eq!(Color::try_from(&v[..]), Err(IntoColorError::BadLen));
}
}