diff --git a/exercises/clippy/clippy1.rs b/exercises/clippy/clippy1.rs index 95c0141..3c4ea7a 100644 --- a/exercises/clippy/clippy1.rs +++ b/exercises/clippy/clippy1.rs @@ -9,12 +9,12 @@ // Execute `rustlings hint clippy1` or use the `hint` watch subcommand for a // hint. -// I AM NOT DONE + use std::f32; fn main() { - let pi = 3.14f32; + let pi = std::f32::consts::PI; let radius = 5.00f32; let area = pi * f32::powi(radius, 2); diff --git a/exercises/clippy/clippy2.rs b/exercises/clippy/clippy2.rs index 9b87a0b..3250cad 100644 --- a/exercises/clippy/clippy2.rs +++ b/exercises/clippy/clippy2.rs @@ -3,12 +3,12 @@ // Execute `rustlings hint clippy2` or use the `hint` watch subcommand for a // hint. -// I AM NOT DONE + fn main() { let mut res = 42; let option = Some(12); - for x in option { + if let Some(x) = option { res += x; } println!("{}", res); diff --git a/exercises/clippy/clippy3.rs b/exercises/clippy/clippy3.rs index 35021f8..382e1aa 100644 --- a/exercises/clippy/clippy3.rs +++ b/exercises/clippy/clippy3.rs @@ -4,28 +4,25 @@ // // Execute `rustlings hint clippy3` or use the `hint` watch subcommand for a hint. -// I AM NOT DONE + #[allow(unused_variables, unused_assignments)] fn main() { let my_option: Option<()> = None; - if my_option.is_none() { - my_option.unwrap(); - } let my_arr = &[ - -1, -2, -3 - -4, -5, -6 + -1, -2, -3, + -4, -5, -6, ]; println!("My array! Here it is: {:?}", my_arr); - let my_empty_vec = vec![1, 2, 3, 4, 5].resize(0, 5); + let mut my_empty_vec = vec![1, 2, 3, 4, 5]; + my_empty_vec.clear(); println!("This Vec is empty, see? {:?}", my_empty_vec); let mut value_a = 45; let mut value_b = 66; // Let's swap these two! - value_a = value_b; - value_b = value_a; + std::mem::swap(&mut value_a, &mut value_b); println!("value a: {}; value b: {}", value_a, value_b); } diff --git a/exercises/conversions/as_ref_mut.rs b/exercises/conversions/as_ref_mut.rs index 626a36c..33fb590 100644 --- a/exercises/conversions/as_ref_mut.rs +++ b/exercises/conversions/as_ref_mut.rs @@ -7,25 +7,26 @@ // 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>(arg: &mut T) { // TODO: Implement the function body. - ??? + let num = arg.as_mut(); + *num *= *num; } #[cfg(test)] diff --git a/exercises/conversions/from_into.rs b/exercises/conversions/from_into.rs index aba471d..1c4973b 100644 --- a/exercises/conversions/from_into.rs +++ b/exercises/conversions/from_into.rs @@ -40,10 +40,30 @@ 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 Person::default(); + } + + let parts: Vec<&str> = s.split(',').collect(); + if parts.len() != 2 { + return Person::default(); + } + + let name = parts[0].to_string(); + if name.is_empty() { + return Person::default(); + } + + let age = match parts[1].parse::() { + Ok(age) => age, + Err(_) => return Person::default(), + }; + + Person { name, age } } } diff --git a/exercises/conversions/from_str.rs b/exercises/conversions/from_str.rs index 34472c3..7eaf1f2 100644 --- a/exercises/conversions/from_str.rs +++ b/exercises/conversions/from_str.rs @@ -31,7 +31,7 @@ enum ParsePersonError { ParseInt(ParseIntError), } -// I AM NOT DONE + // Steps: // 1. If the length of the provided string is 0, an error should be returned @@ -52,6 +52,23 @@ enum ParsePersonError { impl FromStr for Person { type Err = ParsePersonError; fn from_str(s: &str) -> Result { + if s.is_empty() { + return Err(ParsePersonError::Empty); + } + + let parts: Vec<&str> = s.split(',').collect(); + if parts.len() != 2 { + return Err(ParsePersonError::BadLen); + } + + let name = parts[0].to_string(); + if name.is_empty() { + return Err(ParsePersonError::NoName); + } + + let age = parts[1].parse::().map_err(ParsePersonError::ParseInt)?; + + Ok(Person { name, age }) } } diff --git a/exercises/conversions/try_from_into.rs b/exercises/conversions/try_from_into.rs index 32d6ef3..de460e4 100644 --- a/exercises/conversions/try_from_into.rs +++ b/exercises/conversions/try_from_into.rs @@ -27,7 +27,7 @@ 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 @@ -41,6 +41,15 @@ enum IntoColorError { impl TryFrom<(i16, i16, i16)> for Color { type Error = IntoColorError; fn try_from(tuple: (i16, i16, i16)) -> Result { + if tuple.0 < 0 || tuple.1 < 0 || tuple.2 < 0 || tuple.0 > 255 || tuple.1 > 255 || tuple.2 > 255 { + Err(IntoColorError::IntConversion) + } else { + Ok(Color { + red: tuple.0 as u8, + green: tuple.1 as u8, + blue: tuple.2 as u8, + }) + } } } @@ -48,6 +57,7 @@ impl TryFrom<(i16, i16, i16)> for Color { impl TryFrom<[i16; 3]> for Color { type Error = IntoColorError; fn try_from(arr: [i16; 3]) -> Result { + (arr[0], arr[1], arr[2]).try_into() } } @@ -55,6 +65,10 @@ impl TryFrom<[i16; 3]> for Color { impl TryFrom<&[i16]> for Color { type Error = IntoColorError; fn try_from(slice: &[i16]) -> Result { + if slice.len() != 3 { + return Err(IntoColorError::BadLen); + } + (slice[0], slice[1], slice[2]).try_into() } } diff --git a/exercises/conversions/using_as.rs b/exercises/conversions/using_as.rs index 414cef3..f4adc9c 100644 --- a/exercises/conversions/using_as.rs +++ b/exercises/conversions/using_as.rs @@ -10,11 +10,11 @@ // 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() { diff --git a/exercises/macros/macros1.rs b/exercises/macros/macros1.rs index 678de6e..eb0cbba 100644 --- a/exercises/macros/macros1.rs +++ b/exercises/macros/macros1.rs @@ -3,7 +3,7 @@ // Execute `rustlings hint macros1` or use the `hint` watch subcommand for a // hint. -// I AM NOT DONE + macro_rules! my_macro { () => { @@ -12,5 +12,5 @@ macro_rules! my_macro { } fn main() { - my_macro(); + my_macro!(); } diff --git a/exercises/macros/macros2.rs b/exercises/macros/macros2.rs index 788fc16..f53f17e 100644 --- a/exercises/macros/macros2.rs +++ b/exercises/macros/macros2.rs @@ -3,14 +3,16 @@ // Execute `rustlings hint macros2` or use the `hint` watch subcommand for a // hint. -// I AM NOT DONE -fn main() { - my_macro!(); -} macro_rules! my_macro { () => { println!("Check out my macro!"); }; } + +fn main() { + my_macro!(); +} + + diff --git a/exercises/macros/macros3.rs b/exercises/macros/macros3.rs index b795c14..15cddcd 100644 --- a/exercises/macros/macros3.rs +++ b/exercises/macros/macros3.rs @@ -5,9 +5,10 @@ // Execute `rustlings hint macros3` or use the `hint` watch subcommand for a // hint. -// I AM NOT DONE -mod macros { + +pub mod macros { + #[macro_export] macro_rules! my_macro { () => { println!("Check out my macro!"); diff --git a/exercises/macros/macros4.rs b/exercises/macros/macros4.rs index 71b45a0..59b9ee4 100644 --- a/exercises/macros/macros4.rs +++ b/exercises/macros/macros4.rs @@ -3,13 +3,13 @@ // Execute `rustlings hint macros4` or use the `hint` watch subcommand for a // hint. -// I AM NOT DONE + #[rustfmt::skip] macro_rules! my_macro { () => { println!("Check out my macro!"); - } + }; ($val:expr) => { println!("Look at this other macro: {}", $val); } diff --git a/exercises/tests/Cargo.lock b/exercises/tests/Cargo.lock new file mode 100644 index 0000000..5727585 --- /dev/null +++ b/exercises/tests/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "tests8" +version = "0.0.1" diff --git a/exercises/tests/Cargo.toml b/exercises/tests/Cargo.toml new file mode 100644 index 0000000..646d1f0 --- /dev/null +++ b/exercises/tests/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "tests8" +version = "0.0.1" +edition = "2021" +[[bin]] +name = "tests8" +path = "tests8.rs" \ No newline at end of file diff --git a/exercises/tests/build.rs b/exercises/tests/build.rs index aa518ce..610b6fc 100644 --- a/exercises/tests/build.rs +++ b/exercises/tests/build.rs @@ -10,15 +10,12 @@ fn main() { .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_secs(); // What's the use of this timestamp here? - let your_command = format!( - "Your command here with {}, please checkout exercises/tests/build.rs", - timestamp - ); + let your_command = format!("rustc-env=TEST_FOO={}", timestamp); println!("cargo:{}", your_command); // In tests8, we should enable "pass" feature to make the // testcase return early. Fill in the command to tell // Cargo about that. - let your_command = "Your command here, please checkout exercises/tests/build.rs"; + let your_command = "rustc-cfg=feature=\"pass\""; println!("cargo:{}", your_command); } diff --git a/exercises/tests/tests5.rs b/exercises/tests/tests5.rs index 0cd5cb2..b6ac597 100644 --- a/exercises/tests/tests5.rs +++ b/exercises/tests/tests5.rs @@ -22,7 +22,7 @@ // Execute `rustlings hint tests5` or use the `hint` watch subcommand for a // hint. -// I AM NOT DONE + /// # Safety /// @@ -32,7 +32,7 @@ unsafe fn modify_by_address(address: usize) { // code's behavior and the contract of this function. You may use the // comment of the test below as your format reference. unsafe { - todo!("Your code goes here") + *(address as *mut u32) = 0xAABBCCDD; } } diff --git a/exercises/tests/tests6.rs b/exercises/tests/tests6.rs index 4c91377..de96723 100644 --- a/exercises/tests/tests6.rs +++ b/exercises/tests/tests6.rs @@ -7,7 +7,7 @@ // Execute `rustlings hint tests6` or use the `hint` watch subcommand for a // hint. -// I AM NOT DONE + struct Foo { a: u128, @@ -20,8 +20,9 @@ struct Foo { unsafe fn raw_pointer_to_box(ptr: *mut Foo) -> Box { // SAFETY: The `ptr` contains an owned box of `Foo` by contract. We // simply reconstruct the box from that pointer. - let mut ret: Box = unsafe { ??? }; - todo!("The rest of the code goes here") + let mut ret: Box = Box::from_raw(ptr); + ret.b = Some("hello".to_owned()); + ret } #[cfg(test)] diff --git a/exercises/tests/tests7.rs b/exercises/tests/tests7.rs index 66b37b7..8ca36a0 100644 --- a/exercises/tests/tests7.rs +++ b/exercises/tests/tests7.rs @@ -34,7 +34,7 @@ // Execute `rustlings hint tests7` or use the `hint` watch subcommand for a // hint. -// I AM NOT DONE + fn main() {} diff --git a/exercises/tests/tests8.rs b/exercises/tests/tests8.rs index ce7e35d..53a8f22 100644 --- a/exercises/tests/tests8.rs +++ b/exercises/tests/tests8.rs @@ -7,7 +7,7 @@ // Execute `rustlings hint tests8` or use the `hint` watch subcommand for a // hint. -// I AM NOT DONE + fn main() {} diff --git a/exercises/tests/tests9.rs b/exercises/tests/tests9.rs index ea2a8ec..9938b64 100644 --- a/exercises/tests/tests9.rs +++ b/exercises/tests/tests9.rs @@ -27,15 +27,18 @@ // // You should NOT modify any existing code except for adding two lines of attributes. -// I AM NOT DONE + extern "Rust" { + #[link_name = "my_demo_function"] fn my_demo_function(a: u32) -> u32; + #[link_name = "my_demo_function"] fn my_demo_function_alias(a: u32) -> u32; } mod Foo { // No `extern` equals `extern "Rust"`. + #[no_mangle] fn my_demo_function(a: u32) -> u32 { a } diff --git a/exercises/threads/threads1.rs b/exercises/threads/threads1.rs index 80b6def..d45e89d 100644 --- a/exercises/threads/threads1.rs +++ b/exercises/threads/threads1.rs @@ -8,7 +8,7 @@ // Execute `rustlings hint threads1` or use the `hint` watch subcommand for a // hint. -// I AM NOT DONE + use std::thread; use std::time::{Duration, Instant}; @@ -27,6 +27,8 @@ fn main() { let mut results: Vec = vec![]; for handle in handles { // TODO: a struct is returned from thread::spawn, can you use it? + let result = handle.join().expect("threads failed"); + results.push(result); } if results.len() != 10 { diff --git a/exercises/threads/threads2.rs b/exercises/threads/threads2.rs index 62dad80..4fd0558 100644 --- a/exercises/threads/threads2.rs +++ b/exercises/threads/threads2.rs @@ -7,9 +7,9 @@ // Execute `rustlings hint threads2` or use the `hint` watch subcommand for a // hint. -// I AM NOT DONE -use std::sync::Arc; + +use std::sync::{Arc, Mutex}; use std::thread; use std::time::Duration; @@ -18,14 +18,15 @@ struct JobStatus { } fn main() { - let status = Arc::new(JobStatus { jobs_completed: 0 }); + let status = Arc::new(Mutex::new(JobStatus { jobs_completed: 0 })); let mut handles = vec![]; for _ in 0..10 { let status_shared = Arc::clone(&status); let handle = thread::spawn(move || { thread::sleep(Duration::from_millis(250)); // TODO: You must take an action before you update a shared value - status_shared.jobs_completed += 1; + let mut num = status_shared.lock().unwrap(); + num.jobs_completed += 1; }); handles.push(handle); } @@ -34,6 +35,7 @@ fn main() { // TODO: Print the value of the JobStatus.jobs_completed. Did you notice // anything interesting in the output? Do you have to 'join' on all the // handles? - println!("jobs completed {}", ???); + let jobs_completed = status.lock().unwrap().jobs_completed; + println!("jobs completed {}", jobs_completed); } } diff --git a/exercises/threads/threads3.rs b/exercises/threads/threads3.rs index db7d41b..7515294 100644 --- a/exercises/threads/threads3.rs +++ b/exercises/threads/threads3.rs @@ -3,7 +3,7 @@ // Execute `rustlings hint threads3` or use the `hint` watch subcommand for a // hint. -// I AM NOT DONE + use std::sync::mpsc; use std::sync::Arc; @@ -26,34 +26,36 @@ impl Queue { } } -fn send_tx(q: Queue, tx: mpsc::Sender) -> () { - let qc = Arc::new(q); - let qc1 = Arc::clone(&qc); - let qc2 = Arc::clone(&qc); - - thread::spawn(move || { - for val in &qc1.first_half { +fn send_tx(q: Arc, tx: mpsc::Sender) -> () { + let tx1 = mpsc::Sender::clone(&tx); + let q1 = Arc::clone(&q); + let handle1 = thread::spawn(move || { + for val in &q1.first_half { println!("sending {:?}", val); tx.send(*val).unwrap(); thread::sleep(Duration::from_secs(1)); } }); - - thread::spawn(move || { - for val in &qc2.second_half { + let q2 = Arc::clone(&q); + let handle2 = thread::spawn(move || { + for val in &q2.second_half { println!("sending {:?}", val); - tx.send(*val).unwrap(); + tx1.send(*val).unwrap(); thread::sleep(Duration::from_secs(1)); } }); + + handle1.join().unwrap(); + handle2.join().unwrap(); } fn main() { let (tx, rx) = mpsc::channel(); let queue = Queue::new(); let queue_length = queue.length; + let arc_queue = Arc::new(queue); - send_tx(queue, tx); + send_tx(arc_queue, tx); let mut total_received: u32 = 0; for received in rx {