mirror of
https://github.com/rust-lang/rustlings.git
synced 2025-12-28 06:49:19 +00:00
rsync code
This commit is contained in:
commit
e77ba8dcf2
6
.github/workflows/rust.yml
vendored
6
.github/workflows/rust.yml
vendored
@ -23,7 +23,9 @@ jobs:
|
||||
with:
|
||||
globs: "exercises/**/*.md"
|
||||
- name: Run cargo fmt
|
||||
run: cargo fmt --all -- --check
|
||||
run: cargo fmt --all --check
|
||||
- name: Run rustfmt on solutions
|
||||
run: rustfmt --check --edition 2021 --color always solutions/**/*.rs
|
||||
test:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
@ -33,7 +35,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: swatinem/rust-cache@v2
|
||||
- name: Run cargo test
|
||||
run: cargo test
|
||||
run: cargo test --workspace
|
||||
dev-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
21
CHANGELOG.md
21
CHANGELOG.md
@ -1,3 +1,22 @@
|
||||
<a name="6.1.0"></a>
|
||||
|
||||
## 6.1.0 (2024-07-10)
|
||||
|
||||
#### Added
|
||||
|
||||
- `dev check`: Check that all exercises (including third-party ones) include at least one `TODO` comment.
|
||||
- `dev check`: Check that all exercises actually fail to run (not already solved).
|
||||
|
||||
#### Changed
|
||||
|
||||
- Make enum variants more consistent between enum exercises.
|
||||
- `iterators3`: Teach about the possible case of integer overflow during division.
|
||||
|
||||
#### Fixed
|
||||
|
||||
- Exit with a helpful error message on missing/unsupported terminal/TTY.
|
||||
- Mark the last exercise as done.
|
||||
|
||||
<a name="6.0.1"></a>
|
||||
|
||||
## 6.0.1 (2024-07-04)
|
||||
@ -64,7 +83,7 @@ This should avoid issues related to the language server or to running exercises,
|
||||
Clippy lints are now shown on all exercises, not only the Clippy exercises 📎
|
||||
Make Clippy your friend from early on 🥰
|
||||
|
||||
### Third party exercises
|
||||
### Third-party exercises
|
||||
|
||||
Rustlings now supports third-party exercises!
|
||||
|
||||
|
||||
60
Cargo.lock
generated
60
Cargo.lock
generated
@ -151,9 +151,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.8"
|
||||
version = "4.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d"
|
||||
checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@ -161,9 +161,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.8"
|
||||
version = "4.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708"
|
||||
checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@ -354,15 +354,6 @@ version = "1.70.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.13.0"
|
||||
@ -525,7 +516,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall 0.5.2",
|
||||
"redox_syscall 0.5.3",
|
||||
"smallvec",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
@ -594,7 +585,7 @@ dependencies = [
|
||||
"cassowary",
|
||||
"compact_str",
|
||||
"crossterm",
|
||||
"itertools 0.13.0",
|
||||
"itertools",
|
||||
"lru",
|
||||
"paste",
|
||||
"stability",
|
||||
@ -616,9 +607,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.2"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd"
|
||||
checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
]
|
||||
@ -654,7 +645,7 @@ checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
||||
|
||||
[[package]]
|
||||
name = "rustlings"
|
||||
version = "6.0.1"
|
||||
version = "6.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"assert_cmd",
|
||||
@ -673,7 +664,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustlings-macros"
|
||||
version = "6.0.1"
|
||||
version = "6.1.0"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"serde",
|
||||
@ -709,18 +700,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.203"
|
||||
version = "1.0.204"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
|
||||
checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.203"
|
||||
version = "1.0.204"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
|
||||
checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -785,9 +776,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||
|
||||
[[package]]
|
||||
name = "stability"
|
||||
version = "0.2.0"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ff9eaf853dec4c8802325d8b6d3dffa86cc707fd7a1a4cdbf416e13b061787a"
|
||||
checksum = "d904e7009df136af5297832a3ace3370cd14ff1546a232f4f185036c2736fcac"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
@ -829,9 +820,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.68"
|
||||
version = "2.0.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9"
|
||||
checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -855,9 +846,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.22.14"
|
||||
version = "0.22.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38"
|
||||
checksum = "278f3d518e152219c994ce877758516bca5e118eaed6996192a774fb9fbf0788"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
@ -880,11 +871,12 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-truncate"
|
||||
version = "1.0.0"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5fbabedabe362c618c714dbefda9927b5afc8e2a8102f47f081089a9019226"
|
||||
checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf"
|
||||
dependencies = [
|
||||
"itertools 0.12.1",
|
||||
"itertools",
|
||||
"unicode-segmentation",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
@ -1103,9 +1095,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.6.13"
|
||||
version = "0.6.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1"
|
||||
checksum = "374ec40a2d767a3c1b4972d9475ecd557356637be906f2cb3f7fe17a6eb5e22f"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
10
Cargo.toml
10
Cargo.toml
@ -8,7 +8,7 @@ exclude = [
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "6.0.1"
|
||||
version = "6.1.0"
|
||||
authors = [
|
||||
"Liv <mokou@fastmail.com>",
|
||||
"Mo Bitar <mo8it@proton.me>",
|
||||
@ -20,8 +20,8 @@ license = "MIT"
|
||||
edition = "2021"
|
||||
|
||||
[workspace.dependencies]
|
||||
serde = { version = "1.0.203", features = ["derive"] }
|
||||
toml_edit = { version = "0.22.14", default-features = false, features = ["parse", "serde"] }
|
||||
serde = { version = "1.0.204", features = ["derive"] }
|
||||
toml_edit = { version = "0.22.16", default-features = false, features = ["parse", "serde"] }
|
||||
|
||||
[package]
|
||||
name = "rustlings"
|
||||
@ -47,13 +47,13 @@ include = [
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.86"
|
||||
clap = { version = "4.5.8", features = ["derive"] }
|
||||
clap = { version = "4.5.9", features = ["derive"] }
|
||||
crossterm = "0.27.0"
|
||||
hashbrown = "0.14.5"
|
||||
notify-debouncer-mini = { version = "0.4.1", default-features = false }
|
||||
os_pipe = "1.2.0"
|
||||
ratatui = { version = "0.27.0", default-features = false, features = ["crossterm"] }
|
||||
rustlings-macros = { path = "rustlings-macros", version = "=6.0.1" }
|
||||
rustlings-macros = { path = "rustlings-macros", version = "=6.1.0" }
|
||||
serde_json = "1.0.120"
|
||||
serde.workspace = true
|
||||
toml_edit.workspace = true
|
||||
|
||||
15
README.md
15
README.md
@ -53,6 +53,21 @@ After installing Rustlings, run the following command to initialize the `rustlin
|
||||
rustlings init
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary><strong>If the command <code>rustlings</code> can't be found…</strong> (<em>click to expand</em>)</summary>
|
||||
|
||||
You are probably using Linux and installed Rust using your package manager.
|
||||
|
||||
Cargo installs binaries to the directory `~/.cargo/bin`.
|
||||
Sadly, package managers often don't add `~/.cargo/bin` to your `PATH` environment variable.
|
||||
|
||||
The solution is to …
|
||||
|
||||
- either add `~/.cargo/bin` manually to `PATH`
|
||||
- or to uninstall Rust from the package manager and install it using the official way with `rustup`: https://www.rust-lang.org/tools/install
|
||||
|
||||
</details>
|
||||
|
||||
Now, go into the newly initialized directory and launch Rustlings for further instructions on getting started with the exercises:
|
||||
|
||||
```bash
|
||||
|
||||
@ -5,5 +5,5 @@ compiler. In this section, we'll go through the most important ones.
|
||||
|
||||
## Further information
|
||||
|
||||
- [Data Types](https://doc.rust-lang.org/stable/book/ch03-02-data-types.html)
|
||||
- [The Slice Type](https://doc.rust-lang.org/stable/book/ch04-03-slices.html)
|
||||
- [Data Types](https://doc.rust-lang.org/book/ch03-02-data-types.html)
|
||||
- [The Slice Type](https://doc.rust-lang.org/book/ch04-03-slices.html)
|
||||
|
||||
@ -12,6 +12,6 @@ the other useful data structure, hash maps, later.
|
||||
|
||||
## Further information
|
||||
|
||||
- [Storing Lists of Values with Vectors](https://doc.rust-lang.org/stable/book/ch08-01-vectors.html)
|
||||
- [Storing Lists of Values with Vectors](https://doc.rust-lang.org/book/ch08-01-vectors.html)
|
||||
- [`iter_mut`](https://doc.rust-lang.org/std/primitive.slice.html#method.iter_mut)
|
||||
- [`map`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.map)
|
||||
|
||||
@ -8,11 +8,11 @@ mod tests {
|
||||
// Don't add, change or remove any line.
|
||||
#[test]
|
||||
fn move_semantics4() {
|
||||
let mut x = 100;
|
||||
let mut x = Vec::new();
|
||||
let y = &mut x;
|
||||
*y += 100;
|
||||
let z = &mut x;
|
||||
*z += 1000;
|
||||
assert_eq!(x, 1200);
|
||||
y.push(42);
|
||||
z.push(13);
|
||||
assert_eq!(x, [42, 13]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,14 +3,6 @@
|
||||
// TODO: Fix the compiler errors without changing anything except adding or
|
||||
// removing references (the character `&`).
|
||||
|
||||
fn main() {
|
||||
let data = "Rust is great!".to_string();
|
||||
|
||||
get_char(&data);
|
||||
|
||||
string_uppercase(data);
|
||||
}
|
||||
|
||||
// Shouldn't take ownership
|
||||
fn get_char(data: &String) -> char {
|
||||
data.chars().last().unwrap()
|
||||
@ -22,3 +14,11 @@ fn string_uppercase(mut data: String) {
|
||||
|
||||
println!("{data}");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let data = "Rust is great!".to_string();
|
||||
|
||||
get_char(&data);
|
||||
|
||||
string_uppercase(data);
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
// must add fruit to the basket so that there is at least one of each kind and
|
||||
// more than 11 in total - we have a lot of mouths to feed. You are not allowed
|
||||
// to insert any more of the fruits that are already in the basket (Apple,
|
||||
// Mango, and Lyche).
|
||||
// Mango, and Lychee).
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ Option types are very common in Rust code, as they have a number of uses:
|
||||
|
||||
## Further Information
|
||||
|
||||
- [Option Enum Format](https://doc.rust-lang.org/stable/book/ch10-01-syntax.html#in-enum-definitions)
|
||||
- [Option Enum Format](https://doc.rust-lang.org/book/ch10-01-syntax.html#in-enum-definitions)
|
||||
- [Option Module Documentation](https://doc.rust-lang.org/std/option/)
|
||||
- [Option Enum Documentation](https://doc.rust-lang.org/std/option/enum.Option.html)
|
||||
- [if let](https://doc.rust-lang.org/rust-by-example/flow_control/if_let.html)
|
||||
|
||||
@ -19,6 +19,7 @@ fn main() {
|
||||
let mut tokens = 100;
|
||||
let pretend_user_input = "8";
|
||||
|
||||
// Don't change this line.
|
||||
let cost = total_cost(pretend_user_input).unwrap();
|
||||
|
||||
if cost > tokens {
|
||||
|
||||
@ -7,5 +7,5 @@ The simplest and most common use of generics is for type parameters.
|
||||
|
||||
## Further information
|
||||
|
||||
- [Generic Data Types](https://doc.rust-lang.org/stable/book/ch10-01-syntax.html)
|
||||
- [Generic Data Types](https://doc.rust-lang.org/book/ch10-01-syntax.html)
|
||||
- [Bounds](https://doc.rust-lang.org/rust-by-example/generics/bounds.html)
|
||||
|
||||
@ -9,7 +9,7 @@ impl Rectangle {
|
||||
if width <= 0 || height <= 0 {
|
||||
// Returning a `Result` would be better here. But we want to learn
|
||||
// how to test functions that can panic.
|
||||
panic!("Rectangle width and height can't be negative");
|
||||
panic!("Rectangle width and height must be positive");
|
||||
}
|
||||
|
||||
Rectangle { width, height }
|
||||
|
||||
@ -1,14 +1,20 @@
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
enum DivisionError {
|
||||
// Example: 42 / 0
|
||||
DivideByZero,
|
||||
// Only case for `i64`: `i64::MIN / -1` because the result is `i64::MAX + 1`
|
||||
IntegerOverflow,
|
||||
// Example: 5 / 2 = 2.5
|
||||
NotDivisible,
|
||||
}
|
||||
|
||||
// TODO: Calculate `a` divided by `b` if `a` is evenly divisible by `b`.
|
||||
// Otherwise, return a suitable error.
|
||||
fn divide(a: i32, b: i32) -> Result<i32, DivisionError> {
|
||||
fn divide(a: i64, b: i64) -> Result<i64, DivisionError> {
|
||||
if b == 0 {
|
||||
Err(DivisionError::DivideByZero)
|
||||
} else if (a == i64::MIN && b == -1) {
|
||||
Err(DivisionError::IntegerOverflow)
|
||||
} else if a % b == 0 {
|
||||
Ok(a / b)
|
||||
} else {
|
||||
@ -48,6 +54,11 @@ mod tests {
|
||||
assert_eq!(divide(81, 0), Err(DivisionError::DivideByZero));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_integer_overflow() {
|
||||
assert_eq!(divide(i64::MIN, -1), Err(DivisionError::IntegerOverflow));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_not_divisible() {
|
||||
assert_eq!(divide(81, 6), Err(DivisionError::NotDivisible));
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
fn factorial(num: u64) -> u64 {
|
||||
// TODO: Complete this function to return the factorial of `num`.
|
||||
// TODO: Complete this function to return the factorial of `num` which is
|
||||
// defined as `1 * 2 * 3 * … * num`.
|
||||
// https://en.wikipedia.org/wiki/Factorial
|
||||
//
|
||||
// Do not use:
|
||||
// - early returns (using the `return` keyword explicitly)
|
||||
// Try not to use:
|
||||
|
||||
@ -26,7 +26,7 @@ enum Command {
|
||||
mod my_module {
|
||||
use super::Command;
|
||||
|
||||
// TODO: Complete the function.
|
||||
// TODO: Complete the function as described above.
|
||||
pub fn transformer(input: Vec<(String, Command)>) -> Vec<String> {
|
||||
input.iter().map(|(item, cmd)| {
|
||||
match cmd {
|
||||
|
||||
@ -3,7 +3,12 @@
|
||||
# Error out if any command fails
|
||||
set -e
|
||||
|
||||
cargo run -- dev check
|
||||
typos
|
||||
cargo outdated -w --exit-code 1
|
||||
cargo upgrades
|
||||
|
||||
# Similar to CI
|
||||
cargo clippy -- --deny warnings
|
||||
cargo fmt --all --check
|
||||
rustfmt --check --edition 2021 solutions/**/*.rs
|
||||
cargo test --workspace --all-targets
|
||||
cargo run -- dev check --require-solutions
|
||||
|
||||
@ -309,7 +309,7 @@ In Rust, there are two ways to define a Vector.
|
||||
inside the square brackets. This way is simpler when you exactly know
|
||||
the initial values.
|
||||
|
||||
Check this chapter: https://doc.rust-lang.org/stable/book/ch08-01-vectors.html
|
||||
Check this chapter: https://doc.rust-lang.org/book/ch08-01-vectors.html
|
||||
of the Rust book to learn more."""
|
||||
|
||||
[[exercises]]
|
||||
@ -351,7 +351,7 @@ We call this "moving" a variable. When we pass `vec0` into `fill_vec`, it's
|
||||
being "moved" into `vec1`, meaning we can't access `vec0` anymore.
|
||||
|
||||
You could make another, separate version of the data that's in `vec0` and
|
||||
pass it to `fill_vec` instead."""
|
||||
pass it to `fill_vec` instead. This is called cloning in Rust."""
|
||||
|
||||
[[exercises]]
|
||||
name = "move_semantics3"
|
||||
@ -378,7 +378,7 @@ dir = "06_move_semantics"
|
||||
test = false
|
||||
hint = """
|
||||
To find the answer, you can consult the book section "References and Borrowing":
|
||||
https://doc.rust-lang.org/stable/book/ch04-02-references-and-borrowing.html
|
||||
https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html
|
||||
|
||||
The first problem is that `get_char` is taking ownership of the string. So
|
||||
`data` is moved and can't be used for `string_uppercase`. `data` is moved to
|
||||
@ -416,7 +416,7 @@ to its fields.
|
||||
|
||||
There are however some shortcuts that can be taken when instantiating structs.
|
||||
Have a look in The Book to find out more:
|
||||
https://doc.rust-lang.org/stable/book/ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax"""
|
||||
https://doc.rust-lang.org/book/ch05-01-defining-structs.html#creating-instances-from-other-instances-with-struct-update-syntax"""
|
||||
|
||||
[[exercises]]
|
||||
name = "structs3"
|
||||
@ -487,7 +487,7 @@ to add one character to the `if` statement, though, that will coerce the
|
||||
Side note: If you're interested in learning about how this kind of reference
|
||||
conversion works, you can jump ahead in the book and read this part in the
|
||||
smart pointers chapter:
|
||||
https://doc.rust-lang.org/stable/book/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods"""
|
||||
https://doc.rust-lang.org/book/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods"""
|
||||
|
||||
[[exercises]]
|
||||
name = "strings3"
|
||||
@ -498,7 +498,10 @@ some of them:
|
||||
https://doc.rust-lang.org/std/string/struct.String.html#method.trim
|
||||
|
||||
For the `compose_me` method: You can either use the `format!` macro, or convert
|
||||
the string slice into an owned string, which you can then freely extend."""
|
||||
the string slice into an owned string, which you can then freely extend.
|
||||
|
||||
For the `replace_me` method, you can check out the `replace` method:
|
||||
https://doc.rust-lang.org/std/string/struct.String.html#method.replace"""
|
||||
|
||||
[[exercises]]
|
||||
name = "strings4"
|
||||
@ -561,7 +564,7 @@ hint = """
|
||||
Use the `entry()` and `or_insert()` methods of `HashMap` to achieve this.
|
||||
|
||||
Learn more in The Book:
|
||||
https://doc.rust-lang.org/stable/book/ch08-03-hash-maps.html#only-inserting-a-value-if-the-key-has-no-value"""
|
||||
https://doc.rust-lang.org/book/ch08-03-hash-maps.html#only-inserting-a-value-if-the-key-has-no-value"""
|
||||
|
||||
[[exercises]]
|
||||
name = "hashmaps3"
|
||||
@ -572,7 +575,7 @@ Hint 1: Use the `entry()` and `or_insert()` (or `or_insert_with()`) methods of
|
||||
exist in the table yet.
|
||||
|
||||
Learn more in The Book:
|
||||
https://doc.rust-lang.org/stable/book/ch08-03-hash-maps.html#only-inserting-a-value-if-the-key-has-no-value
|
||||
https://doc.rust-lang.org/book/ch08-03-hash-maps.html#only-inserting-a-value-if-the-key-has-no-value
|
||||
|
||||
Hint 2: If there is already an entry for a given key, the value returned by
|
||||
`entry()` can be updated based on the existing value.
|
||||
@ -585,7 +588,7 @@ https://doc.rust-lang.org/book/ch08-03-hash-maps.html#updating-a-value-based-on-
|
||||
[[exercises]]
|
||||
name = "quiz2"
|
||||
dir = "quizzes"
|
||||
hint = "No hints this time ;)"
|
||||
hint = "The `+` operator can concatenate a `String` with a `&str`."
|
||||
|
||||
# OPTIONS
|
||||
|
||||
@ -739,7 +742,7 @@ name = "generics2"
|
||||
dir = "14_generics"
|
||||
hint = """
|
||||
Related section in The Book:
|
||||
https://doc.rust-lang.org/stable/book/ch10-01-syntax.html#in-method-definitions"""
|
||||
https://doc.rust-lang.org/book/ch10-01-syntax.html#in-method-definitions"""
|
||||
|
||||
# TRAITS
|
||||
|
||||
@ -748,7 +751,9 @@ name = "traits1"
|
||||
dir = "15_traits"
|
||||
hint = """
|
||||
More about traits in The Book:
|
||||
https://doc.rust-lang.org/book/ch10-02-traits.html"""
|
||||
https://doc.rust-lang.org/book/ch10-02-traits.html
|
||||
|
||||
The `+` operator can concatenate a `String` with a `&str`."""
|
||||
|
||||
[[exercises]]
|
||||
name = "traits2"
|
||||
@ -869,7 +874,7 @@ We expect the method `Rectangle::new` to panic for negative values.
|
||||
To handle that, you need to add a special attribute to the test function.
|
||||
|
||||
You can refer to the docs:
|
||||
https://doc.rust-lang.org/stable/book/ch11-01-writing-tests.html#checking-for-panics-with-should_panic"""
|
||||
https://doc.rust-lang.org/book/ch11-01-writing-tests.html#checking-for-panics-with-should_panic"""
|
||||
|
||||
# STANDARD LIBRARY TYPES
|
||||
|
||||
@ -888,9 +893,9 @@ hint = """
|
||||
`capitalize_first`:
|
||||
|
||||
The variable `first` is a `char`. It needs to be capitalized and added to the
|
||||
remaining characters in `c` in order to return the correct `String`.
|
||||
remaining characters in `chars` in order to return the correct `String`.
|
||||
|
||||
The remaining characters in `c` can be viewed as a string slice using the
|
||||
The remaining characters in `chars` can be viewed as a string slice using the
|
||||
`as_str` method.
|
||||
|
||||
The documentation for `char` contains many useful methods.
|
||||
@ -1005,7 +1010,7 @@ thread-local copy of the numbers.
|
||||
This is a simple exercise if you understand the underlying concepts, but if this
|
||||
is too much of a struggle, consider reading through all of Chapter 16 in The
|
||||
Book:
|
||||
https://doc.rust-lang.org/stable/book/ch16-00-concurrency.html"""
|
||||
https://doc.rust-lang.org/book/ch16-00-concurrency.html"""
|
||||
|
||||
[[exercises]]
|
||||
name = "cow1"
|
||||
@ -1143,7 +1148,11 @@ test = false
|
||||
strict_clippy = true
|
||||
hint = """
|
||||
`for` loops over `Option` values are more clearly expressed as an `if-let`
|
||||
statement."""
|
||||
statement.
|
||||
|
||||
Not required to solve this exercise, but if you are interested in when iterating
|
||||
over `Option` can be useful, read the following section in the documentation:
|
||||
https://doc.rust-lang.org/std/option/#iterating-over-option"""
|
||||
|
||||
[[exercises]]
|
||||
name = "clippy3"
|
||||
|
||||
@ -7,15 +7,15 @@ mod tests {
|
||||
// TODO: Fix the compiler errors only by reordering the lines in the test.
|
||||
// Don't add, change or remove any line.
|
||||
#[test]
|
||||
fn move_semantics5() {
|
||||
let mut x = 100;
|
||||
fn move_semantics4() {
|
||||
let mut x = Vec::new();
|
||||
let y = &mut x;
|
||||
// `y` used here.
|
||||
*y += 100;
|
||||
y.push(42);
|
||||
// The mutable reference `y` is not used anymore,
|
||||
// therefore a new reference can be created.
|
||||
let z = &mut x;
|
||||
*z += 1000;
|
||||
assert_eq!(x, 1200);
|
||||
z.push(13);
|
||||
assert_eq!(x, [42, 13]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,13 +1,5 @@
|
||||
#![allow(clippy::ptr_arg)]
|
||||
|
||||
fn main() {
|
||||
let data = "Rust is great!".to_string();
|
||||
|
||||
get_char(&data);
|
||||
|
||||
string_uppercase(data);
|
||||
}
|
||||
|
||||
// Borrows instead of taking ownership.
|
||||
// It is recommended to use `&str` instead of `&String` here. But this is
|
||||
// enough for now because we didn't handle strings yet.
|
||||
@ -21,3 +13,11 @@ fn string_uppercase(mut data: String) {
|
||||
|
||||
println!("{data}");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let data = "Rust is great!".to_string();
|
||||
|
||||
get_char(&data);
|
||||
|
||||
string_uppercase(data);
|
||||
}
|
||||
|
||||
@ -5,7 +5,8 @@
|
||||
// Apple (4), Mango (2) and Lychee (5) are already in the basket hash map. You
|
||||
// must add fruit to the basket so that there is at least one of each kind and
|
||||
// more than 11 in total - we have a lot of mouths to feed. You are not allowed
|
||||
// to insert any more of these fruits!
|
||||
// to insert any more of the fruits that are already in the basket (Apple,
|
||||
// Mango, and Lychee).
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ impl Rectangle {
|
||||
if width <= 0 || height <= 0 {
|
||||
// Returning a `Result` would be better here. But we want to learn
|
||||
// how to test functions that can panic.
|
||||
panic!("Rectangle width and height can't be negative");
|
||||
panic!("Rectangle width and height must be positive");
|
||||
}
|
||||
|
||||
Rectangle { width, height }
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
enum DivisionError {
|
||||
// Example: 42 / 0
|
||||
DivideByZero,
|
||||
// Only case for `i64`: `i64::MIN / -1` because the result is `i64::MAX + 1`
|
||||
IntegerOverflow,
|
||||
// Example: 5 / 2 = 2.5
|
||||
NotDivisible,
|
||||
}
|
||||
|
||||
@ -9,6 +13,10 @@ fn divide(a: i64, b: i64) -> Result<i64, DivisionError> {
|
||||
return Err(DivisionError::DivideByZero);
|
||||
}
|
||||
|
||||
if a == i64::MIN && b == -1 {
|
||||
return Err(DivisionError::IntegerOverflow);
|
||||
}
|
||||
|
||||
if a % b != 0 {
|
||||
return Err(DivisionError::NotDivisible);
|
||||
}
|
||||
@ -51,6 +59,11 @@ mod tests {
|
||||
assert_eq!(divide(81, 0), Err(DivisionError::DivideByZero));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_integer_overflow() {
|
||||
assert_eq!(divide(i64::MIN, -1), Err(DivisionError::IntegerOverflow));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_not_divisible() {
|
||||
assert_eq!(divide(81, 6), Err(DivisionError::NotDivisible));
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
// - Append "bar" to the string a specified amount of times
|
||||
//
|
||||
// The exact form of this will be:
|
||||
// - The input is going to be a vector of a 2-length tuple,
|
||||
// - The input is going to be a vector of 2-length tuples,
|
||||
// the first element is the string, the second one is the command.
|
||||
// - The output element is going to be a vector of strings.
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ use anyhow::{bail, Context, Result};
|
||||
use app_state::StateFileStatus;
|
||||
use clap::{Parser, Subcommand};
|
||||
use std::{
|
||||
io::{self, BufRead, StdoutLock, Write},
|
||||
io::{self, BufRead, IsTerminal, StdoutLock, Write},
|
||||
path::Path,
|
||||
process::exit,
|
||||
};
|
||||
@ -148,6 +148,10 @@ fn main() -> Result<()> {
|
||||
|
||||
match args.command {
|
||||
None => {
|
||||
if !io::stdout().is_terminal() {
|
||||
bail!("Unsupported or missing terminal/TTY");
|
||||
}
|
||||
|
||||
let notify_exercise_names = if args.manual_run {
|
||||
None
|
||||
} else {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user