Compare commits
44 Commits
9e63a5cdf6
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8791feb495 | ||
|
|
a2fe212f44 | ||
|
|
20a2b45e49 | ||
|
|
c3cb1b38f6 | ||
|
|
af4fe9cedb | ||
|
|
21f3427c92 | ||
|
|
b839c770b5 | ||
|
|
fd23b201fe | ||
|
|
13850a6b01 | ||
|
|
a7865baf3c | ||
|
|
0e1c66814d | ||
|
|
2f059fc5ba | ||
|
|
63402ef5c2 | ||
|
|
892c37ead9 | ||
|
|
c745cf8ddd | ||
|
|
3f60de3712 | ||
|
|
36f6375c20 | ||
|
|
fb19005d5f | ||
|
|
cc0092b2c6 | ||
|
|
d5e1c00108 | ||
|
|
60947aaacd | ||
|
|
fe40e6e2d0 | ||
|
|
7fb0910b39 | ||
|
|
468b74ba4d | ||
|
|
b0e1e5a1ec | ||
|
|
93536fbcfd | ||
|
|
1993507236 | ||
|
|
a1a2dc1588 | ||
|
|
51cad6bdfe | ||
|
|
ab1eb5d80c | ||
|
|
fd6a56fd84 | ||
|
|
0419e2e8b2 | ||
|
|
4b02e92691 | ||
|
|
eb2d858807 | ||
|
|
4194ee9998 | ||
|
|
9f5e4a0d76 | ||
|
|
da610ee79b | ||
|
|
f1a0eab4a6 | ||
|
|
3addd64dc2 | ||
|
|
a53e4f86a1 | ||
|
|
5edddf102e | ||
|
|
dab563a329 | ||
|
|
c75ff98c6a | ||
|
|
b60e021ab1 |
25
.github/workflows/ci.yml
vendored
25
.github/workflows/ci.yml
vendored
@@ -56,7 +56,7 @@ jobs:
|
|||||||
echo "$PWD/pandoc-${PANDOC_VERSION}/bin" >> $GITHUB_PATH
|
echo "$PWD/pandoc-${PANDOC_VERSION}/bin" >> $GITHUB_PATH
|
||||||
shell: bash
|
shell: bash
|
||||||
- name: Setup TeX Live
|
- name: Setup TeX Live
|
||||||
uses: teatimeguest/setup-texlive-action@v3
|
uses: TeX-Live/setup-texlive-action@v3
|
||||||
with:
|
with:
|
||||||
packages:
|
packages:
|
||||||
scheme-basic
|
scheme-basic
|
||||||
@@ -111,9 +111,9 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fail: true
|
fail: true
|
||||||
args: |
|
args: |
|
||||||
--exclude-loopback
|
--exclude-loopback
|
||||||
--require-https
|
--require-https
|
||||||
--no-progress
|
--no-progress
|
||||||
book/book/html/
|
book/book/html/
|
||||||
# Upload the HTML book as an artifact
|
# Upload the HTML book as an artifact
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
@@ -146,6 +146,23 @@ jobs:
|
|||||||
- run: |
|
- run: |
|
||||||
git diff --exit-code site/_redirects
|
git diff --exit-code site/_redirects
|
||||||
|
|
||||||
|
gravity:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [build]
|
||||||
|
steps:
|
||||||
|
- uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
path: book
|
||||||
|
pattern: online-pdf
|
||||||
|
- uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 9
|
||||||
|
- run: ls -las ./book
|
||||||
|
- name: Run Gravity
|
||||||
|
run: pnpm dlx @gravityci/cli "./book/**/*"
|
||||||
|
env:
|
||||||
|
GRAVITY_TOKEN: ${{ secrets.GRAVITY_TOKEN }}
|
||||||
|
|
||||||
formatter:
|
formatter:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
1927
Cargo.lock
generated
1927
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -18,6 +18,9 @@ after = ["exercise-linker"]
|
|||||||
[output.html]
|
[output.html]
|
||||||
git-repository-url = "https://github.com/mainmatter/100-exercises-to-learn-rust"
|
git-repository-url = "https://github.com/mainmatter/100-exercises-to-learn-rust"
|
||||||
|
|
||||||
|
[output.html.playground]
|
||||||
|
runnable = false
|
||||||
|
|
||||||
[output.pandoc]
|
[output.pandoc]
|
||||||
optional = true
|
optional = true
|
||||||
hosted-html = "https://rust-exercises.com/100-exercises/"
|
hosted-html = "https://rust-exercises.com/100-exercises/"
|
||||||
@@ -49,8 +52,8 @@ sansfontoptions = [
|
|||||||
]
|
]
|
||||||
# You can get these fonts here: https://fonts.google.com/selection?query=noto+color+
|
# You can get these fonts here: https://fonts.google.com/selection?query=noto+color+
|
||||||
monofont = "Noto Sans Mono"
|
monofont = "Noto Sans Mono"
|
||||||
mainfontfallback = ["Open Sans"]
|
mainfontfallback = ["Open Sans:style=Regular"]
|
||||||
sansfontfallback = ["Open Sans"]
|
sansfontfallback = ["Open Sans:style=Regular"]
|
||||||
monofontfallback = [
|
monofontfallback = [
|
||||||
"Noto Color Emoji:mode=harf",
|
"Noto Color Emoji:mode=harf",
|
||||||
]
|
]
|
||||||
@@ -90,8 +93,8 @@ sansfontoptions = [
|
|||||||
]
|
]
|
||||||
# You can get these fonts here: https://fonts.google.com/selection?query=noto+color+
|
# You can get these fonts here: https://fonts.google.com/selection?query=noto+color+
|
||||||
monofont = "Noto Sans Mono"
|
monofont = "Noto Sans Mono"
|
||||||
mainfontfallback = ["Open Sans"]
|
mainfontfallback = ["Open Sans:style=Regular"]
|
||||||
sansfontfallback = ["Open Sans"]
|
sansfontfallback = ["Open Sans:style=Regular"]
|
||||||
monofontfallback = [
|
monofontfallback = [
|
||||||
"Noto Color Emoji:mode=harf",
|
"Noto Color Emoji:mode=harf",
|
||||||
]
|
]
|
||||||
@@ -121,8 +124,8 @@ metadata-file = "metadata.yml"
|
|||||||
[output.pandoc.profile.html.variables]
|
[output.pandoc.profile.html.variables]
|
||||||
# You can get these fonts here: https://fonts.google.com/selection?query=noto+color+
|
# You can get these fonts here: https://fonts.google.com/selection?query=noto+color+
|
||||||
monofont = "Noto Sans Mono"
|
monofont = "Noto Sans Mono"
|
||||||
mainfontfallback = ["Open Sans"]
|
mainfontfallback = ["Open Sans:style=Regular"]
|
||||||
sansfontfallback = ["Open Sans"]
|
sansfontfallback = ["Open Sans:style=Regular"]
|
||||||
monofontfallback = [
|
monofontfallback = [
|
||||||
"Noto Color Emoji:mode=harf",
|
"Noto Color Emoji:mode=harf",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"https://blog.acolyer.org/2019/05/28/cheri-abi/": "f2u",
|
"https://code.visualstudio.com": "f6c",
|
||||||
"https://crates.io": "f4q",
|
"https://crates.io": "f4q",
|
||||||
"https://crates.io/crates/cargo-modules": "f2n",
|
"https://crates.io/crates/cargo-modules": "f2n",
|
||||||
"https://doc.rust-lang.org/book/ch03-02-data-types.html#integer-types": "ffr",
|
"https://doc.rust-lang.org/book/ch03-02-data-types.html#integer-types": "ffr",
|
||||||
@@ -163,7 +163,9 @@
|
|||||||
"https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/": "f4r",
|
"https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/": "f4r",
|
||||||
"https://mainmatter.com/contact/": "ff2",
|
"https://mainmatter.com/contact/": "ff2",
|
||||||
"https://mainmatter.com/rust-consulting/": "fff",
|
"https://mainmatter.com/rust-consulting/": "fff",
|
||||||
|
"https://mainmatter.github.io/rust-workshop-runner/": "fv2",
|
||||||
"https://marabos.nl/atomics/": "fxg",
|
"https://marabos.nl/atomics/": "fxg",
|
||||||
|
"https://marketplace.visualstudio.com/items?itemName=matklad.rust-analyzer": "f6a",
|
||||||
"https://nostarch.com/rust-rustaceans": "f6p",
|
"https://nostarch.com/rust-rustaceans": "f6p",
|
||||||
"https://owasp.org/www-community/vulnerabilities/Doubly_freeing_memory": "f2k",
|
"https://owasp.org/www-community/vulnerabilities/Doubly_freeing_memory": "f2k",
|
||||||
"https://owasp.org/www-community/vulnerabilities/Using_freed_memory": "f2s",
|
"https://owasp.org/www-community/vulnerabilities/Using_freed_memory": "f2s",
|
||||||
@@ -177,14 +179,18 @@
|
|||||||
"https://rust-lang.github.io/api-guidelines/naming.html#casing-conforms-to-rfc-430-c-case": "fze",
|
"https://rust-lang.github.io/api-guidelines/naming.html#casing-conforms-to-rfc-430-c-case": "fze",
|
||||||
"https://rust-lang.github.io/wg-async/vision/submitted_stories/status_quo/barbara_battles_buffered_streams.html": "f6w",
|
"https://rust-lang.github.io/wg-async/vision/submitted_stories/status_quo/barbara_battles_buffered_streams.html": "f6w",
|
||||||
"https://ryhl.io/blog/async-what-is-blocking/": "f6v",
|
"https://ryhl.io/blog/async-what-is-blocking/": "f6v",
|
||||||
|
"https://ti.to/mainmatter/rust-from-scratch-jan-2025": "fvf",
|
||||||
"https://tokio.rs/tokio/tutorial/select": "f6n",
|
"https://tokio.rs/tokio/tutorial/select": "f6n",
|
||||||
"https://valgrind.org/docs/manual/dh-manual.html": "f2t",
|
"https://valgrind.org/docs/manual/dh-manual.html": "f2t",
|
||||||
"https://veykril.github.io/tlborm/": "fz5",
|
"https://veykril.github.io/tlborm/": "fz5",
|
||||||
|
"https://web.archive.org/web/20240517051950/https://blog.acolyer.org/2019/05/28/cheri-abi/": "f2u",
|
||||||
"https://without.boats/blog/the-scoped-task-trilemma/": "f67",
|
"https://without.boats/blog/the-scoped-task-trilemma/": "f67",
|
||||||
"https://www.amazon.com/dp/B0DJ14KQQG/": "f6g",
|
"https://www.amazon.com/dp/B0DJ14KQQG/": "f6g",
|
||||||
|
"https://www.jetbrains.com/rust/": "f6d",
|
||||||
"https://www.lpalmieri.com/": "ffv",
|
"https://www.lpalmieri.com/": "ffv",
|
||||||
"https://www.lpalmieri.com/posts/2020-12-11-zero-to-production-6-domain-modelling/": "f4t",
|
"https://www.lpalmieri.com/posts/2020-12-11-zero-to-production-6-domain-modelling/": "f4t",
|
||||||
"https://www.oreilly.com/library/view/programming-rust-2nd/9781492052586/": "f6y",
|
"https://www.oreilly.com/library/view/programming-rust-2nd/9781492052586/": "f6y",
|
||||||
|
"https://www.rust-lang.org/tools/install": "f6j",
|
||||||
"https://www.youtube.com/playlist?list=PLqbS7AVVErFirH9armw8yXlE6dacF-A6z": "f6l",
|
"https://www.youtube.com/playlist?list=PLqbS7AVVErFirH9armw8yXlE6dacF-A6z": "f6l",
|
||||||
"https://zero2prod.com": "ff8"
|
"https://zero2prod.com": "ff8"
|
||||||
}
|
}
|
||||||
@@ -24,12 +24,12 @@ It has been designed to be interactive and hands-on.
|
|||||||
to be delivered in a classroom setting, over 4 days: each attendee advances
|
to be delivered in a classroom setting, over 4 days: each attendee advances
|
||||||
through the lessons at their own pace, with an experienced instructor providing
|
through the lessons at their own pace, with an experienced instructor providing
|
||||||
guidance, answering questions and diving deeper into the topics as needed.\
|
guidance, answering questions and diving deeper into the topics as needed.\
|
||||||
If you're interested in attending one of our training sessions, or if you'd like to
|
You can sign up for the next tutored session on [our website](https://ti.to/mainmatter/rust-from-scratch-jan-2025).
|
||||||
bring this course to your company, please [get in touch](https://mainmatter.com/contact/).
|
If you'd like to organise a private session for your company, please [get in touch](https://mainmatter.com/contact/).
|
||||||
|
|
||||||
You can also follow the course on your own, but we recommend you find a friend or
|
You can also take the courses on your own, but we recommend you find a friend or
|
||||||
a mentor to help you along the way should you get stuck. You can
|
a mentor to help you along the way should you get stuck. You can
|
||||||
also find solutions to all exercises in the
|
find solutions for all exercises in the
|
||||||
[`solutions` branch of the GitHub repository](https://github.com/mainmatter/100-exercises-to-learn-rust/tree/solutions).
|
[`solutions` branch of the GitHub repository](https://github.com/mainmatter/100-exercises-to-learn-rust/tree/solutions).
|
||||||
|
|
||||||
## Formats
|
## Formats
|
||||||
@@ -67,17 +67,23 @@ Each exercise is structured as a Rust package.
|
|||||||
The package contains the exercise itself, instructions on what to do (in `src/lib.rs`), and a test suite to
|
The package contains the exercise itself, instructions on what to do (in `src/lib.rs`), and a test suite to
|
||||||
automatically verify your solution.
|
automatically verify your solution.
|
||||||
|
|
||||||
### `wr`, the workshop runner
|
### Tools
|
||||||
|
|
||||||
To verify your solutions, we've provided a tool that will guide you through the course.
|
To work through this course, you'll need:
|
||||||
It is the `wr` CLI (short for "workshop runner").
|
|
||||||
Install it with:
|
|
||||||
|
|
||||||
```bash
|
- [**Rust**](https://www.rust-lang.org/tools/install).
|
||||||
cargo install --locked workshop-runner
|
If `rustup` is already installed on your system, run `rustup update` (or another appropriate command depending on how you installed Rust on your system) to ensure you're running on the latest stable version.
|
||||||
```
|
- _(Optional but recommended)_ An IDE with Rust autocompletion support.
|
||||||
|
We recommend one of the following:
|
||||||
|
- [RustRover](https://www.jetbrains.com/rust/);
|
||||||
|
- [Visual Studio Code](https://code.visualstudio.com) with the [`rust-analyzer`](https://marketplace.visualstudio.com/items?itemName=matklad.rust-analyzer) extension.
|
||||||
|
|
||||||
In a new terminal, navigate back to the top-level folder of the repository.
|
### Workshop runner, `wr`
|
||||||
|
|
||||||
|
To verify your solutions, we've also provided a tool to guide you through the course: the `wr` CLI, short for "workshop runner".
|
||||||
|
Install `wr` by following the instructions on [its website](https://mainmatter.github.io/rust-workshop-runner/).
|
||||||
|
|
||||||
|
Once you have `wr` installed, open a new terminal and navigate to the top-level folder of the repository.
|
||||||
Run the `wr` command to start the course:
|
Run the `wr` command to start the course:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -36,6 +36,38 @@ if number < 5 {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `else if` clauses
|
||||||
|
|
||||||
|
Your code drifts more and more to the right when you have multiple `if` expressions, one nested inside the other.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
let number = 3;
|
||||||
|
|
||||||
|
if number < 5 {
|
||||||
|
println!("`number` is smaller than 5");
|
||||||
|
} else {
|
||||||
|
if number >= 3 {
|
||||||
|
println!("`number` is greater than or equal to 3, but smaller than 5");
|
||||||
|
} else {
|
||||||
|
println!("`number` is smaller than 3");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can use the `else if` keyword to combine multiple `if` expressions into a single one:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
let number = 3;
|
||||||
|
|
||||||
|
if number < 5 {
|
||||||
|
println!("`number` is smaller than 5");
|
||||||
|
} else if number >= 3 {
|
||||||
|
println!("`number` is greater than or equal to 3, but smaller than 5");
|
||||||
|
} else {
|
||||||
|
println!("`number` is smaller than 3");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Booleans
|
## Booleans
|
||||||
|
|
||||||
The condition in an `if` expression must be of type `bool`, a **boolean**.\
|
The condition in an `if` expression must be of type `bool`, a **boolean**.\
|
||||||
|
|||||||
@@ -75,16 +75,14 @@ development,
|
|||||||
therefore it sacrifices runtime performance in favor of faster compilation times and a better debugging experience.\
|
therefore it sacrifices runtime performance in favor of faster compilation times and a better debugging experience.\
|
||||||
The `release` profile, instead, is optimized for runtime performance but incurs longer compilation times. You need
|
The `release` profile, instead, is optimized for runtime performance but incurs longer compilation times. You need
|
||||||
to explicitly request via the `--release` flag—e.g. `cargo build --release` or `cargo run --release`.
|
to explicitly request via the `--release` flag—e.g. `cargo build --release` or `cargo run --release`.
|
||||||
The `test` profile is the default profile used by `cargo test`. The `test` profile inherits the settings form the `dev` profile.
|
The `test` profile is the default profile used by `cargo test`. The `test` profile inherits the settings from the `dev` profile.
|
||||||
The `bench` profile is the default profile used by `cargo bench`. The `bench` profile inherits from the `release` profile.
|
The `bench` profile is the default profile used by `cargo bench`. The `bench` profile inherits from the `release` profile.
|
||||||
Use `dev` for iterative development and debugging, `release` for optimized production builds,\
|
Use `dev` for iterative development and debugging, `release` for optimized production builds,\
|
||||||
`test` for correctness testing, and `bench` for performance benchmarking.
|
`test` for correctness testing, and `bench` for performance benchmarking.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
> "Have you built your project in release mode?" is almost a meme in the Rust community.\
|
> "Have you built your project in release mode?" is almost a meme in the Rust community.\
|
||||||
> It refers to developers who are not familiar with Rust and complain about its performance on
|
> It refers to developers who are not familiar with Rust and complain about its performance on
|
||||||
> social media (e.g. Reddit, Twitter, etc.) before realizing they haven't built their project in
|
> social media (e.g. Reddit, Twitter) before realizing they haven't built their project in
|
||||||
> release mode.
|
> release mode.
|
||||||
|
|
||||||
You can also define custom profiles or customize the built-in ones.
|
You can also define custom profiles or customize the built-in ones.
|
||||||
|
|||||||
@@ -85,6 +85,9 @@ You can compose the path in various ways:
|
|||||||
- starting from the parent module, e.g. `super::my_function`
|
- starting from the parent module, e.g. `super::my_function`
|
||||||
- starting from the current module, e.g. `sub_module_1::MyStruct`
|
- starting from the current module, e.g. `sub_module_1::MyStruct`
|
||||||
|
|
||||||
|
Both `crate` and `super` are **keywords**.\
|
||||||
|
`crate` refers to the root of the current crate, while `super` refers to the parent of the current module.
|
||||||
|
|
||||||
Having to write the full path every time you want to refer to a type can be cumbersome.
|
Having to write the full path every time you want to refer to a type can be cumbersome.
|
||||||
To make your life easier, you can introduce a `use` statement to bring the entity into scope.
|
To make your life easier, you can introduce a `use` statement to bring the entity into scope.
|
||||||
|
|
||||||
|
|||||||
@@ -137,6 +137,6 @@ or [a custom allocator](https://docs.rs/dhat/latest/dhat/)) to inspect the heap
|
|||||||
Heap memory will be reserved when you push data into it for the first time.
|
Heap memory will be reserved when you push data into it for the first time.
|
||||||
|
|
||||||
[^equivalence]: The size of a pointer depends on the operating system too.
|
[^equivalence]: The size of a pointer depends on the operating system too.
|
||||||
In certain environments, a pointer is **larger** than a memory address (e.g. [CHERI](https://blog.acolyer.org/2019/05/28/cheri-abi/)).
|
In certain environments, a pointer is **larger** than a memory address (e.g. [CHERI](https://web.archive.org/web/20240517051950/https://blog.acolyer.org/2019/05/28/cheri-abi/)).
|
||||||
Rust makes the simplifying assumption that pointers are the same size as memory addresses,
|
Rust makes the simplifying assumption that pointers are the same size as memory addresses,
|
||||||
which is true for most modern systems you're likely to encounter.
|
which is true for most modern systems you're likely to encounter.
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ that to `consumer` instead.\
|
|||||||
## In memory
|
## In memory
|
||||||
|
|
||||||
Let's look at what happened in memory in the example above.
|
Let's look at what happened in memory in the example above.
|
||||||
When `let mut s: String::from("hello");` is executed, the memory looks like this:
|
When `let mut s = String::from("hello");` is executed, the memory looks like this:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
s
|
s
|
||||||
|
|||||||
@@ -68,3 +68,11 @@ match status {
|
|||||||
```
|
```
|
||||||
|
|
||||||
The `_` pattern matches anything that wasn't matched by the previous patterns.
|
The `_` pattern matches anything that wasn't matched by the previous patterns.
|
||||||
|
|
||||||
|
<div class="warning">
|
||||||
|
By using this catch-all pattern, you _won't_ get the benefits of compiler-driven refactoring.
|
||||||
|
If you add a new enum variant, the compiler _won't_ tell you that you're not handling it.
|
||||||
|
|
||||||
|
If you're keen on correctness, avoid using catch-alls. Leverage the compiler to re-examine all matching sites and determine how new enum variants should be handled.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ match status {
|
|||||||
println!("Assigned to: {}", assigned_to);
|
println!("Assigned to: {}", assigned_to);
|
||||||
},
|
},
|
||||||
Status::ToDo | Status::Done => {
|
Status::ToDo | Status::Done => {
|
||||||
println!("Done");
|
println!("ToDo or Done");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -82,7 +82,7 @@ match status {
|
|||||||
println!("Assigned to: {}", person);
|
println!("Assigned to: {}", person);
|
||||||
},
|
},
|
||||||
Status::ToDo | Status::Done => {
|
Status::ToDo | Status::Done => {
|
||||||
println!("Done");
|
println!("ToDo or Done");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -21,6 +21,15 @@ let numbers: [u32; 3] = [1, 2, 3];
|
|||||||
This creates an array of 3 integers, initialized with the values `1`, `2`, and `3`.\
|
This creates an array of 3 integers, initialized with the values `1`, `2`, and `3`.\
|
||||||
The type of the array is `[u32; 3]`, which reads as "an array of `u32`s with a length of 3".
|
The type of the array is `[u32; 3]`, which reads as "an array of `u32`s with a length of 3".
|
||||||
|
|
||||||
|
If all array elements are the same, you can use a shorter syntax to initialize it:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// [ <value> ; <number of elements> ]
|
||||||
|
let numbers: [u32; 3] = [1; 3];
|
||||||
|
```
|
||||||
|
|
||||||
|
`[1; 3]` creates an array of three elements, all equal to `1`.
|
||||||
|
|
||||||
### Accessing elements
|
### Accessing elements
|
||||||
|
|
||||||
You can access elements of an array using square brackets:
|
You can access elements of an array using square brackets:
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ When the process exits, the operating system will reclaim that memory.
|
|||||||
|
|
||||||
Keeping this in mind, it can be OK to leak memory when:
|
Keeping this in mind, it can be OK to leak memory when:
|
||||||
|
|
||||||
- The amount of memory you need to leak is not unbounded/known upfront, or
|
- The amount of memory you need to leak is bounded/known upfront, or
|
||||||
- Your process is short-lived and you're confident you won't exhaust
|
- Your process is short-lived and you're confident you won't exhaust
|
||||||
all the available memory before it exits
|
all the available memory before it exits
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ Let's unpack what's happening.
|
|||||||
## `scope`
|
## `scope`
|
||||||
|
|
||||||
The `std::thread::scope` function creates a new **scope**.\
|
The `std::thread::scope` function creates a new **scope**.\
|
||||||
`std::thread::scope` takes as input a closure, with a single argument: a `Scope` instance.
|
`std::thread::scope` takes a closure as input, with a single argument: a `Scope` instance.
|
||||||
|
|
||||||
## Scoped spawns
|
## Scoped spawns
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ drop(guard)
|
|||||||
## Locking granularity
|
## Locking granularity
|
||||||
|
|
||||||
What should our `Mutex` wrap?\
|
What should our `Mutex` wrap?\
|
||||||
The simplest option would be the wrap the entire `TicketStore` in a single `Mutex`.\
|
The simplest option would be to wrap the entire `TicketStore` in a single `Mutex`.\
|
||||||
This would work, but it would severely limit the system's performance: you wouldn't be able to read tickets in parallel,
|
This would work, but it would severely limit the system's performance: you wouldn't be able to read tickets in parallel,
|
||||||
because every read would have to wait for the lock to be released.\
|
because every read would have to wait for the lock to be released.\
|
||||||
This is known as **coarse-grained locking**.
|
This is known as **coarse-grained locking**.
|
||||||
|
|||||||
@@ -5,20 +5,20 @@ Before we wrap up this chapter, let's talk about another key trait in Rust's sta
|
|||||||
`Sync` is an auto trait, just like `Send`.\
|
`Sync` is an auto trait, just like `Send`.\
|
||||||
It is automatically implemented by all types that can be safely **shared** between threads.
|
It is automatically implemented by all types that can be safely **shared** between threads.
|
||||||
|
|
||||||
In order words: `T: Sync` means that `&T` is `Send`.
|
In other words: `T` is Sync if `&T` is `Send`.
|
||||||
|
|
||||||
## `Sync` doesn't imply `Send`
|
## `T: Sync` doesn't imply `T: Send`
|
||||||
|
|
||||||
It's important to note that `Sync` doesn't imply `Send`.\
|
It's important to note that `T` can be `Sync` without being `Send`.\
|
||||||
For example: `MutexGuard` is not `Send`, but it is `Sync`.
|
For example: `MutexGuard` is not `Send`, but it is `Sync`.
|
||||||
|
|
||||||
It isn't `Send` because the lock must be released on the same thread that acquired it, therefore we don't
|
It isn't `Send` because the lock must be released on the same thread that acquired it, therefore we don't
|
||||||
want `MutexGuard` to be dropped on a different thread.\
|
want `MutexGuard` to be dropped on a different thread.\
|
||||||
But it is `Sync`, because giving a `&MutexGuard` to another thread has no impact on where the lock is released.
|
But it is `Sync`, because giving a `&MutexGuard` to another thread has no impact on where the lock is released.
|
||||||
|
|
||||||
## `Send` doesn't imply `Sync`
|
## `T: Send` doesn't imply `T: Sync`
|
||||||
|
|
||||||
The opposite is also true: `Send` doesn't imply `Sync`.\
|
The opposite is also true: `T` can be `Send` without being `Sync`.\
|
||||||
For example: `RefCell<T>` is `Send` (if `T` is `Send`), but it is not `Sync`.
|
For example: `RefCell<T>` is `Send` (if `T` is `Send`), but it is not `Sync`.
|
||||||
|
|
||||||
`RefCell<T>` performs runtime borrow checking, but the counters it uses to track borrows are not thread-safe.
|
`RefCell<T>` performs runtime borrow checking, but the counters it uses to track borrows are not thread-safe.
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ at any given time.
|
|||||||
|
|
||||||
### Multithreaded runtime
|
### Multithreaded runtime
|
||||||
|
|
||||||
When using the multithreaded runtime, instead, there can up to `N` tasks running
|
When using the multithreaded runtime, instead, there can be up to `N` tasks running
|
||||||
_in parallel_ at any given time, where `N` is the number of threads used by the
|
_in parallel_ at any given time, where `N` is the number of threads used by the
|
||||||
runtime. By default, `N` matches the number of available CPU cores.
|
runtime. By default, `N` matches the number of available CPU cores.
|
||||||
|
|
||||||
|
|||||||
@@ -2,3 +2,9 @@
|
|||||||
name = "welcome_00"
|
name = "welcome_00"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[lints.rust]
|
||||||
|
# We silence dead code warnings for the time being in order to reduce
|
||||||
|
# compiler noise.
|
||||||
|
# We'll re-enable them again once we explain how visibility works in Rust.
|
||||||
|
dead_code = "allow"
|
||||||
|
|||||||
@@ -2,3 +2,9 @@
|
|||||||
name = "syntax"
|
name = "syntax"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[lints.rust]
|
||||||
|
# We silence dead code warnings for the time being in order to reduce
|
||||||
|
# compiler noise.
|
||||||
|
# We'll re-enable them again once we explain how visibility works in Rust.
|
||||||
|
dead_code = "allow"
|
||||||
|
|||||||
@@ -2,3 +2,9 @@
|
|||||||
name = "intro_01"
|
name = "intro_01"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[lints.rust]
|
||||||
|
# We silence dead code warnings for the time being in order to reduce
|
||||||
|
# compiler noise.
|
||||||
|
# We'll re-enable them again once we explain how visibility works in Rust.
|
||||||
|
dead_code = "allow"
|
||||||
|
|||||||
@@ -2,3 +2,9 @@
|
|||||||
name = "integers"
|
name = "integers"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[lints.rust]
|
||||||
|
# We silence dead code warnings for the time being in order to reduce
|
||||||
|
# compiler noise.
|
||||||
|
# We'll re-enable them again once we explain how visibility works in Rust.
|
||||||
|
dead_code = "allow"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
fn compute(a: u32, b: u32) -> u32 {
|
fn compute(a: u32, b: u32) -> u32 {
|
||||||
// TODO: change the line below to fix the compiler error and make the tests pass.
|
// TODO: change the line below to fix the compiler error and make the tests pass.
|
||||||
a + b * 4u8
|
let multiplier: u8 = 4;
|
||||||
|
a + b * multiplier
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -2,3 +2,9 @@
|
|||||||
name = "variables"
|
name = "variables"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[lints.rust]
|
||||||
|
# We silence dead code warnings for the time being in order to reduce
|
||||||
|
# compiler noise.
|
||||||
|
# We'll re-enable them again once we explain how visibility works in Rust.
|
||||||
|
dead_code = "allow"
|
||||||
|
|||||||
@@ -2,3 +2,9 @@
|
|||||||
name = "if_else"
|
name = "if_else"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[lints.rust]
|
||||||
|
# We silence dead code warnings for the time being in order to reduce
|
||||||
|
# compiler noise.
|
||||||
|
# We'll re-enable them again once we explain how visibility works in Rust.
|
||||||
|
dead_code = "allow"
|
||||||
|
|||||||
@@ -1,24 +1,36 @@
|
|||||||
/// Return `true` if `n` is even, `false` otherwise.
|
/// Return `12` if `n` is even,
|
||||||
fn is_even(n: u32) -> bool {
|
/// `13` if `n` is divisible by `3`,
|
||||||
|
/// `17` otherwise.
|
||||||
|
fn magic_number(n: u32) -> u32 {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::is_even;
|
use crate::magic_number;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn one() {
|
fn one() {
|
||||||
assert!(!is_even(1));
|
assert_eq!(magic_number(1), 17);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn two() {
|
fn two() {
|
||||||
assert!(is_even(2));
|
assert_eq!(magic_number(2), 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn six() {
|
||||||
|
assert_eq!(magic_number(6), 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn nine() {
|
||||||
|
assert_eq!(magic_number(9), 13);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn high() {
|
fn high() {
|
||||||
assert!(!is_even(231));
|
assert_eq!(magic_number(233), 17);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,3 +2,9 @@
|
|||||||
name = "panics"
|
name = "panics"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[lints.rust]
|
||||||
|
# We silence dead code warnings for the time being in order to reduce
|
||||||
|
# compiler noise.
|
||||||
|
# We'll re-enable them again once we explain how visibility works in Rust.
|
||||||
|
dead_code = "allow"
|
||||||
|
|||||||
@@ -2,3 +2,9 @@
|
|||||||
name = "factorial"
|
name = "factorial"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[lints.rust]
|
||||||
|
# We silence dead code warnings for the time being in order to reduce
|
||||||
|
# compiler noise.
|
||||||
|
# We'll re-enable them again once we explain how visibility works in Rust.
|
||||||
|
dead_code = "allow"
|
||||||
|
|||||||
@@ -2,3 +2,9 @@
|
|||||||
name = "while_"
|
name = "while_"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[lints.rust]
|
||||||
|
# We silence dead code warnings for the time being in order to reduce
|
||||||
|
# compiler noise.
|
||||||
|
# We'll re-enable them again once we explain how visibility works in Rust.
|
||||||
|
dead_code = "allow"
|
||||||
|
|||||||
@@ -2,3 +2,9 @@
|
|||||||
name = "for_"
|
name = "for_"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[lints.rust]
|
||||||
|
# We silence dead code warnings for the time being in order to reduce
|
||||||
|
# compiler noise.
|
||||||
|
# We'll re-enable them again once we explain how visibility works in Rust.
|
||||||
|
dead_code = "allow"
|
||||||
|
|||||||
@@ -2,3 +2,9 @@
|
|||||||
name = "overflow"
|
name = "overflow"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[lints.rust]
|
||||||
|
# We silence dead code warnings for the time being in order to reduce
|
||||||
|
# compiler noise.
|
||||||
|
# We'll re-enable them again once we explain how visibility works in Rust.
|
||||||
|
dead_code = "allow"
|
||||||
|
|||||||
@@ -2,3 +2,9 @@
|
|||||||
name = "saturating"
|
name = "saturating"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[lints.rust]
|
||||||
|
# We silence dead code warnings for the time being in order to reduce
|
||||||
|
# compiler noise.
|
||||||
|
# We'll re-enable them again once we explain how visibility works in Rust.
|
||||||
|
dead_code = "allow"
|
||||||
|
|||||||
@@ -2,3 +2,9 @@
|
|||||||
name = "as_cast"
|
name = "as_cast"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[lints.rust]
|
||||||
|
# We silence dead code warnings for the time being in order to reduce
|
||||||
|
# compiler noise.
|
||||||
|
# We'll re-enable them again once we explain how visibility works in Rust.
|
||||||
|
dead_code = "allow"
|
||||||
|
|||||||
@@ -2,3 +2,9 @@
|
|||||||
name = "intro_02"
|
name = "intro_02"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[lints.rust]
|
||||||
|
# We silence dead code warnings for the time being in order to reduce
|
||||||
|
# compiler noise.
|
||||||
|
# We'll re-enable them again once we explain how visibility works in Rust.
|
||||||
|
dead_code = "allow"
|
||||||
|
|||||||
@@ -2,3 +2,9 @@
|
|||||||
name = "struct_"
|
name = "struct_"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[lints.rust]
|
||||||
|
# We silence dead code warnings for the time being in order to reduce
|
||||||
|
# compiler noise.
|
||||||
|
# We'll re-enable them again once we explain how visibility works in Rust.
|
||||||
|
dead_code = "allow"
|
||||||
|
|||||||
@@ -5,3 +5,9 @@ edition = "2021"
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
common = { path = "../../../helpers/common" }
|
common = { path = "../../../helpers/common" }
|
||||||
|
|
||||||
|
[lints.rust]
|
||||||
|
# We silence dead code warnings for the time being in order to reduce
|
||||||
|
# compiler noise.
|
||||||
|
# We'll re-enable them again once we explain how visibility works in Rust.
|
||||||
|
dead_code = "allow"
|
||||||
|
|||||||
@@ -2,3 +2,9 @@
|
|||||||
name = "modules"
|
name = "modules"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[lints.rust]
|
||||||
|
# We silence dead code warnings for the time being in order to reduce
|
||||||
|
# compiler noise.
|
||||||
|
# We'll re-enable them again once we explain how visibility works in Rust.
|
||||||
|
dead_code = "allow"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// TODO: based on what we just learned about ownership, it sounds like immutable references
|
// TODO: based on what we just learned about ownership, it sounds like immutable references
|
||||||
// are a good fit for our accessor methods.
|
// are a good fit for our accessor methods.
|
||||||
// Change the existing implementation of `Ticket`'s accessor methods take a reference
|
// Change the existing implementation of `Ticket`'s accessor methods to take a reference
|
||||||
// to `self` as an argument, rather than taking ownership of it.
|
// to `self` as an argument, rather than taking ownership of it.
|
||||||
|
|
||||||
pub struct Ticket {
|
pub struct Ticket {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
thiserror = "1.0.59"
|
thiserror = "1.0.69"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
common = { path = "../../../helpers/common" }
|
common = { path = "../../../helpers/common" }
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ use ticket_fields::{TicketDescription, TicketTitle};
|
|||||||
// it contains using a `for` loop.
|
// it contains using a `for` loop.
|
||||||
//
|
//
|
||||||
// Hint: you shouldn't have to implement the `Iterator` trait in this case.
|
// Hint: you shouldn't have to implement the `Iterator` trait in this case.
|
||||||
|
// You want to *delegate* the iteration to the `Vec<Ticket>` field in `TicketStore`.
|
||||||
|
// Look at the standard library documentation for `Vec` to find the right type
|
||||||
|
// to return from `into_iter`.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct TicketStore {
|
pub struct TicketStore {
|
||||||
tickets: Vec<Ticket>,
|
tickets: Vec<Ticket>,
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
use ticket_fields::{TicketDescription, TicketTitle};
|
use ticket_fields::{TicketDescription, TicketTitle};
|
||||||
|
|
||||||
// TODO: Provide an `iter` method that returns an iterator over `&Ticket` items.
|
// TODO: Provide an `iter` method that returns an iterator over `&Ticket` items.
|
||||||
|
//
|
||||||
|
// Hint: just like in the previous exercise, you want to delegate the iteration to
|
||||||
|
// the `Vec<Ticket>` field in `TicketStore`. Look at the standard library documentation
|
||||||
|
// for `Vec` to find the right type to return from `iter`.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct TicketStore {
|
pub struct TicketStore {
|
||||||
tickets: Vec<Ticket>,
|
tickets: Vec<Ticket>,
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
thiserror = "1.0.59"
|
thiserror = "1.0.69"
|
||||||
ticket_fields = { path = "../../../helpers/ticket_fields" }
|
ticket_fields = { path = "../../../helpers/ticket_fields" }
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
thiserror = "1.0.60"
|
thiserror = "1.0.69"
|
||||||
ticket_fields = { path = "../../../helpers/ticket_fields" }
|
ticket_fields = { path = "../../../helpers/ticket_fields" }
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
thiserror = "1.0.60"
|
thiserror = "1.0.69"
|
||||||
ticket_fields = { path = "../../../helpers/ticket_fields" }
|
ticket_fields = { path = "../../../helpers/ticket_fields" }
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.83"
|
anyhow = "1.0.100"
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.83"
|
anyhow = "1.0.100"
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.83"
|
anyhow = "1.0.100"
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.83"
|
anyhow = "1.0.100"
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.86"
|
anyhow = "1.0.100"
|
||||||
clap = "4.5.4"
|
clap = "4.5.50"
|
||||||
mdbook = "0.4.40"
|
mdbook = "0.4.52"
|
||||||
semver = "1.0.23"
|
semver = "1.0.27"
|
||||||
serde_json = "1.0.117"
|
serde_json = "1.0.145"
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.86"
|
anyhow = "1.0.100"
|
||||||
bimap = { version = "0.6.3", features = ["serde"] }
|
bimap = { version = "0.6.3", features = ["serde"] }
|
||||||
clap = { version = "4.5.4", features = ["derive"] }
|
clap = { version = "4.5.50", features = ["derive"] }
|
||||||
itertools = "0.13.0"
|
itertools = "0.13.0"
|
||||||
mdbook = "0.4.40"
|
mdbook = "0.4.52"
|
||||||
pulldown-cmark = "0.11.0"
|
pulldown-cmark = "0.11.3"
|
||||||
pulldown-cmark-to-cmark = "15"
|
pulldown-cmark-to-cmark = "15"
|
||||||
semver = "1.0.23"
|
semver = "1.0.27"
|
||||||
serde_json = "1.0.117"
|
serde_json = "1.0.145"
|
||||||
|
|||||||
@@ -5,4 +5,4 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
common = { path = "../common" }
|
common = { path = "../common" }
|
||||||
thiserror = "1.0.59"
|
thiserror = "1.0.69"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/f2u https://blog.acolyer.org/2019/05/28/cheri-abi/
|
/f6c https://code.visualstudio.com
|
||||||
/f4q https://crates.io
|
/f4q https://crates.io
|
||||||
/f2n https://crates.io/crates/cargo-modules
|
/f2n https://crates.io/crates/cargo-modules
|
||||||
/ffr https://doc.rust-lang.org/book/ch03-02-data-types.html#integer-types
|
/ffr https://doc.rust-lang.org/book/ch03-02-data-types.html#integer-types
|
||||||
@@ -162,7 +162,9 @@
|
|||||||
/f4r https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/
|
/f4r https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/
|
||||||
/ff2 https://mainmatter.com/contact/
|
/ff2 https://mainmatter.com/contact/
|
||||||
/fff https://mainmatter.com/rust-consulting/
|
/fff https://mainmatter.com/rust-consulting/
|
||||||
|
/fv2 https://mainmatter.github.io/rust-workshop-runner/
|
||||||
/fxg https://marabos.nl/atomics/
|
/fxg https://marabos.nl/atomics/
|
||||||
|
/f6a https://marketplace.visualstudio.com/items?itemName=matklad.rust-analyzer
|
||||||
/f6p https://nostarch.com/rust-rustaceans
|
/f6p https://nostarch.com/rust-rustaceans
|
||||||
/f2k https://owasp.org/www-community/vulnerabilities/Doubly_freeing_memory
|
/f2k https://owasp.org/www-community/vulnerabilities/Doubly_freeing_memory
|
||||||
/f2s https://owasp.org/www-community/vulnerabilities/Using_freed_memory
|
/f2s https://owasp.org/www-community/vulnerabilities/Using_freed_memory
|
||||||
@@ -176,13 +178,17 @@
|
|||||||
/fze https://rust-lang.github.io/api-guidelines/naming.html#casing-conforms-to-rfc-430-c-case
|
/fze https://rust-lang.github.io/api-guidelines/naming.html#casing-conforms-to-rfc-430-c-case
|
||||||
/f6w https://rust-lang.github.io/wg-async/vision/submitted_stories/status_quo/barbara_battles_buffered_streams.html
|
/f6w https://rust-lang.github.io/wg-async/vision/submitted_stories/status_quo/barbara_battles_buffered_streams.html
|
||||||
/f6v https://ryhl.io/blog/async-what-is-blocking/
|
/f6v https://ryhl.io/blog/async-what-is-blocking/
|
||||||
|
/fvf https://ti.to/mainmatter/rust-from-scratch-jan-2025
|
||||||
/f6n https://tokio.rs/tokio/tutorial/select
|
/f6n https://tokio.rs/tokio/tutorial/select
|
||||||
/f2t https://valgrind.org/docs/manual/dh-manual.html
|
/f2t https://valgrind.org/docs/manual/dh-manual.html
|
||||||
/fz5 https://veykril.github.io/tlborm/
|
/fz5 https://veykril.github.io/tlborm/
|
||||||
|
/f2u https://web.archive.org/web/20240517051950/https://blog.acolyer.org/2019/05/28/cheri-abi/
|
||||||
/f67 https://without.boats/blog/the-scoped-task-trilemma/
|
/f67 https://without.boats/blog/the-scoped-task-trilemma/
|
||||||
/f6g https://www.amazon.com/dp/B0DJ14KQQG/
|
/f6g https://www.amazon.com/dp/B0DJ14KQQG/
|
||||||
|
/f6d https://www.jetbrains.com/rust/
|
||||||
/ffv https://www.lpalmieri.com/
|
/ffv https://www.lpalmieri.com/
|
||||||
/f4t https://www.lpalmieri.com/posts/2020-12-11-zero-to-production-6-domain-modelling/
|
/f4t https://www.lpalmieri.com/posts/2020-12-11-zero-to-production-6-domain-modelling/
|
||||||
/f6y https://www.oreilly.com/library/view/programming-rust-2nd/9781492052586/
|
/f6y https://www.oreilly.com/library/view/programming-rust-2nd/9781492052586/
|
||||||
|
/f6j https://www.rust-lang.org/tools/install
|
||||||
/f6l https://www.youtube.com/playlist?list=PLqbS7AVVErFirH9armw8yXlE6dacF-A6z
|
/f6l https://www.youtube.com/playlist?list=PLqbS7AVVErFirH9armw8yXlE6dacF-A6z
|
||||||
/ff8 https://zero2prod.com
|
/ff8 https://zero2prod.com
|
||||||
|
|||||||
Reference in New Issue
Block a user