From 3a46622b5c0583fbb97efa2a61fbeb4226ccfea1 Mon Sep 17 00:00:00 2001 From: Daniel Baraniak Date: Thu, 14 Sep 2023 00:21:03 +0200 Subject: [PATCH] conversions --- exercises/conversions/as_ref_mut.rs | 10 ++--- exercises/conversions/from_into.rs | 20 +++++++++- exercises/conversions/from_str.rs | 21 ++++++++++- exercises/conversions/try_from_into.rs | 51 ++++++++++++++++++++++---- exercises/conversions/using_as.rs | 4 +- 5 files changed, 85 insertions(+), 21 deletions(-) diff --git a/exercises/conversions/as_ref_mut.rs b/exercises/conversions/as_ref_mut.rs index 626a36c4..f2937387 100644 --- a/exercises/conversions/as_ref_mut.rs +++ b/exercises/conversions/as_ref_mut.rs @@ -7,25 +7,23 @@ // Execute `rustlings hint as_ref_mut` or use the `hint` watch subcommand for a // hint. -// I AM NOT DONE - // Obtain the number of bytes (not characters) in the given argument. // TODO: Add the AsRef trait appropriately as a trait bound. -fn byte_counter(arg: T) -> usize { +fn byte_counter>(arg: T) -> usize { arg.as_ref().as_bytes().len() } // Obtain the number of characters (not bytes) in the given argument. // TODO: Add the AsRef trait appropriately as a trait bound. -fn char_counter(arg: T) -> usize { +fn char_counter>(arg: T) -> usize { arg.as_ref().chars().count() } // Squares a number using as_mut(). // TODO: Add the appropriate trait bound. -fn num_sq(arg: &mut T) { +fn num_sq + AsRef>(arg: &mut T) { // TODO: Implement the function body. - ??? + *arg.as_mut() *= *arg.as_ref(); } #[cfg(test)] diff --git a/exercises/conversions/from_into.rs b/exercises/conversions/from_into.rs index 60911f3e..45678b8e 100644 --- a/exercises/conversions/from_into.rs +++ b/exercises/conversions/from_into.rs @@ -40,10 +40,26 @@ impl Default for Person { // If while parsing the age, something goes wrong, then return the default of // Person Otherwise, then return an instantiated Person object with the results -// I AM NOT DONE - impl From<&str> for Person { fn from(s: &str) -> Person { + if s.is_empty() { + return Default::default(); + } + let mut split = s.split(","); + + let name = split.next().unwrap_or_default(); + if name.is_empty() { + return Default::default(); + } + + let age_str = split.next().unwrap_or_default(); + match age_str.parse() { + Ok(age) => Person { + name: name.to_owned(), + age, + }, + Err(_) => Default::default(), + } } } diff --git a/exercises/conversions/from_str.rs b/exercises/conversions/from_str.rs index 34472c32..972faf90 100644 --- a/exercises/conversions/from_str.rs +++ b/exercises/conversions/from_str.rs @@ -9,6 +9,7 @@ // Execute `rustlings hint from_str` or use the `hint` watch subcommand for a // hint. +use std::f32::consts::E; use std::num::ParseIntError; use std::str::FromStr; @@ -31,8 +32,6 @@ enum ParsePersonError { 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 @@ -52,6 +51,24 @@ enum ParsePersonError { impl FromStr for Person { type Err = ParsePersonError; fn from_str(s: &str) -> Result { + if s.is_empty() { + return Err(ParsePersonError::Empty); + } + let args: Vec<&str> = s.splitn(3, ",").collect(); + + if args.len() != 2 { + return Err(ParsePersonError::BadLen); + } + if args[0].is_empty() { + return Err(ParsePersonError::NoName); + } + + let age = args[1].parse().map_err(ParsePersonError::ParseInt)?; + + Ok(Person { + name: args[0].to_owned(), + age, + }) } } diff --git a/exercises/conversions/try_from_into.rs b/exercises/conversions/try_from_into.rs index 32d6ef39..40b1706a 100644 --- a/exercises/conversions/try_from_into.rs +++ b/exercises/conversions/try_from_into.rs @@ -27,8 +27,6 @@ enum IntoColorError { 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. @@ -38,23 +36,60 @@ enum IntoColorError { // that correct RGB color values must be integers in the 0..=255 range. // Tuple implementation -impl TryFrom<(i16, i16, i16)> for Color { +impl TryFrom<(T, T, T)> for Color +where + u8: TryFrom, +{ type Error = IntoColorError; - fn try_from(tuple: (i16, i16, i16)) -> Result { + fn try_from(tuple: (T, T, T)) -> Result { + Ok(Color { + red: u8::try_from(tuple.0).map_err(|_| IntoColorError::IntConversion)?, + green: u8::try_from(tuple.1).map_err(|_| IntoColorError::IntConversion)?, + blue: u8::try_from(tuple.2).map_err(|_| IntoColorError::IntConversion)?, + }) } } // Array implementation -impl TryFrom<[i16; 3]> for Color { +impl TryFrom<[T; 3]> for Color +where + u8: TryFrom, + T: Copy, +{ type Error = IntoColorError; - fn try_from(arr: [i16; 3]) -> Result { + fn try_from(arr: [T; 3]) -> Result { + let color = Color { + red: u8::try_from(arr[0]).map_err(|_| IntoColorError::IntConversion)?, + green: u8::try_from(arr[1]).map_err(|_| IntoColorError::IntConversion)?, + blue: u8::try_from(arr[2]).map_err(|_| IntoColorError::IntConversion)?, + }; + Ok(color) } } // Slice implementation -impl TryFrom<&[i16]> for Color { +impl TryFrom<&[T]> for Color +where + u8: TryFrom, + T: Copy, +{ type Error = IntoColorError; - fn try_from(slice: &[i16]) -> Result { + fn try_from(slice: &[T]) -> Result { + if slice.len() != 3 { + return Err(IntoColorError::BadLen); + } + let color = Color { + red: slice[0] + .try_into() + .map_err(|_| IntoColorError::IntConversion)?, + green: slice[1] + .try_into() + .map_err(|_| IntoColorError::IntConversion)?, + blue: slice[2] + .try_into() + .map_err(|_| IntoColorError::IntConversion)?, + }; + Ok(color) } } diff --git a/exercises/conversions/using_as.rs b/exercises/conversions/using_as.rs index 414cef3a..a9f1e449 100644 --- a/exercises/conversions/using_as.rs +++ b/exercises/conversions/using_as.rs @@ -10,11 +10,9 @@ // Execute `rustlings hint using_as` or use the `hint` watch subcommand for a // hint. -// I AM NOT DONE - fn average(values: &[f64]) -> f64 { let total = values.iter().sum::(); - total / values.len() + total / values.len() as f64 } fn main() {