Compare commits

..

No commits in common. "b7289e59aae11b294706b219df614efc2d852b60" and "d8c2ab8349854cbc7f4a994c7413d266cc38bc24" have entirely different histories.

133 changed files with 471 additions and 527 deletions

View file

@ -1,7 +0,0 @@
[files]
extend-exclude = [
"CHANGELOG.md",
]
[default.extend-words]
"ratatui" = "ratatui"

View file

@ -1,56 +1,129 @@
# Contributing to Rustlings ## Contributing to Rustlings
First off, thanks for taking the time to contribute! ❤️ First off, thanks for taking the time to contribute!! ❤️
## Quick Reference ### Quick Reference
I want to I want to...
- _report a bug!_ ➡️ [open an issue](#issues) _add an exercise! ➡️ [read this](#addex) and then [open a Pull Request](#prs)_
- _fix a bug!_ ➡️ [open a pull request](#pull-requests)
- _implement a new feature!_ ➡️ [open an issue to discuss it first, then a pull request](#issues)
- _add an exercise!_ ➡️ [read this](#adding-an-exercise)
- _update an outdated exercise!_ ➡️ [open a pull request](#pull-requests)
## Issues _update an outdated exercise! ➡️ [open a Pull Request](#prs)_
_report a bug! ➡️ [open an Issue](#issues)_
_fix a bug! ➡️ [open a Pull Request](#prs)_
_implement a new feature! ➡️ [open an Issue to discuss it first, then a Pull Request](#issues)_
<a name="#src"></a>
### Working on the source code
`rustlings` is basically a glorified `rustc` wrapper. Therefore the source code
isn't really that complicated since the bulk of the work is done by `rustc`.
<a name="addex"></a>
### Adding an exercise
The first step is to add the exercise! Name the file `exercises/yourTopic/yourTopicN.rs`, make sure to
put in some helpful links, and link to sections of the book in `exercises/yourTopic/README.md`.
Next make sure it runs with `rustlings`. The exercise metadata is stored in `info.toml`, under the `exercises` array. The order of the `exercises` array determines the order the exercises are run by `rustlings verify` and `rustlings watch`.
Add the metadata for your exercise in the correct order in the `exercises` array. If you are unsure of the correct ordering, add it at the bottom and ask in your pull request. The exercise metadata should contain the following:
```diff
...
+ [[exercises]]
+ name = "yourTopicN"
+ path = "exercises/yourTopic/yourTopicN.rs"
+ mode = "compile"
+ hint = """
+ Some kind of useful hint for your exercise."""
...
```
The `mode` attribute decides whether Rustlings will only compile your exercise, or compile and test it. If you have tests to verify in your exercise, choose `test`, otherwise `compile`. If you're working on a Clippy exercise, use `mode = "clippy"`.
That's all! Feel free to put up a pull request.
<a name="issues"></a>
### Issues
You can open an issue [here](https://github.com/rust-lang/rustlings/issues/new). You can open an issue [here](https://github.com/rust-lang/rustlings/issues/new).
If you're reporting a bug, please include the output of the following commands: If you're reporting a bug, please include the output of the following commands:
- `cargo --version` - `rustc --version`
- `rustlings --version` - `rustlings --version`
- `ls -la` - `ls -la`
- Your OS name and version - Your OS name and version
## Pull Requests <a name="prs"></a>
### Pull Requests
You are welcome to open a pull request, but unless it is small and trivial, **please open an issue to discuss your idea first** 🙏🏼 Opening a pull request is as easy as forking the repository and committing your
changes. There's a couple of things to watch out for:
Opening a pull request is as easy as forking the repository and committing your changes. #### Write correct commit messages
If you need any help with it or face any Git related problems, don't hesitate to ask for help 🤗
It may take time to review your pull request. We follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/)
Please be patient 😇 specification.
This means that you have to format your commit messages in a specific way. Say
you're working on adding a new exercise called `foobar1.rs`. You could write
the following commit message:
## Adding An Exercise ```
feat: add foobar1.rs exercise
- Name the file `exercises/yourTopic/yourTopicN.rs`.
- Make sure to put in some helpful links, and link to sections of the book in `exercises/yourTopic/README.md`.
- Add a (possible) solution at `solutions/yourTopic/yourTopicN.rs` with comments and links explaining it.
- Add the [metadata for your exercise](#exercise-metadata) in the `info.toml` file.
- Make sure your exercise runs with `rustlings run yourTopicN`.
- [Open a pull request](#pull-requests).
### Exercise Metadata
The exercise metadata should contain the following:
```toml
[[exercises]]
name = "yourTopicN"
dir = "yourTopic"
hint = """A useful (multi-line) hint for your exercise."""
``` ```
If your exercise doesn't contain any test, add `test = false` to the exercise metadata. If you're just fixing a bug, please use the `fix` type:
But adding tests is recommended.
```
fix(verify): make sure verify doesn't self-destruct
```
The scope within the brackets is optional, but should be any of these:
- `installation` (for the installation script)
- `cli` (for general CLI changes)
- `verify` (for the verification source file)
- `watch` (for the watch functionality source)
- `run` (for the run functionality source)
- `EXERCISENAME` (if you're changing a specific exercise, or set of exercises,
substitute them here)
When the commit also happens to close an existing issue, link it in the message
body:
```
fix: update foobar
closes #101029908
```
If you're doing simple changes, like updating a book link, use `chore`:
```
chore: update exercise1.rs book link
```
If you're updating documentation, use `docs`:
```
docs: add more information to Readme
```
If, and only if, you're absolutely sure you want to make a breaking change
(please discuss this beforehand!), add an exclamation mark to the type and
explain the breaking change in the message body:
```
fix!: completely change verification
BREAKING CHANGE: This has to be done because lorem ipsum dolor
```
#### Pull Request Workflow
Once you open a Pull Request, it may be reviewed or labeled (or both) until
the maintainers accept your change. Please be patient, it may take some time
for this to happen!

19
Cargo.lock generated
View file

@ -519,16 +519,6 @@ version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "os_pipe"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57119c3b893986491ec9aa85056780d3a0f3cf4da7cc09dd3650dbd6c6738fb9"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "parking_lot" name = "parking_lot"
version = "0.12.1" version = "0.12.1"
@ -679,7 +669,7 @@ dependencies = [
[[package]] [[package]]
name = "rustlings" name = "rustlings"
version = "6.0.0-beta.3" version = "6.0.0-beta.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"assert_cmd", "assert_cmd",
@ -687,7 +677,6 @@ dependencies = [
"crossterm", "crossterm",
"hashbrown", "hashbrown",
"notify-debouncer-mini", "notify-debouncer-mini",
"os_pipe",
"predicates", "predicates",
"ratatui", "ratatui",
"rustlings-macros", "rustlings-macros",
@ -698,7 +687,7 @@ dependencies = [
[[package]] [[package]]
name = "rustlings-macros" name = "rustlings-macros"
version = "6.0.0-beta.3" version = "6.0.0-beta.0"
dependencies = [ dependencies = [
"quote", "quote",
"serde", "serde",
@ -965,9 +954,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]] [[package]]
name = "winapi-util" name = "winapi-util"
version = "0.1.8" version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" checksum = "134306a13c5647ad6453e8deaec55d3a44d6021970129e6188735e74bf546697"
dependencies = [ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]

View file

@ -8,7 +8,7 @@ exclude = [
] ]
[workspace.package] [workspace.package]
version = "6.0.0-beta.3" version = "6.0.0-beta.0"
authors = [ authors = [
"Liv <mokou@fastmail.com>", "Liv <mokou@fastmail.com>",
"Mo Bitar <mo8it@proton.me>", "Mo Bitar <mo8it@proton.me>",
@ -37,14 +37,11 @@ keywords = [
"learning", "learning",
] ]
include = [ include = [
"/src/",
"/exercises/", "/exercises/",
"/solutions/",
"/info.toml", "/info.toml",
# A symlink to be able to include `dev/Cargo.toml` although `dev` is excluded.
"/dev-Cargo.toml",
"/README.md",
"/LICENSE", "/LICENSE",
"/README.md",
"/src/",
] ]
[dependencies] [dependencies]
@ -53,9 +50,8 @@ clap = { version = "4.5.4", features = ["derive"] }
crossterm = "0.27.0" crossterm = "0.27.0"
hashbrown = "0.14.3" hashbrown = "0.14.3"
notify-debouncer-mini = "0.4.1" notify-debouncer-mini = "0.4.1"
os_pipe = "1.1.5"
ratatui = "0.26.2" ratatui = "0.26.2"
rustlings-macros = { path = "rustlings-macros", version = "=6.0.0-beta.3" } rustlings-macros = { path = "rustlings-macros", version = "6.0.0-beta.0" }
serde.workspace = true serde.workspace = true
toml_edit.workspace = true toml_edit.workspace = true
which = "6.0.1" which = "6.0.1"
@ -69,6 +65,3 @@ panic = "abort"
[profile.dev] [profile.dev]
panic = "abort" panic = "abort"
[package.metadata.release]
pre-release-hook = ["./release-hook.sh"]

View file

@ -29,22 +29,10 @@ This'll also install _Cargo_, Rust's package/project manager.
The following command will download and compile Rustlings: The following command will download and compile Rustlings:
<!-- TODO: Remove @6.0.0-beta.x -->
```bash ```bash
cargo install rustlings@6.0.0-beta.3 cargo install rustlings --locked
``` ```
#### Troubleshooting
If the installation fails…
<!-- TODO: Remove @6.0.0-beta.x -->
- Make sure you have the latest Rust version by running `rustup update`.
- Try adding the `--locked` flag: `cargo install rustlings --locked`
- Otherwise, please [report an issue](https://github.com/rust-lang/rustlings/issues/new).
### Initialization ### Initialization
After installing Rustlings, run the following command to initialize the `rustlings/` directory: After installing Rustlings, run the following command to initialize the `rustlings/` directory:

View file

@ -1 +0,0 @@
dev/Cargo.toml

View file

@ -16,7 +16,7 @@ bin = [
{ name = "if1", path = "../exercises/03_if/if1.rs" }, { name = "if1", path = "../exercises/03_if/if1.rs" },
{ name = "if2", path = "../exercises/03_if/if2.rs" }, { name = "if2", path = "../exercises/03_if/if2.rs" },
{ name = "if3", path = "../exercises/03_if/if3.rs" }, { name = "if3", path = "../exercises/03_if/if3.rs" },
{ name = "quiz1", path = "../exercises/quizzes/quiz1.rs" }, { name = "quiz1", path = "../exercises/quiz1.rs" },
{ name = "primitive_types1", path = "../exercises/04_primitive_types/primitive_types1.rs" }, { name = "primitive_types1", path = "../exercises/04_primitive_types/primitive_types1.rs" },
{ name = "primitive_types2", path = "../exercises/04_primitive_types/primitive_types2.rs" }, { name = "primitive_types2", path = "../exercises/04_primitive_types/primitive_types2.rs" },
{ name = "primitive_types3", path = "../exercises/04_primitive_types/primitive_types3.rs" }, { name = "primitive_types3", path = "../exercises/04_primitive_types/primitive_types3.rs" },
@ -47,7 +47,7 @@ bin = [
{ name = "hashmaps1", path = "../exercises/11_hashmaps/hashmaps1.rs" }, { name = "hashmaps1", path = "../exercises/11_hashmaps/hashmaps1.rs" },
{ name = "hashmaps2", path = "../exercises/11_hashmaps/hashmaps2.rs" }, { name = "hashmaps2", path = "../exercises/11_hashmaps/hashmaps2.rs" },
{ name = "hashmaps3", path = "../exercises/11_hashmaps/hashmaps3.rs" }, { name = "hashmaps3", path = "../exercises/11_hashmaps/hashmaps3.rs" },
{ name = "quiz2", path = "../exercises/quizzes/quiz2.rs" }, { name = "quiz2", path = "../exercises/quiz2.rs" },
{ name = "options1", path = "../exercises/12_options/options1.rs" }, { name = "options1", path = "../exercises/12_options/options1.rs" },
{ name = "options2", path = "../exercises/12_options/options2.rs" }, { name = "options2", path = "../exercises/12_options/options2.rs" },
{ name = "options3", path = "../exercises/12_options/options3.rs" }, { name = "options3", path = "../exercises/12_options/options3.rs" },
@ -64,7 +64,7 @@ bin = [
{ name = "traits3", path = "../exercises/15_traits/traits3.rs" }, { name = "traits3", path = "../exercises/15_traits/traits3.rs" },
{ name = "traits4", path = "../exercises/15_traits/traits4.rs" }, { name = "traits4", path = "../exercises/15_traits/traits4.rs" },
{ name = "traits5", path = "../exercises/15_traits/traits5.rs" }, { name = "traits5", path = "../exercises/15_traits/traits5.rs" },
{ name = "quiz3", path = "../exercises/quizzes/quiz3.rs" }, { name = "quiz3", path = "../exercises/quiz3.rs" },
{ name = "lifetimes1", path = "../exercises/16_lifetimes/lifetimes1.rs" }, { name = "lifetimes1", path = "../exercises/16_lifetimes/lifetimes1.rs" },
{ name = "lifetimes2", path = "../exercises/16_lifetimes/lifetimes2.rs" }, { name = "lifetimes2", path = "../exercises/16_lifetimes/lifetimes2.rs" },
{ name = "lifetimes3", path = "../exercises/16_lifetimes/lifetimes3.rs" }, { name = "lifetimes3", path = "../exercises/16_lifetimes/lifetimes3.rs" },
@ -99,7 +99,6 @@ bin = [
] ]
[package] [package]
name = "exercises" name = "rustlings-dev"
edition = "2021" edition = "2021"
# Don't publish the exercises on crates.io!
publish = false publish = false

143
info.toml
View file

@ -39,7 +39,7 @@ https://github.com/rust-lang/rustlings/blob/main/CONTRIBUTING.md
[[exercises]] [[exercises]]
name = "intro1" name = "intro1"
dir = "00_intro" dir = "00_intro"
test = false mode = "run"
# TODO: Fix hint # TODO: Fix hint
hint = """ hint = """
Remove the `I AM NOT DONE` comment in the `exercises/intro00/intro1.rs` file Remove the `I AM NOT DONE` comment in the `exercises/intro00/intro1.rs` file
@ -48,7 +48,7 @@ to move on to the next exercise."""
[[exercises]] [[exercises]]
name = "intro2" name = "intro2"
dir = "00_intro" dir = "00_intro"
test = false mode = "run"
hint = """ hint = """
The compiler is informing us that we've got the name of the print macro wrong, and has suggested an alternative.""" The compiler is informing us that we've got the name of the print macro wrong, and has suggested an alternative."""
@ -57,7 +57,7 @@ The compiler is informing us that we've got the name of the print macro wrong, a
[[exercises]] [[exercises]]
name = "variables1" name = "variables1"
dir = "01_variables" dir = "01_variables"
test = false mode = "run"
hint = """ hint = """
The declaration in the first line in the main function is missing a keyword The declaration in the first line in the main function is missing a keyword
that is needed in Rust to create a new variable binding.""" that is needed in Rust to create a new variable binding."""
@ -65,7 +65,7 @@ that is needed in Rust to create a new variable binding."""
[[exercises]] [[exercises]]
name = "variables2" name = "variables2"
dir = "01_variables" dir = "01_variables"
test = false mode = "run"
hint = """ hint = """
The compiler message is saying that Rust cannot infer the type that the The compiler message is saying that Rust cannot infer the type that the
variable binding `x` has with what is given here. variable binding `x` has with what is given here.
@ -84,7 +84,7 @@ What if `x` is the same type as `10`? What if it's a different type?"""
[[exercises]] [[exercises]]
name = "variables3" name = "variables3"
dir = "01_variables" dir = "01_variables"
test = false mode = "run"
hint = """ hint = """
Oops! In this exercise, we have a variable binding that we've created on in the Oops! In this exercise, we have a variable binding that we've created on in the
first line in the `main` function, and we're trying to use it in the next line, first line in the `main` function, and we're trying to use it in the next line,
@ -98,7 +98,7 @@ programming language -- thankfully the Rust compiler has caught this for us!"""
[[exercises]] [[exercises]]
name = "variables4" name = "variables4"
dir = "01_variables" dir = "01_variables"
test = false mode = "run"
hint = """ hint = """
In Rust, variable bindings are immutable by default. But here we're trying In Rust, variable bindings are immutable by default. But here we're trying
to reassign a different value to `x`! There's a keyword we can use to make to reassign a different value to `x`! There's a keyword we can use to make
@ -107,7 +107,7 @@ a variable binding mutable instead."""
[[exercises]] [[exercises]]
name = "variables5" name = "variables5"
dir = "01_variables" dir = "01_variables"
test = false mode = "run"
hint = """ hint = """
In `variables4` we already learned how to make an immutable variable mutable In `variables4` we already learned how to make an immutable variable mutable
using a special keyword. Unfortunately this doesn't help us much in this using a special keyword. Unfortunately this doesn't help us much in this
@ -125,7 +125,7 @@ Try to solve this exercise afterwards using this technique."""
[[exercises]] [[exercises]]
name = "variables6" name = "variables6"
dir = "01_variables" dir = "01_variables"
test = false mode = "run"
hint = """ hint = """
We know about variables and mutability, but there is another important type of We know about variables and mutability, but there is another important type of
variable available: constants. variable available: constants.
@ -145,7 +145,7 @@ https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html#constants
[[exercises]] [[exercises]]
name = "functions1" name = "functions1"
dir = "02_functions" dir = "02_functions"
test = false mode = "run"
hint = """ hint = """
This main function is calling a function that it expects to exist, but the This main function is calling a function that it expects to exist, but the
function doesn't exist. It expects this function to have the name `call_me`. function doesn't exist. It expects this function to have the name `call_me`.
@ -155,7 +155,7 @@ Sounds a lot like `main`, doesn't it?"""
[[exercises]] [[exercises]]
name = "functions2" name = "functions2"
dir = "02_functions" dir = "02_functions"
test = false mode = "run"
hint = """ hint = """
Rust requires that all parts of a function's signature have type annotations, Rust requires that all parts of a function's signature have type annotations,
but `call_me` is missing the type annotation of `num`.""" but `call_me` is missing the type annotation of `num`."""
@ -163,7 +163,7 @@ but `call_me` is missing the type annotation of `num`."""
[[exercises]] [[exercises]]
name = "functions3" name = "functions3"
dir = "02_functions" dir = "02_functions"
test = false mode = "run"
hint = """ hint = """
This time, the function *declaration* is okay, but there's something wrong This time, the function *declaration* is okay, but there's something wrong
with the place where we're calling the function.""" with the place where we're calling the function."""
@ -171,7 +171,7 @@ with the place where we're calling the function."""
[[exercises]] [[exercises]]
name = "functions4" name = "functions4"
dir = "02_functions" dir = "02_functions"
test = false mode = "run"
hint = """ hint = """
The error message points to the function `sale_price` and says it expects a type The error message points to the function `sale_price` and says it expects a type
after the `->`. This is where the function's return type should be -- take a after the `->`. This is where the function's return type should be -- take a
@ -180,7 +180,7 @@ look at the `is_even` function for an example!"""
[[exercises]] [[exercises]]
name = "functions5" name = "functions5"
dir = "02_functions" dir = "02_functions"
test = false mode = "run"
hint = """ hint = """
This is a really common error that can be fixed by removing one character. This is a really common error that can be fixed by removing one character.
It happens because Rust distinguishes between expressions and statements: It happens because Rust distinguishes between expressions and statements:
@ -199,6 +199,7 @@ They are not the same. There are two solutions:
[[exercises]] [[exercises]]
name = "if1" name = "if1"
dir = "03_if" dir = "03_if"
mode = "test"
hint = """ hint = """
It's possible to do this in one line if you would like! It's possible to do this in one line if you would like!
@ -214,6 +215,7 @@ Remember in Rust that:
[[exercises]] [[exercises]]
name = "if2" name = "if2"
dir = "03_if" dir = "03_if"
mode = "test"
hint = """ hint = """
For that first compiler error, it's important in Rust that each conditional For that first compiler error, it's important in Rust that each conditional
block returns the same type! To get the tests passing, you will need a couple block returns the same type! To get the tests passing, you will need a couple
@ -222,6 +224,7 @@ conditions checking different input values."""
[[exercises]] [[exercises]]
name = "if3" name = "if3"
dir = "03_if" dir = "03_if"
mode = "test"
hint = """ hint = """
In Rust, every arm of an `if` expression has to return the same type of value. In Rust, every arm of an `if` expression has to return the same type of value.
Make sure the type is consistent across all arms.""" Make sure the type is consistent across all arms."""
@ -231,6 +234,7 @@ Make sure the type is consistent across all arms."""
[[exercises]] [[exercises]]
name = "quiz1" name = "quiz1"
dir = "quizzes" dir = "quizzes"
mode = "test"
hint = "No hints this time ;)" hint = "No hints this time ;)"
# PRIMITIVE TYPES # PRIMITIVE TYPES
@ -238,19 +242,19 @@ hint = "No hints this time ;)"
[[exercises]] [[exercises]]
name = "primitive_types1" name = "primitive_types1"
dir = "04_primitive_types" dir = "04_primitive_types"
test = false mode = "run"
hint = "No hints this time ;)" hint = "No hints this time ;)"
[[exercises]] [[exercises]]
name = "primitive_types2" name = "primitive_types2"
dir = "04_primitive_types" dir = "04_primitive_types"
test = false mode = "run"
hint = "No hints this time ;)" hint = "No hints this time ;)"
[[exercises]] [[exercises]]
name = "primitive_types3" name = "primitive_types3"
dir = "04_primitive_types" dir = "04_primitive_types"
test = false mode = "run"
hint = """ hint = """
There's a shorthand to initialize Arrays with a certain size that does not There's a shorthand to initialize Arrays with a certain size that does not
require you to type in 100 items (but you certainly can if you want!). require you to type in 100 items (but you certainly can if you want!).
@ -266,6 +270,7 @@ for `a.len() >= 100`?"""
[[exercises]] [[exercises]]
name = "primitive_types4" name = "primitive_types4"
dir = "04_primitive_types" dir = "04_primitive_types"
mode = "test"
hint = """ hint = """
Take a look at the 'Understanding Ownership -> Slices -> Other Slices' section Take a look at the 'Understanding Ownership -> Slices -> Other Slices' section
of the book: https://doc.rust-lang.org/book/ch04-03-slices.html and use the of the book: https://doc.rust-lang.org/book/ch04-03-slices.html and use the
@ -280,7 +285,7 @@ https://doc.rust-lang.org/nomicon/coercions.html"""
[[exercises]] [[exercises]]
name = "primitive_types5" name = "primitive_types5"
dir = "04_primitive_types" dir = "04_primitive_types"
test = false mode = "run"
hint = """ hint = """
Take a look at the 'Data Types -> The Tuple Type' section of the book: Take a look at the 'Data Types -> The Tuple Type' section of the book:
https://doc.rust-lang.org/book/ch03-02-data-types.html#the-tuple-type https://doc.rust-lang.org/book/ch03-02-data-types.html#the-tuple-type
@ -293,6 +298,7 @@ of the tuple. You can do it!!"""
[[exercises]] [[exercises]]
name = "primitive_types6" name = "primitive_types6"
dir = "04_primitive_types" dir = "04_primitive_types"
mode = "test"
hint = """ hint = """
While you could use a destructuring `let` for the tuple here, try While you could use a destructuring `let` for the tuple here, try
indexing into it instead, as explained in the last example of the indexing into it instead, as explained in the last example of the
@ -305,6 +311,7 @@ Now you have another tool in your toolbox!"""
[[exercises]] [[exercises]]
name = "vecs1" name = "vecs1"
dir = "05_vecs" dir = "05_vecs"
mode = "test"
hint = """ hint = """
In Rust, there are two ways to define a Vector. In Rust, there are two ways to define a Vector.
1. One way is to use the `Vec::new()` function to create a new vector 1. One way is to use the `Vec::new()` function to create a new vector
@ -319,6 +326,7 @@ of the Rust book to learn more.
[[exercises]] [[exercises]]
name = "vecs2" name = "vecs2"
dir = "05_vecs" dir = "05_vecs"
mode = "test"
hint = """ hint = """
In the first function we are looping over the Vector and getting a reference to In the first function we are looping over the Vector and getting a reference to
one `element` at a time. one `element` at a time.
@ -341,6 +349,7 @@ What do you think is the more commonly used pattern under Rust developers?
[[exercises]] [[exercises]]
name = "move_semantics1" name = "move_semantics1"
dir = "06_move_semantics" dir = "06_move_semantics"
mode = "test"
hint = """ hint = """
So you've got the "cannot borrow immutable local variable `vec` as mutable" So you've got the "cannot borrow immutable local variable `vec` as mutable"
error on the line where we push an element to the vector, right? error on the line where we push an element to the vector, right?
@ -354,6 +363,7 @@ happens!"""
[[exercises]] [[exercises]]
name = "move_semantics2" name = "move_semantics2"
dir = "06_move_semantics" dir = "06_move_semantics"
mode = "test"
hint = """ hint = """
When running this exercise for the first time, you'll notice an error about When running this exercise for the first time, you'll notice an error about
"borrow of moved value". In Rust, when an argument is passed to a function and "borrow of moved value". In Rust, when an argument is passed to a function and
@ -374,6 +384,7 @@ try them all:
[[exercises]] [[exercises]]
name = "move_semantics3" name = "move_semantics3"
dir = "06_move_semantics" dir = "06_move_semantics"
mode = "test"
hint = """ hint = """
The difference between this one and the previous ones is that the first line The difference between this one and the previous ones is that the first line
of `fn fill_vec` that had `let mut vec = vec;` is no longer there. You can, of `fn fill_vec` that had `let mut vec = vec;` is no longer there. You can,
@ -383,6 +394,7 @@ an existing binding to be a mutable binding instead of an immutable one :)"""
[[exercises]] [[exercises]]
name = "move_semantics4" name = "move_semantics4"
dir = "06_move_semantics" dir = "06_move_semantics"
mode = "test"
hint = """ hint = """
Stop reading whenever you feel like you have enough direction :) Or try Stop reading whenever you feel like you have enough direction :) Or try
doing one step and then fixing the compiler errors that result! doing one step and then fixing the compiler errors that result!
@ -396,6 +408,7 @@ So the end goal is to:
[[exercises]] [[exercises]]
name = "move_semantics5" name = "move_semantics5"
dir = "06_move_semantics" dir = "06_move_semantics"
mode = "test"
hint = """ hint = """
Carefully reason about the range in which each mutable reference is in Carefully reason about the range in which each mutable reference is in
scope. Does it help to update the value of referent (`x`) immediately after scope. Does it help to update the value of referent (`x`) immediately after
@ -407,7 +420,7 @@ https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#mutable-ref
[[exercises]] [[exercises]]
name = "move_semantics6" name = "move_semantics6"
dir = "06_move_semantics" dir = "06_move_semantics"
test = false mode = "run"
hint = """ hint = """
To find the answer, you can consult the book section "References and Borrowing": 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/stable/book/ch04-02-references-and-borrowing.html
@ -428,6 +441,7 @@ Another hint: it has to do with the `&` character."""
[[exercises]] [[exercises]]
name = "structs1" name = "structs1"
dir = "07_structs" dir = "07_structs"
mode = "test"
hint = """ hint = """
Rust has more than one type of struct. Three actually, all variants are used to Rust has more than one type of struct. Three actually, all variants are used to
package related data together. package related data together.
@ -447,6 +461,7 @@ https://doc.rust-lang.org/book/ch05-01-defining-structs.html"""
[[exercises]] [[exercises]]
name = "structs2" name = "structs2"
dir = "07_structs" dir = "07_structs"
mode = "test"
hint = """ hint = """
Creating instances of structs is easy, all you need to do is assign some values Creating instances of structs is easy, all you need to do is assign some values
to its fields. to its fields.
@ -458,6 +473,7 @@ https://doc.rust-lang.org/stable/book/ch05-01-defining-structs.html#creating-ins
[[exercises]] [[exercises]]
name = "structs3" name = "structs3"
dir = "07_structs" dir = "07_structs"
mode = "test"
hint = """ hint = """
For `is_international`: What makes a package international? Seems related to For `is_international`: What makes a package international? Seems related to
the places it goes through right? the places it goes through right?
@ -473,13 +489,13 @@ https://doc.rust-lang.org/book/ch05-03-method-syntax.html"""
[[exercises]] [[exercises]]
name = "enums1" name = "enums1"
dir = "08_enums" dir = "08_enums"
test = false mode = "run"
hint = "No hints this time ;)" hint = "No hints this time ;)"
[[exercises]] [[exercises]]
name = "enums2" name = "enums2"
dir = "08_enums" dir = "08_enums"
test = false mode = "run"
hint = """ hint = """
You can create enumerations that have different variants with different types You can create enumerations that have different variants with different types
such as no data, anonymous structs, a single string, tuples, ...etc""" such as no data, anonymous structs, a single string, tuples, ...etc"""
@ -487,6 +503,7 @@ such as no data, anonymous structs, a single string, tuples, ...etc"""
[[exercises]] [[exercises]]
name = "enums3" name = "enums3"
dir = "08_enums" dir = "08_enums"
mode = "test"
hint = """ hint = """
As a first step, you can define enums to compile this code without errors. As a first step, you can define enums to compile this code without errors.
@ -500,7 +517,7 @@ to get value in the variant."""
[[exercises]] [[exercises]]
name = "strings1" name = "strings1"
dir = "09_strings" dir = "09_strings"
test = false mode = "run"
hint = """ hint = """
The `current_favorite_color` function is currently returning a string slice The `current_favorite_color` function is currently returning a string slice
with the `'static` lifetime. We know this because the data of the string lives with the `'static` lifetime. We know this because the data of the string lives
@ -514,7 +531,7 @@ another way that uses the `From` trait."""
[[exercises]] [[exercises]]
name = "strings2" name = "strings2"
dir = "09_strings" dir = "09_strings"
test = false mode = "run"
hint = """ hint = """
Yes, it would be really easy to fix this by just changing the value bound to Yes, it would be really easy to fix this by just changing the value bound to
`word` to be a string slice instead of a `String`, wouldn't it?? There is a way `word` to be a string slice instead of a `String`, wouldn't it?? There is a way
@ -529,6 +546,7 @@ https://doc.rust-lang.org/stable/book/ch15-02-deref.html#implicit-deref-coercion
[[exercises]] [[exercises]]
name = "strings3" name = "strings3"
dir = "09_strings" dir = "09_strings"
mode = "test"
hint = """ hint = """
There's tons of useful standard library functions for strings. Let's try and use some of them: There's tons of useful standard library functions for strings. Let's try and use some of them:
https://doc.rust-lang.org/std/string/struct.String.html#method.trim https://doc.rust-lang.org/std/string/struct.String.html#method.trim
@ -539,7 +557,7 @@ the string slice into an owned string, which you can then freely extend."""
[[exercises]] [[exercises]]
name = "strings4" name = "strings4"
dir = "09_strings" dir = "09_strings"
test = false mode = "run"
hint = "No hints this time ;)" hint = "No hints this time ;)"
# MODULES # MODULES
@ -547,7 +565,7 @@ hint = "No hints this time ;)"
[[exercises]] [[exercises]]
name = "modules1" name = "modules1"
dir = "10_modules" dir = "10_modules"
test = false mode = "run"
hint = """ hint = """
Everything is private in Rust by default-- but there's a keyword we can use Everything is private in Rust by default-- but there's a keyword we can use
to make something public! The compiler error should point to the thing that to make something public! The compiler error should point to the thing that
@ -556,7 +574,7 @@ needs to be public."""
[[exercises]] [[exercises]]
name = "modules2" name = "modules2"
dir = "10_modules" dir = "10_modules"
test = false mode = "run"
hint = """ hint = """
The delicious_snacks module is trying to present an external interface that is The delicious_snacks module is trying to present an external interface that is
different than its internal structure (the `fruits` and `veggies` modules and different than its internal structure (the `fruits` and `veggies` modules and
@ -568,7 +586,7 @@ Learn more at https://doc.rust-lang.org/book/ch07-04-bringing-paths-into-scope-w
[[exercises]] [[exercises]]
name = "modules3" name = "modules3"
dir = "10_modules" dir = "10_modules"
test = false mode = "run"
hint = """ hint = """
`UNIX_EPOCH` and `SystemTime` are declared in the `std::time` module. Add a `UNIX_EPOCH` and `SystemTime` are declared in the `std::time` module. Add a
`use` statement for these two to bring them into scope. You can use nested `use` statement for these two to bring them into scope. You can use nested
@ -579,6 +597,7 @@ paths or the glob operator to bring these two in using only one line."""
[[exercises]] [[exercises]]
name = "hashmaps1" name = "hashmaps1"
dir = "11_hashmaps" dir = "11_hashmaps"
mode = "test"
hint = """ hint = """
Hint 1: Take a look at the return type of the function to figure out Hint 1: Take a look at the return type of the function to figure out
the type for the `basket`. the type for the `basket`.
@ -590,6 +609,7 @@ Hint 2: Number of fruits should be at least 5. And you have to put
[[exercises]] [[exercises]]
name = "hashmaps2" name = "hashmaps2"
dir = "11_hashmaps" dir = "11_hashmaps"
mode = "test"
hint = """ hint = """
Use the `entry()` and `or_insert()` methods of `HashMap` to achieve this. Use the `entry()` and `or_insert()` methods of `HashMap` to achieve this.
Learn more at https://doc.rust-lang.org/stable/book/ch08-03-hash-maps.html#only-inserting-a-value-if-the-key-has-no-value Learn more at https://doc.rust-lang.org/stable/book/ch08-03-hash-maps.html#only-inserting-a-value-if-the-key-has-no-value
@ -598,6 +618,7 @@ Learn more at https://doc.rust-lang.org/stable/book/ch08-03-hash-maps.html#only-
[[exercises]] [[exercises]]
name = "hashmaps3" name = "hashmaps3"
dir = "11_hashmaps" dir = "11_hashmaps"
mode = "test"
hint = """ hint = """
Hint 1: Use the `entry()` and `or_insert()` methods of `HashMap` to insert Hint 1: Use the `entry()` and `or_insert()` methods of `HashMap` to insert
entries corresponding to each team in the scores table. entries corresponding to each team in the scores table.
@ -615,6 +636,7 @@ Learn more at https://doc.rust-lang.org/book/ch08-03-hash-maps.html#updating-a-v
[[exercises]] [[exercises]]
name = "quiz2" name = "quiz2"
dir = "quizzes" dir = "quizzes"
mode = "test"
hint = "No hints this time ;)" hint = "No hints this time ;)"
# OPTIONS # OPTIONS
@ -622,6 +644,7 @@ hint = "No hints this time ;)"
[[exercises]] [[exercises]]
name = "options1" name = "options1"
dir = "12_options" dir = "12_options"
mode = "test"
hint = """ hint = """
Options can have a `Some` value, with an inner value, or a `None` value, Options can have a `Some` value, with an inner value, or a `None` value,
without an inner value. without an inner value.
@ -633,6 +656,7 @@ it doesn't panic in your face later?"""
[[exercises]] [[exercises]]
name = "options2" name = "options2"
dir = "12_options" dir = "12_options"
mode = "test"
hint = """ hint = """
Check out: Check out:
@ -649,7 +673,7 @@ Also see `Option::flatten`
[[exercises]] [[exercises]]
name = "options3" name = "options3"
dir = "12_options" dir = "12_options"
test = false mode = "run"
hint = """ hint = """
The compiler says a partial move happened in the `match` statement. How can The compiler says a partial move happened in the `match` statement. How can
this be avoided? The compiler shows the correction needed. this be avoided? The compiler shows the correction needed.
@ -662,6 +686,7 @@ https://doc.rust-lang.org/std/keyword.ref.html"""
[[exercises]] [[exercises]]
name = "errors1" name = "errors1"
dir = "13_error_handling" dir = "13_error_handling"
mode = "test"
hint = """ hint = """
`Ok` and `Err` are the two variants of `Result`, so what the tests are saying `Ok` and `Err` are the two variants of `Result`, so what the tests are saying
is that `generate_nametag_text` should return a `Result` instead of an `Option`. is that `generate_nametag_text` should return a `Result` instead of an `Option`.
@ -677,6 +702,7 @@ To make this change, you'll need to:
[[exercises]] [[exercises]]
name = "errors2" name = "errors2"
dir = "13_error_handling" dir = "13_error_handling"
mode = "test"
hint = """ hint = """
One way to handle this is using a `match` statement on One way to handle this is using a `match` statement on
`item_quantity.parse::<i32>()` where the cases are `Ok(something)` and `item_quantity.parse::<i32>()` where the cases are `Ok(something)` and
@ -692,7 +718,7 @@ and give it a try!"""
[[exercises]] [[exercises]]
name = "errors3" name = "errors3"
dir = "13_error_handling" dir = "13_error_handling"
test = false mode = "run"
hint = """ hint = """
If other functions can return a `Result`, why shouldn't `main`? It's a fairly If other functions can return a `Result`, why shouldn't `main`? It's a fairly
common convention to return something like `Result<(), ErrorType>` from your common convention to return something like `Result<(), ErrorType>` from your
@ -704,6 +730,7 @@ positive results."""
[[exercises]] [[exercises]]
name = "errors4" name = "errors4"
dir = "13_error_handling" dir = "13_error_handling"
mode = "test"
hint = """ hint = """
`PositiveNonzeroInteger::new` is always creating a new instance and returning `PositiveNonzeroInteger::new` is always creating a new instance and returning
an `Ok` result. an `Ok` result.
@ -715,7 +742,7 @@ everything is... okay :)"""
[[exercises]] [[exercises]]
name = "errors5" name = "errors5"
dir = "13_error_handling" dir = "13_error_handling"
test = false mode = "run"
hint = """ hint = """
There are two different possible `Result` types produced within `main()`, which There are two different possible `Result` types produced within `main()`, which
are propagated using `?` operators. How do we declare a return type from are propagated using `?` operators. How do we declare a return type from
@ -739,6 +766,7 @@ https://doc.rust-lang.org/stable/rust-by-example/error/multiple_error_types/reen
[[exercises]] [[exercises]]
name = "errors6" name = "errors6"
dir = "13_error_handling" dir = "13_error_handling"
mode = "test"
hint = """ hint = """
This exercise uses a completed version of `PositiveNonzeroInteger` from This exercise uses a completed version of `PositiveNonzeroInteger` from
errors4. errors4.
@ -760,7 +788,7 @@ https://doc.rust-lang.org/std/result/enum.Result.html#method.map_err"""
[[exercises]] [[exercises]]
name = "generics1" name = "generics1"
dir = "14_generics" dir = "14_generics"
test = false mode = "run"
hint = """ hint = """
Vectors in Rust make use of generics to create dynamically sized arrays of any Vectors in Rust make use of generics to create dynamically sized arrays of any
type. type.
@ -770,6 +798,7 @@ You need to tell the compiler what type we are pushing onto this vector."""
[[exercises]] [[exercises]]
name = "generics2" name = "generics2"
dir = "14_generics" dir = "14_generics"
mode = "test"
hint = """ hint = """
Currently we are wrapping only values of type `u32`. Currently we are wrapping only values of type `u32`.
@ -783,6 +812,7 @@ If you are still stuck https://doc.rust-lang.org/stable/book/ch10-01-syntax.html
[[exercises]] [[exercises]]
name = "traits1" name = "traits1"
dir = "15_traits" dir = "15_traits"
mode = "test"
hint = """ hint = """
A discussion about Traits in Rust can be found at: A discussion about Traits in Rust can be found at:
https://doc.rust-lang.org/book/ch10-02-traits.html https://doc.rust-lang.org/book/ch10-02-traits.html
@ -791,6 +821,7 @@ https://doc.rust-lang.org/book/ch10-02-traits.html
[[exercises]] [[exercises]]
name = "traits2" name = "traits2"
dir = "15_traits" dir = "15_traits"
mode = "test"
hint = """ hint = """
Notice how the trait takes ownership of `self`, and returns `Self`. Notice how the trait takes ownership of `self`, and returns `Self`.
@ -803,6 +834,7 @@ the documentation at: https://doc.rust-lang.org/std/vec/struct.Vec.html"""
[[exercises]] [[exercises]]
name = "traits3" name = "traits3"
dir = "15_traits" dir = "15_traits"
mode = "test"
hint = """ hint = """
Traits can have a default implementation for functions. Structs that implement Traits can have a default implementation for functions. Structs that implement
the trait can then use the default version of these functions if they choose not the trait can then use the default version of these functions if they choose not
@ -814,6 +846,7 @@ See the documentation at: https://doc.rust-lang.org/book/ch10-02-traits.html#def
[[exercises]] [[exercises]]
name = "traits4" name = "traits4"
dir = "15_traits" dir = "15_traits"
mode = "test"
hint = """ hint = """
Instead of using concrete types as parameters you can use traits. Try replacing Instead of using concrete types as parameters you can use traits. Try replacing
the '??' with 'impl <what goes here?>' the '??' with 'impl <what goes here?>'
@ -824,7 +857,7 @@ See the documentation at: https://doc.rust-lang.org/book/ch10-02-traits.html#tra
[[exercises]] [[exercises]]
name = "traits5" name = "traits5"
dir = "15_traits" dir = "15_traits"
test = false mode = "run"
hint = """ hint = """
To ensure a parameter implements multiple traits use the '+ syntax'. Try To ensure a parameter implements multiple traits use the '+ syntax'. Try
replacing the '??' with 'impl <> + <>'. replacing the '??' with 'impl <> + <>'.
@ -837,6 +870,7 @@ See the documentation at: https://doc.rust-lang.org/book/ch10-02-traits.html#spe
[[exercises]] [[exercises]]
name = "quiz3" name = "quiz3"
dir = "quizzes" dir = "quizzes"
mode = "test"
hint = """ hint = """
To find the best solution to this challenge you're going to need to think back To find the best solution to this challenge you're going to need to think back
to your knowledge of traits, specifically 'Trait Bound Syntax' to your knowledge of traits, specifically 'Trait Bound Syntax'
@ -848,7 +882,7 @@ You may also need this: `use std::fmt::Display;`."""
[[exercises]] [[exercises]]
name = "lifetimes1" name = "lifetimes1"
dir = "16_lifetimes" dir = "16_lifetimes"
test = false mode = "run"
hint = """ hint = """
Let the compiler guide you. Also take a look at the book if you need help: Let the compiler guide you. Also take a look at the book if you need help:
https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html""" https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html"""
@ -856,7 +890,7 @@ https://doc.rust-lang.org/book/ch10-03-lifetime-syntax.html"""
[[exercises]] [[exercises]]
name = "lifetimes2" name = "lifetimes2"
dir = "16_lifetimes" dir = "16_lifetimes"
test = false mode = "run"
hint = """ hint = """
Remember that the generic lifetime `'a` will get the concrete lifetime that is Remember that the generic lifetime `'a` will get the concrete lifetime that is
equal to the smaller of the lifetimes of `x` and `y`. equal to the smaller of the lifetimes of `x` and `y`.
@ -870,7 +904,7 @@ inner block:
[[exercises]] [[exercises]]
name = "lifetimes3" name = "lifetimes3"
dir = "16_lifetimes" dir = "16_lifetimes"
test = false mode = "run"
hint = """ hint = """
If you use a lifetime annotation in a struct's fields, where else does it need If you use a lifetime annotation in a struct's fields, where else does it need
to be added?""" to be added?"""
@ -880,6 +914,7 @@ to be added?"""
[[exercises]] [[exercises]]
name = "tests1" name = "tests1"
dir = "17_tests" dir = "17_tests"
mode = "test"
hint = """ hint = """
You don't even need to write any code to test -- you can just test values and You don't even need to write any code to test -- you can just test values and
run that, even though you wouldn't do that in real life. :) run that, even though you wouldn't do that in real life. :)
@ -894,6 +929,7 @@ ones pass, and which ones fail :)"""
[[exercises]] [[exercises]]
name = "tests2" name = "tests2"
dir = "17_tests" dir = "17_tests"
mode = "test"
hint = """ hint = """
Like the previous exercise, you don't need to write any code to get this test Like the previous exercise, you don't need to write any code to get this test
to compile and run. to compile and run.
@ -906,6 +942,7 @@ argument comes first and which comes second!"""
[[exercises]] [[exercises]]
name = "tests3" name = "tests3"
dir = "17_tests" dir = "17_tests"
mode = "test"
hint = """ hint = """
You can call a function right where you're passing arguments to `assert!`. So You can call a function right where you're passing arguments to `assert!`. So
you could do something like `assert!(having_fun())`. you could do something like `assert!(having_fun())`.
@ -916,6 +953,7 @@ what you're doing using `!`, like `assert!(!having_fun())`."""
[[exercises]] [[exercises]]
name = "tests4" name = "tests4"
dir = "17_tests" dir = "17_tests"
mode = "test"
hint = """ hint = """
We expect method `Rectangle::new()` to panic for negative values. We expect method `Rectangle::new()` to panic for negative values.
@ -929,6 +967,7 @@ https://doc.rust-lang.org/stable/book/ch11-01-writing-tests.html#checking-for-pa
[[exercises]] [[exercises]]
name = "iterators1" name = "iterators1"
dir = "18_iterators" dir = "18_iterators"
mode = "test"
hint = """ hint = """
Step 1: Step 1:
@ -951,6 +990,7 @@ https://doc.rust-lang.org/std/iter/trait.Iterator.html for some ideas.
[[exercises]] [[exercises]]
name = "iterators2" name = "iterators2"
dir = "18_iterators" dir = "18_iterators"
mode = "test"
hint = """ hint = """
Step 1: Step 1:
@ -976,6 +1016,7 @@ powerful and very general. Rust just needs to know the desired type."""
[[exercises]] [[exercises]]
name = "iterators3" name = "iterators3"
dir = "18_iterators" dir = "18_iterators"
mode = "test"
hint = """ hint = """
The `divide` function needs to return the correct error when even division is The `divide` function needs to return the correct error when even division is
not possible. not possible.
@ -994,6 +1035,7 @@ powerful! It can make the solution to this exercise infinitely easier."""
[[exercises]] [[exercises]]
name = "iterators4" name = "iterators4"
dir = "18_iterators" dir = "18_iterators"
mode = "test"
hint = """ hint = """
In an imperative language, you might write a `for` loop that updates a mutable In an imperative language, you might write a `for` loop that updates a mutable
variable. Or, you might write code utilizing recursion and a match clause. In variable. Or, you might write code utilizing recursion and a match clause. In
@ -1005,6 +1047,7 @@ Hint 2: Check out the `fold` and `rfold` methods!"""
[[exercises]] [[exercises]]
name = "iterators5" name = "iterators5"
dir = "18_iterators" dir = "18_iterators"
mode = "test"
hint = """ hint = """
The documentation for the `std::iter::Iterator` trait contains numerous methods The documentation for the `std::iter::Iterator` trait contains numerous methods
that would be helpful here. that would be helpful here.
@ -1023,6 +1066,7 @@ a different method that could make your code more compact than using `fold`."""
[[exercises]] [[exercises]]
name = "box1" name = "box1"
dir = "19_smart_pointers" dir = "19_smart_pointers"
mode = "test"
hint = """ hint = """
Step 1: Step 1:
@ -1046,6 +1090,7 @@ definition and try other types!
[[exercises]] [[exercises]]
name = "rc1" name = "rc1"
dir = "19_smart_pointers" dir = "19_smart_pointers"
mode = "test"
hint = """ hint = """
This is a straightforward exercise to use the `Rc<T>` type. Each `Planet` has This is a straightforward exercise to use the `Rc<T>` type. Each `Planet` has
ownership of the `Sun`, and uses `Rc::clone()` to increment the reference count ownership of the `Sun`, and uses `Rc::clone()` to increment the reference count
@ -1064,7 +1109,7 @@ See more at: https://doc.rust-lang.org/book/ch15-04-rc.html
[[exercises]] [[exercises]]
name = "arc1" name = "arc1"
dir = "19_smart_pointers" dir = "19_smart_pointers"
test = false mode = "run"
hint = """ hint = """
Make `shared_numbers` be an `Arc` from the numbers vector. Then, in order Make `shared_numbers` be an `Arc` from the numbers vector. Then, in order
to avoid creating a copy of `numbers`, you'll need to create `child_numbers` to avoid creating a copy of `numbers`, you'll need to create `child_numbers`
@ -1082,6 +1127,7 @@ https://doc.rust-lang.org/stable/book/ch16-00-concurrency.html
[[exercises]] [[exercises]]
name = "cow1" name = "cow1"
dir = "19_smart_pointers" dir = "19_smart_pointers"
mode = "test"
hint = """ hint = """
If `Cow` already owns the data it doesn't need to clone it when `to_mut()` is If `Cow` already owns the data it doesn't need to clone it when `to_mut()` is
called. called.
@ -1095,7 +1141,7 @@ on the `Cow` type.
[[exercises]] [[exercises]]
name = "threads1" name = "threads1"
dir = "20_threads" dir = "20_threads"
test = false mode = "run"
hint = """ hint = """
`JoinHandle` is a struct that is returned from a spawned thread: `JoinHandle` is a struct that is returned from a spawned thread:
https://doc.rust-lang.org/std/thread/fn.spawn.html https://doc.rust-lang.org/std/thread/fn.spawn.html
@ -1113,7 +1159,7 @@ https://doc.rust-lang.org/std/thread/struct.JoinHandle.html
[[exercises]] [[exercises]]
name = "threads2" name = "threads2"
dir = "20_threads" dir = "20_threads"
test = false mode = "run"
hint = """ hint = """
`Arc` is an Atomic Reference Counted pointer that allows safe, shared access `Arc` is an Atomic Reference Counted pointer that allows safe, shared access
to **immutable** data. But we want to *change* the number of `jobs_completed` to **immutable** data. But we want to *change* the number of `jobs_completed`
@ -1135,6 +1181,7 @@ https://doc.rust-lang.org/book/ch16-03-shared-state.html#sharing-a-mutext-betwee
[[exercises]] [[exercises]]
name = "threads3" name = "threads3"
dir = "20_threads" dir = "20_threads"
mode = "test"
hint = """ hint = """
An alternate way to handle concurrency between threads is to use an `mpsc` An alternate way to handle concurrency between threads is to use an `mpsc`
(multiple producer, single consumer) channel to communicate. (multiple producer, single consumer) channel to communicate.
@ -1153,7 +1200,7 @@ See https://doc.rust-lang.org/book/ch16-02-message-passing.html for more info.
[[exercises]] [[exercises]]
name = "macros1" name = "macros1"
dir = "21_macros" dir = "21_macros"
test = false mode = "run"
hint = """ hint = """
When you call a macro, you need to add something special compared to a When you call a macro, you need to add something special compared to a
regular function call. If you're stuck, take a look at what's inside regular function call. If you're stuck, take a look at what's inside
@ -1162,7 +1209,7 @@ regular function call. If you're stuck, take a look at what's inside
[[exercises]] [[exercises]]
name = "macros2" name = "macros2"
dir = "21_macros" dir = "21_macros"
test = false mode = "run"
hint = """ hint = """
Macros don't quite play by the same rules as the rest of Rust, in terms of Macros don't quite play by the same rules as the rest of Rust, in terms of
what's available where. what's available where.
@ -1173,7 +1220,7 @@ Unlike other things in Rust, the order of "where you define a macro" versus
[[exercises]] [[exercises]]
name = "macros3" name = "macros3"
dir = "21_macros" dir = "21_macros"
test = false mode = "run"
hint = """ hint = """
In order to use a macro outside of its module, you need to do something In order to use a macro outside of its module, you need to do something
special to the module to lift the macro out into its parent. special to the module to lift the macro out into its parent.
@ -1184,7 +1231,7 @@ exported macros, if you've seen any of those around."""
[[exercises]] [[exercises]]
name = "macros4" name = "macros4"
dir = "21_macros" dir = "21_macros"
test = false mode = "run"
hint = """ hint = """
You only need to add a single character to make this compile. You only need to add a single character to make this compile.
@ -1201,8 +1248,7 @@ https://veykril.github.io/tlborm/"""
[[exercises]] [[exercises]]
name = "clippy1" name = "clippy1"
dir = "22_clippy" dir = "22_clippy"
test = false mode = "clippy"
strict_clippy = true
hint = """ hint = """
Rust stores the highest precision version of any long or infinite precision Rust stores the highest precision version of any long or infinite precision
mathematical constants in the Rust standard library: mathematical constants in the Rust standard library:
@ -1218,16 +1264,14 @@ appropriate replacement constant from `std::f32::consts`..."""
[[exercises]] [[exercises]]
name = "clippy2" name = "clippy2"
dir = "22_clippy" dir = "22_clippy"
test = false mode = "clippy"
strict_clippy = true
hint = """ hint = """
`for` loops over `Option` values are more clearly expressed as an `if let`""" `for` loops over `Option` values are more clearly expressed as an `if let`"""
[[exercises]] [[exercises]]
name = "clippy3" name = "clippy3"
dir = "22_clippy" dir = "22_clippy"
test = false mode = "clippy"
strict_clippy = true
hint = "No hints this time!" hint = "No hints this time!"
# TYPE CONVERSIONS # TYPE CONVERSIONS
@ -1235,6 +1279,7 @@ hint = "No hints this time!"
[[exercises]] [[exercises]]
name = "using_as" name = "using_as"
dir = "23_conversions" dir = "23_conversions"
mode = "test"
hint = """ hint = """
Use the `as` operator to cast one of the operands in the last line of the Use the `as` operator to cast one of the operands in the last line of the
`average` function into the expected return type.""" `average` function into the expected return type."""
@ -1242,12 +1287,14 @@ Use the `as` operator to cast one of the operands in the last line of the
[[exercises]] [[exercises]]
name = "from_into" name = "from_into"
dir = "23_conversions" dir = "23_conversions"
mode = "test"
hint = """ hint = """
Follow the steps provided right before the `From` implementation""" Follow the steps provided right before the `From` implementation"""
[[exercises]] [[exercises]]
name = "from_str" name = "from_str"
dir = "23_conversions" dir = "23_conversions"
mode = "test"
hint = """ hint = """
The implementation of `FromStr` should return an `Ok` with a `Person` object, The implementation of `FromStr` should return an `Ok` with a `Person` object,
or an `Err` with an error if the string is not valid. or an `Err` with an error if the string is not valid.
@ -1268,6 +1315,7 @@ https://doc.rust-lang.org/stable/rust-by-example/error/multiple_error_types/reen
[[exercises]] [[exercises]]
name = "try_from_into" name = "try_from_into"
dir = "23_conversions" dir = "23_conversions"
mode = "test"
hint = """ hint = """
Follow the steps provided right before the `TryFrom` implementation. Follow the steps provided right before the `TryFrom` implementation.
You can also use the example at You can also use the example at
@ -1290,5 +1338,6 @@ Challenge: Can you make the `TryFrom` implementations generic over many integer
[[exercises]] [[exercises]]
name = "as_ref_mut" name = "as_ref_mut"
dir = "23_conversions" dir = "23_conversions"
mode = "test"
hint = """ hint = """
Add `AsRef<str>` or `AsMut<u32>` as a trait bound to the functions.""" Add `AsRef<str>` or `AsMut<u32>` as a trait bound to the functions."""

View file

@ -1,9 +0,0 @@
#!/bin/bash
# Error out if any command fails
set -e
cargo run -- dev check
typos
cargo outdated -w --exit-code 1
cargo test --workspace --all-targets

View file

@ -6,10 +6,6 @@ authors.workspace = true
repository.workspace = true repository.workspace = true
license.workspace = true license.workspace = true
edition.workspace = true edition.workspace = true
include = [
"/src/",
"/info.toml",
]
[lib] [lib]
proc-macro = true proc-macro = true

View file

@ -1 +0,0 @@
../info.toml

View file

@ -15,7 +15,7 @@ struct InfoFile {
#[proc_macro] #[proc_macro]
pub fn include_files(_: TokenStream) -> TokenStream { pub fn include_files(_: TokenStream) -> TokenStream {
let exercises = toml_edit::de::from_str::<InfoFile>(include_str!("../info.toml")) let exercises = toml_edit::de::from_str::<InfoFile>(include_str!("../../info.toml"))
.expect("Failed to parse `info.toml`") .expect("Failed to parse `info.toml`")
.exercises; .exercises;

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

View file

@ -1 +1 @@
// Solutions will be available before the stable release. Thank you for testing the beta version 🥰 // TODO

Some files were not shown because too many files have changed in this diff Show more