Compare commits
6 Commits
my_solutio
...
5660a2f7a8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5660a2f7a8 | ||
|
|
491319a6d5 | ||
|
|
83cf1cad62 | ||
|
|
d8d7e73f1c | ||
|
|
468de3c0ac | ||
|
|
c86360f3c4 |
@@ -1,6 +1,3 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
members = ["exercises/*/*", "helpers/common", "helpers/mdbook-exercise-linker", "helpers/ticket_fields"]
|
members = ["exercises/*/*", "helpers/common", "helpers/mdbook-exercise-linker", "helpers/ticket_fields"]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
[profile.dev]
|
|
||||||
overflow-checks = false
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ impl Ticket {
|
|||||||
match &self.status {
|
match &self.status {
|
||||||
Status::InProgress { assigned_to } => assigned_to,
|
Status::InProgress { assigned_to } => assigned_to,
|
||||||
Status::Done | Status::ToDo => {
|
Status::Done | Status::ToDo => {
|
||||||
panic!("Only `In-Progress` tickets can be assigned to someone"),
|
panic!("Only `In-Progress` tickets can be assigned to someone")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ fn main() {
|
|||||||
let guard = lock.lock().unwrap();
|
let guard = lock.lock().unwrap();
|
||||||
|
|
||||||
spawn(move || {
|
spawn(move || {
|
||||||
receiver.recv().unwrap();;
|
receiver.recv().unwrap();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Try to send the guard over the channel
|
// Try to send the guard over the channel
|
||||||
@@ -118,7 +118,7 @@ error[E0277]: `MutexGuard<'_, i32>` cannot be sent between threads safely
|
|||||||
| _-----_^
|
| _-----_^
|
||||||
| | |
|
| | |
|
||||||
| | required by a bound introduced by this call
|
| | required by a bound introduced by this call
|
||||||
11 | | receiver.recv().unwrap();;
|
11 | | receiver.recv().unwrap();
|
||||||
12 | | });
|
12 | | });
|
||||||
| |_^ `MutexGuard<'_, i32>` cannot be sent between threads safely
|
| |_^ `MutexGuard<'_, i32>` cannot be sent between threads safely
|
||||||
|
|
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
// You can also find solutions to all exercises in the `solutions` git branch.
|
// You can also find solutions to all exercises in the `solutions` git branch.
|
||||||
fn greeting() -> &'static str {
|
fn greeting() -> &'static str {
|
||||||
// TODO: fix me 👇
|
// TODO: fix me 👇
|
||||||
"I'm ready to learn Rust!"
|
"I'm ready to __!"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Your solutions will be automatically verified by a set of tests.
|
// Your solutions will be automatically verified by a set of tests.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// partner in this course and it'll often guide you in the right direction!
|
// 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.
|
// The input parameters should have the same type of the return type.
|
||||||
fn compute(a: u32, b: u32) -> u32 {
|
fn compute(a, b) -> u32 {
|
||||||
// Don't touch the function body.
|
// Don't touch the function body.
|
||||||
a + b * 2
|
a + b * 2
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
fn intro() -> &'static str {
|
fn intro() -> &'static str {
|
||||||
// TODO: fix me 👇
|
// TODO: fix me 👇
|
||||||
"I'm ready to build a calculator in Rust!"
|
"I'm ready to __!"
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
fn compute(a: u32, b: u32) -> u32 {
|
fn compute(a: u32, b: u32) -> u32 {
|
||||||
// TODO: change the line below to fix the compiler error and make the tests pass.
|
// TODO: change the line below to fix the compiler error and make the tests pass.
|
||||||
a + b * 4u32
|
a + b * 4u8
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
pub fn speed(start: u32, end: u32, time_elapsed: u32) -> u32 {
|
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
|
// 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?
|
// Do you need to annotate the type of `distance`? Why or why not?
|
||||||
let distance: u32 = end - start;
|
|
||||||
// Don't change the line below
|
// Don't change the line below
|
||||||
distance / time_elapsed
|
distance / time_elapsed
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/// Return `true` if `n` is even, `false` otherwise.
|
/// Return `true` if `n` is even, `false` otherwise.
|
||||||
fn is_even(n: u32) -> bool {
|
fn is_even(n: u32) -> bool {
|
||||||
n % 2 == 0
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -2,9 +2,7 @@
|
|||||||
/// calculate the average speed of the journey.
|
/// calculate the average speed of the journey.
|
||||||
fn speed(start: u32, end: u32, time_elapsed: u32) -> u32 {
|
fn speed(start: u32, end: u32, time_elapsed: u32) -> u32 {
|
||||||
// TODO: Panic with a custom message if `time_elapsed` is 0
|
// 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
|
(end - start) / time_elapsed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,13 +9,6 @@
|
|||||||
// `factorial(2)` to return `2`, and so on.
|
// `factorial(2)` to return `2`, and so on.
|
||||||
//
|
//
|
||||||
// Use only what you learned! No loops yet, so you'll have to use recursion!
|
// Use only what you learned! No loops yet, so you'll have to use recursion!
|
||||||
fn factorial(n: u16) -> u16 {
|
|
||||||
if n == 0 {
|
|
||||||
1
|
|
||||||
} else {
|
|
||||||
n * factorial(n - 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|||||||
@@ -4,13 +4,7 @@ pub fn factorial(n: u32) -> u32 {
|
|||||||
// interprets as "I'll get back to this later", thus
|
// interprets as "I'll get back to this later", thus
|
||||||
// suppressing type errors.
|
// suppressing type errors.
|
||||||
// It panics at runtime.
|
// It panics at runtime.
|
||||||
let mut result: u32 = 1; // base case
|
todo!()
|
||||||
let mut i: u32 = 1;
|
|
||||||
while i <= n {
|
|
||||||
result *= i;
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
// Rewrite the factorial function using a `for` loop.
|
// Rewrite the factorial function using a `for` loop.
|
||||||
pub fn factorial(n: u32) -> u32 {
|
pub fn factorial(n: u32) -> u32 {
|
||||||
let mut result: u32 = 1; // base case
|
todo!()
|
||||||
for i in 2..=n {
|
|
||||||
result *= i;
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
pub fn factorial(n: u32) -> u32 {
|
pub fn factorial(n: u32) -> u32 {
|
||||||
let mut result: u32 = 1;
|
let mut result = 1;
|
||||||
for i in 1..=n {
|
for i in 1..=n {
|
||||||
// Use saturating multiplication to stop at the maximum value of u32
|
// Use saturating multiplication to stop at the maximum value of u32
|
||||||
// rather than overflowing and wrapping around
|
// rather than overflowing and wrapping around
|
||||||
result = result.saturating_mul(i);
|
result *= i;
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn u16_to_u32() {
|
fn u16_to_u32() {
|
||||||
let v: u32 = 47;
|
let v: u32 = todo!();
|
||||||
assert_eq!(47u16 as u32, v);
|
assert_eq!(47u16 as u32, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,14 +24,14 @@ mod tests {
|
|||||||
// You could solve this by using exactly the same expression as above,
|
// 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
|
// but that would defeat the purpose of the exercise. Instead, use a genuine
|
||||||
// `i8` value that is equivalent to `255` when converted from `u8`.
|
// `i8` value that is equivalent to `255` when converted from `u8`.
|
||||||
let y: i8 = -1;
|
let y: i8 = todo!();
|
||||||
|
|
||||||
assert_eq!(x, y);
|
assert_eq!(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn bool_to_u8() {
|
fn bool_to_u8() {
|
||||||
let v: u8 = 1;
|
let v: u8 = todo!();
|
||||||
assert_eq!(true as u8, v);
|
assert_eq!(true as u8, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
fn intro() -> &'static str {
|
fn intro() -> &'static str {
|
||||||
// TODO: fix me 👇
|
// TODO: fix me 👇
|
||||||
"I'm ready to start modelling a software ticket!"
|
"I'm ready to __!"
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -4,16 +4,6 @@
|
|||||||
//
|
//
|
||||||
// It should also have a method named `is_available` that returns a `true` if the quantity is
|
// It should also have a method named `is_available` that returns a `true` if the quantity is
|
||||||
// greater than 0, otherwise `false`.
|
// greater than 0, otherwise `false`.
|
||||||
struct Order {
|
|
||||||
price: u8,
|
|
||||||
quantity: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Order {
|
|
||||||
fn is_available(self) -> bool {
|
|
||||||
self.quantity > 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|||||||
@@ -17,22 +17,7 @@ impl Ticket {
|
|||||||
// as well as some `String` methods. Use the documentation of Rust's standard library
|
// 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
|
// 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 {
|
fn new(title: String, description: String, status: String) -> Self {
|
||||||
if status != "To-Do" && status != "In Progress" && status != "Done" {
|
todo!();
|
||||||
panic!("Only `To-Do`, `In Progress`, and `Done` statuses are allowed")
|
|
||||||
}
|
|
||||||
if title.is_empty() {
|
|
||||||
panic!("Title cannot be empty")
|
|
||||||
}
|
|
||||||
if description.is_empty() {
|
|
||||||
panic!("Description cannot be empty")
|
|
||||||
}
|
|
||||||
if title.len() > 50 {
|
|
||||||
panic!("Title cannot be longer than 50 bytes")
|
|
||||||
}
|
|
||||||
if description.len() > 500 {
|
|
||||||
panic!("Description cannot be longer than 500 bytes")
|
|
||||||
}
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
mod helpers {
|
mod helpers {
|
||||||
// TODO: Make this code compile, either by adding a `use` statement or by using
|
// TODO: Make this code compile, either by adding a `use` statement or by using
|
||||||
// the appropriate path to refer to the `Ticket` struct.
|
// the appropriate path to refer to the `Ticket` struct.
|
||||||
use super::Ticket;
|
|
||||||
|
|
||||||
fn create_todo_ticket(title: String, description: String) -> Ticket {
|
fn create_todo_ticket(title: String, description: String) -> Ticket {
|
||||||
Ticket::new(title, description, "To-Do".into())
|
Ticket::new(title, description, "To-Do".into())
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
mod ticket {
|
mod ticket {
|
||||||
pub struct Ticket {
|
struct Ticket {
|
||||||
title: String,
|
title: String,
|
||||||
description: String,
|
description: String,
|
||||||
status: String,
|
status: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ticket {
|
impl Ticket {
|
||||||
pub fn new(title: String, description: String, status: String) -> Ticket {
|
fn new(title: String, description: String, status: String) -> Ticket {
|
||||||
if title.is_empty() {
|
if title.is_empty() {
|
||||||
panic!("Title cannot be empty");
|
panic!("Title cannot be empty");
|
||||||
}
|
}
|
||||||
@@ -48,14 +48,14 @@ mod tests {
|
|||||||
|
|
||||||
// You should be seeing this error when trying to run this exercise:
|
// You should be seeing this error when trying to run this exercise:
|
||||||
//
|
//
|
||||||
// error[E0616]: field `description` of struct `encapsulation::ticket::Ticket` is private
|
// error[E0616]: field `description` of struct `Ticket` is private
|
||||||
// |
|
// |
|
||||||
// | assert_eq!(ticket.description, "A description");
|
// | assert_eq!(ticket.description, "A description");
|
||||||
// | ^^^^^^^^^^^^^^^^^^
|
// | ^^^^^^^^^^^^^^^^^^
|
||||||
//
|
//
|
||||||
// TODO: Once you have verified that the below does not compile,
|
// TODO: Once you have verified that the below does not compile,
|
||||||
// comment the line out to move on to the next exercise!
|
// 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() {
|
fn encapsulation_cannot_be_violated() {
|
||||||
@@ -68,10 +68,10 @@ mod tests {
|
|||||||
//
|
//
|
||||||
// TODO: Once you have verified that the below does not compile,
|
// TODO: Once you have verified that the below does not compile,
|
||||||
// comment the lines out to move on to the next exercise!
|
// comment the lines out to move on to the next exercise!
|
||||||
// let ticket = Ticket {
|
let ticket = Ticket {
|
||||||
// title: "A title".into(),
|
title: "A title".into(),
|
||||||
// description: "A description".into(),
|
description: "A description".into(),
|
||||||
// status: "To-Do".into(),
|
status: "To-Do".into(),
|
||||||
// };
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,17 +34,6 @@ pub mod ticket {
|
|||||||
// - `title` that returns the `title` field.
|
// - `title` that returns the `title` field.
|
||||||
// - `description` that returns the `description` field.
|
// - `description` that returns the `description` field.
|
||||||
// - `status` that returns the `status` field.
|
// - `status` that returns the `status` field.
|
||||||
pub fn title(self) -> String {
|
|
||||||
self.title
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn description(self) -> String {
|
|
||||||
self.description
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn status(self) -> String {
|
|
||||||
self.status
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,16 +34,16 @@ impl Ticket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn title(&self) -> &String {
|
pub fn title(self) -> String {
|
||||||
&self.title
|
self.title
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn description(&self) -> &String {
|
pub fn description(self) -> String {
|
||||||
&self.description
|
self.description
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn status(&self) -> &String {
|
pub fn status(self) -> String {
|
||||||
&self.status
|
self.status
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,21 @@ pub struct Ticket {
|
|||||||
|
|
||||||
impl Ticket {
|
impl Ticket {
|
||||||
pub fn new(title: String, description: String, status: String) -> Ticket {
|
pub fn new(title: String, description: String, status: String) -> Ticket {
|
||||||
validate_title(&title);
|
if title.is_empty() {
|
||||||
validate_description(&description);
|
panic!("Title cannot be empty");
|
||||||
validate_status(&status);
|
}
|
||||||
|
if title.len() > 50 {
|
||||||
|
panic!("Title cannot be longer than 50 bytes");
|
||||||
|
}
|
||||||
|
if description.is_empty() {
|
||||||
|
panic!("Description cannot be empty");
|
||||||
|
}
|
||||||
|
if description.len() > 500 {
|
||||||
|
panic!("Description cannot be longer than 500 bytes");
|
||||||
|
}
|
||||||
|
if status != "To-Do" && status != "In Progress" && status != "Done" {
|
||||||
|
panic!("Only `To-Do`, `In Progress`, and `Done` statuses are allowed");
|
||||||
|
}
|
||||||
|
|
||||||
Ticket {
|
Ticket {
|
||||||
title,
|
title,
|
||||||
@@ -33,45 +45,6 @@ impl Ticket {
|
|||||||
pub fn status(&self) -> &String {
|
pub fn status(&self) -> &String {
|
||||||
&self.status
|
&self.status
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_title(&mut self, title: String) {
|
|
||||||
validate_title(&title);
|
|
||||||
self.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_description(&mut self, description: String) {
|
|
||||||
validate_description(&description);
|
|
||||||
self.description = description;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_status(&mut self, status: String) {
|
|
||||||
validate_status(&status);
|
|
||||||
self.status = status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn validate_title(title: &String) {
|
|
||||||
if title.is_empty() {
|
|
||||||
panic!("Title cannot be empty");
|
|
||||||
}
|
|
||||||
if title.len() > 50 {
|
|
||||||
panic!("Title cannot be longer than 50 bytes");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn validate_description(description: &String) {
|
|
||||||
if description.is_empty() {
|
|
||||||
panic!("Description cannot be empty");
|
|
||||||
}
|
|
||||||
if description.len() > 500 {
|
|
||||||
panic!("Description cannot be longer than 500 bytes");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn validate_status(status: &String) {
|
|
||||||
if status != "To-Do" && status != "In Progress" && status != "Done" {
|
|
||||||
panic!("Only `To-Do`, `In Progress`, and `Done` statuses are allowed");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -6,16 +6,16 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn u16_size() {
|
fn u16_size() {
|
||||||
assert_eq!(size_of::<u16>(), 2);
|
assert_eq!(size_of::<u16>(), todo!());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn i32_size() {
|
fn i32_size() {
|
||||||
assert_eq!(size_of::<i32>(), 4);
|
assert_eq!(size_of::<i32>(), todo!());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn bool_size() {
|
fn bool_size() {
|
||||||
assert_eq!(size_of::<bool>(), 1);
|
assert_eq!(size_of::<bool>(), todo!());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn string_size() {
|
fn string_size() {
|
||||||
assert_eq!(size_of::<String>(), 24);
|
assert_eq!(size_of::<String>(), todo!());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -23,6 +23,6 @@ mod tests {
|
|||||||
// but, in general, the memory layout of structs is a more complex topic.
|
// but, in general, the memory layout of structs is a more complex topic.
|
||||||
// If you're curious, check out the "Data layout" section of the Rustonomicon
|
// If you're curious, check out the "Data layout" section of the Rustonomicon
|
||||||
// https://doc.rust-lang.org/nomicon/data.html for more information.
|
// https://doc.rust-lang.org/nomicon/data.html for more information.
|
||||||
assert_eq!(size_of::<Ticket>(), 72);
|
assert_eq!(size_of::<Ticket>(), todo!());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,16 +13,16 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn u16_ref_size() {
|
fn u16_ref_size() {
|
||||||
assert_eq!(size_of::<&u16>(), 8);
|
assert_eq!(size_of::<&u16>(), todo!());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn u64_mut_ref_size() {
|
fn u64_mut_ref_size() {
|
||||||
assert_eq!(size_of::<&mut u64>(), 8);
|
assert_eq!(size_of::<&mut u64>(), todo!());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ticket_ref_size() {
|
fn ticket_ref_size() {
|
||||||
assert_eq!(size_of::<&Ticket>(), 8);
|
assert_eq!(size_of::<&Ticket>(), todo!());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// We'll pick the concept up again in a later chapter after covering traits and
|
// We'll pick the concept up again in a later chapter after covering traits and
|
||||||
// interior mutability.
|
// interior mutability.
|
||||||
fn outro() -> &'static str {
|
fn outro() -> &'static str {
|
||||||
"I have a basic understanding of destructors!"
|
"I have a basic understanding of __!"
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -11,74 +11,3 @@
|
|||||||
// Integration here has a very specific meaning: they test **the public API** of your project.
|
// 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
|
// You'll need to pay attention to the visibility of your types and methods; integration
|
||||||
// tests can't access private or `pub(crate)` items.
|
// 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) -> Order {
|
|
||||||
validate_product_name(&product_name);
|
|
||||||
validate_quantity(&quantity);
|
|
||||||
validate_unit_price(&unit_price);
|
|
||||||
|
|
||||||
Order {
|
|
||||||
product_name,
|
|
||||||
quantity,
|
|
||||||
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) {
|
|
||||||
validate_product_name(&product_name);
|
|
||||||
self.product_name = product_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_quantity(&mut self, quantity: u32) {
|
|
||||||
validate_quantity(&quantity);
|
|
||||||
self.quantity = quantity;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_unit_price(&mut self, unit_price: u32) {
|
|
||||||
validate_unit_price(&unit_price);
|
|
||||||
self.unit_price = unit_price;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn total(&self) -> u32 {
|
|
||||||
self.quantity * self.unit_price
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn validate_product_name(product_name: &String) {
|
|
||||||
if product_name.is_empty() {
|
|
||||||
panic!("Product name cannot be empty");
|
|
||||||
}
|
|
||||||
if product_name.len() > 300 {
|
|
||||||
panic!("Product name cannot be longer than 300 bytes");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn validate_quantity(quantity: &u32) {
|
|
||||||
if quantity == &0 {
|
|
||||||
panic!("Quantity must be greater than zero");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn validate_unit_price(unit_price: &u32) {
|
|
||||||
if unit_price == &0 {
|
|
||||||
panic!("Unit price must be greater than zero");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
fn intro() -> &'static str {
|
fn intro() -> &'static str {
|
||||||
// TODO: fix me 👇
|
// TODO: fix me 👇
|
||||||
"I'm ready to learn about traits!"
|
"I'm ready to __!"
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -3,22 +3,6 @@
|
|||||||
//
|
//
|
||||||
// Then implement the trait for `u32` and `i32`.
|
// Then implement the trait for `u32` and `i32`.
|
||||||
|
|
||||||
pub trait IsEven {
|
|
||||||
fn is_even(self) -> bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IsEven for u32 {
|
|
||||||
fn is_even(self) -> bool {
|
|
||||||
self % 2 == 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IsEven for i32 {
|
|
||||||
fn is_even(self) -> bool {
|
|
||||||
self % 2 == 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
@@ -3,3 +3,9 @@
|
|||||||
// a foreign type (`u32`, from `std`).
|
// a foreign type (`u32`, from `std`).
|
||||||
// Look at the compiler error to get familiar with what it looks like.
|
// Look at the compiler error to get familiar with what it looks like.
|
||||||
// Then delete the code below and move on to the next exercise.
|
// Then delete the code below and move on to the next exercise.
|
||||||
|
|
||||||
|
impl PartialEq for u32 {
|
||||||
|
fn eq(&self, _other: &Self) -> bool {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,13 +8,7 @@ struct Ticket {
|
|||||||
|
|
||||||
// TODO: Implement the `PartialEq` trait for `Ticket`.
|
// TODO: Implement the `PartialEq` trait for `Ticket`.
|
||||||
|
|
||||||
impl PartialEq for Ticket {
|
impl PartialEq for Ticket {}
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
self.title == other.title
|
|
||||||
&& self.description == other.description
|
|
||||||
&& self.status == other.status
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
// print both sides of the comparison to the terminal.
|
// print both sides of the comparison to the terminal.
|
||||||
// If the compared type doesn't implement `Debug`, it doesn't know how to represent them!
|
// If the compared type doesn't implement `Debug`, it doesn't know how to represent them!
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(PartialEq)]
|
||||||
struct Ticket {
|
struct Ticket {
|
||||||
title: String,
|
title: String,
|
||||||
description: String,
|
description: String,
|
||||||
|
|||||||
@@ -6,10 +6,7 @@
|
|||||||
// collections (e.g. BTreeMap).
|
// collections (e.g. BTreeMap).
|
||||||
|
|
||||||
/// Return the minimum of two values.
|
/// Return the minimum of two values.
|
||||||
pub fn min<T>(left: T, right: T) -> T
|
pub fn min<T>(left: T, right: T) -> T {
|
||||||
where
|
|
||||||
T: Ord,
|
|
||||||
{
|
|
||||||
if left <= right {
|
if left <= right {
|
||||||
left
|
left
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -6,11 +6,12 @@ fn test_saturating_u16() {
|
|||||||
let b: SaturatingU16 = 5u8.into();
|
let b: SaturatingU16 = 5u8.into();
|
||||||
let c: SaturatingU16 = u16::MAX.into();
|
let c: SaturatingU16 = u16::MAX.into();
|
||||||
let d: SaturatingU16 = (&1u16).into();
|
let d: SaturatingU16 = (&1u16).into();
|
||||||
|
let e = &c;
|
||||||
|
|
||||||
assert_eq!(a + b, SaturatingU16::from(15u16));
|
assert_eq!(a + b, SaturatingU16::from(15u16));
|
||||||
assert_eq!(a + c, SaturatingU16::from(u16::MAX));
|
assert_eq!(a + c, SaturatingU16::from(u16::MAX));
|
||||||
assert_eq!(a + d, SaturatingU16::from(11u16));
|
assert_eq!(a + d, SaturatingU16::from(11u16));
|
||||||
assert_eq!(a + a, 20u16);
|
assert_eq!(a + a, 20u16);
|
||||||
assert_eq!(a + 5u16, 15u16);
|
assert_eq!(a + 5u16, 15u16);
|
||||||
assert_eq!(a + &u16::MAX, SaturatingU16::from(u16::MAX));
|
assert_eq!(a + e, SaturatingU16::from(u16::MAX));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn thirthieth() {
|
fn thirtieth() {
|
||||||
assert_eq!(fibonacci(30), 832040);
|
assert_eq!(fibonacci(30), 832040);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// TODO: Define a function named `lowercase` that converts all characters in a string to lowercase,
|
// TODO: Define a function named `lowercase` that converts all characters in a string to lowercase,
|
||||||
// modifying the input in place.
|
// modifying the input in place.
|
||||||
// Does it need to take a `&mut String`? Does a `&mut [str]` work? Why or why not?
|
// Does it need to take a `&mut String`? Does a `&mut str` work? Why or why not?
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|||||||
Reference in New Issue
Block a user