diff --git a/Cargo.toml b/Cargo.toml index 52e8a87aa4..44b42197f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,5 +10,5 @@ resolver = "2" # This is needed to guarantee the expected behaviour on that specific exercise, # regardless of the "global" setting for `overflow-checks` on the `dev` profile. -[profile.dev.package.copy] -overflow-checks = true +[profile.dev] +overflow-checks = false diff --git a/exercises/01_intro/00_welcome/src/lib.rs b/exercises/01_intro/00_welcome/src/lib.rs index ec95b6ca75..e0f1fc2653 100644 --- a/exercises/01_intro/00_welcome/src/lib.rs +++ b/exercises/01_intro/00_welcome/src/lib.rs @@ -17,7 +17,7 @@ // You can also find solutions to all exercises in the `solutions` git branch. fn greeting() -> &'static str { // TODO: fix me 👇 - "I'm ready to __!" + "I'm ready to learn Rust!" } // Your solutions will be automatically verified by a set of tests. diff --git a/exercises/01_intro/01_syntax/src/lib.rs b/exercises/01_intro/01_syntax/src/lib.rs index 676d81b22e..535b6dfda4 100644 --- a/exercises/01_intro/01_syntax/src/lib.rs +++ b/exercises/01_intro/01_syntax/src/lib.rs @@ -3,7 +3,7 @@ // partner in this course and it'll often guide you in the right direction! // // The input parameters should have the same type of the return type. -fn compute(a, b) -> u32 { +fn compute(a: u32, b: u32) -> u32 { // Don't touch the function body. a + b * 2 } diff --git a/exercises/02_basic_calculator/00_intro/src/lib.rs b/exercises/02_basic_calculator/00_intro/src/lib.rs index 03aeb16339..d65a5cd207 100644 --- a/exercises/02_basic_calculator/00_intro/src/lib.rs +++ b/exercises/02_basic_calculator/00_intro/src/lib.rs @@ -1,6 +1,6 @@ fn intro() -> &'static str { // TODO: fix me 👇 - "I'm ready to __!" + "I'm ready to build a calculator in Rust!" } #[cfg(test)] diff --git a/exercises/02_basic_calculator/01_integers/src/lib.rs b/exercises/02_basic_calculator/01_integers/src/lib.rs index a87b56fba3..4eb97f56ee 100644 --- a/exercises/02_basic_calculator/01_integers/src/lib.rs +++ b/exercises/02_basic_calculator/01_integers/src/lib.rs @@ -1,6 +1,6 @@ fn compute(a: u32, b: u32) -> u32 { // TODO: change the line below to fix the compiler error and make the tests pass. - let multiplier: u8 = 4; + let multiplier: u32 = 4; a + b * multiplier } diff --git a/exercises/02_basic_calculator/02_variables/src/lib.rs b/exercises/02_basic_calculator/02_variables/src/lib.rs index e8d116749a..c894ac98df 100644 --- a/exercises/02_basic_calculator/02_variables/src/lib.rs +++ b/exercises/02_basic_calculator/02_variables/src/lib.rs @@ -8,7 +8,7 @@ pub fn speed(start: u32, end: u32, time_elapsed: u32) -> u32 { // TODO: define a variable named `distance` with the right value to get tests to pass // Do you need to annotate the type of `distance`? Why or why not? - + let distance = end - start; // Don't change the line below distance / time_elapsed } diff --git a/exercises/02_basic_calculator/03_if_else/src/lib.rs b/exercises/02_basic_calculator/03_if_else/src/lib.rs index fa2e06ea76..5c396e50b3 100644 --- a/exercises/02_basic_calculator/03_if_else/src/lib.rs +++ b/exercises/02_basic_calculator/03_if_else/src/lib.rs @@ -2,7 +2,13 @@ /// `13` if `n` is divisible by `3`, /// `17` otherwise. fn magic_number(n: u32) -> u32 { - todo!() + if n % 2 == 0 { + 12 + } else if n % 3 == 0 { + 13 + } else { + 17 + } } #[cfg(test)] diff --git a/exercises/02_basic_calculator/04_panics/src/lib.rs b/exercises/02_basic_calculator/04_panics/src/lib.rs index 702b7bd85c..4fab861b72 100644 --- a/exercises/02_basic_calculator/04_panics/src/lib.rs +++ b/exercises/02_basic_calculator/04_panics/src/lib.rs @@ -2,7 +2,9 @@ /// calculate the average speed of the journey. fn speed(start: u32, end: u32, time_elapsed: u32) -> u32 { // TODO: Panic with a custom message if `time_elapsed` is 0 - + if time_elapsed <= 0 { + panic!("The journey took no time at all. That's impossible!"); + } (end - start) / time_elapsed } diff --git a/exercises/02_basic_calculator/05_factorial/src/lib.rs b/exercises/02_basic_calculator/05_factorial/src/lib.rs index d2f11a7216..4230ce303a 100644 --- a/exercises/02_basic_calculator/05_factorial/src/lib.rs +++ b/exercises/02_basic_calculator/05_factorial/src/lib.rs @@ -9,7 +9,13 @@ // `factorial(2)` to return `2`, and so on. // // Use only what you learned! No loops yet, so you'll have to use recursion! - +fn factorial(n: u32) -> u32 { + if n == 0 { + 1 + } else { + n * factorial(n - 1) + } +} #[cfg(test)] mod tests { use crate::factorial; diff --git a/exercises/02_basic_calculator/06_while/src/lib.rs b/exercises/02_basic_calculator/06_while/src/lib.rs index dbc30ebb2d..4b89f5e16a 100644 --- a/exercises/02_basic_calculator/06_while/src/lib.rs +++ b/exercises/02_basic_calculator/06_while/src/lib.rs @@ -4,7 +4,14 @@ pub fn factorial(n: u32) -> u32 { // interprets as "I'll get back to this later", thus // suppressing type errors. // It panics at runtime. - todo!() + // todo!() + let mut result = 1; + let mut i = 1; + while i <= n { + result *= i; + i += 1; + } + result } #[cfg(test)] diff --git a/exercises/02_basic_calculator/07_for/src/lib.rs b/exercises/02_basic_calculator/07_for/src/lib.rs index d571d57d90..6ba14f489d 100644 --- a/exercises/02_basic_calculator/07_for/src/lib.rs +++ b/exercises/02_basic_calculator/07_for/src/lib.rs @@ -1,6 +1,10 @@ // Rewrite the factorial function using a `for` loop. pub fn factorial(n: u32) -> u32 { - todo!() + let mut result = 1; + for i in 1..=n { + result *= i; + } + result } #[cfg(test)] diff --git a/exercises/02_basic_calculator/09_saturating/src/lib.rs b/exercises/02_basic_calculator/09_saturating/src/lib.rs index 4b0addec59..a254b434f3 100644 --- a/exercises/02_basic_calculator/09_saturating/src/lib.rs +++ b/exercises/02_basic_calculator/09_saturating/src/lib.rs @@ -1,9 +1,9 @@ pub fn factorial(n: u32) -> u32 { - let mut result = 1; + let mut result: u32 = 1; for i in 1..=n { // Use saturating multiplication to stop at the maximum value of u32 // rather than overflowing and wrapping around - result *= i; + result = result.saturating_mul(i); } result } diff --git a/exercises/02_basic_calculator/10_as_casting/src/lib.rs b/exercises/02_basic_calculator/10_as_casting/src/lib.rs index 2ba058c49a..6a783235dc 100644 --- a/exercises/02_basic_calculator/10_as_casting/src/lib.rs +++ b/exercises/02_basic_calculator/10_as_casting/src/lib.rs @@ -6,7 +6,7 @@ mod tests { #[test] fn u16_to_u32() { - let v: u32 = todo!(); + let v: u32 = 47; assert_eq!(47u16 as u32, v); } @@ -24,14 +24,14 @@ mod tests { // You could solve this by using exactly the same expression as above, // but that would defeat the purpose of the exercise. Instead, use a genuine // `i8` value that is equivalent to `255` when converted to `u8`. - let y: i8 = todo!(); + let y: i8 = -1; assert_eq!(x, y); } #[test] fn bool_to_u8() { - let v: u8 = todo!(); + let v: u8 = 1; assert_eq!(true as u8, v); } } diff --git a/exercises/03_ticket_v1/00_intro/src/lib.rs b/exercises/03_ticket_v1/00_intro/src/lib.rs index f7afa4701e..c52e3ac9c2 100644 --- a/exercises/03_ticket_v1/00_intro/src/lib.rs +++ b/exercises/03_ticket_v1/00_intro/src/lib.rs @@ -1,6 +1,6 @@ fn intro() -> &'static str { // TODO: fix me 👇 - "I'm ready to __!" + "I'm ready to start modelling a software ticket!" } #[cfg(test)] diff --git a/exercises/03_ticket_v1/01_struct/src/lib.rs b/exercises/03_ticket_v1/01_struct/src/lib.rs index 1119e330aa..d38e0e6b45 100644 --- a/exercises/03_ticket_v1/01_struct/src/lib.rs +++ b/exercises/03_ticket_v1/01_struct/src/lib.rs @@ -4,7 +4,16 @@ // // It should also have a method named `is_available` that returns a `true` if the quantity is // greater than 0, otherwise `false`. +struct Order { + price: u32, + quantity: u32, +} +impl Order { + fn is_available(self) -> bool{ + self.quantity > 0 + } +} #[cfg(test)] mod tests { use super::*; diff --git a/exercises/03_ticket_v1/02_validation/src/lib.rs b/exercises/03_ticket_v1/02_validation/src/lib.rs index 7eaa5e5c6e..ba30a82dfa 100644 --- a/exercises/03_ticket_v1/02_validation/src/lib.rs +++ b/exercises/03_ticket_v1/02_validation/src/lib.rs @@ -18,7 +18,22 @@ impl Ticket { // as well as some `String` methods. Use the documentation of Rust's standard library // to find the most appropriate options -> https://doc.rust-lang.org/std/string/struct.String.html fn new(title: String, description: String, status: String) -> Self { - todo!(); + if status != "To-Do" && status != "In Progress" && status != "Done" { + panic!("Only `To-Do`, `In Progress`, and `Done` statuses are allowed"); + } + + if title.len() == 0 { + panic!("Title cannot be empty"); + } else if title.len() >= 50 { + panic!("Title cannot be longer than 50 bytes"); + } + + if description.len() == 0 { + panic!("Description cannot be empty"); + } else if description.len() >= 500 { + panic!("Description cannot be longer than 500 bytes"); + } + Self { title, description, diff --git a/exercises/03_ticket_v1/03_modules/src/lib.rs b/exercises/03_ticket_v1/03_modules/src/lib.rs index df0762094b..b4c808b39f 100644 --- a/exercises/03_ticket_v1/03_modules/src/lib.rs +++ b/exercises/03_ticket_v1/03_modules/src/lib.rs @@ -1,7 +1,7 @@ mod helpers { // TODO: Make this code compile, either by adding a `use` statement or by using // the appropriate path to refer to the `Ticket` struct. - + use crate::Ticket; fn create_todo_ticket(title: String, description: String) -> Ticket { Ticket::new(title, description, "To-Do".into()) } diff --git a/exercises/03_ticket_v1/04_visibility/src/lib.rs b/exercises/03_ticket_v1/04_visibility/src/lib.rs index b494fc945b..55deaddaff 100644 --- a/exercises/03_ticket_v1/04_visibility/src/lib.rs +++ b/exercises/03_ticket_v1/04_visibility/src/lib.rs @@ -1,12 +1,12 @@ mod ticket { - struct Ticket { + pub(crate) struct Ticket { title: String, description: String, status: String, } impl Ticket { - fn new(title: String, description: String, status: String) -> Ticket { + pub(crate) fn new(title: String, description: String, status: String) -> Ticket { if title.is_empty() { panic!("Title cannot be empty"); } @@ -55,7 +55,7 @@ mod tests { // // TODO: Once you have verified that the below does not compile, // comment the line out to move on to the next exercise! - assert_eq!(ticket.description, "A description"); + // assert_eq!(ticket.description, "A description"); } fn encapsulation_cannot_be_violated() { @@ -68,10 +68,10 @@ mod tests { // // TODO: Once you have verified that the below does not compile, // comment the lines out to move on to the next exercise! - let ticket = Ticket { - title: "A title".into(), - description: "A description".into(), - status: "To-Do".into(), - }; + // let ticket = Ticket { + // title: "A title".into(), + // description: "A description".into(), + // status: "To-Do".into(), + // }; } } diff --git a/exercises/03_ticket_v1/05_encapsulation/src/lib.rs b/exercises/03_ticket_v1/05_encapsulation/src/lib.rs index 91e06eb2ab..5a63e0d0a0 100644 --- a/exercises/03_ticket_v1/05_encapsulation/src/lib.rs +++ b/exercises/03_ticket_v1/05_encapsulation/src/lib.rs @@ -34,6 +34,15 @@ pub mod ticket { // - `title` that returns the `title` field. // - `description` that returns the `description` field. // - `status` that returns the `status` field. + pub fn title(&self) -> String { + self.title.clone() + } + pub fn description(&self) -> String { + self.description.clone() + } + pub fn status(&self) -> String { + self.status.clone() + } } } diff --git a/exercises/03_ticket_v1/06_ownership/src/lib.rs b/exercises/03_ticket_v1/06_ownership/src/lib.rs index a9639b2b2a..f110ea8cf9 100644 --- a/exercises/03_ticket_v1/06_ownership/src/lib.rs +++ b/exercises/03_ticket_v1/06_ownership/src/lib.rs @@ -34,16 +34,16 @@ impl Ticket { } } - pub fn title(self) -> String { - self.title + pub fn title(&self) -> String { + self.title.clone() } - pub fn description(self) -> String { - self.description + pub fn description(&self) -> String { + self.description.clone() } - pub fn status(self) -> String { - self.status + pub fn status(&self) -> String { + self.status.clone() } } diff --git a/exercises/03_ticket_v1/07_setters/src/lib.rs b/exercises/03_ticket_v1/07_setters/src/lib.rs index e13ec87729..187da6544d 100644 --- a/exercises/03_ticket_v1/07_setters/src/lib.rs +++ b/exercises/03_ticket_v1/07_setters/src/lib.rs @@ -9,29 +9,42 @@ pub struct Ticket { status: String, } + impl Ticket { pub fn new(title: String, description: String, status: String) -> Ticket { + Ticket { + title: Self::check_title(title), + description: Self::check_description(description), + status: Self::check_status(status), + } + } + + fn check_title(title: String) -> String { if title.is_empty() { panic!("Title cannot be empty"); } if title.len() > 50 { panic!("Title cannot be longer than 50 bytes"); } + + title + } + + fn check_description(description: String) -> String { if description.is_empty() { panic!("Description cannot be empty"); } if description.len() > 500 { panic!("Description cannot be longer than 500 bytes"); } + description + } + + fn check_status(status: String) -> String { if status != "To-Do" && status != "In Progress" && status != "Done" { panic!("Only `To-Do`, `In Progress`, and `Done` statuses are allowed"); } - - Ticket { - title, - description, - status, - } + status } pub fn title(&self) -> &String { @@ -45,6 +58,18 @@ impl Ticket { pub fn status(&self) -> &String { &self.status } + + pub fn set_title(&mut self, title: String) { + self.title = Self::check_title(title); + } + + pub fn set_description(&mut self, description: String) { + self.description = Self::check_description(description); + } + + pub fn set_status(&mut self, status: String) { + self.status = Self::check_status(status); + } } #[cfg(test)] diff --git a/exercises/03_ticket_v1/08_stack/src/lib.rs b/exercises/03_ticket_v1/08_stack/src/lib.rs index e97518cfac..ad7d2a491c 100644 --- a/exercises/03_ticket_v1/08_stack/src/lib.rs +++ b/exercises/03_ticket_v1/08_stack/src/lib.rs @@ -6,16 +6,16 @@ mod tests { #[test] fn u16_size() { - assert_eq!(size_of::(), todo!()); + assert_eq!(size_of::(), 2); } #[test] fn i32_size() { - assert_eq!(size_of::(), todo!()); + assert_eq!(size_of::(), 4); } #[test] fn bool_size() { - assert_eq!(size_of::(), todo!()); + assert_eq!(size_of::(), 1); } } diff --git a/exercises/03_ticket_v1/09_heap/src/lib.rs b/exercises/03_ticket_v1/09_heap/src/lib.rs index 7273c2086a..89da015e9d 100644 --- a/exercises/03_ticket_v1/09_heap/src/lib.rs +++ b/exercises/03_ticket_v1/09_heap/src/lib.rs @@ -13,7 +13,7 @@ mod tests { #[test] fn string_size() { - assert_eq!(size_of::(), todo!()); + assert_eq!(size_of::(), 24); } #[test] @@ -23,6 +23,6 @@ mod tests { // but, in general, the memory layout of structs is a more complex topic. // If you're curious, check out the "Type layout" section of The Rust Reference // https://doc.rust-lang.org/reference/type-layout.html for more information. - assert_eq!(size_of::(), todo!()); + assert_eq!(size_of::(), 72); } } diff --git a/exercises/03_ticket_v1/10_references_in_memory/src/lib.rs b/exercises/03_ticket_v1/10_references_in_memory/src/lib.rs index d580758311..d184a1929c 100644 --- a/exercises/03_ticket_v1/10_references_in_memory/src/lib.rs +++ b/exercises/03_ticket_v1/10_references_in_memory/src/lib.rs @@ -13,16 +13,16 @@ mod tests { #[test] fn u16_ref_size() { - assert_eq!(size_of::<&u16>(), todo!()); + assert_eq!(size_of::<&u16>(), 8); } #[test] fn u64_mut_ref_size() { - assert_eq!(size_of::<&mut u64>(), todo!()); + assert_eq!(size_of::<&mut u64>(), 8); } #[test] fn ticket_ref_size() { - assert_eq!(size_of::<&Ticket>(), todo!()); + assert_eq!(size_of::<&Ticket>(), 8); } } diff --git a/exercises/03_ticket_v1/11_destructor/src/lib.rs b/exercises/03_ticket_v1/11_destructor/src/lib.rs index 45bc89cf31..6555fbb589 100644 --- a/exercises/03_ticket_v1/11_destructor/src/lib.rs +++ b/exercises/03_ticket_v1/11_destructor/src/lib.rs @@ -2,7 +2,7 @@ // We'll pick the concept up again in a later chapter after covering traits and // interior mutability. fn outro() -> &'static str { - "I have a basic understanding of __!" + "I have a basic understanding of destructors!" } #[cfg(test)] diff --git a/exercises/03_ticket_v1/12_outro/src/lib.rs b/exercises/03_ticket_v1/12_outro/src/lib.rs index 15c99b83b5..3a03b00116 100644 --- a/exercises/03_ticket_v1/12_outro/src/lib.rs +++ b/exercises/03_ticket_v1/12_outro/src/lib.rs @@ -11,3 +11,70 @@ // Integration here has a very specific meaning: they test **the public API** of your project. // You'll need to pay attention to the visibility of your types and methods; integration // tests can't access private or `pub(crate)` items. +pub struct Order { + product_name: String, + quantity: u32, + unit_price: u32, +} + +impl Order { + pub fn new(product_name: String, quantity: u32, unit_price: u32) -> Self { + Order { + product_name: check_product_name(product_name), + quantity: check_quantity(quantity), + unit_price: check_unit_price(unit_price), + } + } + + pub fn total(&self) -> u32 { + self.quantity * self.unit_price + } + + pub fn product_name(&self) -> &String { + &self.product_name + } + + pub fn quantity(&self) -> &u32 { + &self.quantity + } + + pub fn unit_price(&self) -> &u32 { + &self.unit_price + } + + pub fn set_product_name(&mut self, product_name: String) { + self.product_name = check_product_name(product_name); + } + + pub fn set_quantity(&mut self, quantity: u32) { + self.quantity = check_quantity(quantity); + } + + pub fn set_unit_price(&mut self, unit_price: u32) { + self.unit_price = check_unit_price(unit_price); + } +} + +fn check_product_name(product_name: String) -> String { + if product_name.is_empty() || product_name.len() > 300 { + panic!("Invaild Product Name!") + } else { + product_name + } +} + +fn check_quantity(quantity: u32) -> u32 { + if quantity <= 0 { + panic!("Invaild Quantity!") + } else { + quantity + } +} + +fn check_unit_price(unit_price: u32) -> u32 { + if unit_price <= 0 { + panic!("Invaild Price!") + } else { + unit_price + } +}