Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod float;
mod signed;
mod string;
mod todo;
mod traits;
mod unsigned;
mod user_struct;

Expand Down
23 changes: 23 additions & 0 deletions src/traits/drop_trait.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// // TODO: implement a so-called "Drop bomb": a type that panics when dropped
// // unless a certain operation has been performed on it.
// // You can see the expected API in the tests below.

// #[cfg(test)]
// mod tests {
// use super::*;

// #[test]
// #[should_panic]
// fn test_drop_bomb() {
// let bomb = DropBomb::new();
// // The bomb should panic when dropped
// }

// #[test]
// fn test_defused_drop_bomb() {
// let mut bomb = DropBomb::new();
// bomb.defuse();
// // The bomb should not panic when dropped
// // since it has been defused
// }
// }
7 changes: 7 additions & 0 deletions src/traits/eight_size_trait.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pub fn example() {
// Trying to get the size of a str (or any other DST)
// via `std::mem::size_of` will result in a compile-time error.
//
// TODO: Comment out the following line and move on to the next exercise.
std::mem::size_of::<&str>();
}
28 changes: 28 additions & 0 deletions src/traits/eleven_clone_trait.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// TODO: add the necessary `Clone` implementations (and invocations)
// to get the code to compile.

pub fn summary(ticket: Ticket) -> (Ticket, Summary) {
let m = ticket.clone().summary();
(ticket, m)
}

#[derive(Clone)]
pub struct Ticket {
pub title: String,
pub description: String,
pub status: String,
}

impl Ticket {
pub fn summary(self) -> Summary {
Summary {
title: self.title,
status: self.status,
}
}
}

pub struct Summary {
pub title: String,
pub status: String,
}
15 changes: 15 additions & 0 deletions src/traits/five_trait_bound.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// TODO: Add the necessary trait bounds to `min` so that it compiles successfully.
// Refer to the documentation of the `std::cmp` module for more information on the traits you might need.
//
// Note: there are different trait bounds that'll make the compiler happy, but they come with
// different _semantics_. We'll cover those differences later in the course when we talk about ordered
// collections (e.g. BTreeMap).

/// Return the minimum of two values.
pub fn min<T: PartialOrd>(left: T, right: T) -> T {
if left <= right {
left
} else {
right
}
}
90 changes: 90 additions & 0 deletions src/traits/four_derive_trait.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// TODO: A (derivable) trait implementation is missing for this exercise to compile successfully.
// Fix it!
//
// # `Debug` primer
//
// `Debug` returns a representation of a Rust type that's suitable for debugging (hence the name).
// `assert_eq!` requires `Ticket` to implement `Debug` because, when the assertion fails, it tries to
// 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!

#[derive(PartialEq, Debug)]
struct Ticket {
title: String,
description: String,
status: String,
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_partial_eq() {
let title = "title";
let description = "description";
let status = "To-Do";
let ticket1 = Ticket {
title: title.to_string(),
description: description.to_string(),
status: status.to_string(),
};
let ticket2 = Ticket {
title: title.to_string(),
description: description.to_string(),
status: status.to_string(),
};
assert_eq!(ticket1, ticket2);
}

#[test]
fn test_description_not_matching() {
let title = "title";
let status = "To-Do";
let ticket1 = Ticket {
title: title.to_string(),
description: "description".to_string(),
status: status.to_string(),
};
let ticket2 = Ticket {
title: title.to_string(),
description: "description2".to_string(),
status: status.to_string(),
};
assert_ne!(ticket1, ticket2);
}

#[test]
fn test_title_not_matching() {
let status = "To-Do";
let description = "description";
let ticket1 = Ticket {
title: "title".to_string(),
description: description.to_string(),
status: status.to_string(),
};
let ticket2 = Ticket {
title: "title2".to_string(),
description: description.to_string(),
status: status.to_string(),
};
assert_ne!(ticket1, ticket2);
}

#[test]
fn test_status_not_matching() {
let title = "title";
let description = "description";
let ticket1 = Ticket {
title: title.to_string(),
description: description.to_string(),
status: "status".to_string(),
};
let ticket2 = Ticket {
title: title.to_string(),
description: description.to_string(),
status: "status2".to_string(),
};
assert_ne!(ticket1, ticket2);
}
}
14 changes: 14 additions & 0 deletions src/traits/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
pub mod drop_trait;
pub mod eight_size_trait;
pub mod eleven_clone_trait;
pub mod five_trait_bound;
pub mod four_derive_trait;
pub mod nine_from_trait;
pub mod one_trait;
pub mod outro_trait;
pub mod seven_deref_trait;
pub mod six_str_slice_trait;
pub mod ten_assos_vs_generic;
pub mod three_operator_trait;
pub mod twelve_copy_trait;
pub mod two_trait;
16 changes: 16 additions & 0 deletions src/traits/nine_from_trait.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// TODO: Implement the `From` trait for the `WrappingU32` type to make `example` compile.

pub struct WrappingU32 {
value: u32,
}

impl From<u32> for WrappingU32 {
fn from(value: u32) -> Self {
Self { value }
}
}

fn example() {
let wrapping: WrappingU32 = 42.into();
let wrapping = WrappingU32::from(42);
}
40 changes: 40 additions & 0 deletions src/traits/one_trait.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use std::ops::Rem;

// Define a trait named `IsEven` that has a method `is_even` that returns a `true` if `self` is
// even, otherwise `false`.
//
// 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)]
mod tests {
use super::*;

#[test]
fn test_u32_is_even() {
assert!(42u32.is_even());
assert!(!43u32.is_even());
}

#[test]
fn test_i32_is_even() {
assert!(42i32.is_even());
assert!(!43i32.is_even());
assert!(0i32.is_even());
assert!(!(-1i32).is_even());
}
}
10 changes: 10 additions & 0 deletions src/traits/outro_trait.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// TODO: Define a new `SaturatingU16` type.
// It should hold a `u16` value.
// It should provide conversions from `u16`, `u8`, `&u16` and `&u8`.
// It should support addition with a right-hand side of type
// SaturatingU16, u16, &u16, and &SaturatingU16. Addition should saturate at the
// maximum value for `u16`.
// It should be possible to compare it with another `SaturatingU16` or a `u16`.
// It should be possible to print its debug representation.
//
// Tests are located in the `tests` folder—pay attention to the visibility of your types and methods.
38 changes: 38 additions & 0 deletions src/traits/seven_deref_trait.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// TODO: whenever `title` and `description` are returned via their accessor methods, they
// should be normalized—i.e. leading and trailing whitespace should be removed.
// There is a method in Rust's standard library that can help with this, but you won't
// find it in the documentation for `String`.
// Can you figure out where it is defined and how to use it?

pub struct Ticket {
title: String,
description: String,
status: String,
}

impl Ticket {
pub fn title(&self) -> &str {
self.title.as_str().trim()
}

pub fn description(&self) -> &str {
self.description.as_str().trim()
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_normalization() {
let ticket = Ticket {
title: " A title ".to_string(),
description: " A description ".to_string(),
status: "To-Do".to_string(),
};

assert_eq!("A title", ticket.title());
assert_eq!("A description", ticket.description());
}
}
70 changes: 70 additions & 0 deletions src/traits/six_str_slice_trait.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// TODO: Re-implement `Ticket`'s accessor methods. This time return a `&str` rather than a `&String`.

pub struct Ticket {
title: String,
description: String,
status: String,
}

impl Ticket {
pub fn new(title: String, description: String, status: String) -> Ticket {
if title.is_empty() {
panic!("Title cannot be empty");
}
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 {
title,
description,
status,
}
}

pub fn title(&self) -> &str {
&self.title.as_str()
}

pub fn description(&self) -> &str {
&self.description.as_str()
}

pub fn status(&self) -> &str {
&self.status.as_str()
}
}

mod common {
pub fn valid_description() -> String {
"fan of a fan".to_string()
}
pub fn valid_title() -> String {
"INDIGO".to_string()
}
}

#[cfg(test)]
mod tests {
use super::*;
use common::{valid_description, valid_title};
use std::any::{Any, TypeId};

#[test]
fn test_type() {
let ticket = Ticket::new(valid_title(), valid_description(), "To-Do".to_string());
// Some dark magic to verify that you used the expected return types
assert_eq!(TypeId::of::<str>(), ticket.title().type_id());
assert_eq!(TypeId::of::<str>(), ticket.description().type_id());
assert_eq!(TypeId::of::<str>(), ticket.status().type_id());
}
}
Loading