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
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ resolver = "2"
# regardless of the "global" setting for `overflow-checks` on the `dev` profile.
[profile.dev.package.copy]
overflow-checks = true

[profile.dev]
overflow-checks = false
11 changes: 3 additions & 8 deletions book/src/01_intro/00_welcome.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,10 @@ To work through this course, you'll need:
- [RustRover](https://www.jetbrains.com/rust/);
- [Visual Studio Code](https://code.visualstudio.com) with the [`rust-analyzer`](https://marketplace.visualstudio.com/items?itemName=matklad.rust-analyzer) extension.

To verify your solutions, we've also provided a tool to guide you through the course.
It is the `wr` CLI (short for "workshop runner").
Install it with:
To verify your solutions, we've also provided a tool to guide you through the course: the `wr` CLI, short for "workshop runner".
Install `wr` by following the instructions on [its website](https://mainmatter.github.io/rust-workshop-runner/).

```bash
cargo install --locked workshop-runner
```

In a new terminal, navigate back to the top-level folder of the repository.
Once you have `wr` installed, open a new terminal and navigate to the top-level folder of the repository.
Run the `wr` command to start the course:

```bash
Expand Down
2 changes: 1 addition & 1 deletion exercises/01_intro/00_welcome/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions exercises/01_intro/01_syntax/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -16,4 +16,4 @@ mod tests {
fn case() {
assert_eq!(compute(1, 2), 5);
}
}
}
2 changes: 1 addition & 1 deletion exercises/02_basic_calculator/00_intro/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand Down
5 changes: 3 additions & 2 deletions exercises/02_basic_calculator/01_integers/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
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;
// ^ You could also omit `: u32` entirely.
// The compiler will infer the correct type based on the usage below.
a + b * multiplier
}

Expand Down
1 change: 1 addition & 0 deletions exercises/02_basic_calculator/02_variables/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +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
Expand Down
8 changes: 7 additions & 1 deletion exercises/02_basic_calculator/03_if_else/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
3 changes: 3 additions & 0 deletions exercises/02_basic_calculator/04_panics/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +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
}
Expand Down
7 changes: 7 additions & 0 deletions exercises/02_basic_calculator/05_factorial/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +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 {
Expand Down
8 changes: 7 additions & 1 deletion exercises/02_basic_calculator/06_while/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ pub fn factorial(n: u32) -> u32 {
// interprets as "I'll get back to this later", thus
// suppressing type errors.
// It panics at runtime.
todo!()
let mut result = 1;
let mut i = 1;
while i <= n {
result *= i;
i += 1;
}
result
}

#[cfg(test)]
Expand Down
6 changes: 5 additions & 1 deletion exercises/02_basic_calculator/07_for/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand Down
4 changes: 2 additions & 2 deletions exercises/02_basic_calculator/09_saturating/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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
}
Expand Down
8 changes: 4 additions & 4 deletions exercises/02_basic_calculator/10_as_casting/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand All @@ -23,15 +23,15 @@ 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!();
// `i8` value that is equivalent to `255` when converted from `u8`.
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);
}
}
2 changes: 1 addition & 1 deletion exercises/03_ticket_v1/00_intro/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand Down
10 changes: 10 additions & 0 deletions exercises/03_ticket_v1/01_struct/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +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 {
Expand Down
19 changes: 18 additions & 1 deletion exercises/03_ticket_v1/02_validation/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,24 @@ 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 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");
}

Self {
title,
description,
Expand Down
1 change: 1 addition & 0 deletions exercises/03_ticket_v1/03_modules/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +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 super::Ticket;

fn create_todo_ticket(title: String, description: String) -> Ticket {
Ticket::new(title, description, "To-Do".into())
Expand Down
16 changes: 8 additions & 8 deletions exercises/03_ticket_v1/04_visibility/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
mod ticket {
struct Ticket {
pub struct Ticket {
title: String,
description: String,
status: String,
}

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() {
panic!("Title cannot be empty");
}
Expand Down Expand Up @@ -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() {
Expand All @@ -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(),
// };
}
}
11 changes: 11 additions & 0 deletions exercises/03_ticket_v1/05_encapsulation/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@ 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
}

pub fn description(self) -> String {
self.description
}

pub fn status(self) -> String {
self.status
}
}
}

Expand Down
12 changes: 6 additions & 6 deletions exercises/03_ticket_v1/06_ownership/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@ impl Ticket {
}
}

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

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

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

Expand Down
Loading