Compare commits

..

14 Commits

Author SHA1 Message Date
7a1ca00837 solution to exercise 04_05 2024-07-13 17:39:46 +02:00
1789d43730 solution to exercise 04_04 2024-07-13 17:30:01 +02:00
604a5a20ae solution to exercise 04_03 2024-07-01 16:30:43 +02:00
0829174983 solution to exercise 04_02 2024-07-01 16:23:02 +02:00
ebe07acd1e solution to exercise 04_01 2024-07-01 16:15:42 +02:00
4a4fc2ea0d solution to exercise 03_12 2024-06-27 16:38:30 +02:00
91e6bf5ae4 solution to exercise 03_11 2024-06-27 16:29:31 +02:00
3f57819e4c solution to exercise 03_10 2024-06-27 16:24:32 +02:00
d54a1e160b solution to exercise 03_09 2024-06-27 16:16:19 +02:00
4913da035f solution to exercise 03_08 2024-06-27 16:08:42 +02:00
1f0823a6a4 solution to exercise 03_07 2024-06-23 18:22:03 +02:00
56075fa40e solution to exercise 03_06 2024-06-23 18:08:59 +02:00
852cd5f0b9 solution to exercise 03_05 2024-06-23 17:58:03 +02:00
1c16ac8c22 solution to exercise 03_04 2024-06-23 17:54:39 +02:00
15 changed files with 176 additions and 48 deletions

View File

@@ -1,12 +1,12 @@
mod ticket { mod ticket {
struct Ticket { pub struct Ticket {
title: String, title: String,
description: String, description: String,
status: String, status: String,
} }
impl Ticket { impl Ticket {
fn new(title: String, description: String, status: String) -> Ticket { pub 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");
} }
@@ -55,7 +55,7 @@ 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 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(),
}; // };
} }
} }

View File

@@ -34,6 +34,17 @@ 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
}
} }
} }

View File

@@ -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
} }
} }

View File

@@ -11,21 +11,9 @@ 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 {
if title.is_empty() { validate_title(&title);
panic!("Title cannot be empty"); validate_description(&description);
} 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,
@@ -45,6 +33,45 @@ 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)]

View File

@@ -6,16 +6,16 @@ mod tests {
#[test] #[test]
fn u16_size() { fn u16_size() {
assert_eq!(size_of::<u16>(), todo!()); assert_eq!(size_of::<u16>(), 2);
} }
#[test] #[test]
fn i32_size() { fn i32_size() {
assert_eq!(size_of::<i32>(), todo!()); assert_eq!(size_of::<i32>(), 4);
} }
#[test] #[test]
fn bool_size() { fn bool_size() {
assert_eq!(size_of::<bool>(), todo!()); assert_eq!(size_of::<bool>(), 1);
} }
} }

View File

@@ -13,7 +13,7 @@ mod tests {
#[test] #[test]
fn string_size() { fn string_size() {
assert_eq!(size_of::<String>(), todo!()); assert_eq!(size_of::<String>(), 24);
} }
#[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>(), todo!()); assert_eq!(size_of::<Ticket>(), 72);
} }
} }

View File

@@ -13,16 +13,16 @@ mod tests {
#[test] #[test]
fn u16_ref_size() { fn u16_ref_size() {
assert_eq!(size_of::<&u16>(), todo!()); assert_eq!(size_of::<&u16>(), 8);
} }
#[test] #[test]
fn u64_mut_ref_size() { fn u64_mut_ref_size() {
assert_eq!(size_of::<&mut u64>(), todo!()); assert_eq!(size_of::<&mut u64>(), 8);
} }
#[test] #[test]
fn ticket_ref_size() { fn ticket_ref_size() {
assert_eq!(size_of::<&Ticket>(), todo!()); assert_eq!(size_of::<&Ticket>(), 8);
} }
} }

View File

@@ -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 __!" "I have a basic understanding of destructors!"
} }
#[cfg(test)] #[cfg(test)]

View File

@@ -11,3 +11,74 @@
// 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");
}
}

View File

@@ -1,6 +1,6 @@
fn intro() -> &'static str { fn intro() -> &'static str {
// TODO: fix me 👇 // TODO: fix me 👇
"I'm ready to __!" "I'm ready to learn about traits!"
} }
#[cfg(test)] #[cfg(test)]

View File

@@ -3,6 +3,22 @@
// //
// 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::*;

View File

@@ -3,9 +3,3 @@
// 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!()
}
}

View File

@@ -8,7 +8,13 @@ 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 {

View File

@@ -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(PartialEq)] #[derive(Debug, PartialEq)]
struct Ticket { struct Ticket {
title: String, title: String,
description: String, description: String,

View File

@@ -6,7 +6,10 @@
// 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 {