Compare commits

...

85 Commits

Author SHA1 Message Date
Jonas Kruckenberg
8791feb495 Merge pull request #308 from mainmatter/push-uxpvpkpzunoq
update dependencies
2025-10-24 15:05:41 +02:00
Jonas Kruckenberg
a2fe212f44 update dependencies 2025-10-24 14:42:11 +02:00
Meatball Sub
20a2b45e49 Fix typo in TeX Live setup action and format command arguments (#302) 2025-09-30 17:02:41 +02:00
Marcin
c3cb1b38f6 Fix typo in 02_match (#296) 2025-09-03 08:28:37 -07:00
xiorcale
af4fe9cedb fix typo in 7.14 sync (#278) 2025-06-09 07:04:07 +02:00
Geert-Johan Riemer
21f3427c92 Update 03_variants_with_data.md (#264) 2025-03-03 16:32:13 +01:00
Karolis Strazdas
b839c770b5 Fix typos in 08_overflow.md. (#261)
* Fix a typo in "Profiles" section - change "form" to "from". 
* Remove "etc.", as it should not be used together with "e.g.".
2025-02-23 09:57:34 +01:00
dawe
fd23b201fe add missing word in 03_runtime.md (#259) 2025-02-15 10:09:16 +01:00
David Ekete
13850a6b01 Update 04_scoped_threads.md (#258)
Improved phrasing for  the `scope` h2
2025-02-08 10:21:56 +01:00
LukeMathWalker
a7865baf3c Update redirects 2025-01-30 15:14:11 +01:00
LukeMathWalker
0e1c66814d Update shortened links 2025-01-30 15:07:03 +01:00
Luca Palmieri
2f059fc5ba Link to wr website 2025-01-30 14:29:47 +01:00
James Judd
63402ef5c2 Fix dead link to blog.acolyer.org (#253)
Co-authored-by: James Judd <james@lucidchart.com>
2025-01-30 14:13:05 +01:00
Luca Palmieri
892c37ead9 Typo. 2025-01-30 14:03:45 +01:00
Gabriel Crispino
c745cf8ddd fix grammar in exercise 06 from section 03 (#248)
Add missing "to" preposition in first TODO comment
2025-01-19 11:42:03 +01:00
Luca Palmieri
3f60de3712 Avoid using a suffix (#239) 2024-12-18 17:38:05 +01:00
Luca Palmieri
36f6375c20 Change if-else exercise to require an if-else (#238) 2024-12-18 17:33:03 +01:00
Luca Palmieri
fb19005d5f Clarify Send-Sync relationship (#237) 2024-12-18 17:22:16 +01:00
Luca Palmieri
cc0092b2c6 Clarify that both crate and super are keywords (#236) 2024-12-18 17:13:27 +01:00
Luca Palmieri
d5e1c00108 Give a more structure hint for iteration exercises (#235) 2024-12-18 17:03:24 +01:00
Luca Palmieri
60947aaacd Showcase else-if (#234) 2024-12-18 16:53:14 +01:00
LukeMathWalker
fe40e6e2d0 Don't mark Rust code snippets as runnable 2024-12-18 16:48:57 +01:00
LukeMathWalker
7fb0910b39 Format all manifests 2024-12-18 16:39:16 +01:00
Luca Palmieri
468b74ba4d Ignore dead code warnings until visibility has been explained (#232) 2024-12-18 16:38:07 +01:00
LukeMathWalker
b0e1e5a1ec Link to the next tutored session in the methodology section 2024-12-18 11:38:21 +01:00
LukeMathWalker
93536fbcfd Formatting 2024-12-18 11:25:30 +01:00
LukeMathWalker
1993507236 Update redirects 2024-12-18 11:24:29 +01:00
LukeMathWalker
a1a2dc1588 Update aliases 2024-12-18 11:23:03 +01:00
Maor Levy
51cad6bdfe doc: update book 06_01_arrays (#195) 2024-12-18 11:12:50 +01:00
Daniel Wagner-Hall
ab1eb5d80c Warn about the risks of using catch-all patterns (#200) 2024-12-18 11:05:01 +01:00
Daniel Wagner-Hall
fd6a56fd84 Add install steps to the welcome page (#196) 2024-12-18 11:02:25 +01:00
Will Bush
0419e2e8b2 Fix typo in 03_leak.md (#220)
Corrected a confusing sentence with double negative.
2024-11-19 09:19:50 +01:00
dawe
4b02e92691 fix a small typo in 11_locks.md (#219) 2024-11-18 10:58:59 +01:00
dawe
eb2d858807 fix a superfluous word in a comment (#217) 2024-11-15 17:53:27 +01:00
Marco Otte-Witte
4194ee9998 Merge pull request #208 from mainmatter/gravity
run Gravity on online PDF
2024-11-12 12:50:23 +01:00
Marco Otte-Witte
9f5e4a0d76 debug 2024-11-12 12:43:03 +01:00
Marco Otte-Witte
da610ee79b run Gravity on online PDF 2024-11-12 12:29:08 +01:00
Marco Otte-Witte
f1a0eab4a6 Merge pull request #213 from mainmatter/fix-verbosity
switch off Pandoc verbosity
2024-11-12 11:58:47 +01:00
Marco Otte-Witte
3addd64dc2 switch off Pandoc verbosity 2024-11-12 11:51:00 +01:00
Marco Otte-Witte
a53e4f86a1 Merge pull request #212 from mainmatter/debug-build
Fix build
2024-11-12 11:46:58 +01:00
Marco Otte-Witte
5edddf102e fix reference to fallback font 2024-11-12 11:41:00 +01:00
Marco Otte-Witte
dab563a329 debug pandoc build 2024-11-12 11:34:52 +01:00
Marco Otte-Witte
c75ff98c6a format 2024-11-12 11:17:13 +01:00
Robertino
b60e021ab1 Update 11_clone.md (#205)
typo in code
2024-11-01 08:22:23 +01:00
Henk Oordt
9e63a5cdf6 Merge pull request #190 from Manubi/patch-1 2024-10-29 15:48:35 +01:00
Manuel Bichler
f4a7472f30 Update 08_overflow.md
Added some context.
2024-10-29 15:40:56 +01:00
Henk Oordt
04b89ff26e Merge pull request #188 from cenviity/push-usrtukunqysw
exercises 02_basic_calculator/04_panics: fix comma splice in panic message
2024-10-29 14:39:03 +01:00
Henk Oordt
26e78072cd Merge pull request #187 from half2me/patch-1
Fix docstring: "when converted to `u8`"
2024-10-29 14:30:20 +01:00
Henk Oordt
c540242c15 Merge pull request #172 from marcoow/fix-fork-build
Fix builds for PRs originating from forks
2024-10-29 14:16:29 +01:00
Henk Oordt
12fb62d8be Merge pull request #192 from mainmatter/ci-schedule
chore(ci): re-create book artifacts at the beginning of each month
2024-10-28 13:33:42 +01:00
Bartlomiej Dudzik
0bf398a351 chore(ci): re-create book artifacts at the beginning of each month 2024-10-28 13:19:50 +01:00
Manuel Bichler
f14a047e8b Update 08_overflow.md
if you read threw the profile docs it provides 4 profiles. https://doc.rust-lang.org/cargo/reference/profiles.html
2024-10-27 19:32:58 +01:00
Vincent Ging Ho Yim
5e23bee61e exercises 02_basic_calculator/04_panics: fix comma splice in panic message 2024-10-24 15:18:53 +11:00
Benjamin Tamasi
8488317564 Change docstring: "when converted to u8"
Fixed docstring
2024-10-22 13:39:17 +02:00
Henk Oordt
bd17a59e8e Merge pull request #177 from LucaBoschetto/patch-1
Update reference from Rustonomicon to Rust Reference
2024-10-21 13:27:25 +02:00
Henk Oordt
8c3e40033b Merge pull request #174 from drguildo/channels-typo-fix
Fix typo
2024-10-21 13:24:04 +02:00
iacri
a392371ef0 05_ticket_v2 outro: correct comment on title (#179)
Characters was meant to be bytes, this was missed in a former refactoring
2024-10-19 09:36:26 +02:00
Luca Boschetto
f4cb4b55d0 Update reference from Rustonomicon to Rust Reference
The exercise refers to the "Data layout" section of the Rustonomicon, but now that section claims itself deprecated and redirects to the "Type layout" section of The Rust Reference.
2024-10-16 18:15:59 +02:00
Simon Morgan
45c32d8e41 Fix typo 2024-10-14 22:41:16 +01:00
Marco Otte-Witte
4ca49fa5fd use OpenSans as fallback font on PRs from forks 2024-10-14 12:56:17 +02:00
Adalfarus
c437f75fcf Update lib.rs, added info that needed panic messages can be found in the tests. (#157) 2024-10-09 09:44:47 +02:00
Marco Otte-Witte
f839fc00f9 Merge pull request #161 from mainmatter/cover-for-pdf
add cover and back to downloadable pdf
2024-10-08 11:22:45 +02:00
Marco Otte-Witte
954dd0ff14 add real back and front cover 2024-10-08 11:11:20 +02:00
Marco Otte-Witte
33bcaf0a7a add cover and back to downloadable pdf 2024-10-02 16:00:32 +02:00
Marco Otte-Witte
0aecb5380e Merge pull request #159 from mainmatter/style-ebook
simplify ebook styling
2024-10-02 15:40:46 +02:00
Marco Otte-Witte
276bdbbcdc simplify ebook styling config 2024-10-02 15:30:40 +02:00
Remo Senekowitsch
a899ecec96 Fix typo (#160) 2024-10-02 15:20:17 +02:00
Luca Palmieri
a0537f8c51 chore: Shorten links 2024-09-27 14:47:00 +02:00
Luca Palmieri
73649001ba Add link to paperback. 2024-09-27 10:13:15 +02:00
David Parra
99ee4b27c5 Typo (#154)
Thanks for such a great book, found a small typo.
2024-09-22 08:12:14 +02:00
Marco Otte-Witte
af6c605fe6 Merge pull request #133 from mainmatter/style-book
Style book
2024-09-19 11:47:52 +02:00
Marco Otte-Witte
f613c9a58b Merge pull request #150 from mainmatter/LukeMathWalker-patch-1
Don't omit macros from PDF and ePUB versions
2024-09-19 11:40:52 +02:00
Luca Palmieri
e9c4f37130 Don't omit macros from PDF and ePUB versions 2024-09-19 10:33:03 +02:00
Abdelrahman Omar
e768d9dbd8 add test coverage for IndexMut<&TicketId> (#142) 2024-09-11 11:37:23 +02:00
Tobias Hermann
ea71ac2c0a Remove duplicated mention of slices in 00_intro.md (#144)
Slices are already mentioned in bullet point 4, so they can be removed from bullet point 2.
2024-09-11 11:36:58 +02:00
Marco Otte-Witte
0ca42ba058 move comment to meaningful place 2024-08-27 09:14:20 +02:00
Marco Otte-Witte
681903a853 make fontsize 1pt smaller 2024-08-27 09:13:38 +02:00
Marco Otte-Witte
6bdcf19f5f use less teal for sh theme 2024-08-22 15:43:19 +02:00
Marco Otte-Witte
297d78d750 actually use custom highlighting theme 2024-08-22 15:38:18 +02:00
Marco Otte-Witte
cab4de6433 remove background color on operators 2024-08-22 15:25:58 +02:00
Marco Otte-Witte
52c21a241d add lost settings for print version back in 2024-08-22 15:22:03 +02:00
Marco Otte-Witte
982a8f0789 copy config to paperback 2024-08-20 18:26:26 +02:00
Marco Otte-Witte
1b050774e7 custom syntax highlighting 2024-08-20 18:26:26 +02:00
Marco Otte-Witte
d269320825 set link and url styles 2024-08-20 18:26:26 +02:00
Marco Otte-Witte
8730a8458a use Core Sans font 2024-08-20 18:26:26 +02:00
65 changed files with 1701 additions and 902 deletions

View File

@@ -7,6 +7,10 @@ on:
pull_request:
branches:
- main
workflow_dispatch:
schedule:
# First day of a month
- cron: '0 0 1 * *'
jobs:
build:
@@ -15,23 +19,44 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get Core Sans
uses: actions/checkout@v4
if: "!github.event.pull_request.head.repo.fork"
with:
fetch-depth: 0
repository: mainmatter/core-sans-a-fonts
ssh-key: ${{ secrets.SSH_PRIVATE_KEY }}
path: core-sans-a-fonts
- name: Install Core Sans Font
if: "!github.event.pull_request.head.repo.fork"
run: |
sudo cp -r core-sans-a-fonts/* /usr/local/share/fonts/
sudo fc-cache -f -v
fc-list | grep "Core Sans"
- name: Use Fallback font for fork PRs
if: "github.event.pull_request.head.repo.fork"
run: |
sed -i 's/"BoldFont=CoreSansA65.ttf",//g' book/book.toml
sed -i 's/"ItalicFont=CoreSansA45It.ttf",//g' book/book.toml
sed -i 's/"BoldItalicFont=CoreSansA65It.ttf",//g' book/book.toml
sed -i 's/CoreSansA45.ttf/Open Sans:style=Regular/g' book/book.toml
- uses: actions-rust-lang/setup-rust-toolchain@v1
- name: Install exercise plugin
run: cargo install --path helpers/mdbook-exercise-linker
- name: Install link shortener plugin
run: cargo install --path helpers/mdbook-link-shortener
- name: Install mdbook-pandoc, calibre and related dependencies
- name: Install mdbook-pandoc, calibre, pdftk and related dependencies
run: |
cargo install mdbook-pandoc --locked --version 0.7.1
sudo apt-get update
sudo apt-get install -y fonts-noto calibre
sudo apt-get install -y fonts-noto fonts-open-sans calibre pdftk
sudo fc-cache -f -v
export PANDOC_VERSION=3.3
curl -LsSf https://github.com/jgm/pandoc/releases/download/${PANDOC_VERSION}/pandoc-${PANDOC_VERSION}-linux-amd64.tar.gz | tar zxf -
echo "$PWD/pandoc-${PANDOC_VERSION}/bin" >> $GITHUB_PATH
shell: bash
- name: Setup TeX Live
uses: teatimeguest/setup-texlive-action@v3
uses: TeX-Live/setup-texlive-action@v3
with:
packages:
scheme-basic
@@ -70,6 +95,10 @@ jobs:
run: |
cd book
mdbook build
- name: Add cover and back to downloadable PDF
run: |
pdftk book/assets/cover.pdf book/book/pandoc/pdf/100-exercises-to-learn-rust.pdf book/assets/back.pdf cat output book/book/pandoc/pdf/100-exercises-to-learn-rust-with-cover.pdf
mv book/book/pandoc/pdf/100-exercises-to-learn-rust-with-cover.pdf book/book/pandoc/pdf/100-exercises-to-learn-rust.pdf
- name: Convert HTML to ePUB
run: |
cd book/book/pandoc/html
@@ -82,9 +111,9 @@ jobs:
with:
fail: true
args: |
--exclude-loopback
--require-https
--no-progress
--exclude-loopback
--require-https
--no-progress
book/book/html/
# Upload the HTML book as an artifact
- uses: actions/upload-artifact@v4
@@ -117,6 +146,23 @@ jobs:
- run: |
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:
runs-on: ubuntu-latest
steps:

1927
Cargo.lock generated

File diff suppressed because it is too large Load Diff

BIN
book/assets/back.pdf Normal file

Binary file not shown.

BIN
book/assets/cover.pdf Normal file

Binary file not shown.

View File

@@ -18,36 +18,53 @@ after = ["exercise-linker"]
[output.html]
git-repository-url = "https://github.com/mainmatter/100-exercises-to-learn-rust"
[output.html.playground]
runnable = false
[output.pandoc]
optional = true
hosted-html = "https://rust-exercises.com/100-exercises/"
[output.pandoc.code]
show-hidden-lines = true
[output.pandoc.profile.pdf] # options to pass to Pandoc (see https://pandoc.org/MANUAL.html)
output-file = "100-exercises-to-learn-rust.pdf"
to = "latex"
highlight-style = "tango"
highlight-style = "./custom.theme"
# We use `lualatext` because, right now, it's the only engine
# that supports fallback fonts, which we need for emojis.
pdf-engine = "lualatex"
metadata-file = "metadata.yml"
[output.pandoc.profile.pdf.variables]
mainfont = "CoreSansA45.ttf"
mainfontoptions = [
"BoldFont=CoreSansA65.ttf",
"ItalicFont=CoreSansA45It.ttf",
"BoldItalicFont=CoreSansA65It.ttf",
]
sansfont = "CoreSansA45.ttf"
sansfontoptions = [
"BoldFont=CoreSansA65.ttf",
"ItalicFont=CoreSansA45It.ttf",
"BoldItalicFont=CoreSansA65It.ttf",
]
# You can get these fonts here: https://fonts.google.com/selection?query=noto+color+
mainfont = "Noto Serif"
sansfont = "Noto Sans"
monofont = "Noto Sans Mono"
mainfontfallback = ["Noto Color Emoji:mode=harf"]
sansfontfallback = ["Noto Color Emoji:mode=harf"]
mainfontfallback = ["Open Sans:style=Regular"]
sansfontfallback = ["Open Sans:style=Regular"]
monofontfallback = [
"Noto Color Emoji:mode=harf",
]
linkcolor = "blue"
urlcolor = "blue"
linkcolor = "Links"
urlcolor = "Links"
urlstyle = "rm"
documentclass = "book"
fontsize = "11pt"
fontsize = "10pt"
geometry = "papersize={8in,10in},top=2cm,bottom=2cm,left=2.4cm,right=2.4cm"
header-includes = [
"\\definecolor{Links}{HTML}{6200EE}",
# Reduce font size of code blocks
"\\DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\\\\{\\},fontsize=\\small}",
]
@@ -62,20 +79,33 @@ metadata-file = "metadata.yml"
pdf-engine = "lualatex"
[output.pandoc.profile.paperback.variables]
mainfont = "CoreSansA45.ttf"
mainfontoptions = [
"BoldFont=CoreSansA65.ttf",
"ItalicFont=CoreSansA45It.ttf",
"BoldItalicFont=CoreSansA65It.ttf",
]
sansfont = "CoreSansA45.ttf"
sansfontoptions = [
"BoldFont=CoreSansA65.ttf",
"ItalicFont=CoreSansA45It.ttf",
"BoldItalicFont=CoreSansA65It.ttf",
]
# You can get these fonts here: https://fonts.google.com/selection?query=noto+color+
mainfont = "Noto Serif"
sansfont = "Noto Sans"
monofont = "Noto Sans Mono"
mainfontfallback = ["Noto Color Emoji:mode=harf"]
sansfontfallback = ["Noto Color Emoji:mode=harf"]
mainfontfallback = ["Open Sans:style=Regular"]
sansfontfallback = ["Open Sans:style=Regular"]
monofontfallback = [
"Noto Color Emoji:mode=harf",
]
linkcolor = "Links"
urlcolor = "Links"
urlstyle = "rm"
documentclass = "book"
fontsize = "11pt"
fontsize = "10pt"
geometry = "papersize={8in,10in},top=2cm,bottom=2cm,left=2.8cm,right=2.5cm"
header-includes = [
"\\definecolor{Links}{HTML}{6200EE}",
# Reduce font size of code blocks
"\\DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\\\\{\\},fontsize=\\small}",
]
@@ -93,14 +123,10 @@ metadata-file = "metadata.yml"
[output.pandoc.profile.html.variables]
# You can get these fonts here: https://fonts.google.com/selection?query=noto+color+
mainfont = "Noto Serif"
sansfont = "Noto Sans"
monofont = "Noto Sans Mono"
mainfontfallback = ["Noto Color Emoji:mode=harf"]
sansfontfallback = ["Noto Color Emoji:mode=harf"]
mainfontfallback = ["Open Sans:style=Regular"]
sansfontfallback = ["Open Sans:style=Regular"]
monofontfallback = [
"Noto Color Emoji:mode=harf",
]
linkcolor = "blue"
urlcolor = "blue"
urlstyle = "rm"

211
book/custom.theme Normal file
View File

@@ -0,0 +1,211 @@
{
"text-color": "#c9d1d9",
"background-color": "#343942",
"line-number-color": null,
"line-number-background-color": null,
"text-styles": {
"Alert": {
"text-color": "#ff0000",
"background-color": null,
"bold": true,
"italic": false,
"underline": false
},
"Annotation": {
"text-color": "#8b949e",
"background-color": null,
"bold": true,
"italic": true,
"underline": false
},
"Attribute": {
"text-color": "#03DAC5",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"BaseN": {
"text-color": "#a5d6ff",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"BuiltIn": {
"text-color": "#03DAC5",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"Char": {
"text-color": "#a5d6ff",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"Comment": {
"text-color": "#8b949e",
"background-color": null,
"bold": false,
"italic": true,
"underline": false
},
"CommentVar": {
"text-color": "#8b949e",
"background-color": null,
"bold": true,
"italic": true,
"underline": false
},
"Constant": {
"text-color": "#79c0ff",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"ControlFlow": {
"text-color": "#03DAC5",
"background-color": null,
"bold": true,
"italic": false,
"underline": false
},
"DataType": {
"text-color": "#8b949e",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"DecVal": {
"text-color": "#79c0ff",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"Documentation": {
"text-color": "#8b949e",
"background-color": null,
"bold": false,
"italic": true,
"underline": false
},
"Error": {
"text-color": "#ff0000",
"background-color": null,
"bold": true,
"italic": false,
"underline": false
},
"Extension": {
"text-color": null,
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"Float": {
"text-color": "#79c0ff",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"Function": {
"text-color": "#d2a8ff",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"Import": {
"text-color": "#8b949e",
"background-color": null,
"bold": true,
"italic": false,
"underline": false
},
"Information": {
"text-color": "#8b949e",
"background-color": null,
"bold": true,
"italic": true,
"underline": false
},
"Keyword": {
"text-color": "#03DAC5",
"background-color": null,
"bold": true,
"italic": false,
"underline": false
},
"Operator": {
"text-color": "#03DAC5",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"Other": {
"text-color": "#007020",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"Preprocessor": {
"text-color": "#03DAC5",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"SpecialChar": {
"text-color": "#03DAC5",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"SpecialString": {
"text-color": "#03DAC5",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"String": {
"text-color": "#a5d6ff",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"Variable": {
"text-color": "#a8daff",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"VerbatimString": {
"text-color": "#a5d6ff",
"background-color": null,
"bold": false,
"italic": false,
"underline": false
},
"Warning": {
"text-color": "#60a0b0",
"background-color": null,
"bold": true,
"italic": true,
"underline": false
}
}
}

View File

@@ -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/crates/cargo-modules": "f2n",
"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://mainmatter.com/contact/": "ff2",
"https://mainmatter.com/rust-consulting/": "fff",
"https://mainmatter.github.io/rust-workshop-runner/": "fv2",
"https://marabos.nl/atomics/": "fxg",
"https://marketplace.visualstudio.com/items?itemName=matklad.rust-analyzer": "f6a",
"https://nostarch.com/rust-rustaceans": "f6p",
"https://owasp.org/www-community/vulnerabilities/Doubly_freeing_memory": "f2k",
"https://owasp.org/www-community/vulnerabilities/Using_freed_memory": "f2s",
@@ -177,13 +179,18 @@
"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://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://valgrind.org/docs/manual/dh-manual.html": "f2t",
"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://www.amazon.com/dp/B0DJ14KQQG/": "f6g",
"https://www.jetbrains.com/rust/": "f6d",
"https://www.lpalmieri.com/": "ffv",
"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.rust-lang.org/tools/install": "f6j",
"https://www.youtube.com/playlist?list=PLqbS7AVVErFirH9armw8yXlE6dacF-A6z": "f6l",
"https://zero2prod.com": "ff8"
}

View File

@@ -24,18 +24,18 @@ It has been designed to be interactive and hands-on.
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
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
bring this course to your company, please [get in touch](https://mainmatter.com/contact/).
You can sign up for the next tutored session on [our website](https://ti.to/mainmatter/rust-from-scratch-jan-2025).
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
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).
## Formats
You can go through the course material [in the browser](https://rust-exercises.com/100-exercises/).\
You can also [download it as a PDF file](https://rust-exercises.com/100-exercises-to-learn-rust.pdf), for offline reading.
You can go through the course material [in the browser](https://rust-exercises.com/100-exercises/) or [download it as a PDF file](https://rust-exercises.com/100-exercises-to-learn-rust.pdf), for offline reading.\
If you prefer to have the course material printed out, [buy a paperback copy on Amazon](https://www.amazon.com/dp/B0DJ14KQQG/).
## Structure
@@ -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
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.
It is the `wr` CLI (short for "workshop runner").
Install it with:
To work through this course, you'll need:
```bash
cargo install --locked workshop-runner
```
- [**Rust**](https://www.rust-lang.org/tools/install).
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:
```bash

View File

@@ -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
The condition in an `if` expression must be of type `bool`, a **boolean**.\

View File

@@ -69,16 +69,20 @@ You may be wondering—what is a profile setting? Let's get into that!
A [**profile**](https://doc.rust-lang.org/cargo/reference/profiles.html) is a set of configuration options that can be
used to customize the way Rust code is compiled.
Cargo provides two built-in profiles: `dev` and `release`.\
Cargo provides 4 built-in profiles: `dev`, `release`, `test`, and `bench`.\
The `dev` profile is used every time you run `cargo build`, `cargo run` or `cargo test`. It's aimed at local
development,
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
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 from the `dev` 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,\
`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.\
> 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.
You can also define custom profiles or customize the built-in ones.

View File

@@ -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 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.
To make your life easier, you can introduce a `use` statement to bring the entity into scope.

View File

@@ -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.
[^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,
which is true for most modern systems you're likely to encounter.

View File

@@ -56,7 +56,7 @@ that to `consumer` instead.\
## In memory
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
s

View File

@@ -68,3 +68,11 @@ match status {
```
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>

View File

@@ -64,7 +64,7 @@ match status {
println!("Assigned to: {}", assigned_to);
},
Status::ToDo | Status::Done => {
println!("Done");
println!("ToDo or Done");
}
}
```
@@ -82,7 +82,7 @@ match status {
println!("Assigned to: {}", person);
},
Status::ToDo | Status::Done => {
println!("Done");
println!("ToDo or Done");
}
}
```

View File

@@ -8,7 +8,7 @@ store and retrieve tickets.
The task will give us an opportunity to explore new Rust concepts, such as:
- Stack-allocated arrays
- `Vec`, a growable array type, and slices
- `Vec`, a growable array type
- `Iterator` and `IntoIterator`, for iterating over collections
- Slices (`&[T]`), to work with parts of a collection
- Lifetimes, to describe how long references are valid

View File

@@ -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`.\
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
You can access elements of an array using square brackets:

View File

@@ -1,7 +1,7 @@
# Combinators
Iterators can do so much more than `for` loops!\
If you look at the documentation for the `Iterator` trait, you'll find a **vast** collections of
If you look at the documentation for the `Iterator` trait, you'll find a **vast** collection of
methods that you can leverage to transform, filter, and combine iterators in various ways.
Let's mention the most common ones:

View File

@@ -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:
- 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
all the available memory before it exits

View File

@@ -27,7 +27,7 @@ Let's unpack what's happening.
## `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

View File

@@ -58,7 +58,7 @@ drop(guard)
## Locking granularity
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,
because every read would have to wait for the lock to be released.\
This is known as **coarse-grained locking**.

View File

@@ -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`.\
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`.
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.\
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`.
`RefCell<T>` performs runtime borrow checking, but the counters it uses to track borrows are not thread-safe.

View File

@@ -107,7 +107,7 @@ asynchronous programming in Rust.
The entrypoint of your executable, the `main` function, must be a synchronous function.
That's where you're supposed to set up and launch your chosen async runtime.
Most runtimes provides a macro to make this easier. For `tokio`, it's `tokio::main`:
Most runtimes provide a macro to make this easier. For `tokio`, it's `tokio::main`:
```rust
#[tokio::main]

View File

@@ -26,7 +26,7 @@ at any given time.
### 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
runtime. By default, `N` matches the number of available CPU cores.

View File

@@ -2,3 +2,9 @@
name = "welcome_00"
version = "0.1.0"
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"

View File

@@ -2,3 +2,9 @@
name = "syntax"
version = "0.1.0"
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"

View File

@@ -2,3 +2,9 @@
name = "intro_01"
version = "0.1.0"
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"

View File

@@ -2,3 +2,9 @@
name = "integers"
version = "0.1.0"
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"

View File

@@ -1,6 +1,7 @@
fn compute(a: u32, b: u32) -> u32 {
// TODO: change the line below to fix the compiler error and make the tests pass.
a + b * 4u8
let multiplier: u8 = 4;
a + b * multiplier
}
#[cfg(test)]

View File

@@ -2,3 +2,9 @@
name = "variables"
version = "0.1.0"
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"

View File

@@ -2,3 +2,9 @@
name = "if_else"
version = "0.1.0"
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"

View File

@@ -1,24 +1,36 @@
/// Return `true` if `n` is even, `false` otherwise.
fn is_even(n: u32) -> bool {
/// Return `12` if `n` is even,
/// `13` if `n` is divisible by `3`,
/// `17` otherwise.
fn magic_number(n: u32) -> u32 {
todo!()
}
#[cfg(test)]
mod tests {
use crate::is_even;
use crate::magic_number;
#[test]
fn one() {
assert!(!is_even(1));
assert_eq!(magic_number(1), 17);
}
#[test]
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]
fn high() {
assert!(!is_even(231));
assert_eq!(magic_number(233), 17);
}
}

View File

@@ -2,3 +2,9 @@
name = "panics"
version = "0.1.0"
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"

View File

@@ -19,7 +19,7 @@ mod tests {
// 👇 With the `#[should_panic]` annotation we can assert that we expect the code
// under test to panic. We can also check the panic message by using `expected`.
// This is all part of Rust's built-in test framework!
#[should_panic(expected = "The journey took no time at all, that's impossible!")]
#[should_panic(expected = "The journey took no time at all. That's impossible!")]
fn by_zero() {
speed(0, 10, 0);
}

View File

@@ -2,3 +2,9 @@
name = "factorial"
version = "0.1.0"
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"

View File

@@ -2,3 +2,9 @@
name = "while_"
version = "0.1.0"
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"

View File

@@ -2,3 +2,9 @@
name = "for_"
version = "0.1.0"
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"

View File

@@ -2,3 +2,9 @@
name = "overflow"
version = "0.1.0"
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"

View File

@@ -2,3 +2,9 @@
name = "saturating"
version = "0.1.0"
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"

View File

@@ -2,3 +2,9 @@
name = "as_cast"
version = "0.1.0"
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"

View File

@@ -23,7 +23,7 @@ mod tests {
// You could solve this by using exactly the same expression as above,
// but that would defeat the purpose of the exercise. Instead, use a genuine
// `i8` value that is equivalent to `255` when converted from `u8`.
// `i8` value that is equivalent to `255` when converted to `u8`.
let y: i8 = todo!();
assert_eq!(x, y);

View File

@@ -2,3 +2,9 @@
name = "intro_02"
version = "0.1.0"
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"

View File

@@ -2,3 +2,9 @@
name = "struct_"
version = "0.1.0"
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"

View File

@@ -5,3 +5,9 @@ edition = "2021"
[dev-dependencies]
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"

View File

@@ -12,6 +12,7 @@ impl Ticket {
// - the `title` should be at most 50 bytes long.
// - the `description` should be at most 500 bytes long.
// The method should panic if any of the requirements are not met.
// You can find the needed panic messages in the tests.
//
// You'll have to use what you learned in the previous exercises,
// as well as some `String` methods. Use the documentation of Rust's standard library

View File

@@ -2,3 +2,9 @@
name = "modules"
version = "0.1.0"
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"

View File

@@ -1,6 +1,6 @@
// TODO: based on what we just learned about ownership, it sounds like immutable references
// 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.
pub struct Ticket {

View File

@@ -21,8 +21,8 @@ mod tests {
// This is a tricky question!
// The "intuitive" answer happens to be the correct answer this time,
// but, in general, the memory layout of structs is a more complex topic.
// If you're curious, check out the "Data layout" section of the Rustonomicon
// https://doc.rust-lang.org/nomicon/data.html for more information.
// If you're curious, check out the "Type layout" section of The Rust Reference
// https://doc.rust-lang.org/reference/type-layout.html for more information.
assert_eq!(size_of::<Ticket>(), todo!());
}
}

View File

@@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
thiserror = "1.0.59"
thiserror = "1.0.69"
[dev-dependencies]
common = { path = "../../../helpers/common" }

View File

@@ -1,5 +1,5 @@
// TODO: Implement `TryFrom<String>` and `TryFrom<&str>` for the `TicketTitle` type,
// enforcing that the title is not empty and is not longer than 50 characters.
// enforcing that the title is not empty and is not longer than 50 bytes.
// Implement the traits required to make the tests pass too.
pub struct TicketTitle(String);

View File

@@ -5,6 +5,9 @@ use ticket_fields::{TicketDescription, TicketTitle};
// it contains using a `for` loop.
//
// 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)]
pub struct TicketStore {
tickets: Vec<Ticket>,

View File

@@ -1,6 +1,10 @@
use ticket_fields::{TicketDescription, TicketTitle};
// 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)]
pub struct TicketStore {
tickets: Vec<Ticket>,

View File

@@ -99,5 +99,11 @@ mod tests {
let ticket = &store[id];
assert_eq!(ticket.status, Status::InProgress);
let ticket = &mut store[&id];
ticket.status = Status::Done;
let ticket = &store[id];
assert_eq!(ticket.status, Status::Done);
}
}

View File

@@ -7,7 +7,7 @@ pub enum Command {
Insert(todo!()),
}
// Start the system by spawning the server the thread.
// Start the system by spawning the server thread.
// It returns a `Sender` instance which can then be used
// by one or more clients to interact with the server.
pub fn launch() -> Sender<Command> {

View File

@@ -4,5 +4,5 @@ version = "0.1.0"
edition = "2021"
[dependencies]
thiserror = "1.0.59"
thiserror = "1.0.69"
ticket_fields = { path = "../../../helpers/ticket_fields" }

View File

@@ -4,5 +4,5 @@ version = "0.1.0"
edition = "2021"
[dependencies]
thiserror = "1.0.60"
thiserror = "1.0.69"
ticket_fields = { path = "../../../helpers/ticket_fields" }

View File

@@ -4,5 +4,5 @@ version = "0.1.0"
edition = "2021"
[dependencies]
thiserror = "1.0.60"
thiserror = "1.0.69"
ticket_fields = { path = "../../../helpers/ticket_fields" }

View File

@@ -4,5 +4,5 @@ version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1.0.83"
anyhow = "1.0.100"
tokio = { version = "1", features = ["full"] }

View File

@@ -4,5 +4,5 @@ version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1.0.83"
anyhow = "1.0.100"
tokio = { version = "1", features = ["full"] }

View File

@@ -4,5 +4,5 @@ version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1.0.83"
anyhow = "1.0.100"
tokio = { version = "1", features = ["full"] }

View File

@@ -4,5 +4,5 @@ version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1.0.83"
anyhow = "1.0.100"
tokio = { version = "1", features = ["full"] }

View File

@@ -4,8 +4,8 @@ version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1.0.86"
clap = "4.5.4"
mdbook = "0.4.40"
semver = "1.0.23"
serde_json = "1.0.117"
anyhow = "1.0.100"
clap = "4.5.50"
mdbook = "0.4.52"
semver = "1.0.27"
serde_json = "1.0.145"

View File

@@ -4,12 +4,12 @@ version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1.0.86"
anyhow = "1.0.100"
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"
mdbook = "0.4.40"
pulldown-cmark = "0.11.0"
mdbook = "0.4.52"
pulldown-cmark = "0.11.3"
pulldown-cmark-to-cmark = "15"
semver = "1.0.23"
serde_json = "1.0.117"
semver = "1.0.27"
serde_json = "1.0.145"

View File

@@ -5,4 +5,4 @@ edition = "2021"
[dependencies]
common = { path = "../common" }
thiserror = "1.0.59"
thiserror = "1.0.69"

View File

@@ -1,4 +1,4 @@
/f2u https://blog.acolyer.org/2019/05/28/cheri-abi/
/f6c https://code.visualstudio.com
/f4q https://crates.io
/f2n https://crates.io/crates/cargo-modules
/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/
/ff2 https://mainmatter.com/contact/
/fff https://mainmatter.com/rust-consulting/
/fv2 https://mainmatter.github.io/rust-workshop-runner/
/fxg https://marabos.nl/atomics/
/f6a https://marketplace.visualstudio.com/items?itemName=matklad.rust-analyzer
/f6p https://nostarch.com/rust-rustaceans
/f2k https://owasp.org/www-community/vulnerabilities/Doubly_freeing_memory
/f2s https://owasp.org/www-community/vulnerabilities/Using_freed_memory
@@ -176,12 +178,17 @@
/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
/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
/f2t https://valgrind.org/docs/manual/dh-manual.html
/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/
/f6g https://www.amazon.com/dp/B0DJ14KQQG/
/f6d https://www.jetbrains.com/rust/
/ffv https://www.lpalmieri.com/
/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/
/f6j https://www.rust-lang.org/tools/install
/f6l https://www.youtube.com/playlist?list=PLqbS7AVVErFirH9armw8yXlE6dacF-A6z
/ff8 https://zero2prod.com