Compare commits

..

486 Commits

Author SHA1 Message Date
Mo Bitar
4bab596677 Merge pull request #2405 from aeft/improve-doc
Align section references with Rust Book section names
2026-05-25 15:14:05 +02:00
Zhijie Wang
9172a5bf27 Align section references with Rust Book section names 2026-05-24 16:51:48 -07:00
Remo Senekowitsch
b18a8c3036 strings4: remove From-based conversion
To understand From-based conversion, an understanding of traits is
required, which we teach in a later chapter. The From trait specifically
is taught in one of the conversion exercises. So, we can safely remove
it here without users missing out on learning something important.

A specific source of confusion for users was a warning that the
conversion is useless, which appeared when using the `string_slice`
function for the expression with `.into()`. closes #2190
2026-05-24 06:23:34 +02:00
Remo Senekowitsch
60b369a2fd Explain changed line in if3 solution 2026-05-17 08:49:57 +02:00
Mo Bitar
db3f332507 Merge pull request #2315 from Lev200501/enum-constructor
Update `13_error_handling/error6`: Remove redundant functions, use enum constructors instead
2026-05-17 01:52:35 +02:00
Remo Senekowitsch
ef218cd5d0 Merge pull request #2386 from senekor/senekor/lxuqllrrmroy
Use infallible conversion to teach From trait
2026-05-15 10:44:52 +02:00
Remo Senekowitsch
361a7f501e Add inverted formula and its derivation to hint 2026-05-15 10:41:35 +02:00
Remo Senekowitsch
360344ab6c Simplify story and increase difficulty
Conversion between Celsius and Fahrenheit should be understandable to
most. Inverting the formula is still not very hard, but a little harder
than only multiplying by 100.
2026-05-15 10:41:35 +02:00
Remo Senekowitsch
db5ad7f42f Use infallible conversion to teach From trait 2026-05-15 09:18:40 +02:00
Remo Senekowitsch
9b50da484f Merge pull request #2397 from rust-lang/senekor/onvlpnlyoqww
Redesign vec1 to avoid confusing array literal
2026-05-14 23:34:25 +02:00
Remo Senekowitsch
f3036315a0 Clarify order of elements
Co-authored-by: Mo Bitar <76752051+mo8it@users.noreply.github.com>
2026-05-14 23:31:11 +02:00
Remo Senekowitsch
97a723508c Redesign vec1 to avoid confusing array literal
Learners were sometimes confused by the literal array. Their assumption
was that they are supposed to convert the array to a vector. Duplicating
the literal elements was not an intuitive solution.

This redesign avoids putting an identical array literal near the place
where learners are supposed to use the vec! macro.
2026-05-14 16:19:53 +02:00
Remo Senekowitsch
03ddf3683b Update changelog 2026-05-14 16:14:40 +02:00
Remo Senekowitsch
06ca7b8718 Merge pull request #2393 from foxfromworld/issue-2023-rename-exercises
Apply Option A naming for smart_pointers and conversions exercises
2026-05-13 14:43:17 +02:00
Jane
ef99b5cb9e docs: update README after rebase 2026-05-13 19:57:17 +08:00
Jane
5b1edf5f4f Rename smart_pointers and conversions exercises with numeric prefix (Option A) 2026-05-13 19:36:32 +08:00
Jane
4338c58079 Rename smart_pointers and conversions exercises with numeric prefix
Update rustlings-macros/info.toml and dev/Cargo.toml accordingly
2026-05-13 19:36:32 +08:00
mo8it
e38c82ccbb Add a hint about opening the book offline 2026-05-11 12:14:28 +02:00
mo8it
a40a4dd43b Update deps 2026-05-11 12:09:01 +02:00
mo8it
60edde0f59 Make Ferris more symmetrical 2026-05-11 12:08:00 +02:00
mo8it
848e3f9294 Upgrade upload-pages-artifact 2026-05-11 12:08:00 +02:00
Remo Senekowitsch
fd237df59a Merge pull request #2317 from EugenDueck/patch-1
try_from_into.rs: Improve slice implementation
2026-05-11 09:28:06 +02:00
Remo Senekowitsch
d9e0b103c4 Update hint of enums2
This was discussed in another PR, but it was merged before the code was
updated to the most recent consensus:
https://github.com/rust-lang/rustlings/pull/2353

Co-authored-by: Piotr Spieker <p.spieker@posteo.de>
2026-05-09 21:15:18 +02:00
Mo Bitar
0907e65245 Merge pull request #2284 from noroutine/rustlingsua
Community Rustlings in Ukrainian
2026-05-09 12:32:33 +02:00
Mo Bitar
d6caefb139 Merge branch 'main' into rustlingsua 2026-05-09 12:32:23 +02:00
Mo Bitar
d9b63641e5 Merge pull request #2351 from dipan-ck/docs-add-string-links
docs: add str and String documentation links
2026-05-09 12:27:28 +02:00
Mo Bitar
3b0e7393f7 Merge pull request #2352 from eoncheole/patch-1
docs: add Korean Rustlings to community exercises list
2026-05-09 12:26:26 +02:00
Mo Bitar
d3d414c7b1 Merge pull request #2353 from orzechow/improve_enums2_hint
Mention struct-like variants in enums2 hint instead of anonymous structs
2026-05-09 12:24:36 +02:00
Mo Bitar
6c392609a3 Merge pull request #2388 from senekor/senekor/vnopstqrrszn
Use slice instead of array in iterator1
2026-05-09 10:41:13 +02:00
Mo Bitar
1d53bd1b54 Merge pull request #2380 from MatrixFrog/std-docs
Add a note about offline stdlib docs
2026-05-09 10:17:41 +02:00
Remo Senekowitsch
124708acd9 Use slice instead of array in iterator1
This avoids confusion between `.into_iter()` and `.iter()`. On a slice,
both methods do the same (correct) thing. Using `.into_iter()` will
result in a clippy warning about the slice not being consumed.
2026-05-03 14:56:32 +02:00
Piotr Spieker
f9f8a37bc7 Improve the list of enum variants in enums2 hint 2026-04-30 12:05:50 +02:00
Mo Bitar
4f1a440962 Merge pull request #2381 from senekor/senekor/soqukxyvzplr
Emphasize hotkeys in footer with color
2026-04-25 14:14:15 +02:00
Remo Senekowitsch
4c4dd20be3 Merge main into senekor/soqukxyvzplr 2026-04-25 14:08:53 +02:00
Remo Senekowitsch
e0334f79fe Avoid nested function definition 2026-04-25 14:08:53 +02:00
Mo Bitar
b06c843179 Merge pull request #2384 from senekor/senekor/kvvswrqlorup
Allow selecting next exercise with enter key
2026-04-25 14:04:11 +02:00
Remo Senekowitsch
b86a532e28 Document enter keybind in list footer 2026-04-25 13:58:31 +02:00
Remo Senekowitsch
c658a997f3 Turn unnecessary closure into regular function 2026-04-20 13:55:08 +02:00
Remo Senekowitsch
870776d03b Allow selecting next exercise with enter key 2026-04-19 00:38:18 +02:00
Tyler Breisacher
013a88a1e6 new wording from @senekor 2026-04-17 21:05:13 -07:00
Remo Senekowitsch
03c5baf35c Emphasize hotkeys in footer with color 2026-04-18 05:57:14 +02:00
Tyler Breisacher
5464fcd7e6 Add a note about offline stdlib docs 2026-04-16 19:21:08 -07:00
Mo Bitar
b7308825ec Merge pull request #2296 from senekor/senekor/nqmzmklxswoz
Make users type method syntax themselves in `structs3`
2026-04-13 19:01:44 +02:00
Remo Senekowitsch
346753b673 Make starting fireworks more fun :) 2026-04-13 18:58:53 +02:00
Mo Bitar
3bbc3001c9 Merge pull request #2378 from k7a-tomohiro/remove-unnecessary-tmp-file
Remove unnecessary tmp.txt file
2026-04-08 13:02:33 +02:00
k7a-tomohiro
b59f444bbc remove 2026-04-08 08:26:23 +09:00
mo8it
a307599b0b Fix test 2026-04-07 00:15:33 +02:00
mo8it
432d1f84ea Add --no-editor 2026-04-07 00:10:25 +02:00
mo8it
b5fbf59c0c Check if editor program exists before choosing it 2026-04-07 00:04:56 +02:00
mo8it
695f927893 Show file link on reset command 2026-04-06 23:29:59 +02:00
mo8it
f403d9e1b6 Show current exercise on hint command 2026-04-06 23:29:59 +02:00
mo8it
95499f18dd Close editor on quit 2026-04-06 23:11:35 +02:00
mo8it
bc0b4e9f9a Simplify Editor::open 2026-04-06 17:32:30 +02:00
mo8it
b0dc014040 Improve description of --edit-cmd 2026-04-06 17:24:55 +02:00
mo8it
b48663030b Add shlex 2026-04-06 16:58:15 +02:00
mo8it
dace3e3953 Add run_cmd 2026-04-06 16:58:15 +02:00
mo8it
c9ccedcff6 Support VSCode and --edit-cmd as editor 2026-04-06 16:58:15 +02:00
mo8it
4d97c31c0f Add Zellij support 2026-04-06 01:32:29 +02:00
Remo Senekowitsch
7c1d8ebf49 Make users type method syntax themselves in structs3
closes #2286
2026-04-05 22:23:47 +02:00
mo8it
95b6160b54 Don't manually inline 2026-04-05 17:29:24 +02:00
mo8it
c466d01da9 Unify imports 2026-04-05 17:28:27 +02:00
mo8it
7ed2316040 Update changelog 2026-04-05 15:53:36 +02:00
mo8it
7d53dc4c95 Update deps 2026-04-05 15:35:16 +02:00
mo8it
7150a9eb79 Add rumdl 2026-03-30 17:34:13 +02:00
mo8it
37cbcd9049 Adjust CI triggers 2026-03-25 18:29:58 +01:00
mo8it
3e46d8c50a Update deps 2026-03-25 18:29:37 +01:00
mo8it
08eb634db5 Upgrade deply-pages 2026-03-25 18:25:08 +01:00
mo8it
573d5a2acd Fix integration tests for build dir layout v2 2026-03-17 12:48:43 +01:00
mo8it
d3df105167 Upgrade to Zola 0.22 2026-03-17 12:48:43 +01:00
mo8it
2c9c31e8a2 Remove cargo-upgrades from release hook 2026-03-17 12:48:43 +01:00
mo8it
a28b9eda84 Delay inside_vcs_repo check until Git initialization 2026-03-14 18:26:03 +01:00
Mo Bitar
802dcfc987 Merge pull request #2285 from senekor/senekor/kvtomxvosvvx
Avoid initializing nested Git repository
2026-03-14 18:00:03 +01:00
mo8it
ceb98475e2 Avoid unneeded castings 2026-03-14 17:41:13 +01:00
mo8it
337f6b1521 Apply pedantic Clippy lints 2026-03-14 17:29:37 +01:00
mo8it
0ffeb14402 Avoid unneeded computation on full progress bar 2026-03-14 17:29:37 +01:00
mo8it
611d62951f Update deps 2026-03-14 17:29:37 +01:00
Mo Bitar
415bf695be Merge pull request #2367 from gabfec/fix/term-width-oeverflow
Fix u16 mul overflow with big term width
2026-03-14 17:29:10 +01:00
Gabriel Feceoru
d87a3b6ca5 Fix u16 mul overflow with big term width
When running rustlings in Rover IDE, term width could have a value of 2480
which causes u16 mul overflow.
2026-03-14 16:34:38 +01:00
mo8it
064f057b10 Improve integration testing 2026-02-26 18:02:07 +01:00
Remo Senekowitsch
17ff88902b Avoid initializing nested Git repository
Previously a Git repository was initialized if a Cargo workspace was
detected. However, it's also possible for users to initialize rustlings
in an existing Git repository that doesn't contain a Cargo workspace. In
that case, it's still undesirable to initialize a nested Git repository
for rustlings. We therefore search all ancestors of the current working
directory for `.git` or `.jj` directories to determine if rustlings is
being initialized in an existing Git repository.
2026-02-26 17:57:47 +01:00
Mo Bitar
75c06bb7f4 Merge pull request #2361 from senekor/senekor/mxstspkxoyyp
Improve error messages if tests fail
2026-02-26 17:54:22 +01:00
mo8it
7e5793b642 Remove \r on Windows 2026-02-26 17:43:44 +01:00
Remo Senekowitsch
c163bfe563 Improve error messages if tests fail 2026-02-26 17:40:35 +01:00
mo8it
e91647b023 Add RUSTBACKTRACE as env 2026-02-26 16:26:41 +01:00
mo8it
aaf8cad778 Add backtrace to CI 2026-02-26 16:22:27 +01:00
mo8it
8738518699 Use rustlings_dir when deleting the temporary dir before recreating it 2026-02-26 16:21:49 +01:00
mo8it
9011d34987 Swap name and dir to stay consistent with the info file 2026-02-26 16:12:34 +01:00
mo8it
2512701e2f Keep exercise path owned 2026-02-26 16:10:09 +01:00
mo8it
0cbcb8964c Borrow deserialized values 2026-02-26 16:10:09 +01:00
mo8it
13564207cb Update deps 2026-02-26 15:18:08 +01:00
Mo Bitar
fb87a26f4f Merge pull request #2331 from chapeupreto/minor-improvements
chore: minor improvements
2026-02-21 09:42:47 +01:00
Piotr Spieker
4817abcc14 Mention struct-like variants in enums2 hint instead of anonymous structs 2026-02-12 12:01:11 +01:00
cheoleon (pstor)
3a00274335 docs: add Korean Rustlings to community exercises list 2026-02-12 17:44:49 +09:00
Dipan Chakraborty
de695c46f3 docs: add str and String documentation links 2026-02-10 19:00:41 +05:30
Mo Bitar
87ac600b7c Merge pull request #2335 from pgoslatara/actup/update-actions-1769087609
chore: Update outdated GitHub Actions versions
2026-01-22 14:32:05 +01:00
Padraic Slattery
1b47fd97c0 chore: Update outdated GitHub Actions versions 2026-01-22 14:13:29 +01:00
Rod Elias
45f789114b chore: minor improvements 2026-01-12 00:22:59 -03:00
Mo Bitar
7850a73d95 Merge pull request #2324 from JatinSanghvi/main
fix: Match solution files with exercise files
2025-12-22 14:09:00 +00:00
Jatin Sanghvi
1ebb4d25a6 Update solution files to match exercise files 2025-12-19 19:32:24 +05:30
Eugen
0bed579a4b try_from_into.rs: Improve slice implementation
Using pattern matching, we can reduce four bound checks to just one.
2025-11-29 19:24:55 +09:00
Lev Krikken
c6c6d27232 Remove redundant error conversion functions, use enum constructors instead 2025-11-25 05:41:16 +01:00
mo8it
b5d440fdc3 Fix clippy3 2025-11-20 12:49:27 +01:00
Mo Bitar
4700e8a12c Merge pull request #2310 from DerWario/main
fix: mapping typo in the exercieses README.md
2025-11-20 11:39:25 +00:00
Marlon
8753dd6b2e Fixed typo in the exercieses README.md 2025-11-12 21:58:28 +01:00
Mo Bitar
f80fbca12e Merge pull request #2294 from senekor/senekor/qxykzqyxnnwy
Remove use of `map` in early vecs2 exercise
2025-09-25 16:55:36 +02:00
Remo Senekowitsch
d8f4b06c91 Remove use of map in early vecs2 exercise
Students do not have the necessary knowledge at this point to understand
what's happening with the iterator combinators. This topic is covered
well by the dedicated exercises about iterators later.

closes #2102
2025-09-24 21:19:40 +02:00
Mo Bitar
1955313362 Merge pull request #2291 from senekor/senekor/llttzkqnommp
Fix workspace detection with windows line endings
2025-09-23 16:18:05 +02:00
Remo Senekowitsch
95a597eb82 Fix workspace detection with windows line endings
Some cargo workspaces may contain windows line endings. Even if the
file is stored in a repo with unix line endings, users may have some
setting activated that automatically translates them to windows line
endings when working locally.
2025-09-23 15:29:26 +02:00
Oleksii Khilkevych
c2455bc676 Added rustlings in Ukrainian 2025-09-07 21:23:34 +02:00
mo8it
2af9e89ba5 chore: Release 2025-08-22 00:05:12 +02:00
mo8it
6ec2e194ae Apply Clippy lints 2025-08-22 00:01:23 +02:00
mo8it
295ad2e4bd Raise MSRV 2025-08-21 23:55:58 +02:00
mo8it
628ef55337 Fix Clippy chapter 2025-08-21 23:46:37 +02:00
mo8it
b6b94e3e96 Sync solution 2025-08-21 23:46:37 +02:00
Mo Bitar
6765a0b61a Merge pull request #2255 from zeonzip/clarify_errors_4_return
Clarify how to find return type of error4
2025-08-21 23:46:14 +02:00
Mo Bitar
436c95f4cc Merge pull request #2262 from aCactusOrSomething/main
Fix incorrect book chapter number
2025-08-21 23:36:03 +02:00
Mo Bitar
c6888685e6 Merge pull request #2265 from deafloo/main
Add positive tests in `iterators3.rs`
2025-08-21 23:26:29 +02:00
mo8it
208a593216 Ready to release 2025-08-21 23:17:53 +02:00
mo8it
2d1d531550 Fix file links in VS Code 2025-08-21 23:15:48 +02:00
mo8it
a712e484d0 Update deps 2025-08-18 12:01:21 +02:00
deafloo
4f9f0907c3 Add positive tests
This prevents solving the exercise without a real IntegerOverflow
2025-07-21 12:13:32 +02:00
Hud Miller
3a2fe2c394 Fix incorrect book chapter number 2025-07-18 13:02:56 -05:00
mo8it
f24861957a Check for Clippy on init 2025-07-04 23:35:13 +02:00
mo8it
1a633e2757 Split lines after newline 2025-07-04 23:22:05 +02:00
mo8it
9fecdba101 No need to flush after printing newlines 2025-06-28 02:15:14 +02:00
mo8it
7af38e684d Print newline after progress on failure 2025-06-28 02:08:00 +02:00
mo8it
e8da6869f8 Don't run rustfmt during dev check if there are no solutions 2025-06-28 01:43:41 +02:00
mo8it
57b3727b3e Don't ignore .rustlings-state.txt in .gitignore of rustlings dev new 2025-06-28 01:32:18 +02:00
zeonzip
278edc0b96 Clarify how to find return type of error4 2025-06-13 12:24:09 +02:00
mo8it
cb60c8887c Update deps 2025-06-03 10:30:36 +02:00
mo8it
46814d397a Fix path in action 2025-05-23 13:44:30 +02:00
mo8it
734fc482eb Make path relative 2025-05-23 13:37:15 +02:00
mo8it
520dfdc464 Add workflow_dispatch to website workflow 2025-05-23 13:33:51 +02:00
Mo Bitar
2267f99684 Merge pull request #2247 from rust-lang/website
Website
2025-05-23 13:26:52 +02:00
mo8it
bf74a3d0a7 Update the README with more context before the website link 2025-05-23 13:21:05 +02:00
mo8it
adf3ddd968 Remove rustywind from dev deps 2025-05-23 13:17:21 +02:00
mo8it
f80c2edc3d Remove fnm 2025-05-23 13:17:14 +02:00
mo8it
04520ae7ad Use the website link as header 2025-05-19 18:30:40 +02:00
mo8it
e36dd7a120 Update MSRV in the release hook 2025-05-19 18:21:40 +02:00
mo8it
edc8528dde Improve CI 2025-05-19 18:20:34 +02:00
mo8it
47e490a997 Run rustywind 2025-05-17 22:33:17 +02:00
mo8it
596e7f36cc Add website CI 2025-05-17 22:33:00 +02:00
mo8it
512ded81c4 Done community exercises page 2025-05-17 22:05:57 +02:00
mo8it
69a9e9cafc Less top margin for blockquotes 2025-05-17 22:05:48 +02:00
mo8it
54a74fd638 Use internal links for validation 2025-05-17 21:28:25 +02:00
mo8it
a51d6f1309 third-party/custom -> community 2025-05-17 21:25:19 +02:00
mo8it
f6a657a0c3 Finish the usage page 2025-05-17 21:02:45 +02:00
mo8it
8c24763259 Q/A -> Q&A 2025-05-17 21:02:01 +02:00
mo8it
dc468882cc Highlight platform 2025-05-17 20:45:28 +02:00
mo8it
5fc787f4e4 Style details body 2025-05-17 20:45:20 +02:00
mo8it
8fa598ae7e Add details shortcode 2025-05-17 20:20:19 +02:00
mo8it
2f700991f3 Remove macros 2025-05-17 19:53:30 +02:00
mo8it
b4a6b87e24 Less padding 2025-05-17 19:34:53 +02:00
mo8it
984e9fea7c Merge branch 'main' 2025-05-17 16:17:20 +02:00
mo8it
8339007633 Update setup and usage 2025-05-17 16:06:04 +02:00
mo8it
23b9aa3a15 Move Q/A menu item 2025-05-17 16:05:42 +02:00
mo8it
69fe9626da Update base URL 2025-05-17 16:05:26 +02:00
mo8it
f387f4c1d9 Add setup and usage pages 2025-05-17 15:49:26 +02:00
liv
40fe3aa741 remove oranda path_prefix 2025-05-17 15:48:04 +02:00
mo8it
b30973afa1 Compress the intro 2025-05-17 14:53:38 +02:00
mo8it
3d8bef4bc3 Remove landscape mode recommendation 2025-05-17 14:53:20 +02:00
mo8it
2673177b17 Update header and footer 2025-05-17 13:02:34 +02:00
mo8it
6d5369d4d0 Add more menu and footer items 2025-05-17 12:25:55 +02:00
mo8it
b9d1e636a4 Reduce the README to the website link 2025-05-17 12:25:32 +02:00
mo8it
7e26418952 Remove the third-party exercises file 2025-05-17 12:25:08 +02:00
mo8it
61c17cb349 Change syntax highlighting theme 2025-05-17 12:24:44 +02:00
mo8it
fda18e8895 Add Ferris SVGs 2025-05-17 12:24:27 +02:00
mo8it
7ec6986965 Add templates 2025-05-16 23:11:08 +02:00
mo8it
74ab9924b4 Start with Zola 2025-05-16 21:08:29 +02:00
mo8it
a28000acc4 Remove markdown lint 2025-05-16 11:35:46 +02:00
mo8it
08548abcc2 Remove .editorconfig 2025-05-16 11:35:24 +02:00
mo8it
5927a781a3 Remove Oranda 2025-05-16 11:29:32 +02:00
mo8it
e73fff3bd4 Add dev alias 2025-05-16 11:09:06 +02:00
mo8it
8dff0df266 Use std pipe 2025-05-16 11:09:06 +02:00
liv
5ee7dfb5c2 chore: build site with proper path prefix 2025-05-16 11:05:02 +02:00
mo8it
9a3586878d Sync solution 2025-05-13 16:24:42 +02:00
Mo Bitar
a99433c62d Merge pull request #2215 from Rudxain/strim
test idempotence of `trim_me` in `strings3.rs`
2025-05-13 16:23:35 +02:00
mo8it
e76ca5e2b9 Use a separate target dir for rust analyzer 2025-05-12 20:38:04 +02:00
mo8it
48bab77609 Apply Clippy lints 2025-05-12 20:31:13 +02:00
mo8it
a063bcfb4c Update deps 2025-05-12 20:30:56 +02:00
mo8it
c5f49cfa48 Remove needless_option_as_deref exception 2025-05-12 20:30:51 +02:00
mo8it
9bcd4198c5 Fix formatting 2025-04-29 21:36:56 +02:00
mo8it
29dc8ea9fa Update deps 2025-04-29 21:35:58 +02:00
Mo Bitar
fa91814aa9 Merge pull request #2232 from ethdew19/main
Fix typo in traits hint
2025-04-29 21:34:47 +02:00
Mo Bitar
0b91db2195 Merge pull request #2236 from rahmatnazali/ice_cream
Fix possible typo of `icecream` to `ice cream` on `options1.rs`
2025-04-29 21:34:21 +02:00
Rahmat Nazali Salimi
7b2d42b0f0 Change icecream to ice cream 2025-04-10 15:38:43 +07:00
Ethan
bd3bdd620b Fix typo in traits hint 2025-04-08 20:23:11 -05:00
Mo Bitar
8b4562e102 Merge pull request #2219 from ubitux/no-todo
Remove TODO from 2 solutions
2025-04-03 19:36:06 +02:00
mo8it
63d8986f2a Update links 2025-04-03 18:22:55 +02:00
mo8it
ecaecc2f76 Update deps 2025-04-03 17:58:36 +02:00
Mo Bitar
78194b4441 Merge pull request #2224 from cassian-goode/patch-1
Fix typo - errors5.rs
2025-04-03 17:52:57 +02:00
Mo Bitar
44699e9b1b Merge pull request #2227 from Hunter-Plus/patch-1
Update README.md
2025-04-03 17:52:15 +02:00
Hunter Z
9978c17d5f Update README.md
Update the URL while add more reference.
2025-03-31 12:58:06 +08:00
cassian-goode
3cc7e0377c Fix typo - errors5.rs
Minor typo correction in exercise instructions
2025-03-25 09:24:49 -04:00
Clément Bœsch
d2abc359cc Remove TODO from 2 solutions 2025-03-17 18:36:13 +01:00
mo8it
7c0d269279 Update README 2025-03-14 11:42:16 +01:00
mo8it
8db85946af Update deps 2025-03-14 11:33:56 +01:00
mo8it
7019f4d178 Update pipeline 2025-03-14 11:33:56 +01:00
Ricardo Fernández Serrata
fcd77a83cc test trim idempotence 2025-03-07 19:17:11 -04:00
Mo Bitar
ae444eb3da Merge pull request #2213 from peterneave/main
Use consistent apostrophes in markdown files
2025-03-02 17:30:29 +01:00
Peter Neave
425c9821e0 Use consistent apostrophes in markdown files 2025-02-28 11:46:39 +11:00
mo8it
46c6fb2c82 Update deps 2025-02-25 11:21:19 +01:00
mo8it
374c3874af Apply 2024 edition formatting to solutions 2025-02-21 13:08:34 +01:00
mo8it
1eb6c1e469 Update the edition of the solution format checker 2025-02-21 13:06:11 +01:00
mo8it
06af3ffc99 Bump MSRV in release hook 2025-02-18 20:17:27 +01:00
mo8it
65dc019fa6 Fix new Clippy error in solution 2025-02-18 20:15:50 +01:00
mo8it
a56ccb6f4f Fix new Clippy lint 2025-02-18 20:12:23 +01:00
mo8it
d9872f2615 Upgrade to edition 2024 2025-02-18 20:10:52 +01:00
mo8it
298be671b9 Update deps 2025-02-18 20:03:49 +01:00
mo8it
fbfd4f25e7 Disable following symlinks in the watcher 2025-01-16 10:41:48 +01:00
mo8it
d12735a573 Update deps 2025-01-16 10:41:17 +01:00
mo8it
1aec7c1152 Fix Windows CI 2025-01-01 22:07:41 +01:00
mo8it
0b55809bb9 Fix building from source on Windows 2025-01-01 22:01:39 +01:00
mo8it
bde6f7470c Co-ordinates -> Coordinates 2024-12-28 16:46:24 +01:00
mo8it
53ec59ed95 Rename translations 2024-12-28 16:41:43 +01:00
mo8it
ed1ee38923 Link to simplified Chinese translation 2024-12-28 16:40:07 +01:00
Mo
26cf4989a2 Merge pull request #2173 from JoelMarcey/if2-comment-fix
Fix argument comment in test of if2.rs
2024-12-13 19:48:16 +01:00
Joel Marcey
6e60f441e9 Fix argument comment in test of if2.rs 2024-12-13 10:44:21 -08:00
mo8it
d07de879a7 Update deps 2024-12-11 00:12:49 +01:00
Mo
dd0634c483 Merge pull request #2158 from mnshdw/mnshdw/feedback-errors6
errors6: Add alternative solution using From trait
2024-11-14 14:49:57 +01:00
Antoine Dupuis
fc0cd8f0f8 Switch comment style to // 2024-11-14 09:14:40 +01:00
Antoine Dupuis
d5cae8ff59 Add alternative solution using From trait 2024-11-13 23:51:09 +01:00
mo8it
38016cb2d6 clippy3: Make the intent more clear 2024-11-13 16:06:41 +01:00
mo8it
e6cb104294 chore: Release 2024-11-11 15:51:27 +01:00
mo8it
410eb69d25 Remove "chore: " from the commit message of releases 2024-11-11 15:49:50 +01:00
mo8it
243cf5f261 Update CHANGELOG 2024-11-11 15:49:24 +01:00
mo8it
eff2ce8a23 Ignore input while checking all exercises in watch mode 2024-11-11 14:55:58 +01:00
mo8it
fd33c29b26 Test with MSRV before release 2024-11-11 14:43:51 +01:00
mo8it
f49164e69b Fix typo 2024-11-11 14:43:38 +01:00
mo8it
9bc7bbe4b4 Update deps 2024-11-11 14:35:22 +01:00
mo8it
46ad25f925 Fix contrast in terminals with a light theme 2024-11-11 14:34:33 +01:00
mo8it
2a725fb137 Upgrade notify 2024-10-29 14:25:44 +01:00
mo8it
449858655d Update deps 2024-10-26 16:55:15 +02:00
mo8it
e8c2a79516 Deduplicate code for printing keys 2024-10-26 16:55:15 +02:00
Mo
ea85c1b46e Merge pull request #2142 from cenviity/push-qoxkvmtkyvmv
threads1: Fix typos in description
2024-10-22 12:35:25 +02:00
Vincent Ging Ho Yim
6bec6f92c4 threads1: Fix typos in description 2024-10-22 16:53:23 +11:00
mo8it
930a0ea73b list: Highlight search match in exercise names 2024-10-17 16:00:10 +02:00
mo8it
7e2f56f41a Use the default hasher 2024-10-17 15:03:43 +02:00
mo8it
e90f5f03f3 Mention the Q&A category 2024-10-17 14:59:37 +02:00
mo8it
0e090ae112 Add required type annotation 2024-10-17 14:49:07 +02:00
mo8it
99496706c5 Apply new Clippy lints 2024-10-17 14:49:07 +02:00
mo8it
f146553dea hashmap3: Use or_default 2024-10-17 14:49:07 +02:00
Mo
0432e07864 Merge pull request #2130 from Nahor/typo
Fix typos
2024-10-14 20:06:30 +02:00
Nahor
f33ba139b4 Fix typos 2024-10-14 10:17:17 -07:00
mo8it
990a722852 Limit the maximum number of exercises to 999 2024-10-14 15:57:44 +02:00
mo8it
a675cb5754 Replace ahash with foldhash 2024-10-14 15:24:42 +02:00
Mo
baeeff389c Merge pull request #2122 from Nahor/check_all
Improvement to "check all exercises"
2024-10-14 01:29:25 +02:00
mo8it
932bc25d88 Remove unneeded line 2024-10-14 01:28:34 +02:00
mo8it
bdc6dad8de Update names 2024-10-14 01:28:12 +02:00
mo8it
ea73af9ba3 Separate initialization with a struct 2024-10-14 01:06:11 +02:00
mo8it
fc5fc0920f Remove outdated comments 2024-10-14 00:48:12 +02:00
mo8it
9705c161b4 Remove the tracking of done and pending 2024-10-14 00:45:41 +02:00
mo8it
8cac21511c Small improvements to showing progress 2024-10-14 00:42:49 +02:00
mo8it
396ee4d618 Show progress with exercise numbers 2024-10-13 23:28:17 +02:00
mo8it
326169a7fa Improve check-all command 2024-10-13 22:02:41 +02:00
mo8it
685e069c58 First PR review changes 2024-10-10 19:43:35 +02:00
mo8it
84a42a2b24 Update third-party exercises section 2024-10-09 15:42:16 +02:00
Mo
ac6e1b7ce5 Merge pull request #2121 from sotanengel/add/link-to-THIRD_PARTY-repository-for-Japanese-translations
Add Third-Party List about rustlings-jp on README
2024-10-09 15:35:30 +02:00
mo8it
f516da4138 Avoid single char variables 2024-10-09 15:27:36 +02:00
Mo
e852e60416 Merge pull request #2124 from Polycarbohydrate/main
fix: typo in `exercises/23_conversions/from_str.rs`
2024-10-06 01:50:18 +02:00
Polycarbohydrate
bf7d171915 Update from_str.rs 2024-10-05 16:05:35 -04:00
Nahor
d3f819f86f Add command line command to check all exercises 2024-10-04 14:36:36 -07:00
Nahor
aa83fd6bc4 Show a progress bar when running check_all
Replace the "Progress: xxx/yyy" with a progress bar when checking all
the exercises
2024-10-02 15:28:42 -07:00
Nahor
e2f7734f37 Limit the amount of parallelism in check_all
Don't create more threads than there are CPU cores.
2024-10-02 14:42:50 -07:00
Nahor
5c17abd1bf Use a channel to update the check_all progress
The previous code was checking the threads in the order they were
created. So the progress update would be blocked on an earlier thread
even if later thread were already done.

Add to that that multiple instances of `cargo build` cannot run in
parallel, they will be serialized instead. So if the exercises needs to
be recompiled, depending on the order those `cargo build` are run,
the first update can be a long time coming.

So instead of relying on the thread terminating, use a channel to get
notified when an exercise check is done, regardless of the order they
finish in.
2024-10-02 14:10:26 -07:00
Nahor
c52867eb8b Add command to check all the exercises
This allows for skipping repeating "next" when multiple exercises
are done at once, or when earlier exercises have been updated/changed
(and thus must be redone) while still working of the whole set (i.e.
the final check_all is not yet available to flag those undone exercises)
2024-10-02 13:40:32 -07:00
Nahor
26fd97a209 Update all exercises during the final check
The previous code run the check on all exercises but only updates one
exercise (the first that failed) even if multiple failed. The user won't
be able to see all the failed exercises when viewing the list, and will
have to run check_all after each fixed exercise.

This change will update all the exercises so the user can see all that
failed, fix them all, and only then need run check_all again.
2024-10-02 11:45:55 -07:00
sotanengel
f0a2cdeb18 Merge branch 'rust-lang:main' into add/link-to-THIRD_PARTY-repository-for-Japanese-translations 2024-09-29 11:09:34 +09:00
mo8it
0c79f2ea3e Reset in prompt with confirmation 2024-09-26 18:15:45 +02:00
mo8it
0e9eb9e87e Replace three dots with dot in hint 2024-09-26 18:05:05 +02:00
mo8it
0d258b9e96 Update deps 2024-09-26 12:28:48 +02:00
mo8it
d4fa61e435 Debounce file change events 2024-09-26 12:26:24 +02:00
mo8it
554301b8e9 Clear terminal before final check in watch mode 2024-09-24 16:12:44 +02:00
sota.n
e3ec0abca4 add Third-Party List about rustlings-jp on README 2024-09-24 16:58:37 +09:00
Mo
a55e848359 Merge pull request #2114 from samueltardieu/push-ptorzrrnmxyp
Do not use `.as_bytes().len()` on strings
2024-09-22 11:40:45 +02:00
Samuel Tardieu
2653c3c4d4 Do not use .as_bytes().len() on strings 2024-09-22 10:49:55 +02:00
mo8it
4e4b65711a Only handle file changes for the current exercise, no jumping back 2024-09-18 01:44:13 +02:00
mo8it
89c40ba256 Optimize the file watcher 2024-09-18 01:43:48 +02:00
mo8it
e56ae6d651 Update deps 2024-09-17 23:33:48 +02:00
Mo
64b2f18d92 Merge pull request #2103 from senekor/senk/kvuzvzqqkskk
Remove redundant enum definition task
2024-09-16 12:56:28 +02:00
Mo
2894f3c45c Merge pull request #2110 from senekor/remo/skkynvtqxkoz
Make if2 less confusing
2024-09-16 12:54:20 +02:00
Mo
1bae2dcb00 Merge pull request #2109 from bri-rose/main
grammatical error in info.toml
2024-09-14 23:52:54 +02:00
Remo Senekowitsch
b540c6df25 Make if2 less confusing
Some people would get stuck on this exercise, trying to understand the meaning
behind foo, fuzz, baz etc. Making the theme of the code make a little more sense
to humans should hopefully prevent people from getting confused by abstract and
non-sensical tests.
2024-09-14 10:03:52 +02:00
bri-rose
8b476e678a Update info.toml
Fixed grammatical error, subject/verb agreement at line 124-125.
2024-09-13 10:23:05 -05:00
mo8it
47f8a0cbe5 Add rust-analyzer.toml on dev new 2024-09-13 16:39:28 +02:00
mo8it
9459eef032 Use Clippy with Rust-Analyzer 2024-09-13 16:38:53 +02:00
mo8it
5aaa8924a6 <s>earch isn't a typo 2024-09-13 15:07:53 +02:00
mo8it
4ffce1c297 Move lint to Rust lints 2024-09-13 14:59:34 +02:00
mo8it
0513660b05 Allow dead code for all exercises and solutions 2024-09-13 14:56:46 +02:00
mo8it
3947c4de28 Pause input while running an exercise 2024-09-12 17:46:06 +02:00
mo8it
664228ef8b Improve quit message 2024-09-12 17:46:06 +02:00
mo8it
234a61a3ee Update deps 2024-09-12 17:46:06 +02:00
mo8it
83d1275d72 Add missing # in comment 2024-09-12 17:46:06 +02:00
Mo
45abd7d59e Merge pull request #2107 from alibektas/ratoml_for_rustlings
Add rust-analyzer.toml file
2024-09-12 15:49:31 +02:00
Ali Bektas
88e10a9e54 hardcode ratoml in init.rs 2024-09-12 15:46:09 +02:00
Ali Bektas
1f624d4c2a Add rust-analyzer.toml file 2024-09-12 15:26:40 +02:00
Remo Senekowitsch
9a25309c1c Remove redundant enum definition task
The exercise enums2.rs already contains a task where an identical enum
has to be defined.
2024-09-11 16:57:12 +02:00
mo8it
2b7caf6fcb Too polite :P 2024-09-06 16:36:36 +02:00
mo8it
938500fd2f Fix dev check in official repo 2024-09-06 16:35:12 +02:00
mo8it
2d26358602 Use the thread builder and handle the spawn error 2024-09-06 15:40:25 +02:00
mo8it
9faa5d3aa4 Avoid asking for terminal size on each rendering 2024-09-05 17:45:27 +02:00
mo8it
bcc2a136c8 Add error message when unable to get terminal size 2024-09-05 17:37:34 +02:00
mo8it
dcad002057 Only render when needed 2024-09-05 17:32:59 +02:00
mo8it
51b8d2ab25 Remove unused import 2024-09-05 17:23:56 +02:00
mo8it
aa3eda70e5 Simplify handling terminal events for unbuffered stdin 2024-09-05 17:12:26 +02:00
mo8it
2d0860fe1b Hide input and disable its line buffering 2024-09-05 02:11:19 +02:00
mo8it
17877366b7 Update deps 2024-09-05 01:55:31 +02:00
mo8it
5eb3dee59c Create solution even if the solution's directory is missing 2024-09-05 00:21:24 +02:00
mo8it
247bd19f93 Canonicalize exercise paths only once 2024-09-04 02:19:45 +02:00
mo8it
e5ed115288 Match filter once 2024-09-04 01:20:48 +02:00
mo8it
03baa471d9 Simplify handling p in list 2024-09-04 01:07:08 +02:00
mo8it
da8b3d143a Final touches to searching 2024-09-04 01:05:30 +02:00
Mo
20616ff954 Merge pull request #2098 from frroossst/main
Made the list of exercises searchable, ref #2093
2024-09-04 00:40:22 +02:00
Adhyan
f463cf8662 passes clippy lints and removed extra code from the merge 2024-09-03 15:10:44 -06:00
Adhyan
e9879eac91 merge of origin/main 2024-09-03 15:04:45 -06:00
Adhyan
47148e78a3 replaced enumerate() with position(); converted select_if_matches_search_query to apply_search_query 2024-09-03 15:03:25 -06:00
Adhyan
fea917c8f2 removed unnecessary update_rows() call and minor refactoring 2024-09-03 14:52:09 -06:00
Adhyan
948e16e3c7 moved continue to end of if-block 2024-09-03 14:40:24 -06:00
Adhyan
1e7fc46406 Merge branch 'main' of https://github.com/frroossst/rustlings 2024-09-02 11:02:21 -06:00
Adhyan
71494264ca fixed clippy lints 2024-09-02 11:02:17 -06:00
Adhyan H. Patel
3125561474 Merge branch 'rust-lang:main' into main 2024-09-02 12:00:22 -05:00
Adhyan
abf1228a0a search now filters the list first 2024-09-02 10:59:23 -06:00
Adhyan
547a9d947b escape/enter no longer exits the list, exits only the search 2024-09-02 10:45:45 -06:00
Mo
f696d98270 Merge pull request #2097 from jsejcksn/ux
style: reduce pre-formatted message line lengths to 80 columns
2024-09-02 14:20:18 +02:00
Adhyan
44ab7f995d Merge branch 'main' of https://github.com/frroossst/rustlings 2024-09-01 19:05:28 -06:00
Adhyan
92a1214dcd passes clippy lints 2024-09-01 19:05:23 -06:00
Adhyan
388f8da97f removed debug statements 2024-09-01 19:03:33 -06:00
Adhyan H. Patel
e96623588c Merge branch 'rust-lang:main' into main 2024-09-01 19:57:35 -05:00
Adhyan
e1e316b931 Merge branch 'main' of https://github.com/frroossst/rustlings 2024-09-01 18:56:52 -06:00
Adhyan
c4fd29541b added a way to search through list, ref #2093 2024-09-01 18:52:26 -06:00
mo8it
a8b13f5a82 Remove "exercises" from the end of the progress bar 2024-09-01 22:04:09 +02:00
mo8it
86fc573d7a Remove the footer separators 2024-09-01 22:02:07 +02:00
Jesse Jackson
f82e47f2af style: reduce pre-formatted message line lengths to 80 columns 2024-09-01 14:48:28 -05:00
mo8it
75a38fa38b Add search to the help footer 2024-09-01 20:44:19 +02:00
mo8it
ac62a3713c Fix typo 2024-09-01 20:31:16 +02:00
Mo
ea52c99560 Merge pull request #2092 from wugalde19/fix-hint-example-for-primitive-types3
Fix example in 'primitive_types3' hint
2024-08-31 05:27:36 +02:00
William Ugalde Gamboa
7d4100ed8a Fix example in 'primitive_types3' hint 2024-08-30 20:27:26 -06:00
mo8it
c8d1d9c51f chore: Release 2024-08-29 17:20:17 +02:00
mo8it
ab2eb3442e Update changelog 2024-08-29 17:10:39 +02:00
mo8it
dbbeb7d4ed Fix displaying the list message in narrow mode 2024-08-29 17:06:37 +02:00
mo8it
bfa00ffbdc Update deps 2024-08-29 16:40:40 +02:00
mo8it
10eb1a3aee Fix header padding 2024-08-29 16:01:41 +02:00
mo8it
fd2bf9f6f6 Simplify next_pending_exercise_ind 2024-08-29 01:59:04 +02:00
mo8it
fc1f9f0124 Optimize reading and writing the state file 2024-08-29 01:56:45 +02:00
mo8it
789492d1a9 The number of exercises can't be zero, but still 2024-08-29 00:32:58 +02:00
mo8it
afc320bed4 Fix error about too many open files during the final check 2024-08-29 00:17:22 +02:00
mo8it
cba4a6f9c8 Only disable links in VS code in the list 2024-08-28 01:19:53 +02:00
mo8it
5556d42b46 Use sol_path 2024-08-28 01:10:19 +02:00
mo8it
7d2bc1c7a4 Use a Vec for the name col padding 2024-08-28 00:56:22 +02:00
mo8it
c209c874a9 Check the exercise name length 2024-08-28 00:34:24 +02:00
mo8it
dd52e9cd72 Separate the scroll state 2024-08-27 00:03:50 +02:00
mo8it
0f71a150ff Making code prettier :P 2024-08-26 22:03:09 +02:00
mo8it
74388d4bf4 Only trigger write when needed 2024-08-26 04:41:26 +02:00
mo8it
e811dd15b5 Fix list on terminals that don't disable line wrapping 2024-08-26 04:29:58 +02:00
mo8it
f22700a4ec Use the correct environment variable 2024-08-26 02:43:08 +02:00
mo8it
ee25a7d458 Disable terminal links in VS-Code 2024-08-26 02:41:22 +02:00
mo8it
594e212b8a Darker highlighting in the list 2024-08-26 00:53:42 +02:00
mo8it
5c355468c1 File link in the list? No problem :D 2024-08-26 00:49:56 +02:00
mo8it
d1571d18f9 Only reset color and underline after link 2024-08-26 00:48:12 +02:00
mo8it
cb86b44dea LOL, swapped colors 2024-08-26 00:40:30 +02:00
mo8it
833e6e0c92 Newline after resetting attributes 2024-08-26 00:24:39 +02:00
mo8it
159273e532 Take stdout as argument in watch mode 2024-08-26 00:09:04 +02:00
mo8it
631f2db1a3 Lower the maximum scroll padding 2024-08-25 23:54:18 +02:00
mo8it
a1f0eaab54 Add disallowed types and methods in Clippy 2024-08-25 23:54:04 +02:00
mo8it
b1898f6d8b Use queue instead of Stylize 2024-08-25 23:53:50 +02:00
mo8it
d29e9e7e07 Update deps 2024-08-25 20:42:13 +02:00
mo8it
360605e284 Merge branch 'rm-ratatui' 2024-08-25 20:31:08 +02:00
mo8it
64772544fa Final touches :D 2024-08-25 20:29:54 +02:00
mo8it
5f4875e2ba Almost done with list 2024-08-25 19:24:12 +02:00
mo8it
fd2a8c01cb Separate drawing rows 2024-08-24 19:18:13 +02:00
mo8it
b6129ad081 Use the full length for the wide footer 2024-08-24 17:45:38 +02:00
mo8it
28d0b0a21e Highlight selected row 2024-08-24 17:45:02 +02:00
mo8it
b779c43126 Almost done with list display 2024-08-24 17:17:56 +02:00
mo8it
4e12725616 Don't exit the list on "to current" if nothing is selected 2024-08-24 00:23:45 +02:00
mo8it
570bc9f32d Start list without Ratatui 2024-08-24 00:14:12 +02:00
mo8it
47976caa69 Import Ordering 2024-08-22 14:42:17 +02:00
mo8it
f1abd8577c Add missing Clippy allows to solutions 2024-08-22 14:41:25 +02:00
mo8it
423b50b068 Use match instead of comparison chain 2024-08-22 14:37:47 +02:00
mo8it
bedf0789f2 Always use strict Clippy when checking solutions 2024-08-22 14:25:14 +02:00
mo8it
a2d1cb3b22 Push newline after running an exercise instead on each rendering 2024-08-20 16:05:52 +02:00
mo8it
e7ba88f905 Highlight the solution file 2024-08-20 16:04:29 +02:00
mo8it
50f6e5232e Leak info_file and cmd_runner in dev check 2024-08-20 14:47:08 +02:00
mo8it
8854f0a5ed Use anyhow! 2024-08-20 14:32:47 +02:00
mo8it
13cc3acdfd Improve readability 2024-08-20 13:56:52 +02:00
mo8it
5b7368c46d Improve error message if no exercise exists 2024-08-20 13:54:20 +02:00
mo8it
27999f2d26 Check if exercise doesn't contain tests 2024-08-20 13:49:48 +02:00
mo8it
e74f2a4274 Check for #[test] with newline at the end 2024-08-20 13:39:14 +02:00
mo8it
d141a73493 threads3: Improve the test 2024-08-20 13:35:07 +02:00
mo8it
631f44331e Remove --show-output for tests and use --format pretty 2024-08-20 13:08:15 +02:00
mo8it
b01fddef8b Show progress of dev check 2024-08-19 23:52:22 +02:00
mo8it
78a8553f1c "Continue at" quits the list 2024-08-19 23:29:17 +02:00
mo8it
b70c1abd7c Update deps 2024-08-19 23:28:53 +02:00
mo8it
71f31d74bc Update deps 2024-08-17 16:57:58 +02:00
mo8it
72e557b3a9 Break help footer on narrow terminals 2024-08-17 16:54:44 +02:00
mo8it
3eaccbb61a Restore the terminal after an error in the list 2024-08-17 16:49:07 +02:00
mo8it
b678bd8ed2 Disable mouse in the list 2024-08-17 16:34:43 +02:00
mo8it
2baa140615 q only quits the list 2024-08-17 15:53:34 +02:00
mo8it
e760f07767 Make it clear that reset only resets one exercise 2024-08-17 15:53:24 +02:00
mo8it
ca5d5f0a49 Remove dot for copy-pasta 2024-08-17 15:45:02 +02:00
mo8it
69b4fd49fc Only take a u8 to avoid huge output 2024-08-17 14:59:00 +02:00
mo8it
36f315c344 Add "the" 2024-08-17 14:56:52 +02:00
mo8it
8016f5ca2d Remove unneeded comma 2024-08-17 14:55:58 +02:00
mo8it
8ef2ff1257 Remove "Hello and" 2024-08-17 14:54:13 +02:00
mo8it
6ce31defb6 Ignore stdout of git init 2024-08-17 14:40:09 +02:00
mo8it
0b3ad9141b Add exercise lints 2024-08-16 00:24:45 +02:00
mo8it
c903db5c53 Add project lints 2024-08-16 00:24:45 +02:00
Mo
8a038b946c Merge pull request #2084 from crd477/patch-1
fix typo
2024-08-16 00:12:58 +02:00
Chad Dougherty
ed9740b72c fix typo
Similarely -> Similarly in comment
2024-08-15 14:21:27 -04:00
mo8it
ce3dcc9856 Fix typo 2024-08-09 12:47:32 +02:00
mo8it
4472d50eba chore: Release 2024-08-09 11:52:31 +02:00
mo8it
a1d5702ba0 Ready for publish 2024-08-09 11:51:56 +02:00
mo8it
52a231ce2f Update Ratatui 2024-08-09 02:17:01 +02:00
mo8it
16af981772 Hide stderr of cargo locate-project 2024-08-09 01:27:31 +02:00
mo8it
fc141b8dfc Put Cargo.toml in `` 2024-08-09 01:16:45 +02:00
mo8it
82ebd29ff6 Add a special confirmation for initialization in a workspace 2024-08-09 01:14:08 +02:00
mo8it
f5737b5a49 Fix typos 2024-08-09 01:08:52 +02:00
mo8it
55e68d2c63 Update deps 2024-08-09 01:06:27 +02:00
mo8it
479f45da9b test_dir is a str anyway 2024-08-09 01:05:44 +02:00
mo8it
140c4e4812 Improve initialization in a Cargo workspace 2024-08-09 00:49:30 +02:00
mo8it
337460d299 Check the status of the cargo metadata command 2024-08-09 00:12:49 +02:00
mo8it
e41c3a7c92 Use fixed seeds with ahash 2024-08-08 23:48:54 +02:00
mo8it
1b9faa4d61 Update CHANGELOG 2024-08-08 23:48:54 +02:00
Mo
9f9a754a64 Merge pull request #2076 from senekor/remo/snryotxotoxv
Improve initialization in workspace
2024-08-08 23:48:09 +02:00
Mo
f7b0cfe8d1 Merge pull request #2075 from senekor/remo/swzqnkxqzutw
Replace hashbrown with ahash
2024-08-08 23:12:43 +02:00
mo8it
4ce8667b9d Show the exercise name in the waiting message 2024-08-08 22:48:53 +02:00
mo8it
0785b24192 Show a message before running the exercise 2024-08-08 22:41:41 +02:00
mo8it
34f02cf83d Attach error message as context 2024-08-08 22:37:56 +02:00
Remo Senekowitsch
8b43d79257 Fix integration tests 2024-08-08 14:08:06 +02:00
Remo Senekowitsch
dc086c6bf1 Improve initialization in workspace
- Detect if we are in a cargo project more reliably.
  (e.g. if `rustlings init` is run in the `src/` directory)

- Refuse to initialize rustlings in a non-workspace cargo project.

- Automatically populate the `workspace.members` field if `rustlings init` is
  run in a workspace.

  This may be considered risky, as there is no guarantee that's what the user
  wanted to do. However, it is consistent with the behavior of `cargo new`.
  Also, newcomers to Rust are unlikely to accidentally be in a cargo workspace,
  as they won't know how to create one in the first place.

  The use case for initialization in a workspace is when a workshop organizer
  wants to use rustlings alongside other exerices and provide a single
  repository with everything in one place.
2024-08-08 13:34:27 +02:00
Remo Senekowitsch
dc0ffbe16e Replace hashbrown with ahash
hashbrown is already used in the standard library, but we want the
improved performance of the different hash algorithm.
Using ahash directly conveys this intent more clearly.
2024-08-08 11:12:17 +02:00
mo8it
8df66f7991 Allow initialization in a workspace 2024-08-08 02:45:18 +02:00
mo8it
39580381fa rust-analyzer problem isn't fixed :( 2024-08-08 01:48:57 +02:00
mo8it
06a0f278e5 Don't recommend the builtin VS-Code terminal because it can't clear scrollback 2024-08-08 01:35:47 +02:00
mo8it
fd97470f35 Adapt type name in hint 2024-08-08 00:42:26 +02:00
mo8it
11fc3f1e56 Fix errors not being shown after the welcome message 2024-08-08 00:41:12 +02:00
mo8it
693bb708b2 Add README to the solutions dir 2024-08-08 00:41:12 +02:00
mo8it
97719fe8da Remove state file and solutions dir from .gitignore 2024-08-08 00:41:12 +02:00
mo8it
4933ace50b Add panic = "abort" for exercises 2024-08-08 00:41:12 +02:00
mo8it
81bf0a6430 Remove redundant rustfmt check for solutions 2024-08-08 00:41:12 +02:00
mo8it
24aed1b14e Update CHANGELOG 2024-08-08 00:41:12 +02:00
Mo
09c3ac02f8 Merge pull request #2062 from jimbo5922/jimbo5922-fix-hashmap3-struct-name
update struct name in hashmap3
2024-08-08 00:40:51 +02:00
Mo
45a39585b3 Merge pull request #2066 from matthewjnield/main
chore: Fix snakecase convention in errors6.rs
2024-08-08 00:36:46 +02:00
mo8it
286a455fa9 Avoid using RUSTFLAGS to not trigger rebuilding, especially in rust-analyzer 2024-08-07 23:35:50 +02:00
mo8it
bdf4960b6a Fix exercise name shift in exercise check 2024-08-07 23:25:22 +02:00
mo8it
13124aafe3 Update deps 2024-08-05 03:15:43 +02:00
Matt Nield
2128be8b28 chore: Fix snakecase convention in errors6.rs
Exercise errors6.rs prompts the user to add a method named `from_parseint`. This commit changes the method name to the corrected snakecase format, `from_parse_int`.
2024-08-04 02:36:45 -04:00
mo8it
175294fa5d Add rust-version 2024-08-02 16:40:06 +02:00
mo8it
5016c7cf7c Use trim_ascii instead of trim 2024-08-02 16:28:05 +02:00
mo8it
1468206052 Stop on first exercise solved 2024-08-02 15:54:14 +02:00
mo8it
d1ff4b5cf0 Remove newline 2024-08-01 19:19:25 +02:00
mo8it
700a065abd Fix rustfmt option 2024-08-01 19:19:14 +02:00
mo8it
3fc462f90f Fix tests 2024-08-01 19:17:40 +02:00
mo8it
65a8f6bb4b Run rustfmt on solutions in dev check 2024-08-01 19:14:09 +02:00
mo8it
e0f0944bff Refactor check_solutions 2024-08-01 15:53:32 +02:00
mo8it
c7590dd752 Improve the runner 2024-08-01 15:23:54 +02:00
mo8it
33a5680328 Hide cargo build warnings if there is no output 2024-08-01 11:28:26 +02:00
mo8it
455d87cadd Fix capacity 2024-08-01 11:26:30 +02:00
Yudai Kawabuchi
e65ae09789 fix format 2024-08-01 09:55:25 +09:00
Yudai Kawabuchi
dacdce1ea2 fix: update struct name in hashmap3 2024-08-01 09:47:50 +09:00
mo8it
766f3c50ec Add hint to run dev check again after dev update 2024-08-01 01:07:56 +02:00
mo8it
802b97b2ed Set stdin to null when running the binary of an exercise 2024-08-01 01:07:31 +02:00
mo8it
2ad408f2b8 Update deps 2024-07-31 18:54:24 +02:00
mo8it
c8fddd8f62 Add Github profile links for every author 2024-07-31 18:53:25 +02:00
mo8it
74fab994e2 Make the output optional 2024-07-28 20:30:23 +02:00
mo8it
3a99542f73 Run the final check in parallel 2024-07-28 17:39:46 +02:00
mo8it
2ae9f3555b Update deps 2024-07-28 13:30:31 +02:00
mo8it
1937b4bf66 Use the rexported crossterm from ratatui 2024-07-25 16:26:48 +02:00
mo8it
8beb290842 Test initialization 2024-07-25 16:14:38 +02:00
mo8it
8fec5155c7 Clean up tests 2024-07-25 15:12:14 +02:00
mo8it
3f49decce9 Remove assert_cmd and predicates 2024-07-25 14:34:43 +02:00
mo8it
e2492f65a0 Update deps 2024-07-25 12:51:44 +02:00
mo8it
5116a812fb tests3: Fix panic message 2024-07-22 12:02:59 +02:00
mo8it
82409c060f Update deps 2024-07-22 12:01:41 +02:00
mo8it
183ed3f88f Update dep 2024-07-17 14:33:29 +02:00
mo8it
447ac3c40b strings3: Improve hint 2024-07-17 14:32:45 +02:00
Mo
96f96927da Merge pull request #2050 from yapjiahong/main
doc: enchane string3 exercise hint
2024-07-17 14:31:17 +02:00
yapjiahong
2c79e29483 doc: enchane string3 exercise hint 2024-07-17 00:43:42 +08:00
mo8it
362473dde0 Sync exercise and solution 2024-07-16 18:21:07 +02:00
Mo
8339682112 Merge pull request #2049 from Vexcited/patch-1
fix: Lyche becomes Lychee
2024-07-16 18:18:46 +02:00
Mikkel ALMONTE--RINGAUD
3f06d767b5 fix: Lyche becomes Lychee
Small typo.
2024-07-16 17:20:26 +02:00
mo8it
2854dc9ab3 Update CI and release hook 2024-07-13 12:32:23 +02:00
mo8it
516fcf9168 Update section 2024-07-13 12:07:52 +02:00
mo8it
12d1971b0d Update section about command not found 2024-07-13 12:02:39 +02:00
mo8it
3e09e509d6 Add section about rustlings not found 2024-07-13 12:00:22 +02:00
mo8it
99fb11cc72 Update syn 2024-07-13 11:53:59 +02:00
mo8it
d176ddd27e Improve TODO comment 2024-07-12 16:29:41 +02:00
179 changed files with 5194 additions and 3623 deletions

2
.cargo/config.toml Normal file
View File

@@ -0,0 +1,2 @@
[alias]
dev = ["run", "--", "dev"]

View File

@@ -1,7 +0,0 @@
root = true
[*.rs]
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4

View File

@@ -1,10 +1,18 @@
name: Rustlings Tests
name: Check
on:
push:
branches: [main]
paths-ignore:
- website
- .github/workflows/website.yml
- '*.md'
pull_request:
branches: [main]
paths-ignore:
- website
- .github/workflows/website.yml
- '*.md'
env:
CARGO_TERM_COLOR: always
@@ -13,31 +21,36 @@ jobs:
clippy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: cargo clippy -- --deny warnings
- uses: actions/checkout@v6
- name: Clippy
run: cargo clippy -- --deny warnings
fmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: DavidAnson/markdownlint-cli2-action@v16
with:
globs: "exercises/**/*.md"
- name: Run cargo fmt
run: cargo fmt --all -- --check
- uses: actions/checkout@v6
- name: rustfmt
run: cargo fmt --all --check
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- uses: swatinem/rust-cache@v2
- name: Run cargo test
run: cargo test
- name: cargo test
env:
RUST_BACKTRACE: 1
run: cargo test --workspace
dev-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- uses: swatinem/rust-cache@v2
- name: Run rustlings dev check
run: cargo run -- dev check --require-solutions
- name: rustlings dev check
run: cargo dev check --require-solutions
rumdl:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: rvben/rumdl@v0

View File

@@ -1,87 +0,0 @@
# Workflow to build your docs with oranda (and mdbook)
# and deploy them to Github Pages
name: Web
# We're going to push to the gh-pages branch, so we need that permission
permissions:
contents: write
# What situations do we want to build docs in?
# All of these work independently and can be removed / commented out
# if you don't want oranda/mdbook running in that situation
on:
# Check that a PR didn't break docs!
#
# Note that the "Deploy to Github Pages" step won't run in this mode,
# so this won't have any side-effects. But it will tell you if a PR
# completely broke oranda/mdbook. Sadly we don't provide previews (yet)!
pull_request:
# Whenever something gets pushed to main, update the docs!
# This is great for getting docs changes live without cutting a full release.
#
# Note that if you're using cargo-dist, this will "race" the Release workflow
# that actually builds the Github Release that oranda tries to read (and
# this will almost certainly complete first). As a result you will publish
# docs for the latest commit but the oranda landing page won't know about
# the latest release. The workflow_run trigger below will properly wait for
# cargo-dist, and so this half-published state will only last for ~10 minutes.
#
# If you only want docs to update with releases, disable this, or change it to
# a "release" branch. You can, of course, also manually trigger a workflow run
# when you want the docs to update.
push:
branches:
- main
# Whenever a workflow called "Release" completes, update the docs!
#
# If you're using cargo-dist, this is recommended, as it will ensure that
# oranda always sees the latest release right when it's available. Note
# however that Github's UI is wonky when you use workflow_run, and won't
# show this workflow as part of any commit. You have to go to the "actions"
# tab for your repo to see this one running (the gh-pages deploy will also
# only show up there).
workflow_run:
workflows: [ "Release" ]
types:
- completed
# Alright, let's do it!
jobs:
web:
name: Build and deploy site and docs
runs-on: ubuntu-latest
steps:
# Setup
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: swatinem/rust-cache@v2
# If you use any mdbook plugins, here's the place to install them!
# Install and run oranda (and mdbook)
# This will write all output to ./public/ (including copying mdbook's output to there)
- name: Install and run oranda
run: |
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/oranda/releases/download/v0.3.1/oranda-installer.sh | sh
oranda build
# Deploy to our gh-pages branch (creating it if it doesn't exist)
# the "public" dir that oranda made above will become the root dir
# of this branch.
#
# Note that once the gh-pages branch exists, you must
# go into repo's settings > pages and set "deploy from branch: gh-pages"
# the other defaults work fine.
- name: Deploy to Github Pages
uses: JamesIves/github-pages-deploy-action@v4.4.1
# ONLY if we're on main (so no PRs or feature branches allowed!)
if: ${{ github.ref == 'refs/heads/main' }}
with:
branch: gh-pages
# Gotta tell the action where to find oranda's output
folder: public
token: ${{ secrets.GITHUB_TOKEN }}
single-commit: true

50
.github/workflows/website.yml vendored Normal file
View File

@@ -0,0 +1,50 @@
name: Website
on:
workflow_dispatch:
push:
branches: [main]
paths:
- website
- .github/workflows/website.yml
jobs:
rumdl:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: rvben/rumdl@v0
build:
needs: rumdl
defaults:
run:
working-directory: website
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install TailwindCSS
run: npm install
- name: Build CSS
run: npx @tailwindcss/cli -m -i input.css -o static/main.css
- name: Download Zola
run: curl -fsSL https://github.com/getzola/zola/releases/download/v0.22.1/zola-v0.22.1-x86_64-unknown-linux-gnu.tar.gz | tar xz
- name: Build site
run: ./zola build
- name: Upload static files as artifact
uses: actions/upload-pages-artifact@v5
with:
path: website/public/
deploy:
needs: build
# Grant GITHUB_TOKEN the permissions required to make a Pages deployment
permissions:
pages: write # to deploy to Pages
id-token: write # to verify the deployment originates from an appropriate source
# Deploy to the github-pages environment
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Deploy to GitHub Pages
uses: actions/deploy-pages@v5

4
.gitignore vendored
View File

@@ -6,10 +6,6 @@ Cargo.lock
# State file
.rustlings-state.txt
# oranda
public/
.netlify
# OS
.DS_Store
.direnv/

View File

@@ -1,2 +0,0 @@
# MD013/line-length Line length, Expected: 80
MD013: false

7
.rumdl.toml Normal file
View File

@@ -0,0 +1,7 @@
[global]
output-format = "full"
disable = ["MD013", "MD057"]
[per-file-ignores]
"website/content/_index.md" = ["MD041"]
"website/content/**/*.md" = ["MD028", "MD033"]

View File

@@ -1,7 +1,7 @@
[default.extend-words]
"earch" = "earch" # Because of <s>earch in the list footer
[files]
extend-exclude = [
"CHANGELOG.md",
]
[default.extend-words]
"ratatui" = "ratatui"

View File

@@ -1,31 +1,154 @@
<a name="6.1.0"></a>
# Changelog
## Unreleased
### Added
- Automatically open the current file if Rustlings is running in a VS Code terminal
- Automatically open the current file with `$EDITOR` in a new pane if Rustlings is running in [Zellij](https://zellij.dev)
- New argument `--no-editor` to disable automatic opening of the current file in VS Code or Zellij
- New argument `--edit-cmd` to communicate with an editor running in a different process to open the current exercise
- Show the file link of the current exercise when running `rustlings hint` and `rustlings reset`
### Fixed
- Fix integer overflow on big terminal widths [@gabfec](https://github.com/gabfec)
- Fix workspace detection on Windows [@senekor](https://github.com/senekor)
### Changed
- Avoid initializing a nested Git repository [@senekor](https://github.com/senekor)
- `vecs2`: Removed the use of `map` and `collect`, which are only taught later.
- `structs3`: Rewrote the exercise to make users type method syntax themselves.
- Rename the exercises for smart pointers and conversions so they're sorted alphabetically. [@foxfromworld](https://github.com/foxfromworld)
- `vecs1`: Remove array literal. Some learners assumed their task is to convert it to a vector.
- `conversions2`: Redesign the context such that infallible conversion makes sense.
## 6.5.0 (2025-08-21)
### Added
- Check that Clippy is installed before initialization
### Changed
- Upgrade to Rust edition 2024
- Raise the minimum supported Rust version to `1.88`
- Don't follow symlinks in the file watcher
- `dev new`: Don't add `.rustlings-state.txt` to `.gitignore`
### Fixed
- Fix file links in VS Code
- Fix error printing when the progress bar is shown
- `dev check`: Don't check formatting if there are no solution files
## 6.4.0 (2024-11-11)
### Added
- The list of exercises is now searchable by pressing `s` or `/` 🔍️ (thanks to [@frroossst](https://github.com/frroossst))
- New option `c` in the prompt to manually check all exercises ✅ (thanks to [@Nahor](https://github.com/Nahor))
- New command `check-all` to manually check all exercises ✅ (thanks to [@Nahor](https://github.com/Nahor))
- Addictive animation for showing the progress of checking all exercises. A nice showcase of parallelism in Rust ✨
- New option `x` in the prompt to reset the file of the current exercise 🔄
- Allow `dead_code` for all exercises and solutions ⚰️ (thanks to [@huss4in](https://github.com/huss4in))
- Pause input while running an exercise to avoid unexpected prompt interactions ⏸️
- Limit the maximum number of exercises to 999. Any community exercises willing to reach that limit? 🔝
### Changed
- `enums3`: Remove redundant enum definition task (thanks to [@senekor](https://github.com/senekor))
- `if2`: Make the exercise less confusing by avoiding "fizz", "fuzz", "foo", "bar" and "baz" (thanks to [@senekor](https://github.com/senekor))
- `hashmap3`: Use the method `Entry::or_default`.
- Update the state of all exercises when checking all of them (thanks to [@Nahor](https://github.com/Nahor))
- The main prompt doesn't need a confirmation with ENTER on Unix-like systems anymore.
- No more jumping back to a previous exercise when its file is changed. Use the list to jump between exercises.
- Dump the solution file after an exercise is done even if the solution's directory doesn't exist.
- Rework the footer in the list.
- Optimize the file watcher.
### Fixed
- Fix bad contrast in the list on terminals with a light theme.
## 6.3.0 (2024-08-29)
### Added
- Add the following exercise lints:
- `forbid(unsafe_code)`: You shouldn't write unsafe code in Rustlings.
- `forbid(unstable_features)`: You don't need unstable features in Rustlings and shouldn't rely on them while learning Rust.
- `forbid(todo)`: You forgot a `todo!()`.
- `forbid(empty_loop)`: This can only happen by mistake in Rustlings.
- `deny(infinite_loop)`: No infinite loops are needed in Rustlings.
- `deny(mem_forget)`: You shouldn't leak memory while still learning Rust.
- Show a link to every exercise file in the list.
- Add scroll padding in the list.
- Break the help footer of the list into two lines when the terminal width isn't big enough.
- Enable scrolling with the mouse in the list.
- `dev check`: Show the progress of checks.
- `dev check`: Check that the length of all exercise names is lower than 32.
- `dev check`: Check if exercise contains no tests and isn't marked with `test = false`.
### Changed
- The compilation time when installing Rustlings is reduced.
- Pressing `c` in the list for "continue on" now quits the list after setting the selected exercise as the current one.
- Better highlighting of the solution file after an exercise is done.
- Don't show the output of successful tests anymore. Instead, show the pretty output for tests.
- Be explicit about `q` only quitting the list and not the whole program in the list.
- Be explicit about `r` only resetting one exercise (the selected one) in the list.
- Ignore the standard output of `git init`.
- `threads3`: Remove the queue length and improve tests.
- `errors4`: Use match instead of a comparison chain in the solution.
- `functions3`: Only take `u8` to avoid using a too high number of iterations by mistake.
- `dev check`: Always check with strict Clippy (warnings to errors) when checking the solutions.
### Fixed
- Fix the error on some systems about too many open files during the final check of all exercises.
- Fix the list when the terminal height is too low.
- Restore the terminal after an error in the list.
## 6.2.0 (2024-08-09)
### Added
- Show a message before checking and running an exercise. This gives the user instant feedback and avoids confusion if the checks take too long.
- Show a helpful error message when trying to install Rustlings with a Rust version lower than the minimum one that Rustlings supports.
- Add a `README.md` file to the `solutions/` directory.
- Allow initializing Rustlings in a Cargo workspace.
- `dev check`: Check that all solutions are formatted with `rustfmt`.
### Changed
- Remove the state file and the solutions directory from the generated `.gitignore` file.
- Run the final check of all exercises in parallel.
- Small exercise improvements.
## 6.1.0 (2024-07-10)
#### Added
### Added
- `dev check`: Check that all exercises (including third-party ones) include at least one `TODO` comment.
- `dev check`: Check that all exercises (including community ones) include at least one `TODO` comment.
- `dev check`: Check that all exercises actually fail to run (not already solved).
#### Changed
### Changed
- Make enum variants more consistent between enum exercises.
- `iterators3`: Teach about the possible case of integer overflow during division.
#### Fixed
### Fixed
- Exit with a helpful error message on missing/unsupported terminal/TTY.
- Mark the last exercise as done.
<a name="6.0.1"></a>
## 6.0.1 (2024-07-04)
Small exercise improvements and fixes.
Most importantly, fixed that the exercise `clippy1` was already solved 😅
<a name="6.0.0"></a>
## 6.0.0 (2024-07-03)
This release is the result of a complete rewrite to deliver a ton of new features and improvements ✨
@@ -54,7 +177,7 @@ You can read about the motivations of this change in [this issue](https://github
### List mode
A list mode was added using [Ratatui](https://ratatui.rs).
A new list mode was added!
You can enter it by entering `l` in the watch mode.
It offers the following features:
@@ -83,23 +206,21 @@ This should avoid issues related to the language server or to running exercises,
Clippy lints are now shown on all exercises, not only the Clippy exercises 📎
Make Clippy your friend from early on 🥰
### Third-party exercises
### Community Exercises
Rustlings now supports third-party exercises!
Rustlings now supports community exercises!
Do you want to create your own set of Rustlings exercises to focus on some specific topic?
Or do you want to translate the original Rustlings exercises?
Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXERCISES.md)!
<a name="5.6.1"></a>
Then follow the link to the guide about [community exercises](https://rustlings.rust-lang.org/community-exercises)!
## 5.6.1 (2023-09-18)
#### Changed
### Changed
- Converted all exercises with assertions to test mode.
#### Fixed
### Fixed
- `cow1`: Reverted regression introduced by calling `to_mut` where it
shouldn't have been called, and clarified comment.
@@ -108,11 +229,9 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- `as_ref_mut`: Fixed a typo in a test function name.
- `enums3`: Fixed formatting with `rustfmt`.
<a name="5.6.0"></a>
## 5.6.0 (2023-09-04)
#### Added
### Added
- New exercise: `if3`, teaching the user about `if let` statements.
- `hashmaps2`: Added an extra test function to check if the amount of fruits is higher than zero.
@@ -120,7 +239,7 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- `if1`: Added a test case to check equal values.
- `if3`: Added a note specifying that there are no test changes needed.
#### Changed
### Changed
- Swapped the order of threads and smart pointer exercises.
- Rewrote the CLI to use `clap` - it's matured much since we switched to `argh` :)
@@ -128,7 +247,7 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- `move_semantics`: Switched 1-4 to tests, and rewrote them to be way simpler, while still teaching about the same
concepts.
#### Fixed
### Fixed
- `iterators5`:
- Removed an outdated part of the hint.
@@ -143,25 +262,21 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- `cow1`: Added `.to_mut()` to distinguish from the previous test case.
- `threads2`: Updated hint text to reference the correct book heading.
#### Housekeeping
### Housekeeping
- Cleaned up the explanation paragraphs at the start of each exercise.
- Lots of Nix housekeeping that I don't feel qualified to write about!
- Improved CI workflows, we're now testing on multiple platforms at once.
<a name="5.5.1"></a>
## 5.5.1 (2023-05-17)
#### Fixed
### Fixed
- Reverted `rust-project.json` path generation due to an upstream `rust-analyzer` fix.
<a name="5.5.0"></a>
## 5.5.0 (2023-05-17)
#### Added
### Added
- `strings2`: Added a reference to the book chapter for reference conversion
- `lifetimes`: Added a link to the lifetimekata project
@@ -169,7 +284,7 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- Added a `!` prefix command to watch mode that runs an external command
- Added a `--success-hints` option to watch mode that shows hints on exercise success
#### Changed
### Changed
- `vecs2`: Renamed iterator variable bindings for clarify
- `lifetimes`: Changed order of book references
@@ -178,7 +293,7 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- `options2`: Improved tests for layering options
- `modules2`: Added more information to the hint
#### Fixed
### Fixed
- `errors2`: Corrected a comment wording
- `iterators2`: Fixed a spelling mistake in the hint text
@@ -188,33 +303,29 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- `options3`: Changed exercise to panic when no match is found
- `rustlings lsp` now generates absolute paths, which should fix VSCode `rust-analyzer` usage on Windows
#### Housekeeping
### Housekeeping
- Added a markdown linter to run on GitHub actions
- Split quick installation section into two code blocks
<a name="5.4.1"></a>
## 5.4.1 (2023-03-10)
#### Changed
### Changed
- `vecs`: Added links to `iter_mut` and `map` to README.md
- `cow1`: Changed main to tests
- `iterators1`: Formatted according to rustfmt
#### Fixed
### Fixed
- `errors5`: Unified undisclosed type notation
- `arc1`: Improved readability by avoiding implicit dereference
- `macros4`: Prevented auto-fix by adding `#[rustfmt::skip]`
- `cli`: Actually show correct progress percentages
<a name="5.4.0"></a>
## 5.4.0 (2023-02-12)
#### Changed
### Changed
- Reordered exercises
- Unwrapped `standard_library_types` into `iterators` and `smart_pointers`
@@ -226,7 +337,7 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- Made progress bar update proportional to amount of files verified
- Decreased `watch` delay from 2 to 1 second
#### Fixed
### Fixed
- Capitalized "Rust" in exercise hints
- **enums3**: Removed superfluous tuple brackets
@@ -236,25 +347,23 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- Fixed a typo in a method name
- Specified the edition in `rustc` commands
#### Housekeeping
### Housekeeping
- Bumped min Rust version to 1.58 in installation script
<a name="5.3.0"></a>
## 5.3.0 (2022-12-23)
#### Added
### Added
- **cli**: Added a percentage display in watch mode
- Added a `flake.nix` for Nix users
#### Changed
### Changed
- **structs3**: Added an additional test
- **macros**: Added a link to MacroKata in the README
#### Fixed
### Fixed
- **strings3**: Added a link to `std` in the hint
- **threads1**: Corrected a hint link
@@ -268,63 +377,55 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- **enums2**: Removed unnecessary indirection of self
- **enums3**: Added an extra tuple comment
#### Housekeeping
### Housekeeping
- Added a VSCode extension recommendation
- Applied some Clippy and rustfmt formatting
- Added a note on Windows PowerShell and other shell compatibility
<a name="5.2.1"></a>
## 5.2.1 (2022-09-06)
#### Fixed
### Fixed
- **quiz1**: Reworded the comment to actually reflect what's going on in the tests.
Also added another assert just to make sure.
- **rc1**: Fixed a typo in the hint.
- **lifetimes**: Add quotes to the `println!` output, for readability.
#### Housekeeping
### Housekeeping
- Fixed a typo in README.md
<a name="5.2.0"></a>
## 5.2.0 (2022-08-27)
#### Added
### Added
- Added a `reset` command
#### Changed
### Changed
- **options2**: Convert the exercise to use tests
#### Fixed
### Fixed
- **threads3**: Fixed a typo
- **quiz1**: Adjusted the explanations to be consistent with
the tests
<a name="5.1.1"></a>
## 5.1.1 (2022-08-17)
#### Bug Fixes
### Bug Fixes
- Fixed an incorrect assertion in options1
<a name="5.1.0"></a>
## 5.1.0 (2022-08-16)
#### Features
### Features
- Added a new `rc1` exercise.
- Added a new `cow1` exercise.
#### Bug Fixes
### Bug Fixes
- **variables5**: Corrected reference to previous exercise
- **functions4**: Fixed line number reference
@@ -344,18 +445,16 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- Added more granular tests
- Fixed some comment syntax shenanigans in info.toml
#### Housekeeping
### Housekeeping
- Fixed a typo in .editorconfig
- Fixed a typo in integration_tests.rs
- Clarified manual installation instructions using `cargo install --path .`
- Added a link to our Zulip in the readme file
<a name="5.0.0"></a>
## 5.0.0 (2022-07-16)
#### Features
### Features
- Hint comments in exercises now also include a reference to the
`hint` watch mode subcommand.
@@ -387,7 +486,7 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- Added 3 new lifetimes exercises.
- Added 3 new traits exercises.
#### Bug Fixes
### Bug Fixes
- **variables2**: Made output messages more verbose.
- **variables5**: Added a nudging hint about shadowing.
@@ -411,7 +510,7 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
`Box<dyn Error>`.
- **try_from_into**: Fixed the function name in comment.
#### Removed
### Removed
- Removed the legacy LSP feature that was using `mod.rs` files.
- Removed `quiz4`.
@@ -419,67 +518,61 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
order, and I've always felt like they didn't quite fit in with the mostly
simple, book-following style we've had in Rustlings.
#### Housekeeping
### Housekeeping
- Added missing exercises to the book index.
- Updated spacing in Cargo.toml.
- Added a GitHub actions config so that tests run on every PR/commit.
<a name="4.8.0"></a>
## 4.8.0 (2022-07-01)
#### Features
### Features
- Added a progress indicator for `rustlings watch`.
- The installation script now checks for Rustup being installed.
- Added a `rustlings lsp` command to enable `rust-analyzer`.
#### Bug Fixes
### Bug Fixes
- **move_semantics5**: Replaced "in vogue" with "in scope" in hint.
- **if2**: Fixed a typo in the hint.
- **variables1**: Fixed an incorrect line reference in the hint.
- Fixed an out of bounds check in the installation Bash script.
#### Housekeeping
### Housekeeping
- Replaced the git.io URL with the fully qualified URL because of git.io's sunsetting.
- Removed the deprecated Rust GitPod extension.
<a name="4.7.1"></a>
## 4.7.1 (2022-04-20)
#### Features
### Features
- The amount of dependency crates that need to be compiled went down from ~65 to
~45 by bumping dependency versions.
- The minimum Rust version in the install scripts has been bumped to 1.56.0 (this isn't in
the release itself, since install scripts don't really get versioned)
#### Bug Fixes
### Bug Fixes
- **arc1**: A small part has been rewritten using a more functional code style (#968).
- **using_as**: A small part has been refactored to use `sum` instead of `fold`, resulting
in better readability.
#### Housekeeping
### Housekeeping
- The changelog will now be manually written instead of being automatically generated by the
Git log.
<a name="4.7.0"></a>
## 4.7.0 (2022-04-14)
#### Features
### Features
- Add move_semantics6.rs exercise (#908) ([3f0e1303](https://github.com/rust-lang/rustlings/commit/3f0e1303e0b3bf3fecc0baced3c8b8a37f83c184))
- **intro:** Add intro section. ([21c9f441](https://github.com/rust-lang/rustlings/commit/21c9f44168394e08338fd470b5f49b1fd235986f))
- Include exercises folder in the project structure behind a feature, enabling rust-analyzer to work (#917) ([179a75a6](https://github.com/rust-lang/rustlings/commit/179a75a68d03ac9518dec2297fb17f91a4fc506b))
#### Bug Fixes
### Bug Fixes
- Fix a few spelling mistakes ([1c0fe3cb](https://github.com/rust-lang/rustlings/commit/1c0fe3cbcca85f90b3985985b8e265ee872a2ab2))
- **cli:**
@@ -506,16 +599,14 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- **structs3.rs:** assigned value to cents_per_gram in test ([d1ee2daf](https://github.com/rust-lang/rustlings/commit/d1ee2daf14f19105e6db3f9c610f44293d688532))
- **traits1:** rename test functions to snake case (#854) ([1663a16e](https://github.com/rust-lang/rustlings/commit/1663a16eade6ca646b6ed061735f7982434d530d))
#### Documentation improvements
### Documentation improvements
- Add hints on how to get GCC installed (#741) ([bc56861](https://github.com/rust-lang/rustlings/commit/bc5686174463ad6f4f6b824b0e9b97c3039d4886))
- Fix some code blocks that were not highlighted ([17f9d74](https://github.com/rust-lang/rustlings/commit/17f9d7429ccd133a72e815fb5618e0ce79560929))
<a name="4.6.0"></a>
## 4.6.0 (2021-09-25)
#### Features
### Features
- add advanced_errs2 ([abd6b70c](https://github.com/rust-lang/rustlings/commit/abd6b70c72dc6426752ff41f09160b839e5c449e))
- add advanced_errs1 ([882d535b](https://github.com/rust-lang/rustlings/commit/882d535ba8628d5e0b37e8664b3e2f26260b2671))
@@ -524,7 +615,7 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- **modules:** update exercises, add modules3 (#822) ([dfd2fab4](https://github.com/rust-lang/rustlings/commit/dfd2fab4f33d1bf59e2e5ee03123c0c9a67a9481))
- **quiz1:** add default function name in comment (#838) ([0a11bad7](https://github.com/rust-lang/rustlings/commit/0a11bad71402b5403143d642f439f57931278c07))
#### Bug Fixes
### Bug Fixes
- Correct small typo in exercises/conversions/from_str.rs ([86cc8529](https://github.com/rust-lang/rustlings/commit/86cc85295ae36948963ae52882e285d7e3e29323))
- **cli:** typo in exercise.rs (#848) ([06d5c097](https://github.com/rust-lang/rustlings/commit/06d5c0973a3dffa3c6c6f70acb775d4c6630323c))
@@ -535,16 +626,14 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- Clarify instructions ([df25684c](https://github.com/rust-lang/rustlings/commit/df25684cb79f8413915e00b5efef29369849cef1))
- **quiz1:** Fix inconsistent wording (#826) ([03131a3d](https://github.com/rust-lang/rustlings/commit/03131a3d35d9842598150f9da817f7cc26e2669a))
<a name="4.5.0"></a>
## 4.5.0 (2021-07-07)
#### Features
### Features
- Add move_semantics5 exercise. (#746) ([399ab328](https://github.com/rust-lang/rustlings/commit/399ab328d8d407265c09563aa4ef4534b2503ff2))
- **cli:** Add "next" to run the next unsolved exercise. (#785) ([d20e413a](https://github.com/rust-lang/rustlings/commit/d20e413a68772cd493561f2651cf244e822b7ca5))
#### Bug Fixes
### Bug Fixes
- rename result1 to errors4 ([50ab289d](https://github.com/rust-lang/rustlings/commit/50ab289da6b9eb19a7486c341b00048c516b88c0))
- move_semantics5 hints ([1b858285](https://github.com/rust-lang/rustlings/commit/1b85828548f46f58b622b5e0c00f8c989f928807))
@@ -557,11 +646,9 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- **try_from_into, from_str:** hints for dyn Error ([11d2cf0d](https://github.com/rust-lang/rustlings/commit/11d2cf0d604dee3f5023c17802d69438e69fa50e))
- **variables5:** confine the answer further ([48ffcbd2](https://github.com/rust-lang/rustlings/commit/48ffcbd2c4cc4d936c2c7480019190f179813cc5))
<a name="4.4.0"></a>
## 4.4.0 (2021-04-24)
#### Bug Fixes
### Bug Fixes
- Fix spelling error in main.rs ([91ee27f2](https://github.com/rust-lang/rustlings/commit/91ee27f22bd3797a9db57e5fd430801c170c5db8))
- typo in default out text ([644c49f1](https://github.com/rust-lang/rustlings/commit/644c49f1e04cbb24e95872b3a52b07d692ae3bc8))
@@ -589,7 +676,7 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- **threads1:** line number correction ([7857b0a6](https://github.com/rust-lang/rustlings/commit/7857b0a689b0847f48d8c14cbd1865e3b812d5ca))
- **try_from_into:** use trait objects ([2e93a588](https://github.com/rust-lang/rustlings/commit/2e93a588e0abe8badb7eafafb9e7d073c2be5df8))
#### Features
### Features
- Replace clap with argh ([7928122f](https://github.com/rust-lang/rustlings/commit/7928122fcef9ca7834d988b1ec8ca0687478beeb))
- Replace emojis when NO_EMOJI env variable present ([8d62a996](https://github.com/rust-lang/rustlings/commit/8d62a9963708dbecd9312e8bcc4b47049c72d155))
@@ -600,11 +687,9 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- updated progress percentage ([1c6f7e4b](https://github.com/rust-lang/rustlings/commit/1c6f7e4b7b9b3bd36f4da2bb2b69c549cc8bd913))
- added progress info ([c0e3daac](https://github.com/rust-lang/rustlings/commit/c0e3daacaf6850811df5bc57fa43e0f249d5cfa4))
<a name="4.3.0"></a>
## 4.3.0 (2020-12-29)
#### Features
### Features
- Rewrite default out text ([44d39112](https://github.com/rust-lang/rustlings/commit/44d39112ff122b29c9793fe52e605df1612c6490))
- match exercise order to book chapters (#541) ([033bf119](https://github.com/rust-lang/rustlings/commit/033bf1198fc8bfce1b570e49da7cde010aa552e3))
@@ -612,7 +697,7 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- add "rustlings list" command ([838f9f30](https://github.com/rust-lang/rustlings/commit/838f9f30083d0b23fd67503dcf0fbeca498e6647))
- **try_from_into:** remove duplicate annotation ([04f1d079](https://github.com/rust-lang/rustlings/commit/04f1d079aa42a2f49af694bc92c67d731d31a53f))
#### Bug Fixes
### Bug Fixes
- update structs README ([bcf14cf6](https://github.com/rust-lang/rustlings/commit/bcf14cf677adb3a38a3ac3ca53f3c69f61153025))
- added missing exercises to info.toml ([90cfb6ff](https://github.com/rust-lang/rustlings/commit/90cfb6ff28377531bfc34acb70547bdb13374f6b))
@@ -624,18 +709,16 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- Update description (#584) ([96347df9](https://github.com/rust-lang/rustlings/commit/96347df9df294f01153b29d9ad4ba361f665c755))
- **vec1:** Have test compare every element in a and v ([9b6c6293](https://github.com/rust-lang/rustlings/commit/9b6c629397b24b944f484f5b2bbd8144266b5695))
<a name="4.2.0"></a>
## 4.2.0 (2020-11-07)
#### Features
### Features
- Add HashMap exercises ([633c00cf](https://github.com/rust-lang/rustlings/commit/633c00cf8071e1e82959a3010452a32f34f29fc9))
- Add Vec exercises ([0c12fa31](https://github.com/rust-lang/rustlings/commit/0c12fa31c57c03c6287458a0a8aca7afd057baf6))
- **primitive_types6:** Add a test (#548) ([2b1fb2b7](https://github.com/rust-lang/rustlings/commit/2b1fb2b739bf9ad8d6b7b12af25fee173011bfc4))
- **try_from_into:** Add tests (#571) ([95ccd926](https://github.com/rust-lang/rustlings/commit/95ccd92616ae79ba287cce221101e0bbe4f68cdc))
#### Bug Fixes
### Bug Fixes
- log error output when inotify limit is exceeded ([d61b4e5a](https://github.com/rust-lang/rustlings/commit/d61b4e5a13b44d72d004082f523fa1b6b24c1aca))
- more unique temp_file ([5643ef05](https://github.com/rust-lang/rustlings/commit/5643ef05bc81e4a840e9456f4406a769abbe1392))
@@ -646,11 +729,9 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- missing comma in test ([4fb230da](https://github.com/rust-lang/rustlings/commit/4fb230daf1251444fcf29e085cee222a91f8a37e))
- **quiz3:** Second test is for odd numbers, not even. (#553) ([18e0bfef](https://github.com/rust-lang/rustlings/commit/18e0bfef1de53071e353ba1ec5837002ff7290e6))
<a name="4.1.0"></a>
## 4.1.0 (2020-10-05)
#### Bug Fixes
### Bug Fixes
- Update rustlings version in Cargo.lock ([1cc40bc9](https://github.com/rust-lang/rustlings/commit/1cc40bc9ce95c23d56f6d91fa1c4deb646231fef))
- **arc1:** index mod should equal thread count ([b4062ef6](https://github.com/rust-lang/rustlings/commit/b4062ef6993e80dac107c4093ea85166ad3ee0fa))
@@ -660,7 +741,7 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- **structs3:** Small adjustment of variable name ([114b54cb](https://github.com/rust-lang/rustlings/commit/114b54cbdb977234b39e5f180d937c14c78bb8b2))
- **using_as:** Add test so that proper type is returned. (#512) ([3286c5ec](https://github.com/rust-lang/rustlings/commit/3286c5ec19ea5fb7ded81d047da5f8594108a490))
#### Features
### Features
- Added iterators1.rs exercise ([9642f5a3](https://github.com/rust-lang/rustlings/commit/9642f5a3f686270a4f8f6ba969919ddbbc4f7fdd))
- Add ability to run rustlings on repl.it (#471) ([8f7b5bd0](https://github.com/rust-lang/rustlings/commit/8f7b5bd00eb83542b959830ef55192d2d76db90a))
@@ -670,16 +751,14 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- **cli:** Added 'cls' command to 'watch' mode (#474) ([4f2468e1](https://github.com/rust-lang/rustlings/commit/4f2468e14f574a93a2e9b688367b5752ed96ae7b))
- **try_from_into:** Add insufficient length test (#469) ([523d18b8](https://github.com/rust-lang/rustlings/commit/523d18b873a319f7c09262f44bd40e2fab1830e5))
<a name="4.0.0"></a>
## 4.0.0 (2020-07-08)
#### Breaking Changes
### Breaking Changes
- Add a --nocapture option to display test harnesses' outputs ([8ad5f9bf](https://github.com/rust-lang/rustlings/commit/8ad5f9bf531a4848b1104b7b389a20171624c82f))
- Rename test to quiz, fixes #244 ([010a0456](https://github.com/rust-lang/rustlings/commit/010a04569282149cea7f7a76fc4d7f4c9f0f08dd))
#### Features
### Features
- Add traits README ([173bb141](https://github.com/rust-lang/rustlings/commit/173bb14140c5530cbdb59e53ace3991a99d804af))
- Add box1.rs exercise ([7479a473](https://github.com/rust-lang/rustlings/commit/7479a4737bdcac347322ad0883ca528c8675e720))
@@ -688,7 +767,7 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- Added exercise structs3.rs ([b66e2e09](https://github.com/rust-lang/rustlings/commit/b66e2e09622243e086a0f1258dd27e1a2d61c891))
- Add exercise variables6 covering const (#352) ([5999acd2](https://github.com/rust-lang/rustlings/commit/5999acd24a4f203292be36e0fd18d385887ec481))
#### Bug Fixes
### Bug Fixes
- Change then to than ([ddd98ad7](https://github.com/rust-lang/rustlings/commit/ddd98ad75d3668fbb10eff74374148aa5ed2344d))
- rename quiz1 to tests1 in info (#420) ([0dd1c6ca](https://github.com/rust-lang/rustlings/commit/0dd1c6ca6b389789e0972aa955fe17aa15c95f29))
@@ -713,15 +792,13 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- **test2:** name of type String and &str (#394) ([d6c0a688](https://github.com/rust-lang/rustlings/commit/d6c0a688e6a96f93ad60d540d4b326f342fc0d45))
- **variables6:** minor typo (#419) ([524e17df](https://github.com/rust-lang/rustlings/commit/524e17df10db95f7b90a0f75cc8997182a8a4094))
<a name="3.0.0"></a>
## 3.0.0 (2020-04-11)
#### Breaking Changes
### Breaking Changes
- make "compile" exercises print output (#278) ([3b6d5c](https://github.com/fmoko/rustlings/commit/3b6d5c3aaa27a242a832799eb66e96897d26fde3))
#### Bug Fixes
### Bug Fixes
- **primitive_types:** revert primitive_types4 (#296) ([b3a3351e](https://github.com/rust-lang/rustlings/commit/b3a3351e8e6a0bdee07077d7b0382953821649ae))
- **run:** compile clippy exercise files (#295) ([3ab084a4](https://github.com/rust-lang/rustlings/commit/3ab084a421c0f140ae83bf1fc3f47b39342e7373))
@@ -730,32 +807,28 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- remove duplicate not done comment (#292) ([dab90f](https://github.com/fmoko/rustlings/commit/dab90f7b91a6000fe874e3d664f244048e5fa342))
- don't hardcode documentation version for traits (#288) ([30e6af](https://github.com/fmoko/rustlings/commit/30e6af60690c326fb5d3a9b7335f35c69c09137d))
#### Features
### Features
- add Option2 exercise (#290) ([86b5c08b](https://github.com/rust-lang/rustlings/commit/86b5c08b9bea1576127a7c5f599f5752072c087d))
- add exercise for option (#282) ([135e5d47](https://github.com/rust-lang/rustlings/commit/135e5d47a7c395aece6f6022117fb20c82f2d3d4))
- add new exercises for generics (#280) ([76be5e4e](https://github.com/rust-lang/rustlings/commit/76be5e4e991160f5fd9093f03ee2ba260e8f7229))
- **ci:** add buildkite config ([b049fa2c](https://github.com/rust-lang/rustlings/commit/b049fa2c84dba0f0c8906ac44e28fd45fba51a71))
<a name="2.2.1"></a>
## 2.2.1 (2020-02-27)
### 2.2.1 (2020-02-27)
#### Bug Fixes
### Bug Fixes
- Re-add cloning the repo to install scripts ([3d9b03c5](https://github.com/rust-lang/rustlings/commit/3d9b03c52b8dc51b140757f6fd25ad87b5782ef5))
#### Features
### Features
- Add clippy lints (#269) ([1e2fd9c9](https://github.com/rust-lang/rustlings/commit/1e2fd9c92f8cd6e389525ca1a999fca4c90b5921))
<a name="2.2.0"></a>
## 2.2.0 (2020-02-25)
#### Bug Fixes
### Bug Fixes
- Update deps to version compatable with aarch64-pc-windows (#263) ([19a93428](https://github.com/rust-lang/rustlings/commit/19a93428b3c73d994292671f829bdc8e5b7b3401))
- Update deps to version compatible with aarch64-pc-windows (#263) ([19a93428](https://github.com/rust-lang/rustlings/commit/19a93428b3c73d994292671f829bdc8e5b7b3401))
- **docs:**
- Added a necessary step to Windows installation process (#242) ([3906efcd](https://github.com/rust-lang/rustlings/commit/3906efcd52a004047b460ed548037093de3f523f))
- Fixed mangled sentence from book; edited for clarity (#266) ([ade52ff](https://github.com/rust-lang/rustlings/commit/ade52ffb739987287ddd5705944c8777705faed9))
@@ -768,7 +841,7 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- Change test command ([fe10e06c](https://github.com/rust-lang/rustlings/commit/fe10e06c3733ddb4a21e90d09bf79bfe618e97ce)
- Correct test command in tests1.rs comment (#263) ([39fa7ae](https://github.com/rust-lang/rustlings/commit/39fa7ae8b70ad468da49b06f11b2383135a63bcf))
#### Features
### Features
- Add variables5.rs exercise (#264) ([0c73609e](https://github.com/rust-lang/rustlings/commit/0c73609e6f2311295e95d6f96f8c747cfc4cba03))
- Show a completion message when watching (#253) ([d25ee55a](https://github.com/rust-lang/rustlings/commit/d25ee55a3205882d35782e370af855051b39c58c))
@@ -778,11 +851,9 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- Added traits exercises (#274 but specifically #216, which originally added
this :heart:) ([b559cdd](https://github.com/rust-lang/rustlings/commit/b559cdd73f32c0d0cfc1feda39f82b3e3583df17))
<a name="2.1.0"></a>
## 2.1.0 (2019-11-27)
#### Bug Fixes
### Bug Fixes
- add line numbers in several exercises and hints ([b565c4d3](https://github.com/rust-lang/rustlings/commit/b565c4d3e74e8e110bef201a082fa1302722a7c3))
- **arc1:** Fix some words in the comment ([c42c3b21](https://github.com/rust-lang/rustlings/commit/c42c3b2101df9164c8cd7bb344def921e5ba3e61))
@@ -793,37 +864,33 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- **strings2:** update line number in hint ([a09f684f](https://github.com/rust-lang/rustlings/commit/a09f684f05c58d239a6fc59ec5f81c2533e8b820))
- **variables1:** Correct wrong word in comment ([fda5a470](https://github.com/rust-lang/rustlings/commit/fda5a47069e0954f16a04e8e50945e03becb71a5))
#### Features
### Features
- **watch:** show hint while watching ([8143d57b](https://github.com/rust-lang/rustlings/commit/8143d57b4e88c51341dd4a18a14c536042cc009c))
<a name="2.0.0"></a>
## 2.0.0 (2019-11-12)
#### Bug Fixes
### Bug Fixes
- **default:** Clarify the installation procedure ([c371b853](https://github.com/rust-lang/rustlings/commit/c371b853afa08947ddeebec0edd074b171eeaae0))
- **info:** Fix trailing newlines for hints ([795b6e34](https://github.com/rust-lang/rustlings/commit/795b6e348094a898e9227a14f6232f7bb94c8d31))
- **run:** make `run` never prompt ([4b265465](https://github.com/rust-lang/rustlings/commit/4b26546589f7d2b50455429482cf1f386ceae8b3))
#### Breaking Changes
### Breaking Changes
- Refactor hint system ([9bdb0a12](https://github.com/rust-lang/rustlings/commit/9bdb0a12e45a8e9f9f6a4bd4a9c172c5376c7f60))
- improve `watch` execution mode ([2cdd6129](https://github.com/rust-lang/rustlings/commit/2cdd61294f0d9a53775ee24ad76435bec8a21e60))
- Index exercises by name ([627cdc07](https://github.com/rust-lang/rustlings/commit/627cdc07d07dfe6a740e885e0ddf6900e7ec336b))
- **run:** makes `run` never prompt ([4b265465](https://github.com/rust-lang/rustlings/commit/4b26546589f7d2b50455429482cf1f386ceae8b3))
#### Features
### Features
- **cli:** check for rustc before doing anything ([36a033b8](https://github.com/rust-lang/rustlings/commit/36a033b87a6549c1e5639c908bf7381c84f4f425))
- **hint:** Add test for hint ([ce9fa6eb](https://github.com/rust-lang/rustlings/commit/ce9fa6ebbfdc3e7585d488d9409797285708316f))
<a name="1.5.1"></a>
## 1.5.1 (2019-11-11)
### 1.5.1 (2019-11-11)
#### Bug Fixes
### Bug Fixes
- **errors3:** Update hint ([dcfb427b](https://github.com/rust-lang/rustlings/commit/dcfb427b09585f0193f0a294443fdf99f11c64cb), closes [#185](https://github.com/rust-lang/rustlings/issues/185))
- **if1:** Remove `return` reference ([ad03d180](https://github.com/rust-lang/rustlings/commit/ad03d180c9311c0093e56a3531eec1a9a70cdb45))
@@ -832,11 +899,9 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- **threads:** Move Threads behind SLT ([fbe91a67](https://github.com/rust-lang/rustlings/commit/fbe91a67a482bfe64cbcdd58d06ba830a0f39da3), closes [#205](https://github.com/rust-lang/rustlings/issues/205))
- **watch:** clear screen before each `verify()` ([3aff590](https://github.com/rust-lang/rustlings/commit/3aff59085586c24196a547c2693adbdcf4432648))
<a name="1.5.0"></a>
## 1.5.0 (2019-11-09)
#### Bug Fixes
### Bug Fixes
- **test1:** Rewrite logic ([79a56942](https://github.com/rust-lang/rustlings/commit/79a569422c8309cfc9e4aed25bf4ab3b3859996b))
- **installation:** Fix rustlings installation check ([7a252c47](https://github.com/rust-lang/rustlings/commit/7a252c475551486efb52f949b8af55803b700bc6))
@@ -852,27 +917,23 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- Swap assertion parameter order ([4086d463](https://github.com/rust-lang/rustlings/commit/4086d463a981e81d97781851d17db2ced290f446))
- renamed function name to snake case closes #180 ([89d5186c](https://github.com/rust-lang/rustlings/commit/89d5186c0dae8135ecabf90ee8bb35949bc2d29b))
#### Features
### Features
- Add enums exercises ([dc150321](https://github.com/rust-lang/rustlings/commit/dc15032112fc485226a573a18139e5ce928b1755))
- Added exercise for struct update syntax ([1c4c8764](https://github.com/rust-lang/rustlings/commit/1c4c8764ed118740cd4cee73272ddc6cceb9d959))
- **iterators2:** adds iterators2 exercise including config ([9288fccf](https://github.com/rust-lang/rustlings/commit/9288fccf07a2c5043b76d0fd6491e4cf72d76031))
<a name="1.4.1"></a>
## 1.4.1 (2019-08-13)
### 1.4.1 (2019-08-13)
#### Bug Fixes
### Bug Fixes
- **iterators2:** Remove syntax resulting in misleading error message ([4cde8664](https://github.com/rust-lang/rustlings/commit/4cde86643e12db162a66e62f23b78962986046ac))
- **option1:** Add test for prematurely passing exercise ([a750e4a1](https://github.com/rust-lang/rustlings/commit/a750e4a1a3006227292bb17d57d78ce84da6bfc6))
- **test1:** Swap assertion parameter order ([4086d463](https://github.com/rust-lang/rustlings/commit/4086d463a981e81d97781851d17db2ced290f446))
<a name="1.4.0"></a>
## 1.4.0 (2019-07-13)
#### Bug Fixes
### Bug Fixes
- **installation:** Fix rustlings installation check ([7a252c47](https://github.com/rust-lang/rustlings/commit/7a252c475551486efb52f949b8af55803b700bc6))
- **iterators:** Rename iterator3.rs ([433d2115](https://github.com/rust-lang/rustlings/commit/433d2115bc1c04b6d34a335a18c9a8f3e2672bc6))
@@ -881,20 +942,18 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- **cli:** Check if changed exercise file exists before calling verify ([ba85ca3](https://github.com/rust-lang/rustlings/commit/ba85ca32c4cfc61de46851ab89f9c58a28f33c88))
- **structs1:** Fix the irrefutable let pattern warning ([cc6a141](https://github.com/rust-lang/rustlings/commit/cc6a14104d7c034eadc98297eaaa972d09c50b1f))
#### Features
### Features
- **changelog:** Use clog for changelogs ([34e31232](https://github.com/rust-lang/rustlings/commit/34e31232dfddde284a341c9609b33cd27d9d5724))
- **iterators2:** adds iterators2 exercise including config ([9288fccf](https://github.com/rust-lang/rustlings/commit/9288fccf07a2c5043b76d0fd6491e4cf72d76031))
<a name="1.3.0"></a>
## 1.3.0 (2019-06-05)
### 1.3.0 (2019-06-05)
#### Features
### Features
- Adds a simple exercise for structures (#163, @briankung)
#### Bug Fixes
### Bug Fixes
- Add Result type signature as it is difficult for new comers to understand Generics and Error all at once. (#157, @veggiemonk)
- Rustfmt and whitespace fixes (#161, @eddyp)
@@ -903,37 +962,29 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- Fix broken link (#164, @HanKruiger)
- Remove highlighting and syntect (#167, @komaeda)
<a name="1.2.2"></a>
## 1.2.2 (2019-05-07)
### 1.2.2 (2019-05-07)
#### Bug Fixes
### Bug Fixes
- Reverted `--nocapture` flag since it was causing tests to pass unconditionally
<a name="1.2.1"></a>
## 1.2.1 (2019-04-22)
### 1.2.1 (2019-04-22)
#### Bug Fixes
### Bug Fixes
- Fix the `--nocapture` feature (@komaeda)
- Provide a nicer error message for when you're in the wrong directory
<a name="1.2.0"></a>
## 1.2.0 (2019-04-22)
### 1.2.0 (2019-04-22)
#### Features
### Features
- Add errors to exercises that compile without user changes (@yvan-sraka)
- Use --nocapture when testing, enabling `println!` when running (@komaeda)
<a name="1.1.1"></a>
## 1.1.1 (2019-04-14)
### 1.1.1 (2019-04-14)
#### Bug fixes
### Bug fixes
- Fix permissions on exercise files (@zacanger, #133)
- Make installation checks more thorough (@komaeda, 1b3469f236bc6979c27f6e1a04e4138a88e55de3)
@@ -943,9 +994,7 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- Fix links by deleting book version (@diodfr, #142)
- Canonicalize paths to fix path matching (@cjpearce, #143)
<a name="1.1.0"></a>
### 1.1.0 (2019-03-20)
## 1.1.0 (2019-03-20)
- errors2.rs: update link to Rust book (#124)
- Start verification at most recently modified file (#120)
@@ -954,16 +1003,12 @@ Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXER
- Give a warning when Rustlings isn't run from the right directory (#123)
- Verify that rust version is recent enough to install Rustlings (#131)
<a name="1.0.1"></a>
### 1.0.1 (2019-03-06)
## 1.0.1 (2019-03-06)
- Adds a way to install Rustlings in one command (`curl -L https://git.io/rustlings | bash`)
- Makes `rustlings watch` react to create file events (@shaunbennett, #117)
- Reworks the exercise management to use an external TOML file instead of just listing them in the code
<a name="1.0.0"></a>
### 1.0.0 (2019-03-06)
## 1.0.0 (2019-03-06)
Initial release.

View File

@@ -14,7 +14,7 @@ I want to …
## Issues
You can open an issue [here](https://github.com/rust-lang/rustlings/issues/new).
You can [open an issue](https://github.com/rust-lang/rustlings/issues/new).
If you're reporting a bug, please include the output of the following commands:
- `cargo --version`

1044
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,27 +1,25 @@
[workspace]
resolver = "2"
exclude = [
"tests/fixture/failure",
"tests/fixture/state",
"tests/fixture/success",
"tests/test_exercises",
"dev",
]
[workspace.package]
version = "6.1.0"
version = "6.5.0"
authors = [
"Liv <mokou@fastmail.com>",
"Mo Bitar <mo8it@proton.me>",
"Mo Bitar <mo8it@proton.me>", # https://github.com/mo8it
"Liv <mokou@fastmail.com>", # https://github.com/shadows-withal
# Alumni
"Carol (Nichols || Goulding) <carol.nichols@gmail.com>",
"Carol (Nichols || Goulding) <carol.nichols@gmail.com>", # https://github.com/carols10cents
]
repository = "https://github.com/rust-lang/rustlings"
license = "MIT"
edition = "2021"
edition = "2024" # On Update: Update the edition of `rustfmt` in `dev check` and `CARGO_TOML` in `dev new`.
rust-version = "1.88"
[workspace.dependencies]
serde = { version = "1.0.204", features = ["derive"] }
toml_edit = { version = "0.22.15", default-features = false, features = ["parse", "serde"] }
serde = { version = "1", features = ["derive"] }
toml = { version = "1", default-features = false, features = ["std", "parse", "serde"] }
[package]
name = "rustlings"
@@ -31,6 +29,7 @@ authors.workspace = true
repository.workspace = true
license.workspace = true
edition.workspace = true
rust-version.workspace = true
keywords = [
"exercise",
"learning",
@@ -46,21 +45,21 @@ include = [
]
[dependencies]
anyhow = "1.0.86"
clap = { version = "4.5.9", features = ["derive"] }
crossterm = "0.27.0"
hashbrown = "0.14.5"
notify-debouncer-mini = { version = "0.4.1", default-features = false }
os_pipe = "1.2.0"
ratatui = { version = "0.27.0", default-features = false, features = ["crossterm"] }
rustlings-macros = { path = "rustlings-macros", version = "=6.1.0" }
serde_json = "1.0.120"
anyhow = "1"
clap = { version = "4", features = ["derive"] }
crossterm = { version = "0.29", default-features = false, features = ["windows", "events"] }
notify = "8"
rustlings-macros = { path = "rustlings-macros", version = "=6.5.0" }
serde_json = "1"
serde.workspace = true
toml_edit.workspace = true
shlex = "1"
toml.workspace = true
[target.'cfg(not(windows))'.dependencies]
rustix = { version = "1.0", default-features = false, features = ["std", "stdio", "termios"] }
[dev-dependencies]
assert_cmd = "2.0.14"
predicates = "3.1.0"
tempfile = "3"
[profile.release]
panic = "abort"
@@ -70,3 +69,20 @@ panic = "abort"
[package.metadata.release]
pre-release-hook = ["./release-hook.sh"]
pre-release-commit-message = "Release 🎉"
[workspace.lints.rust]
unsafe_code = "forbid"
unstable_features = "forbid"
[workspace.lints.clippy]
empty_loop = "forbid"
disallowed-types = "deny"
disallowed-methods = "deny"
infinite_loop = "deny"
mem_forget = "deny"
dbg_macro = "warn"
todo = "warn"
[lints]
workspace = true

144
README.md
View File

@@ -1,143 +1,7 @@
<div class="oranda-hide">
# [Rustlings](https://rustlings.rust-lang.org) 🦀
# Rustlings 🦀❤️
Small exercises to get you used to reading and writing [Rust](https://www.rust-lang.org) code - _Recommended in parallel to reading [the official Rust book](https://doc.rust-lang.org/book) 📚️_
</div>
Visit the **website** for a demo, info about setup and more:
Greetings and welcome to Rustlings.
This project contains small exercises to get you used to reading and writing Rust code.
This includes reading and responding to compiler messages!
It is recommended to do the Rustlings exercises in parallel to reading [the official Rust book](https://doc.rust-lang.org/book/), the most comprehensive resource for learning Rust 📚️
[Rust By Example](https://doc.rust-lang.org/rust-by-example/) is another recommended resource that you might find helpful.
It contains code examples and exercises similar to Rustlings, but online.
## Getting Started
### Installing Rust
Before installing Rustlings, you need to have _Rust installed_.
Visit [www.rust-lang.org/tools/install](https://www.rust-lang.org/tools/install) for further instructions on installing Rust.
This will also install _Cargo_, Rust's package/project manager.
> 🐧 If you're on Linux, make sure you've installed `gcc` (for a linker).
>
> Deb: `sudo apt install gcc`.
> Dnf: `sudo dnf install gcc`.
> 🍎 If you're on MacOS, make sure you've installed Xcode and its developer tools by running `xcode-select --install`.
### Installing Rustlings
The following command will download and compile Rustlings:
```bash
cargo install rustlings
```
<details>
<summary><strong>If the installation fails…</strong> (<em>click to expand</em>)</summary>
- Make sure you have the latest Rust version by running `rustup update`
- Try adding the `--locked` flag: `cargo install rustlings --locked`
- Otherwise, please [report the issue](https://github.com/rust-lang/rustlings/issues/new)
</details>
### Initialization
After installing Rustlings, run the following command to initialize the `rustlings/` directory:
```bash
rustlings init
```
Now, go into the newly initialized directory and launch Rustlings for further instructions on getting started with the exercises:
```bash
cd rustlings/
rustlings
```
## Working environment
### Editor
Our general recommendation is [VS Code](https://code.visualstudio.com/) with the [rust-analyzer plugin](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer).
But any editor that supports [rust-analyzer](https://rust-analyzer.github.io/) should be enough for working on the exercises.
### Terminal
While working with Rustlings, please use a modern terminal for the best user experience.
The default terminal on Linux and Mac should be sufficient.
On Windows, we recommend the [Windows Terminal](https://aka.ms/terminal).
If you use VS Code, the builtin terminal should also be fine.
## Doing exercises
The exercises are sorted by topic and can be found in the subdirectory `exercises/<topic>`.
For every topic, there is an additional `README.md` file with some resources to get you started on the topic.
We highly recommend that you have a look at them before you start 📚️
Most exercises contain an error that keeps them from compiling, and it's up to you to fix it!
Some exercises contain tests that need to pass for the exercise to be done ✅
Search for `TODO` and `todo!()` to find out what you need to change.
Ask for hints by entering `h` in the _watch mode_ 💡
### Watch Mode
After [initialization](#initialization), Rustlings can be launched by simply running the command `rustlings`.
This will start the _watch mode_ which walks you through the exercises in a predefined order (what we think is best for newcomers).
It will rerun the current exercise automatically every time you change the exercise's file in the `exercises/` directory.
<details>
<summary><strong>If detecting file changes in the <code>exercises/</code> directory fails…</strong> (<em>click to expand</em>)</summary>
> You can add the **`--manual-run`** flag (`rustlings --manual-run`) to manually rerun the current exercise by entering `r` in the watch mode.
>
> Please [report the issue](https://github.com/rust-lang/rustlings/issues/new) with some information about your operating system and whether you run Rustlings in a container or virtual machine (e.g. WSL).
</details>
### Exercise List
In the [watch mode](#watch-mode) (after launching `rustlings`), you can enter `l` to open the interactive exercise list.
The list allows you to…
- See the status of all exercises (done or pending)
- `c`: Continue at another exercise (temporarily skip some exercises or go back to a previous one)
- `r`: Reset status and file of an exercise (you need to _reload/reopen_ its file in your editor afterwards)
See the footer of the list for all possible keys.
## Continuing On
Once you've completed Rustlings, put your new knowledge to good use!
Continue practicing your Rust skills by building your own projects, contributing to Rustlings, or finding other open-source projects to contribute to.
## Third-Party Exercises
Do you want to create your own set of Rustlings exercises to focus on some specific topic?
Or do you want to translate the original Rustlings exercises?
Then follow the link to the guide about [third-party exercises](https://github.com/rust-lang/rustlings/blob/main/THIRD_PARTY_EXERCISES.md)!
## Uninstalling Rustlings
If you want to remove Rustlings from your system, run the following command:
```bash
cargo uninstall rustlings
```
## Contributing
See [CONTRIBUTING.md](https://github.com/rust-lang/rustlings/blob/main/CONTRIBUTING.md) 🔗
## Contributors ✨
Thanks to [all the wonderful contributors](https://github.com/rust-lang/rustlings/graphs/contributors) 🎉
## ➡️ [rustlings.rust-lang.org](https://rustlings.rust-lang.org) ⬅️

View File

@@ -1,53 +0,0 @@
# Third-Party Exercises
The support of Rustlings for third-party exercises allows you to create your own set of Rustlings exercises to focus on some specific topic.
You could also offer a translation of the original Rustlings exercises as third-party exercises.
## Getting started
To create third-party exercises, install Rustlings and run `rustlings dev new PROJECT_NAME`.
This command will, similar to `cargo new PROJECT_NAME`, create a template directory called `PROJECT_NAME` with all what you need to get started.
Read the comments in the generated `info.toml` file to understand its format.
It allows you to set a custom welcome and final message and specify the metadata of every exercise.
## Create an exercise
Here is an example of the metadata of one file:
```toml
[[exercises]]
name = "intro1"
hint = """
To finish this exercise, you need to …
This link might help you …"""
```
After entering this in `info.toml`, create the file `intro1.rs` in the `exercises/` directory.
The exercise needs to contain a `main` function, but it can be empty.
Adding tests is recommended.
Look at the official Rustlings exercises for inspiration.
You can optionally add a solution file `intro1.rs` to the `solutions/` directory.
Now, run `rustlings dev check`.
It will tell you about any issues with your exercises.
For example, it will tell you to run `rustlings dev update` to update the `Cargo.toml` file to include the new exercise `intro1`.
`rustlings dev check` will also run your solutions (if you have any) to make sure that they run successfully.
That's it!
You finished your first exercise 🎉
## Publish
Now, add more exercises and publish them as a Git repository.
Users just have to clone that repository and run `rustlings` in it to start working on your set of exercises just like the official ones.
One difference to the official exercises is that the solution files will not be hidden until the user finishes an exercise.
But you can trust the users to not look at the solution too early 😉
## Share
After publishing your set of exercises, open an issue or a pull request in the official Rustlings repository to link to your project in the README 😃

5
build.rs Normal file
View File

@@ -0,0 +1,5 @@
fn main() {
// Fix building from source on Windows because it can't handle file links.
#[cfg(windows)]
let _ = std::fs::copy("dev/Cargo.toml", "dev-Cargo.toml");
}

11
clippy.toml Normal file
View File

@@ -0,0 +1,11 @@
disallowed-types = [
{ path = "crossterm::style::Stylize", reason = "inefficient, use `.queue(…)` instead" },
{ path = "crossterm::style::styled_content::StyledContent", reason = "inefficient, use `.queue(…)` instead" },
]
disallowed-methods = [
{ path = "crossterm::style::style", reason = "inefficient, use `.queue(…)` instead" },
{ path = "std::thread::spawn", replacement = "std::thread::Builder::spawn", reason = "handle the error" },
{ path = "std::thread::Scope::spawn", replacement = "std::thread::Builder::spawn", reason = "handle the error" },
{ path = "std::process::exit", replacement = "std::process::ExitCode" },
]

View File

@@ -1,4 +1,4 @@
# Don't edit the `bin` list manually! It is updated by `cargo run -- dev update`. This comment line will be stripped in `rustlings init`.
# Don't edit the `bin` list manually! It is updated by `cargo dev update`. This comment line will be stripped in `rustlings init`.
bin = [
{ name = "intro1", path = "../exercises/00_intro/intro1.rs" },
{ name = "intro1_sol", path = "../solutions/00_intro/intro1.rs" },
@@ -150,14 +150,14 @@ bin = [
{ name = "iterators4_sol", path = "../solutions/18_iterators/iterators4.rs" },
{ name = "iterators5", path = "../exercises/18_iterators/iterators5.rs" },
{ name = "iterators5_sol", path = "../solutions/18_iterators/iterators5.rs" },
{ name = "box1", path = "../exercises/19_smart_pointers/box1.rs" },
{ name = "box1_sol", path = "../solutions/19_smart_pointers/box1.rs" },
{ name = "rc1", path = "../exercises/19_smart_pointers/rc1.rs" },
{ name = "rc1_sol", path = "../solutions/19_smart_pointers/rc1.rs" },
{ name = "arc1", path = "../exercises/19_smart_pointers/arc1.rs" },
{ name = "arc1_sol", path = "../solutions/19_smart_pointers/arc1.rs" },
{ name = "cow1", path = "../exercises/19_smart_pointers/cow1.rs" },
{ name = "cow1_sol", path = "../solutions/19_smart_pointers/cow1.rs" },
{ name = "smart_pointers1", path = "../exercises/19_smart_pointers/smart_pointers1.rs" },
{ name = "smart_pointers1_sol", path = "../solutions/19_smart_pointers/smart_pointers1.rs" },
{ name = "smart_pointers2", path = "../exercises/19_smart_pointers/smart_pointers2.rs" },
{ name = "smart_pointers2_sol", path = "../solutions/19_smart_pointers/smart_pointers2.rs" },
{ name = "smart_pointers3", path = "../exercises/19_smart_pointers/smart_pointers3.rs" },
{ name = "smart_pointers3_sol", path = "../solutions/19_smart_pointers/smart_pointers3.rs" },
{ name = "smart_pointers4", path = "../exercises/19_smart_pointers/smart_pointers4.rs" },
{ name = "smart_pointers4_sol", path = "../solutions/19_smart_pointers/smart_pointers4.rs" },
{ name = "threads1", path = "../exercises/20_threads/threads1.rs" },
{ name = "threads1_sol", path = "../solutions/20_threads/threads1.rs" },
{ name = "threads2", path = "../exercises/20_threads/threads2.rs" },
@@ -178,20 +178,46 @@ bin = [
{ name = "clippy2_sol", path = "../solutions/22_clippy/clippy2.rs" },
{ name = "clippy3", path = "../exercises/22_clippy/clippy3.rs" },
{ name = "clippy3_sol", path = "../solutions/22_clippy/clippy3.rs" },
{ name = "using_as", path = "../exercises/23_conversions/using_as.rs" },
{ name = "using_as_sol", path = "../solutions/23_conversions/using_as.rs" },
{ name = "from_into", path = "../exercises/23_conversions/from_into.rs" },
{ name = "from_into_sol", path = "../solutions/23_conversions/from_into.rs" },
{ name = "from_str", path = "../exercises/23_conversions/from_str.rs" },
{ name = "from_str_sol", path = "../solutions/23_conversions/from_str.rs" },
{ name = "try_from_into", path = "../exercises/23_conversions/try_from_into.rs" },
{ name = "try_from_into_sol", path = "../solutions/23_conversions/try_from_into.rs" },
{ name = "as_ref_mut", path = "../exercises/23_conversions/as_ref_mut.rs" },
{ name = "as_ref_mut_sol", path = "../solutions/23_conversions/as_ref_mut.rs" },
{ name = "conversions1", path = "../exercises/23_conversions/conversions1.rs" },
{ name = "conversions1_sol", path = "../solutions/23_conversions/conversions1.rs" },
{ name = "conversions2", path = "../exercises/23_conversions/conversions2.rs" },
{ name = "conversions2_sol", path = "../solutions/23_conversions/conversions2.rs" },
{ name = "conversions3", path = "../exercises/23_conversions/conversions3.rs" },
{ name = "conversions3_sol", path = "../solutions/23_conversions/conversions3.rs" },
{ name = "conversions4", path = "../exercises/23_conversions/conversions4.rs" },
{ name = "conversions4_sol", path = "../solutions/23_conversions/conversions4.rs" },
{ name = "conversions5", path = "../exercises/23_conversions/conversions5.rs" },
{ name = "conversions5_sol", path = "../solutions/23_conversions/conversions5.rs" },
]
[package]
name = "exercises"
edition = "2021"
edition = "2024"
# Don't publish the exercises on crates.io!
publish = false
[profile.release]
panic = "abort"
[profile.dev]
panic = "abort"
[lints.rust]
# You shouldn't write unsafe code in Rustlings!
unsafe_code = "forbid"
# You don't need unstable features in Rustlings and shouldn't rely on them while learning Rust.
unstable_features = "forbid"
# Dead code warnings can't be avoided in some exercises and might distract while learning.
dead_code = "allow"
[lints.clippy]
# You forgot a `todo!()`!
todo = "forbid"
# This can only happen by mistake in Rustlings.
empty_loop = "forbid"
# No infinite loops are needed in Rustlings.
infinite_loop = "deny"
# You shouldn't leak memory while still learning Rust!
mem_forget = "deny"
# Currently, there are no disallowed methods. This line avoids problems when developing Rustlings.
disallowed_methods = "allow"

View File

@@ -1,4 +1,4 @@
// TODO: We sometimes encourage you to keep trying things on a given exercise,
// TODO: We sometimes encourage you to keep trying things on a given exercise
// even after you already figured it out. If you got everything working and feel
// ready for the next exercise, enter `n` in the terminal.
//
@@ -6,8 +6,7 @@
// Try adding a new `println!` and check the updated output in the terminal.
fn main() {
println!("Hello and");
println!(r#" welcome to... "#);
println!(r#" Welcome to... "#);
println!(r#" _ _ _ "#);
println!(r#" _ __ _ _ ___| |_| (_)_ __ __ _ ___ "#);
println!(r#" | '__| | | / __| __| | | '_ \ / _` / __| "#);

View File

@@ -1,7 +1,7 @@
# Variables
In Rust, variables are immutable by default.
When a variable is immutable, once a value is bound to a name, you cant change that value.
When a variable is immutable, once a value is bound to a name, you can't change that value.
You can make them mutable by adding `mut` in front of the variable name.
## Further information

View File

@@ -1,5 +1,5 @@
fn main() {
// TODO: Add missing keyword.
// TODO: Add the missing keyword.
x = 5;
println!("x has the value {x}");

View File

@@ -1,6 +1,6 @@
fn main() {
let number = "T-H-R-E-E"; // Don't change this line
println!("Spell a number: {}", number);
println!("Spell a number: {number}");
// TODO: Fix the compiler error by changing the line below without renaming the variable.
number = 3;

View File

@@ -1,4 +1,4 @@
fn call_me(num: u32) {
fn call_me(num: u8) {
for i in 0..num {
println!("Ring! Call number {}", i + 1);
}

View File

@@ -1,7 +1,7 @@
// TODO: Fix the compiler error on this function.
fn foo_if_fizz(fizzish: &str) -> &str {
if fizzish == "fizz" {
"foo"
fn picky_eater(food: &str) -> &str {
if food == "strawberry" {
"Yummy!"
} else {
1
}
@@ -18,18 +18,20 @@ mod tests {
use super::*;
#[test]
fn foo_for_fizz() {
// This means that calling `foo_if_fizz` with the argument "fizz" should return "foo".
assert_eq!(foo_if_fizz("fizz"), "foo");
fn yummy_food() {
// This means that calling `picky_eater` with the argument "strawberry" should return "Yummy!".
assert_eq!(picky_eater("strawberry"), "Yummy!");
}
#[test]
fn bar_for_fuzz() {
assert_eq!(foo_if_fizz("fuzz"), "bar");
fn neutral_food() {
assert_eq!(picky_eater("potato"), "I guess I can eat that.");
}
#[test]
fn default_to_baz() {
assert_eq!(foo_if_fizz("literally anything"), "baz");
fn default_disliked_food() {
assert_eq!(picky_eater("broccoli"), "No thanks!");
assert_eq!(picky_eater("gummy bears"), "No thanks!");
assert_eq!(picky_eater("literally anything"), "No thanks!");
}
}

View File

@@ -1,11 +1,6 @@
fn array_and_vec() -> ([i32; 4], Vec<i32>) {
let a = [10, 20, 30, 40]; // Array
// TODO: Create a vector called `v` which contains the exact same elements as in the array `a`.
// Use the vector macro.
// let v = ???;
(a, v)
fn elems_to_vec(a: i32, b: i32, c: i32) -> Vec<i32> {
// TODO: Return a vector containing the elements a, b and c (in this order).
// Use the "vec!" macro.
}
fn main() {
@@ -17,8 +12,11 @@ mod tests {
use super::*;
#[test]
fn test_array_and_vec_similarity() {
let (a, v) = array_and_vec();
assert_eq!(a, *v);
fn test_elems_to_vec() {
let (a, b, c) = (2, 7, 12);
let v = elems_to_vec(a, b, c);
assert_eq!(v[0], a);
assert_eq!(v[1], b);
assert_eq!(v[2], c);
}
}

View File

@@ -9,26 +9,6 @@ fn vec_loop(input: &[i32]) -> Vec<i32> {
output
}
fn vec_map_example(input: &[i32]) -> Vec<i32> {
// An example of collecting a vector after mapping.
// We map each element of the `input` slice to its value plus 1.
// If the input is `[1, 2, 3]`, the output is `[2, 3, 4]`.
input.iter().map(|element| element + 1).collect()
}
fn vec_map(input: &[i32]) -> Vec<i32> {
// TODO: Here, we also want to multiply each element in the `input` slice
// by 2, but with iterator mapping instead of manually pushing into an empty
// vector.
// See the example in the function `vec_map_example` above.
input
.iter()
.map(|element| {
// ???
})
.collect()
}
fn main() {
// You can optionally experiment here.
}
@@ -43,18 +23,4 @@ mod tests {
let ans = vec_loop(&input);
assert_eq!(ans, [4, 8, 12, 16, 20]);
}
#[test]
fn test_vec_map_example() {
let input = [1, 2, 3];
let ans = vec_map_example(&input);
assert_eq!(ans, [2, 3, 4]);
}
#[test]
fn test_vec_map() {
let input = [2, 4, 6, 8, 10];
let ans = vec_map(&input);
assert_eq!(ans, [4, 8, 12, 16, 20]);
}
}

View File

@@ -1,38 +1,28 @@
// Structs contain data, but can also have logic. In this exercise, we have
// defined the `Package` struct, and we want to test some logic attached to it.
// defined the `Fireworks` struct and a couple of functions that work with it.
// Turn these free-standing functions into methods and associated functions
// to express that relationship more clearly in the code.
#![deny(clippy::use_self)] // practice using the `Self` type
#[derive(Debug)]
struct Package {
sender_country: String,
recipient_country: String,
weight_in_grams: u32,
struct Fireworks {
rockets: usize,
}
impl Package {
fn new(sender_country: String, recipient_country: String, weight_in_grams: u32) -> Self {
if weight_in_grams < 10 {
// This isn't how you should handle errors in Rust, but we will
// learn about error handling later.
panic!("Can't ship a package with weight below 10 grams");
}
// TODO: Turn this function into an associated function on `Fireworks`.
fn new_fireworks() -> Fireworks {
Fireworks { rockets: 0 }
}
Self {
sender_country,
recipient_country,
weight_in_grams,
}
}
// TODO: Turn this function into a method on `Fireworks`.
fn add_rockets(fireworks: &mut Fireworks, rockets: usize) {
fireworks.rockets += rockets
}
// TODO: Add the correct return type to the function signature.
fn is_international(&self) {
// TODO: Read the tests that use this method to find out when a package
// is considered international.
}
// TODO: Add the correct return type to the function signature.
fn get_fees(&self, cents_per_gram: u32) {
// TODO: Calculate the package's fees.
}
// TODO: Turn this function into a method on `Fireworks`.
fn start(fireworks: Fireworks) -> String {
"🚀".repeat(fireworks.rockets)
}
fn main() {
@@ -44,44 +34,18 @@ mod tests {
use super::*;
#[test]
#[should_panic]
fn fail_creating_weightless_package() {
let sender_country = String::from("Spain");
let recipient_country = String::from("Austria");
fn start_some_fireworks() {
let f = Fireworks::new();
assert_eq!(f.start(), "");
Package::new(sender_country, recipient_country, 5);
}
let mut f = Fireworks::new();
f.add_rockets(3);
assert_eq!(f.start(), "🚀🚀🚀");
#[test]
fn create_international_package() {
let sender_country = String::from("Spain");
let recipient_country = String::from("Russia");
let package = Package::new(sender_country, recipient_country, 1200);
assert!(package.is_international());
}
#[test]
fn create_local_package() {
let sender_country = String::from("Canada");
let recipient_country = sender_country.clone();
let package = Package::new(sender_country, recipient_country, 1200);
assert!(!package.is_international());
}
#[test]
fn calculate_transport_fees() {
let sender_country = String::from("Spain");
let recipient_country = String::from("Spain");
let cents_per_gram = 3;
let package = Package::new(sender_country, recipient_country, 1500);
assert_eq!(package.get_fees(cents_per_gram), 4500);
assert_eq!(package.get_fees(cents_per_gram * 2), 9000);
let mut f = Fireworks::new();
f.add_rockets(7);
// We don't use method syntax in the last test to ensure the `start`
// function takes ownership of the fireworks.
assert_eq!(Fireworks::start(f), "🚀🚀🚀🚀🚀🚀🚀");
}
}

View File

@@ -1,10 +1,10 @@
# Enums
Rust allows you to define types called "enums" which enumerate possible values.
Enums are a feature in many languages, but their capabilities differ in each language. Rusts enums are most similar to algebraic data types in functional languages, such as F#, OCaml, and Haskell.
Enums are a feature in many languages, but their capabilities differ in each language. Rust's enums are most similar to algebraic data types in functional languages, such as F#, OCaml, and Haskell.
Useful in combination with enums is Rust's "pattern matching" facility, which makes it easy to run different code for different values of an enumeration.
## Further information
- [Enums](https://doc.rust-lang.org/book/ch06-00-enums.html)
- [Pattern syntax](https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html)
- [Pattern syntax](https://doc.rust-lang.org/book/ch19-03-pattern-syntax.html)

View File

@@ -1,5 +1,3 @@
#![allow(dead_code)]
#[derive(Debug)]
struct Point {
x: u64,

View File

@@ -4,7 +4,11 @@ struct Point {
}
enum Message {
// TODO: Implement the message variant types based on their usage below.
Resize { width: u64, height: u64 },
Move(Point),
Echo(String),
ChangeColor(u8, u8, u8),
Quit,
}
struct State {

View File

@@ -1,9 +1,11 @@
# Strings
Rust has two string types, a string slice (`&str`) and an owned string (`String`).
Rust has two string types: a string slice (`&str`) and an owned string (`String`).
We're not going to dictate when you should use which one, but we'll show you how
to identify and create them, as well as use them.
## Further information
- [Strings](https://doc.rust-lang.org/book/ch08-02-strings.html)
- [Strings (Rust Book)](https://doc.rust-lang.org/book/ch08-02-strings.html)
- [`str` methods](https://doc.rust-lang.org/std/primitive.str.html)
- [`String` methods](https://doc.rust-lang.org/std/string/struct.String.html)

View File

@@ -23,6 +23,7 @@ mod tests {
assert_eq!(trim_me("Hello! "), "Hello!");
assert_eq!(trim_me(" What's up!"), "What's up!");
assert_eq!(trim_me(" Hola! "), "Hola!");
assert_eq!(trim_me("Hi!"), "Hi!");
}
#[test]

View File

@@ -21,8 +21,6 @@ fn main() {
placeholder("rust is fun!".to_owned());
placeholder("nice weather".into());
placeholder(format!("Interpolation {}", "Station"));
// WARNING: This is byte indexing, not character indexing.

View File

@@ -1,7 +1,6 @@
// You can bring module paths into scopes and provide new names for them with
// the `use` and `as` keywords.
#[allow(dead_code)]
mod delicious_snacks {
// TODO: Add the following two `use` statements after fixing them.
// use self::fruits::PEAR as ???;

View File

@@ -6,7 +6,7 @@
// must add fruit to the basket so that there is at least one of each kind and
// more than 11 in total - we have a lot of mouths to feed. You are not allowed
// to insert any more of the fruits that are already in the basket (Apple,
// Mango, and Lyche).
// Mango, and Lychee).
use std::collections::HashMap;

View File

@@ -10,14 +10,14 @@ use std::collections::HashMap;
// A structure to store the goal details of a team.
#[derive(Default)]
struct Team {
struct TeamScores {
goals_scored: u8,
goals_conceded: u8,
}
fn build_scores_table(results: &str) -> HashMap<&str, Team> {
fn build_scores_table(results: &str) -> HashMap<&str, TeamScores> {
// The name of the team is the key and its associated struct is the value.
let mut scores = HashMap::new();
let mut scores = HashMap::<&str, TeamScores>::new();
for line in results.lines() {
let mut split_iterator = line.split(',');

View File

@@ -1,8 +1,8 @@
// This function returns how much icecream there is left in the fridge.
// This function returns how much ice cream there is left in the fridge.
// If it's before 22:00 (24-hour system), then 5 scoops are left. At 22:00,
// someone eats it all, so no icecream is left (value 0). Return `None` if
// someone eats it all, so no ice cream is left (value 0). Return `None` if
// `hour_of_day` is higher than 23.
fn maybe_icecream(hour_of_day: u16) -> Option<u16> {
fn maybe_ice_cream(hour_of_day: u16) -> Option<u16> {
// TODO: Complete the function body.
}
@@ -18,19 +18,19 @@ mod tests {
fn raw_value() {
// TODO: Fix this test. How do you get the value contained in the
// Option?
let icecreams = maybe_icecream(12);
let ice_creams = maybe_ice_cream(12);
assert_eq!(icecreams, 5); // Don't change this line.
assert_eq!(ice_creams, 5); // Don't change this line.
}
#[test]
fn check_icecream() {
assert_eq!(maybe_icecream(0), Some(5));
assert_eq!(maybe_icecream(9), Some(5));
assert_eq!(maybe_icecream(18), Some(5));
assert_eq!(maybe_icecream(22), Some(0));
assert_eq!(maybe_icecream(23), Some(0));
assert_eq!(maybe_icecream(24), None);
assert_eq!(maybe_icecream(25), None);
fn check_ice_cream() {
assert_eq!(maybe_ice_cream(0), Some(5));
assert_eq!(maybe_ice_cream(9), Some(5));
assert_eq!(maybe_ice_cream(18), Some(5));
assert_eq!(maybe_ice_cream(22), Some(0));
assert_eq!(maybe_ice_cream(23), Some(0));
assert_eq!(maybe_ice_cream(24), None);
assert_eq!(maybe_ice_cream(25), None);
}
}

View File

@@ -9,7 +9,7 @@ fn main() {
// TODO: Fix the compiler error by adding something to this match statement.
match optional_point {
Some(p) => println!("Co-ordinates are {},{}", p.x, p.y),
Some(p) => println!("Coordinates are {},{}", p.x, p.y),
_ => panic!("No match!"),
}

View File

@@ -1,8 +1,8 @@
# Error handling
Most errors arent serious enough to require the program to stop entirely.
Sometimes, when a function fails, its for a reason that you can easily interpret and respond to.
For example, if you try to open a file and that operation fails because the file doesnt exist, you might want to create the file instead of terminating the process.
Most errors aren't serious enough to require the program to stop entirely.
Sometimes, when a function fails, it's for a reason that you can easily interpret and respond to.
For example, if you try to open a file and that operation fails because the file doesn't exist, you might want to create the file instead of terminating the process.
## Further information

View File

@@ -6,7 +6,7 @@
// of `Option<String>`.
fn generate_nametag_text(name: String) -> Option<String> {
if name.is_empty() {
// Empty names aren't allowed.
// Empty names aren't allowed
None
} else {
Some(format!("Hi! My name is {name}"))

View File

@@ -1,5 +1,3 @@
#![allow(clippy::comparison_chain)]
#[derive(PartialEq, Debug)]
enum CreationError {
Negative,
@@ -12,6 +10,7 @@ struct PositiveNonzeroInteger(u64);
impl PositiveNonzeroInteger {
fn new(value: i64) -> Result<Self, CreationError> {
// TODO: This function shouldn't always return an `Ok`.
// Read the tests below to clarify what should be returned.
Ok(Self(value as u64))
}
}

View File

@@ -6,7 +6,7 @@
//
// In short, this particular use case for boxes is for when you want to own a
// value and you care only that it is a type which implements a particular
// trait. To do so, The `Box` is declared as of type `Box<dyn Trait>` where
// trait. To do so, the `Box` is declared as of type `Box<dyn Trait>` where
// `Trait` is the trait the compiler looks for on any value used in that
// context. For this exercise, that context is the potential errors which
// can be returned in a `Result`.

View File

@@ -19,15 +19,6 @@ enum ParsePosNonzeroError {
ParseInt(ParseIntError),
}
impl ParsePosNonzeroError {
fn from_creation(err: CreationError) -> Self {
Self::Creation(err)
}
// TODO: Add another error conversion function here.
// fn from_parseint(???) -> Self { ??? }
}
#[derive(PartialEq, Debug)]
struct PositiveNonzeroInteger(u64);
@@ -44,7 +35,7 @@ impl PositiveNonzeroInteger {
// TODO: change this to return an appropriate error instead of panicking
// when `parse()` returns an error.
let x: i64 = s.parse().unwrap();
Self::new(x).map_err(ParsePosNonzeroError::from_creation)
Self::new(x).map_err(ParsePosNonzeroError::Creation)
}
}

View File

@@ -1,5 +1,3 @@
#![allow(dead_code)]
trait Licensed {
// TODO: Add a default implementation for `licensing_info` so that
// implementors like the two structs below can share that default behavior

View File

@@ -9,7 +9,7 @@ impl Rectangle {
if width <= 0 || height <= 0 {
// Returning a `Result` would be better here. But we want to learn
// how to test functions that can panic.
panic!("Rectangle width and height can't be negative");
panic!("Rectangle width and height must be positive");
}
Rectangle { width, height }

View File

@@ -10,9 +10,9 @@ fn main() {
mod tests {
#[test]
fn iterators() {
let my_fav_fruits = ["banana", "custard apple", "avocado", "peach", "raspberry"];
let my_fav_fruits = &["banana", "custard apple", "avocado", "peach", "raspberry"];
// TODO: Create an iterator over the array.
// TODO: Create an iterator over the slice.
let mut fav_fruits_iterator = todo!();
assert_eq!(fav_fruits_iterator.next(), Some(&"banana"));

View File

@@ -39,6 +39,8 @@ mod tests {
#[test]
fn test_success() {
assert_eq!(divide(81, 9), Ok(9));
assert_eq!(divide(81, -1), Ok(-81));
assert_eq!(divide(i64::MIN, i64::MIN), Ok(1));
}
#[test]

View File

@@ -8,7 +8,6 @@ use std::rc::Rc;
#[derive(Debug)]
struct Sun;
#[allow(dead_code)]
#[derive(Debug)]
enum Planet {
Mercury(Rc<Sun>),

View File

@@ -1,5 +1,5 @@
// This program spawns multiple threads that each run for at least 250ms, and
// each thread returns how much time they took to complete. The program should
// This program spawns multiple threads that each runs for at least 250ms, and
// each thread returns how much time it took to complete. The program should
// wait until all the spawned threads have finished and should collect their
// return values into a vector.

View File

@@ -1,7 +1,6 @@
use std::{sync::mpsc, thread, time::Duration};
struct Queue {
length: u32,
first_half: Vec<u32>,
second_half: Vec<u32>,
}
@@ -9,7 +8,6 @@ struct Queue {
impl Queue {
fn new() -> Self {
Self {
length: 10,
first_half: vec![1, 2, 3, 4, 5],
second_half: vec![6, 7, 8, 9, 10],
}
@@ -48,17 +46,15 @@ mod tests {
fn threads3() {
let (tx, rx) = mpsc::channel();
let queue = Queue::new();
let queue_length = queue.length;
send_tx(queue, tx);
let mut total_received: u32 = 0;
for received in rx {
println!("Got: {received}");
total_received += 1;
let mut received = Vec::with_capacity(10);
for value in rx {
received.push(value);
}
println!("Number of received values: {total_received}");
assert_eq!(total_received, queue_length);
received.sort();
assert_eq!(received, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
}
}

View File

@@ -10,5 +10,6 @@ of exercises to Rustlings, but is all about learning to write Macros.
## Further information
- [Macros](https://doc.rust-lang.org/book/ch19-06-macros.html)
- [The Rust Book - Macros](https://doc.rust-lang.org/book/ch20-05-macros.html)
- [The Little Book of Rust Macros](https://veykril.github.io/tlborm/)
- [Rust by Example - macro_rules!](https://doc.rust-lang.org/rust-by-example/macros.html)

View File

@@ -1,22 +1,25 @@
// Here are some more easy Clippy fixes so you can see its utility 📎
// Here are some more easy Clippy fixes so you can see its utility.
// TODO: Fix all the Clippy lints.
#[rustfmt::skip]
#[allow(unused_variables, unused_assignments)]
fn main() {
let my_option: Option<()> = None;
let my_option: Option<&str> = None;
// Assume that you don't know the value of `my_option`.
// In the case of `Some`, we want to print its value.
if my_option.is_none() {
println!("{:?}", my_option.unwrap());
println!("{}", my_option.unwrap());
}
#[rustfmt::skip]
let my_arr = &[
-1, -2, -3
-4, -5, -6
];
println!("My array! Here it is: {my_arr:?}");
let my_empty_vec = vec![1, 2, 3, 4, 5].resize(0, 5);
println!("This Vec is empty, see? {my_empty_vec:?}");
let mut my_vec = vec![1, 2, 3, 4, 5];
my_vec.resize(0, 5);
println!("This Vec is empty, see? {my_vec:?}");
let mut value_a = 45;
let mut value_b = 66;

View File

@@ -2,14 +2,14 @@
Rust offers a multitude of ways to convert a value of a given type into another type.
The simplest form of type conversion is a type cast expression. It is denoted with the binary operator `as`. For instance, `println!("{}", 1 + 1.0);` would not compile, since `1` is an integer while `1.0` is a float. However, `println!("{}", 1 as f32 + 1.0)` should compile. The exercise [`using_as`](using_as.rs) tries to cover this.
The simplest form of type conversion is a type cast expression. It is denoted with the binary operator `as`. For instance, `println!("{}", 1 + 1.0);` would not compile, since `1` is an integer while `1.0` is a float. However, `println!("{}", 1 as f32 + 1.0)` should compile. The exercise [`conversions1`](conversions1.rs) tries to cover this.
Rust also offers traits that facilitate type conversions upon implementation. These traits can be found under the [`convert`](https://doc.rust-lang.org/std/convert/index.html) module.
The traits are the following:
- `From` and `Into` covered in [`from_into`](from_into.rs)
- `TryFrom` and `TryInto` covered in [`try_from_into`](try_from_into.rs)
- `AsRef` and `AsMut` covered in [`as_ref_mut`](as_ref_mut.rs)
- `From` and `Into` covered in [`conversions2`](conversions2.rs)
- `TryFrom` and `TryInto` covered in [`conversions4`](conversions4.rs)
- `AsRef` and `AsMut` covered in [`conversions5`](conversions5.rs)
Furthermore, the `std::str` module offers a trait called [`FromStr`](https://doc.rust-lang.org/std/str/trait.FromStr.html) which helps with converting strings into target types via the `parse` method on strings. If properly implemented for a given type `Person`, then `let p: Person = "Mark,20".parse().unwrap()` should both compile and run without panicking.

View File

@@ -0,0 +1,54 @@
// The `From` trait is used for value-to-value conversions. If `From` is
// implemented, an implementation of `Into` is automatically provided.
// You can read more about it in the documentation:
// https://doc.rust-lang.org/std/convert/trait.From.html
//
// Representing units of measurements with separate types is a common practice.
// It avoids accidentally mixing up values of different units of measurement.
struct Celsius(f64);
struct Fahrenheit(f64);
impl From<Celsius> for Fahrenheit {
// TODO: Convert Celsius to Fahrenheit. Don't worry about floating-point
// precision. The formula is: F = C * 1.8 + 32
}
impl From<Fahrenheit> for Celsius {
// TODO: Convert Fahrenheit to Celsius.
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
const CASES: [(f64, f64); 6] = [
(-50.0, -58.0),
(0.0, 32.0),
(20.0, 68.0),
(100.0, 212.0),
(400.0, 752.0),
(1000.0, 1832.0),
];
#[test]
fn celsius_to_fahrenheit() {
for (celsius, fahrenheit) in CASES {
let Fahrenheit(actual) = Celsius(celsius).into();
assert_eq!(actual.round(), fahrenheit);
}
}
#[test]
fn fahrenheit_to_celsius() {
for (celsius, fahrenheit) in CASES {
let Celsius(actual) = Fahrenheit(fahrenheit).into();
assert_eq!(actual.round(), celsius);
}
}
}

View File

@@ -25,7 +25,7 @@ enum ParsePersonError {
ParseInt(ParseIntError),
}
// TODO: Complete this `From` implementation to be able to parse a `Person`
// TODO: Complete this `FromStr` implementation to be able to parse a `Person`
// out of a string in the form of "Mark,20".
// Note that you'll need to parse the age component into a `u8` with something
// like `"4".parse::<u8>()`.

View File

@@ -2,10 +2,11 @@
// about them at https://doc.rust-lang.org/std/convert/trait.AsRef.html and
// https://doc.rust-lang.org/std/convert/trait.AsMut.html, respectively.
// Obtain the number of bytes (not characters) in the given argument.
// Obtain the number of bytes (not characters) in the given argument
// (`.len()` returns the number of bytes in a string).
// TODO: Add the `AsRef` trait appropriately as a trait bound.
fn byte_counter<T>(arg: T) -> usize {
arg.as_ref().as_bytes().len()
arg.as_ref().len()
}
// Obtain the number of characters (not bytes) in the given argument.

View File

@@ -1,130 +0,0 @@
// The `From` trait is used for value-to-value conversions. If `From` is
// implemented, an implementation of `Into` is automatically provided.
// You can read more about it in the documentation:
// https://doc.rust-lang.org/std/convert/trait.From.html
#[derive(Debug)]
struct Person {
name: String,
age: u8,
}
// We implement the Default trait to use it as a fallback when the provided
// string is not convertible into a `Person` object.
impl Default for Person {
fn default() -> Self {
Self {
name: String::from("John"),
age: 30,
}
}
}
// TODO: Complete this `From` implementation to be able to parse a `Person`
// out of a string in the form of "Mark,20".
// Note that you'll need to parse the age component into a `u8` with something
// like `"4".parse::<u8>()`.
//
// Steps:
// 1. Split the given string on the commas present in it.
// 2. If the split operation returns less or more than 2 elements, return the
// default of `Person`.
// 3. Use the first element from the split operation as the name.
// 4. If the name is empty, return the default of `Person`.
// 5. Parse the second element from the split operation into a `u8` as the age.
// 6. If parsing the age fails, return the default of `Person`.
impl From<&str> for Person {
fn from(s: &str) -> Self {}
}
fn main() {
// Use the `from` function.
let p1 = Person::from("Mark,20");
println!("{p1:?}");
// Since `From` is implemented for Person, we are able to use `Into`.
let p2: Person = "Gerald,70".into();
println!("{p2:?}");
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default() {
let dp = Person::default();
assert_eq!(dp.name, "John");
assert_eq!(dp.age, 30);
}
#[test]
fn test_bad_convert() {
let p = Person::from("");
assert_eq!(p.name, "John");
assert_eq!(p.age, 30);
}
#[test]
fn test_good_convert() {
let p = Person::from("Mark,20");
assert_eq!(p.name, "Mark");
assert_eq!(p.age, 20);
}
#[test]
fn test_bad_age() {
let p = Person::from("Mark,twenty");
assert_eq!(p.name, "John");
assert_eq!(p.age, 30);
}
#[test]
fn test_missing_comma_and_age() {
let p: Person = Person::from("Mark");
assert_eq!(p.name, "John");
assert_eq!(p.age, 30);
}
#[test]
fn test_missing_age() {
let p: Person = Person::from("Mark,");
assert_eq!(p.name, "John");
assert_eq!(p.age, 30);
}
#[test]
fn test_missing_name() {
let p: Person = Person::from(",1");
assert_eq!(p.name, "John");
assert_eq!(p.age, 30);
}
#[test]
fn test_missing_name_and_age() {
let p: Person = Person::from(",");
assert_eq!(p.name, "John");
assert_eq!(p.age, 30);
}
#[test]
fn test_missing_name_and_invalid_age() {
let p: Person = Person::from(",one");
assert_eq!(p.name, "John");
assert_eq!(p.age, 30);
}
#[test]
fn test_trailing_comma() {
let p: Person = Person::from("Mike,32,");
assert_eq!(p.name, "John");
assert_eq!(p.age, 30);
}
#[test]
fn test_trailing_comma_and_some_string() {
let p: Person = Person::from("Mike,32,dog");
assert_eq!(p.name, "John");
assert_eq!(p.age, 30);
}
}

View File

@@ -9,7 +9,7 @@
| vecs | §8.1 |
| move_semantics | §4.1-2 |
| structs | §5.1, §5.3 |
| enums | §6, §18.3 |
| enums | §6, §19.3 |
| strings | §8.2 |
| modules | §7 |
| hashmaps | §8.3 |
@@ -22,6 +22,6 @@
| iterators | §13.2-4 |
| smart_pointers | §15, §16.3 |
| threads | §16.1-3 |
| macros | §19.5 |
| clippy | §21.4 |
| macros | §20.5 |
| clippy | Appendix D |
| conversions | n/a |

View File

@@ -26,7 +26,7 @@ enum Command {
mod my_module {
use super::Command;
// TODO: Complete the function.
// TODO: Complete the function as described above.
// pub fn transformer(input: ???) -> ??? { ??? }
}

View File

@@ -1,13 +0,0 @@
{
"project": {
"homepage": "https://rustlings.cool",
"repository": "https://github.com/rust-lang/rustlings"
},
"marketing": {
"analytics": {
"plausible": {
"domain": "rustlings.cool"
}
}
}
}

View File

@@ -3,7 +3,13 @@
# Error out if any command fails
set -e
cargo run -- dev check
typos
cargo outdated -w --exit-code 1
cargo test --workspace --all-targets
# Similar to CI
cargo clippy -- --deny warnings
cargo fmt --all --check
cargo test --workspace
cargo dev check --require-solutions
# MSRV
cargo +1.88 dev check --require-solutions

View File

@@ -6,6 +6,7 @@ authors.workspace = true
repository.workspace = true
license.workspace = true
edition.workspace = true
rust-version.workspace = true
include = [
"/src/",
"/info.toml",
@@ -15,6 +16,9 @@ include = [
proc-macro = true
[dependencies]
quote = "1.0.36"
quote = "1"
serde.workspace = true
toml_edit.workspace = true
toml.workspace = true
[lints]
workspace = true

View File

@@ -1,6 +1,7 @@
format_version = 1
welcome_message = """Is this your first time? Don't worry, Rustlings is made for beginners!
welcome_message = """
Is this your first time? Don't worry, Rustlings is made for beginners!
We are going to teach you a lot of things about Rust, but before we can
get started, here are some notes about how Rustlings operates:
@@ -10,16 +11,17 @@ get started, here are some notes about how Rustlings operates:
and fix them!
2. Make sure to have your editor open in the `rustlings/` directory. Rustlings
will show you the path of the current exercise under the progress bar. Open
the exercise file in your editor, fix errors and save the file. Rustlings will
automatically detect the file change and rerun the exercise. If all errors are
fixed, Rustlings will ask you to move on to the next exercise.
the exercise file in your editor, fix errors and save the file. Rustlings
will automatically detect the file change and rerun the exercise. If all
errors are fixed, Rustlings will ask you to move on to the next exercise.
3. If you're stuck on an exercise, enter `h` to show a hint.
4. If an exercise doesn't make sense to you, feel free to open an issue on GitHub!
(https://github.com/rust-lang/rustlings). We look at every issue, and sometimes,
other learners do too so you can help each other out!"""
4. If an exercise doesn't make sense to you, feel free to open an issue on
GitHub! (https://github.com/rust-lang/rustlings). We look at every issue, and
sometimes, other learners do too so you can help each other out!"""
final_message = """We hope you enjoyed learning about the various aspects of Rust!
If you noticed any issues, don't hesitate to report them on Github.
final_message = """
We hope you enjoyed learning about the various aspects of Rust!
If you noticed any issues, don't hesitate to report them on GitHub.
You can also contribute your own exercises to help the greater community!
Before reporting an issue or contributing, please read our guidelines:
@@ -120,10 +122,10 @@ dir = "01_variables"
test = false
hint = """
We know about variables and mutability, but there is another important type of
variables available: constants.
variable available: constants.
Constants are always immutable. They are declared with the keyword `const` instead
of `let`.
Constants are always immutable. They are declared with the keyword `const`
instead of `let`.
The type of Constants must always be annotated.
@@ -253,7 +255,7 @@ require you to type in 100 items (but you certainly can if you want!).
For example, you can do:
```
let array = ["Are we there yet?"; 10];
let array = ["Are we there yet?"; 100];
```
Bonus: what are some other things you could have that would return `true`
@@ -263,10 +265,10 @@ for `a.len() >= 100`?"""
name = "primitive_types4"
dir = "04_primitive_types"
hint = """
Take a look at the 'Understanding Ownership -> Slices -> Other Slices' section
of the book: https://doc.rust-lang.org/book/ch04-03-slices.html and use the
starting and ending (plus one) indices of the items in the array that you want
to end up in the slice.
Take a look at the 'Understanding Ownership -> The Slice Type -> Other Slices'
section of the book: https://doc.rust-lang.org/book/ch04-03-slices.html and use
the starting and ending (plus one) indices of the items in the array that you
want to end up in the slice.
If you're curious why the first argument of `assert_eq!` does not have an
ampersand for a reference since the second argument is a reference, take a look
@@ -316,15 +318,7 @@ of the Rust book to learn more."""
name = "vecs2"
dir = "05_vecs"
hint = """
In the first function, we create an empty vector and want to push new elements
to it.
In the second function, we map the values of the input and collect them into a vector.
After you've completed both functions, decide for yourself which approach you
like better.
What do you think is the more commonly used pattern under Rust developers?"""
Use the `.push()` method on the vector to push new elements to it."""
# MOVE SEMANTICS
@@ -332,8 +326,8 @@ What do you think is the more commonly used pattern under Rust developers?"""
name = "move_semantics1"
dir = "06_move_semantics"
hint = """
So you've got the "cannot borrow `vec` as mutable, as it is not declared as mutable"
error on the line where we push an element to the vector, right?
So you've got the "cannot borrow `vec` as mutable, as it is not declared as
mutable" error on the line where we push an element to the vector, right?
The fix for this is going to be adding one keyword, and the addition is NOT on
the line where we push to the vector (where the error is).
@@ -369,7 +363,8 @@ hint = """
Carefully reason about the range in which each mutable reference is in
scope. Does it help to update the value of `x` immediately after
the mutable reference is taken?
Read more about 'Mutable References' in the book's section 'References and Borrowing':
Read more about 'Mutable References' in the book's section 'References and
Borrowing':
https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#mutable-references."""
[[exercises]]
@@ -422,11 +417,10 @@ https://doc.rust-lang.org/book/ch05-01-defining-structs.html#creating-instances-
name = "structs3"
dir = "07_structs"
hint = """
For `is_international`: What makes a package international? Seems related to
the places it goes through right?
For `get_fees`: This method takes an additional argument, is there a field in
the `Package` struct that this relates to?
Methods and associated functions are both declared in an `impl MyType {}`
block. Methods have a `self`, `&self` or `&mut self` parameter, where `self`
implicitly has the type of the impl block. Associated functions do not have
a `self` parameter.
Have a look in The Book to find out more about method implementations:
https://doc.rust-lang.org/book/ch05-03-method-syntax.html"""
@@ -444,8 +438,14 @@ name = "enums2"
dir = "08_enums"
test = false
hint = """
You can create enumerations that have different variants with different types
such as anonymous structs, structs, a single string, tuples, no data, etc."""
Enum variants can be defined using three different forms: struct-, tuple- and
unit-like. Here's an example enum definition, which uses all three forms:
enum EnumUsingAllVariantForms {
StructLike { named_field: bool },
TupleLike(bool),
UnitLike,
}"""
[[exercises]]
name = "enums3"
@@ -498,14 +498,18 @@ some of them:
https://doc.rust-lang.org/std/string/struct.String.html#method.trim
For the `compose_me` method: You can either use the `format!` macro, or convert
the string slice into an owned string, which you can then freely extend."""
the string slice into an owned string, which you can then freely extend.
For the `replace_me` method, you can check out the `replace` method:
https://doc.rust-lang.org/std/string/struct.String.html#method.replace"""
[[exercises]]
name = "strings4"
dir = "09_strings"
test = false
hint = """
Replace `placeholder` with either `string` or `string_slice` in the `main` function.
Replace `placeholder` with either `string` or `string_slice` in the `main`
function.
Example:
`placeholder("blue");`
@@ -567,12 +571,8 @@ https://doc.rust-lang.org/book/ch08-03-hash-maps.html#only-inserting-a-value-if-
name = "hashmaps3"
dir = "11_hashmaps"
hint = """
Hint 1: Use the `entry()` and `or_insert()` (or `or_insert_with()`) methods of
`HashMap` to insert the default value of `Team` if a team doesn't
exist in the table yet.
Learn more in The Book:
https://doc.rust-lang.org/book/ch08-03-hash-maps.html#only-inserting-a-value-if-the-key-has-no-value
Hint 1: Use the `entry()` and `or_default()` methods of `HashMap` to insert the
default value of `TeamScores` if a team doesn't exist in the table yet.
Hint 2: If there is already an entry for a given key, the value returned by
`entry()` can be updated based on the existing value.
@@ -760,7 +760,7 @@ Notice how the trait takes ownership of `self` and returns `Self`.
Although the signature of `append_bar` in the trait takes `self` as argument,
the implementation can take `mut self` instead. This is possible because the
the value is owned anyway."""
value is owned anyway."""
[[exercises]]
name = "traits3"
@@ -959,7 +959,7 @@ a different method that could make your code more compact than using `fold`."""
# SMART POINTERS
[[exercises]]
name = "box1"
name = "smart_pointers1"
dir = "19_smart_pointers"
hint = """
The compiler's message should help: Since we cannot store the value of the
@@ -976,7 +976,7 @@ Although the current list is one of integers (`i32`), feel free to change the
definition and try other types!"""
[[exercises]]
name = "rc1"
name = "smart_pointers2"
dir = "19_smart_pointers"
hint = """
This is a straightforward exercise to use the `Rc<T>` type. Each `Planet` has
@@ -993,7 +993,7 @@ See more at: https://doc.rust-lang.org/book/ch15-04-rc.html
Unfortunately, Pluto is no longer considered a planet :("""
[[exercises]]
name = "arc1"
name = "smart_pointers3"
dir = "19_smart_pointers"
test = false
hint = """
@@ -1010,7 +1010,7 @@ Book:
https://doc.rust-lang.org/book/ch16-00-concurrency.html"""
[[exercises]]
name = "cow1"
name = "smart_pointers4"
dir = "19_smart_pointers"
hint = """
If `Cow` already owns the data, it doesn't need to clone it when `to_mut()` is
@@ -1136,7 +1136,7 @@ constants, but clippy recognizes those imprecise mathematical constants as a
source of potential error.
See the suggestions of the Clippy warning in the compile output and use the
appropriate replacement constant from `std::f32::consts`..."""
appropriate replacement constant from `std::f32::consts`."""
[[exercises]]
name = "clippy2"
@@ -1161,20 +1161,26 @@ hint = "No hints this time!"
# TYPE CONVERSIONS
[[exercises]]
name = "using_as"
name = "conversions1"
dir = "23_conversions"
hint = """
Use the `as` operator to cast one of the operands in the last line of the
`average` function into the expected return type."""
[[exercises]]
name = "from_into"
name = "conversions2"
dir = "23_conversions"
hint = """
Follow the steps provided right before the `From` implementation."""
The formula for converting from Fahrenheit to Celsius is: C = (F - 32) / 1.8
This can be derived from the first formula:
F = C * 1.8 + 32 // now subtract 32 on both sides
F - 32 = C * 1.8 // then divide by 1.8
(F - 32) / 1.8 = C
"""
[[exercises]]
name = "from_str"
name = "conversions3"
dir = "23_conversions"
hint = """
The implementation of `FromStr` should return an `Ok` with a `Person` object,
@@ -1191,16 +1197,17 @@ operator in your solution, you might want to look at
https://doc.rust-lang.org/stable/rust-by-example/error/multiple_error_types/reenter_question_mark.html"""
[[exercises]]
name = "try_from_into"
name = "conversions4"
dir = "23_conversions"
hint = """
Is there an implementation of `TryFrom` in the standard library that can both do
the required integer conversion and check the range of the input?
Challenge: Can you make the `TryFrom` implementations generic over many integer types?"""
Challenge: Can you make the `TryFrom` implementations generic over many integer
types?"""
[[exercises]]
name = "as_ref_mut"
name = "conversions5"
dir = "23_conversions"
hint = """
Add `AsRef<str>` or `AsMut<u32>` as a trait bound to the functions."""

View File

@@ -3,20 +3,29 @@ use quote::quote;
use serde::Deserialize;
#[derive(Deserialize)]
struct ExerciseInfo {
name: String,
dir: String,
struct ExerciseInfo<'a> {
name: &'a str,
dir: &'a str,
}
#[derive(Deserialize)]
struct InfoFile {
exercises: Vec<ExerciseInfo>,
struct InfoFile<'a> {
#[serde(borrow)]
exercises: Vec<ExerciseInfo<'a>>,
}
#[proc_macro]
pub fn include_files(_: TokenStream) -> TokenStream {
let info_file = include_str!("../info.toml");
let exercises = toml_edit::de::from_str::<InfoFile>(info_file)
// Remove `\r` on Windows
let info_file = String::from_utf8(
include_bytes!("../info.toml")
.iter()
.copied()
.filter(|c| *c != b'\r')
.collect(),
)
.expect("Failed to parse `info.toml` as UTF8");
let exercises = toml::de::from_str::<InfoFile>(&info_file)
.expect("Failed to parse `info.toml`")
.exercises;
@@ -37,7 +46,7 @@ pub fn include_files(_: TokenStream) -> TokenStream {
continue;
}
dirs.push(exercise.dir.as_str());
dirs.push(exercise.dir);
*dir_ind = dirs.len() - 1;
}

View File

@@ -1,6 +1,6 @@
fn main() {
let number = "T-H-R-E-E";
println!("Spell a number: {}", number);
println!("Spell a number: {number}");
// Using variable shadowing
// https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html#shadowing

View File

@@ -1,4 +1,4 @@
fn call_me(num: u32) {
fn call_me(num: u8) {
for i in 0..num {
println!("Ring! Call number {}", i + 1);
}

View File

@@ -1,9 +1,5 @@
fn bigger(a: i32, b: i32) -> i32 {
if a > b {
a
} else {
b
}
if a > b { a } else { b }
}
fn main() {

View File

@@ -1,10 +1,10 @@
fn foo_if_fizz(fizzish: &str) -> &str {
if fizzish == "fizz" {
"foo"
} else if fizzish == "fuzz" {
"bar"
fn picky_eater(food: &str) -> &str {
if food == "strawberry" {
"Yummy!"
} else if food == "potato" {
"I guess I can eat that."
} else {
"baz"
"No thanks!"
}
}
@@ -17,17 +17,19 @@ mod tests {
use super::*;
#[test]
fn foo_for_fizz() {
assert_eq!(foo_if_fizz("fizz"), "foo");
fn yummy_food() {
assert_eq!(picky_eater("strawberry"), "Yummy!");
}
#[test]
fn bar_for_fuzz() {
assert_eq!(foo_if_fizz("fuzz"), "bar");
fn neutral_food() {
assert_eq!(picky_eater("potato"), "I guess I can eat that.");
}
#[test]
fn default_to_baz() {
assert_eq!(foo_if_fizz("literally anything"), "baz");
fn default_disliked_food() {
assert_eq!(picky_eater("broccoli"), "No thanks!");
assert_eq!(picky_eater("gummy bears"), "No thanks!");
assert_eq!(picky_eater("literally anything"), "No thanks!");
}
}

View File

@@ -2,6 +2,7 @@ fn animal_habitat(animal: &str) -> &str {
let identifier = if animal == "crab" {
1
} else if animal == "gopher" {
// Integer, so that every branch has the same type.
2
} else if animal == "snake" {
3

View File

@@ -1,10 +1,5 @@
fn array_and_vec() -> ([i32; 4], Vec<i32>) {
let a = [10, 20, 30, 40]; // Array
// Used the `vec!` macro.
let v = vec![10, 20, 30, 40];
(a, v)
fn elems_to_vec(a: i32, b: i32, c: i32) -> Vec<i32> {
vec![a, b, c]
}
fn main() {
@@ -16,8 +11,11 @@ mod tests {
use super::*;
#[test]
fn test_array_and_vec_similarity() {
let (a, v) = array_and_vec();
assert_eq!(a, *v);
fn test_elems_to_vec() {
let (a, b, c) = (2, 7, 12);
let v = elems_to_vec(a, b, c);
assert_eq!(v[0], a);
assert_eq!(v[1], b);
assert_eq!(v[2], c);
}
}

View File

@@ -8,22 +8,6 @@ fn vec_loop(input: &[i32]) -> Vec<i32> {
output
}
fn vec_map_example(input: &[i32]) -> Vec<i32> {
// An example of collecting a vector after mapping.
// We map each element of the `input` slice to its value plus 1.
// If the input is `[1, 2, 3]`, the output is `[2, 3, 4]`.
input.iter().map(|element| element + 1).collect()
}
fn vec_map(input: &[i32]) -> Vec<i32> {
// We will dive deeper into iterators, but for now, this is all what you
// had to do!
// Advanced note: This method is more efficient because it automatically
// preallocates enough capacity. This can be done manually in `vec_loop`
// using `Vec::with_capacity(input.len())` instead of `Vec::new()`.
input.iter().map(|element| 2 * element).collect()
}
fn main() {
// You can optionally experiment here.
}
@@ -38,18 +22,4 @@ mod tests {
let ans = vec_loop(&input);
assert_eq!(ans, [4, 8, 12, 16, 20]);
}
#[test]
fn test_vec_map_example() {
let input = [1, 2, 3];
let ans = vec_map_example(&input);
assert_eq!(ans, [2, 3, 4]);
}
#[test]
fn test_vec_map() {
let input = [2, 4, 6, 8, 10];
let ans = vec_map(&input);
assert_eq!(ans, [4, 8, 12, 16, 20]);
}
}

View File

@@ -4,8 +4,6 @@ fn main() {
#[cfg(test)]
mod tests {
// TODO: Fix the compiler errors only by reordering the lines in the test.
// Don't add, change or remove any line.
#[test]
fn move_semantics4() {
let mut x = Vec::new();

View File

@@ -1,33 +1,21 @@
#![deny(clippy::use_self)] // practice using the `Self` type
#[derive(Debug)]
struct Package {
sender_country: String,
recipient_country: String,
weight_in_grams: u32,
struct Fireworks {
rockets: usize,
}
impl Package {
fn new(sender_country: String, recipient_country: String, weight_in_grams: u32) -> Self {
if weight_in_grams < 10 {
// This isn't how you should handle errors in Rust, but we will
// learn about error handling later.
panic!("Can't ship a package with weight below 10 grams");
}
Self {
sender_country,
recipient_country,
weight_in_grams,
}
impl Fireworks {
fn new() -> Self {
Self { rockets: 0 }
}
fn is_international(&self) -> bool {
// ^^^^^^^ added
self.sender_country != self.recipient_country
fn add_rockets(&mut self, rockets: usize) {
self.rockets += rockets
}
fn get_fees(&self, cents_per_gram: u32) -> u32 {
// ^^^^^^ added
self.weight_in_grams * cents_per_gram
fn start(self) -> String {
"🚀".repeat(self.rockets)
}
}
@@ -40,44 +28,18 @@ mod tests {
use super::*;
#[test]
#[should_panic]
fn fail_creating_weightless_package() {
let sender_country = String::from("Spain");
let recipient_country = String::from("Austria");
fn start_some_fireworks() {
let f = Fireworks::new();
assert_eq!(f.start(), "");
Package::new(sender_country, recipient_country, 5);
}
let mut f = Fireworks::new();
f.add_rockets(3);
assert_eq!(f.start(), "🚀🚀🚀");
#[test]
fn create_international_package() {
let sender_country = String::from("Spain");
let recipient_country = String::from("Russia");
let package = Package::new(sender_country, recipient_country, 1200);
assert!(package.is_international());
}
#[test]
fn create_local_package() {
let sender_country = String::from("Canada");
let recipient_country = sender_country.clone();
let package = Package::new(sender_country, recipient_country, 1200);
assert!(!package.is_international());
}
#[test]
fn calculate_transport_fees() {
let sender_country = String::from("Spain");
let recipient_country = String::from("Spain");
let cents_per_gram = 3;
let package = Package::new(sender_country, recipient_country, 1500);
assert_eq!(package.get_fees(cents_per_gram), 4500);
assert_eq!(package.get_fees(cents_per_gram * 2), 9000);
let mut f = Fireworks::new();
f.add_rockets(7);
// We don't use method syntax in the last test to ensure the `start`
// function takes ownership of the fireworks.
assert_eq!(Fireworks::start(f), "🚀🚀🚀🚀🚀🚀🚀");
}
}

View File

@@ -1,5 +1,3 @@
#![allow(dead_code)]
#[derive(Debug)]
struct Point {
x: u64,

View File

@@ -46,8 +46,8 @@ impl State {
match message {
Message::Resize { width, height } => self.resize(width, height),
Message::Move(point) => self.move_position(point),
Message::Echo(s) => self.echo(s),
Message::ChangeColor(r, g, b) => self.change_color(r, g, b),
Message::Echo(string) => self.echo(string),
Message::ChangeColor(red, green, blue) => self.change_color(red, green, blue),
Message::Quit => self.quit(),
}
}

View File

@@ -26,6 +26,7 @@ mod tests {
assert_eq!(trim_me("Hello! "), "Hello!");
assert_eq!(trim_me(" What's up!"), "What's up!");
assert_eq!(trim_me(" Hola! "), "Hola!");
assert_eq!(trim_me("Hi!"), "Hi!");
}
#[test]

View File

@@ -15,16 +15,6 @@ fn main() {
string("rust is fun!".to_owned());
// Here, both answers work.
// `.into()` converts a type into an expected type.
// If it is called where `String` is expected, it will convert `&str` to `String`.
// But if is called where `&str` is expected, then `&str` is kept `&str` since no
// conversion is needed.
string("nice weather".into());
string_slice("nice weather".into());
// ^^^^^^^ the compiler recommends removing the `.into()`
// call because it is a useless conversion.
string(format!("Interpolation {}", "Station"));
// WARNING: This is byte indexing, not character indexing.

View File

@@ -1,4 +1,3 @@
#[allow(dead_code)]
mod delicious_snacks {
// Added `pub` and used the expected alias after `as`.
pub use self::fruits::PEAR as fruit;

View File

@@ -1,7 +1,7 @@
// A basket of fruits in the form of a hash map needs to be defined. The key
// represents the name of the fruit and the value represents how many of that
// particular fruit is in the basket. You have to put at least 3 different
// types of fruits (e.g apple, banana, mango) in the basket and the total count
// types of fruits (e.g. apple, banana, mango) in the basket and the total count
// of all the fruits should be at least 5.
use std::collections::HashMap;

View File

@@ -5,7 +5,8 @@
// Apple (4), Mango (2) and Lychee (5) are already in the basket hash map. You
// must add fruit to the basket so that there is at least one of each kind and
// more than 11 in total - we have a lot of mouths to feed. You are not allowed
// to insert any more of these fruits!
// to insert any more of the fruits that are already in the basket (Apple,
// Mango, and Lychee).
use std::collections::HashMap;

View File

@@ -10,14 +10,14 @@ use std::collections::HashMap;
// A structure to store the goal details of a team.
#[derive(Default)]
struct Team {
struct TeamScores {
goals_scored: u8,
goals_conceded: u8,
}
fn build_scores_table(results: &str) -> HashMap<&str, Team> {
fn build_scores_table(results: &str) -> HashMap<&str, TeamScores> {
// The name of the team is the key and its associated struct is the value.
let mut scores = HashMap::new();
let mut scores = HashMap::<&str, TeamScores>::new();
for line in results.lines() {
let mut split_iterator = line.split(',');
@@ -28,13 +28,13 @@ fn build_scores_table(results: &str) -> HashMap<&str, Team> {
let team_2_score: u8 = split_iterator.next().unwrap().parse().unwrap();
// Insert the default with zeros if a team doesn't exist yet.
let team_1 = scores.entry(team_1_name).or_insert_with(Team::default);
let team_1 = scores.entry(team_1_name).or_default();
// Update the values.
team_1.goals_scored += team_1_score;
team_1.goals_conceded += team_2_score;
// Similarely for the second team.
let team_2 = scores.entry(team_2_name).or_insert_with(Team::default);
// Similarly for the second team.
let team_2 = scores.entry(team_2_name).or_default();
team_2.goals_scored += team_2_score;
team_2.goals_conceded += team_1_score;
}
@@ -60,9 +60,11 @@ England,Spain,1,0";
fn build_scores() {
let scores = build_scores_table(RESULTS);
assert!(["England", "France", "Germany", "Italy", "Poland", "Spain"]
.into_iter()
.all(|team_name| scores.contains_key(team_name)));
assert!(
["England", "France", "Germany", "Italy", "Poland", "Spain"]
.into_iter()
.all(|team_name| scores.contains_key(team_name))
);
}
#[test]

View File

@@ -1,8 +1,8 @@
// This function returns how much icecream there is left in the fridge.
// This function returns how much ice cream there is left in the fridge.
// If it's before 22:00 (24-hour system), then 5 scoops are left. At 22:00,
// someone eats it all, so no icecream is left (value 0). Return `None` if
// someone eats it all, so no ice cream is left (value 0). Return `None` if
// `hour_of_day` is higher than 23.
fn maybe_icecream(hour_of_day: u16) -> Option<u16> {
fn maybe_ice_cream(hour_of_day: u16) -> Option<u16> {
match hour_of_day {
0..=21 => Some(5),
22..=23 => Some(0),
@@ -21,19 +21,19 @@ mod tests {
#[test]
fn raw_value() {
// Using `unwrap` is fine in a test.
let icecreams = maybe_icecream(12).unwrap();
let ice_creams = maybe_ice_cream(12).unwrap();
assert_eq!(icecreams, 5);
assert_eq!(ice_creams, 5);
}
#[test]
fn check_icecream() {
assert_eq!(maybe_icecream(0), Some(5));
assert_eq!(maybe_icecream(9), Some(5));
assert_eq!(maybe_icecream(18), Some(5));
assert_eq!(maybe_icecream(22), Some(0));
assert_eq!(maybe_icecream(23), Some(0));
assert_eq!(maybe_icecream(24), None);
assert_eq!(maybe_icecream(25), None);
fn check_ice_cream() {
assert_eq!(maybe_ice_cream(0), Some(5));
assert_eq!(maybe_ice_cream(9), Some(5));
assert_eq!(maybe_ice_cream(18), Some(5));
assert_eq!(maybe_ice_cream(22), Some(0));
assert_eq!(maybe_ice_cream(23), Some(0));
assert_eq!(maybe_ice_cream(24), None);
assert_eq!(maybe_ice_cream(25), None);
}
}

View File

@@ -10,7 +10,7 @@ fn main() {
// Solution 1: Matching over the `Option` (not `&Option`) but without moving
// out of the `Some` variant.
match optional_point {
Some(ref p) => println!("Co-ordinates are {},{}", p.x, p.y),
Some(ref p) => println!("Coordinates are {},{}", p.x, p.y),
// ^^^ added
_ => panic!("No match!"),
}
@@ -18,7 +18,8 @@ fn main() {
// Solution 2: Matching over a reference (`&Option`) by added `&` before
// `optional_point`.
match &optional_point {
Some(p) => println!("Co-ordinates are {},{}", p.x, p.y),
//^ added
Some(p) => println!("Coordinates are {},{}", p.x, p.y),
_ => panic!("No match!"),
}

View File

@@ -16,7 +16,7 @@
use std::num::ParseIntError;
#[allow(unused_variables)]
#[allow(unused_variables, clippy::question_mark)]
fn total_cost(item_quantity: &str) -> Result<i32, ParseIntError> {
let processing_fee = 1;
let cost_per_item = 5;

View File

@@ -1,4 +1,4 @@
#![allow(clippy::comparison_chain)]
use std::cmp::Ordering;
#[derive(PartialEq, Debug)]
enum CreationError {
@@ -11,12 +11,10 @@ struct PositiveNonzeroInteger(u64);
impl PositiveNonzeroInteger {
fn new(value: i64) -> Result<Self, CreationError> {
if value == 0 {
Err(CreationError::Zero)
} else if value < 0 {
Err(CreationError::Negative)
} else {
Ok(Self(value as u64))
match value.cmp(&0) {
Ordering::Less => Err(CreationError::Negative),
Ordering::Equal => Err(CreationError::Zero),
Ordering::Greater => Ok(Self(value as u64)),
}
}
}

View File

@@ -6,7 +6,7 @@
//
// In short, this particular use case for boxes is for when you want to own a
// value and you care only that it is a type which implements a particular
// trait. To do so, The `Box` is declared as of type `Box<dyn Trait>` where
// trait. To do so, the `Box` is declared as of type `Box<dyn Trait>` where
// `Trait` is the trait the compiler looks for on any value used in that
// context. For this exercise, that context is the potential errors which
// can be returned in a `Result`.

View File

@@ -19,13 +19,18 @@ enum ParsePosNonzeroError {
ParseInt(ParseIntError),
}
impl ParsePosNonzeroError {
fn from_creation(err: CreationError) -> Self {
Self::Creation(err)
}
fn from_parseint(err: ParseIntError) -> Self {
Self::ParseInt(err)
// As an alternative solution, implementing the `From` trait allows for the
// automatic conversion from a `ParseIntError` into a `ParsePosNonzeroError`
// using the `?` operator, without the need to call `map_err`.
//
// ```
// let x: i64 = s.parse()?;
// ```
//
// Traits like `From` will be dealt with in later exercises.
impl From<ParseIntError> for ParsePosNonzeroError {
fn from(err: ParseIntError) -> Self {
ParsePosNonzeroError::ParseInt(err)
}
}
@@ -44,9 +49,9 @@ impl PositiveNonzeroInteger {
fn parse(s: &str) -> Result<Self, ParsePosNonzeroError> {
// Return an appropriate error instead of panicking when `parse()`
// returns an error.
let x: i64 = s.parse().map_err(ParsePosNonzeroError::from_parseint)?;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Self::new(x).map_err(ParsePosNonzeroError::from_creation)
let x: i64 = s.parse().map_err(ParsePosNonzeroError::ParseInt)?;
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Self::new(x).map_err(ParsePosNonzeroError::Creation)
}
}

View File

@@ -1,5 +1,3 @@
#![allow(dead_code)]
trait Licensed {
fn licensing_info(&self) -> String {
"Default license".to_string()

View File

@@ -5,11 +5,7 @@
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
// ^^^^ ^^ ^^ ^^
if x.len() > y.len() {
x
} else {
y
}
if x.len() > y.len() { x } else { y }
}
fn main() {

View File

@@ -1,14 +1,10 @@
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
if x.len() > y.len() { x } else { y }
}
fn main() {
let string1 = String::from("long string is long");
// Solution1: You can move `strings2` out of the inner block so that it is
// Solution 1: You can move `strings2` out of the inner block so that it is
// not dropped before the print statement.
let string2 = String::from("xyz");
let result;
@@ -25,7 +21,7 @@ fn main() {
{
let string2 = String::from("xyz");
result = longest(&string1, &string2);
// Solution2: You can move the print statement into the inner block so
// Solution 2: You can move the print statement into the inner block so
// that it is executed before `string2` is dropped.
println!("The longest string is '{result}'");
// `string2` dropped here (end of the inner scope).

View File

@@ -9,7 +9,7 @@ impl Rectangle {
if width <= 0 || height <= 0 {
// Returning a `Result` would be better here. But we want to learn
// how to test functions that can panic.
panic!("Rectangle width and height can't be negative");
panic!("Rectangle width and height must be positive");
}
Rectangle { width, height }

View File

@@ -10,9 +10,9 @@ fn main() {
mod tests {
#[test]
fn iterators() {
let my_fav_fruits = ["banana", "custard apple", "avocado", "peach", "raspberry"];
let my_fav_fruits = &["banana", "custard apple", "avocado", "peach", "raspberry"];
// Create an iterator over the array.
// Create an iterator over the slice.
let mut fav_fruits_iterator = my_fav_fruits.iter();
assert_eq!(fav_fruits_iterator.next(), Some(&"banana"));

View File

@@ -52,6 +52,8 @@ mod tests {
#[test]
fn test_success() {
assert_eq!(divide(81, 9), Ok(9));
assert_eq!(divide(81, -1), Ok(-81));
assert_eq!(divide(i64::MIN, i64::MIN), Ok(1));
}
#[test]

View File

@@ -25,6 +25,7 @@ fn factorial_fold(num: u64) -> u64 {
// -> 1 * 2 is calculated, then the result 2 is multiplied by
// the second element 3 so the result 6 is returned.
// And so on…
#[allow(clippy::unnecessary_fold)]
(2..=num).fold(1, |acc, x| acc * x)
}

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