diff --git a/.all-contributorsrc b/.all-contributorsrc index bdcf53c6..1ad4d589 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -2037,6 +2037,339 @@ "contributions": [ "content" ] + }, + { + "login": "smlavine", + "name": "Sebastian LaVine", + "avatar_url": "https://avatars.githubusercontent.com/u/33563640?v=4", + "profile": "http://smlavine.com", + "contributions": [ + "code" + ] + }, + { + "login": "akgerber", + "name": "Alan Gerber", + "avatar_url": "https://avatars.githubusercontent.com/u/201313?v=4", + "profile": "http://www.alangerber.us", + "contributions": [ + "content" + ] + }, + { + "login": "esotuvaka", + "name": "Eric", + "avatar_url": "https://avatars.githubusercontent.com/u/104941850?v=4", + "profile": "http://esotuvaka.github.io", + "contributions": [ + "content" + ] + }, + { + "login": "az0977776", + "name": "Aaron Wang", + "avatar_url": "https://avatars.githubusercontent.com/u/9172038?v=4", + "profile": "https://github.com/az0977776", + "contributions": [ + "content" + ] + }, + { + "login": "nmay231", + "name": "Noah", + "avatar_url": "https://avatars.githubusercontent.com/u/35386821?v=4", + "profile": "https://github.com/nmay231", + "contributions": [ + "content" + ] + }, + { + "login": "rb5014", + "name": "rb5014", + "avatar_url": "https://avatars.githubusercontent.com/u/105397317?v=4", + "profile": "https://github.com/rb5014", + "contributions": [ + "content" + ] + }, + { + "login": "deedy5", + "name": "deedy5", + "avatar_url": "https://avatars.githubusercontent.com/u/65482418?v=4", + "profile": "https://github.com/deedy5", + "contributions": [ + "content" + ] + }, + { + "login": "lionel-rowe", + "name": "lionel-rowe", + "avatar_url": "https://avatars.githubusercontent.com/u/26078826?v=4", + "profile": "https://github.com/lionel-rowe", + "contributions": [ + "content" + ] + }, + { + "login": "Ben2917", + "name": "Ben", + "avatar_url": "https://avatars.githubusercontent.com/u/10279994?v=4", + "profile": "https://github.com/Ben2917", + "contributions": [ + "content" + ] + }, + { + "login": "b1ue64", + "name": "b1ue64", + "avatar_url": "https://avatars.githubusercontent.com/u/77976308?v=4", + "profile": "https://github.com/b1ue64", + "contributions": [ + "content" + ] + }, + { + "login": "lazywalker", + "name": "lazywalker", + "avatar_url": "https://avatars.githubusercontent.com/u/53956?v=4", + "profile": "https://github.com/lazywalker", + "contributions": [ + "content" + ] + }, + { + "login": "proofconstruction", + "name": "proofconstruction", + "avatar_url": "https://avatars.githubusercontent.com/u/74747193?v=4", + "profile": "https://github.com/proofconstruction", + "contributions": [ + "infra" + ] + }, + { + "login": "IVIURRAY", + "name": "IVIURRAY", + "avatar_url": "https://avatars.githubusercontent.com/u/16007179?v=4", + "profile": "https://www.youtube.com/channel/UCQCjA6qUutAtWqkCA4Z36CQ", + "contributions": [ + "content" + ] + }, + { + "login": "b-apperlo", + "name": "Bert Apperlo", + "avatar_url": "https://avatars.githubusercontent.com/u/91734527?v=4", + "profile": "https://github.com/b-apperlo", + "contributions": [ + "content" + ] + }, + { + "login": "FWDekker", + "name": "Florine W. Dekker", + "avatar_url": "https://avatars.githubusercontent.com/u/13442533?v=4", + "profile": "https://fwdekker.com/", + "contributions": [ + "content" + ] + }, + { + "login": "luhem7", + "name": "Mehul Gangavelli", + "avatar_url": "https://avatars.githubusercontent.com/u/4008215?v=4", + "profile": "https://github.com/luhem7", + "contributions": [ + "content" + ] + }, + { + "login": "Frosthage", + "name": "Mikael Frosthage", + "avatar_url": "https://avatars.githubusercontent.com/u/14823314?v=4", + "profile": "https://github.com/Frosthage", + "contributions": [ + "content" + ] + }, + { + "login": "robertefry", + "name": "Robert Fry", + "avatar_url": "https://avatars.githubusercontent.com/u/43712054?v=4", + "profile": "https://robertfry.xyz", + "contributions": [ + "content" + ] + }, + { + "login": "tajo48", + "name": "tajo48", + "avatar_url": "https://avatars.githubusercontent.com/u/55502906?v=4", + "profile": "https://github.com/tajo48", + "contributions": [ + "content" + ] + }, + { + "login": "novanish", + "name": "Anish", + "avatar_url": "https://avatars.githubusercontent.com/u/98446102?v=4", + "profile": "https://anishchhetri.com.np", + "contributions": [ + "content" + ] + }, + { + "login": "vnprc", + "name": "vnprc", + "avatar_url": "https://avatars.githubusercontent.com/u/9425366?v=4", + "profile": "https://github.com/vnprc", + "contributions": [ + "content" + ] + }, + { + "login": "jrcarl624", + "name": "Joshua Carlson", + "avatar_url": "https://avatars.githubusercontent.com/u/61999256?v=4", + "profile": "http://androecia.net", + "contributions": [ + "content" + ] + }, + { + "login": "johnDeSilencio", + "name": "Nicholas R. Smith", + "avatar_url": "https://avatars.githubusercontent.com/u/20136554?v=4", + "profile": "https://johndesilencio.me", + "contributions": [ + "code" + ] + }, + { + "login": "alexfertel", + "name": "Alexander González", + "avatar_url": "https://avatars.githubusercontent.com/u/22298999?v=4", + "profile": "https://alexfertel.me", + "contributions": [ + "content" + ] + }, + { + "login": "softarn", + "name": "Marcus Höjvall", + "avatar_url": "https://avatars.githubusercontent.com/u/517619?v=4", + "profile": "https://github.com/softarn", + "contributions": [ + "content" + ] + }, + { + "login": "barlevalon", + "name": "Alon Hearter", + "avatar_url": "https://avatars.githubusercontent.com/u/3397911?v=4", + "profile": "https://github.com/barlevalon", + "contributions": [ + "content" + ] + }, + { + "login": "shirts", + "name": "shirts", + "avatar_url": "https://avatars.githubusercontent.com/u/4952151?v=4", + "profile": "https://github.com/shirts", + "contributions": [ + "content" + ] + }, + { + "login": "eLVas", + "name": "Ivan Vasiunyk", + "avatar_url": "https://avatars.githubusercontent.com/u/6797156?v=4", + "profile": "https://github.com/eLVas", + "contributions": [ + "content" + ] + }, + { + "login": "mo8it", + "name": "Mo", + "avatar_url": "https://avatars.githubusercontent.com/u/76752051?v=4", + "profile": "https://mo8it.com", + "contributions": [ + "code" + ] + }, + { + "login": "x10an14", + "name": "x10an14", + "avatar_url": "https://avatars.githubusercontent.com/u/710608?v=4", + "profile": "https://github.com/x10an14", + "contributions": [ + "infra" + ] + }, + { + "login": "gabay", + "name": "Roi Gabay", + "avatar_url": "https://avatars.githubusercontent.com/u/5773610?v=4", + "profile": "https://github.com/gabay", + "contributions": [ + "content" + ] + }, + { + "login": "mkovaxx", + "name": "Máté Kovács", + "avatar_url": "https://avatars.githubusercontent.com/u/481354?v=4", + "profile": "https://github.com/mkovaxx", + "contributions": [ + "content" + ] + }, + { + "login": "szabgab", + "name": "Gábor Szabó", + "avatar_url": "https://avatars.githubusercontent.com/u/48833?v=4", + "profile": "https://szabgab.com/", + "contributions": [ + "content" + ] + }, + { + "login": "yamila-moreno", + "name": "Yamila Moreno", + "avatar_url": "https://avatars.githubusercontent.com/u/3340793?v=4", + "profile": "https://moduslaborandi.net", + "contributions": [ + "content" + ] + }, + { + "login": "willhack", + "name": "Will Hack", + "avatar_url": "https://avatars.githubusercontent.com/u/18036720?v=4", + "profile": "https://github.com/willhack", + "contributions": [ + "content" + ] + }, + { + "login": "bean5", + "name": "Michael", + "avatar_url": "https://avatars.githubusercontent.com/u/2052646?v=4", + "profile": "http://cancompute.tech", + "contributions": [ + "content" + ] + }, + { + "login": "pksadiq", + "name": "Mohammed Sadiq", + "avatar_url": "https://avatars.githubusercontent.com/u/1289514?v=4", + "profile": "https://www.sadiqpk.org", + "contributions": [ + "content" + ] } ], "contributorsPerLine": 8, @@ -2045,5 +2378,6 @@ "repoType": "github", "repoHost": "https://github.com", "skipCi": true, - "commitConvention": "angular" + "commitConvention": "angular", + "commitType": "docs" } diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..48541064 --- /dev/null +++ b/.envrc @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +# Automatically Load nix devShell w/dotenv +use flake diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index bf2a041a..1b244b1a 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -14,6 +14,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 + - name: Fetch & maybe update Cargo.lock + run: cargo fetch --locked - name: Build run: cargo build --verbose - name: Run tests diff --git a/.gitignore b/.gitignore index c14f9227..f319d39d 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,8 @@ rust-project.json !.vscode/extensions.json *.iml *.o +public/ +.direnv/ + +# Local Netlify folder +.netlify diff --git a/AUTHORS.md b/AUTHORS.md index 9e757bc2..54ead917 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -288,6 +288,53 @@ authors. Aaron Suggs
Aaron Suggs

🖋 Alex
Alex

🖋 Sebastian Törnquist
Sebastian Törnquist

🖋 + Sebastian LaVine
Sebastian LaVine

💻 + + + Alan Gerber
Alan Gerber

🖋 + Eric
Eric

🖋 + Aaron Wang
Aaron Wang

🖋 + Noah
Noah

🖋 + rb5014
rb5014

🖋 + deedy5
deedy5

🖋 + lionel-rowe
lionel-rowe

🖋 + Ben
Ben

🖋 + + + b1ue64
b1ue64

🖋 + lazywalker
lazywalker

🖋 + proofconstruction
proofconstruction

🚇 + IVIURRAY
IVIURRAY

🖋 + Bert Apperlo
Bert Apperlo

🖋 + Florine W. Dekker
Florine W. Dekker

🖋 + Mehul Gangavelli
Mehul Gangavelli

🖋 + Mikael Frosthage
Mikael Frosthage

🖋 + + + Robert Fry
Robert Fry

🖋 + tajo48
tajo48

🖋 + Anish
Anish

🖋 + vnprc
vnprc

🖋 + Joshua Carlson
Joshua Carlson

🖋 + Nicholas R. Smith
Nicholas R. Smith

💻 + Alexander González
Alexander González

🖋 + Marcus Höjvall
Marcus Höjvall

🖋 + + + Alon Hearter
Alon Hearter

🖋 + shirts
shirts

🖋 + Ivan Vasiunyk
Ivan Vasiunyk

🖋 + Mo
Mo

💻 + x10an14
x10an14

🚇 + Roi Gabay
Roi Gabay

🖋 + Máté Kovács
Máté Kovács

🖋 + Gábor Szabó
Gábor Szabó

🖋 + + + Yamila Moreno
Yamila Moreno

🖋 + Will Hack
Will Hack

🖋 + Michael
Michael

🖋 + Mohammed Sadiq
Mohammed Sadiq

🖋 diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c14e7d7..a802faaf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,45 @@ + +## 5.5.1 (2023-05-17) + +#### Fixed + +- Reverted `rust-project.json` path generation due to an upstream `rust-analyzer` fix. + + +## 5.5.0 (2023-05-17) + +#### Added + +- `strings2`: Added a reference to the book chapter for reference conversion +- `lifetimes`: Added a link to the lifetimekata project +- Added a new `tests4` exercises, which teaches about testing for panics +- 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 + +- `vecs2`: Renamed iterator variable bindings for clarify +- `lifetimes`: Changed order of book references +- `hashmaps2`: Clarified instructions in the todo block +- Moved lifetime exercises before test exercises (via the recommended book ordering) +- `options2`: Improved tests for layering options +- `modules2`: Added more information to the hint + +#### Fixed + +- `errors2`: Corrected a comment wording +- `iterators2`: Fixed a spelling mistake in the hint text +- `variables`: Wrapped the mut keyword with backticks for readability +- `move_semantics2`: Removed references to line numbers +- `cow1`: Clarified the `owned_no_mutation` comments +- `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 + +- Added a markdown linter to run on GitHub actions +- Split quick installation section into two code blocks + ## 5.4.1 (2023-03-10) diff --git a/Cargo.lock b/Cargo.lock index 192a4ac0..e5b85530 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,18 +4,66 @@ version = 3 [[package]] name = "aho-corasick" -version = "0.7.20" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783" dependencies = [ "memchr", ] [[package]] -name = "argh" -version = "0.1.10" +name = "anstream" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab257697eb9496bf75526f0217b5ed64636a9cfafa78b8365c71bd283fcef93e" +checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15c4c2c83f81532e5845a733998b6971faca23490340a418e9b72a3ec9de12ea" + +[[package]] +name = "anstyle-parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "anstyle-wincon" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" +dependencies = [ + "anstyle", + "windows-sys 0.48.0", +] + +[[package]] +name = "argh" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7af5ba06967ff7214ce4c7419c7d185be7ecd6cc4965a8f6e1d8ce0398aad219" dependencies = [ "argh_derive", "argh_shared", @@ -23,32 +71,38 @@ dependencies = [ [[package]] name = "argh_derive" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b382dbd3288e053331f03399e1db106c9fb0d8562ad62cb04859ae926f324fa6" +checksum = "56df0aeedf6b7a2fc67d06db35b09684c3e8da0c95f8f27685cb17e08413d87a" dependencies = [ "argh_shared", "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] name = "argh_shared" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64cb94155d965e3d37ffbbe7cc5b82c3dd79dd33bd48e536f73d2cfb8d85506f" +checksum = "5693f39141bda5760ecc4111ab08da40565d1771038c4a0250f03457ec707531" +dependencies = [ + "serde", +] [[package]] name = "assert_cmd" -version = "0.11.1" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc477793bd82ec39799b6f6b3df64938532fdf2ab0d49ef817eac65856a5a1e" +checksum = "88903cb14723e4d4003335bb7f8a14f27691649105346a0f0957466c096adfe6" dependencies = [ - "escargot", + "anstyle", + "bstr", + "doc-comment", "predicates", "predicates-core", "predicates-tree", + "wait-timeout", ] [[package]] @@ -63,6 +117,17 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bstr" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c2f7349907b712260e64b0afe2f84692af14a454be26187d9df565c7f69266a" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + [[package]] name = "cfg-if" version = "0.1.10" @@ -76,23 +141,81 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "console" -version = "0.15.5" +name = "clap" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60" +checksum = "6a13b88d2c62ff462f88e4a121f17a82c1af05693a2f192b5c38d14de73c19f6" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "console" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" dependencies = [ "encode_unicode", "lazy_static", "libc", "unicode-width", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] -name = "difference" -version = "2.0.0" +name = "difflib" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "encode_unicode" @@ -101,34 +224,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] -name = "escargot" -version = "0.4.0" +name = "equivalent" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceb9adbf9874d5d028b5e4c5739d22b71988252b25c9c98fe7cf9738bee84597" -dependencies = [ - "lazy_static", - "log", - "serde", - "serde_json", -] +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "filetime" -version = "0.2.20" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" +checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] name = "float-cmp" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1267f4ac4f343772758f7b1bdcbe767c218bbab93bb432acbf5162bbf85a6c4" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" dependencies = [ "num-traits", ] @@ -175,24 +292,47 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] -name = "home" -version = "0.5.4" +name = "hashbrown" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747309b4b440c06d57b0b25f2aee03ee9b5e5397d288c60e21fc709bb98a7408" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" dependencies = [ - "winapi 0.3.9", + "windows-sys 0.48.0", +] + +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown", ] [[package]] name = "indicatif" -version = "0.16.2" +version = "0.17.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d207dc617c7a380ab07ff572a6e52fa202a2a8f355860ac9c38e23f8196be1b" +checksum = "0b297dc40733f23a0e52728a58fa9489a5b7638a324932de16b41adc3ef80730" dependencies = [ "console", - "lazy_static", + "instant", "number_prefix", - "regex", + "portable-atomic", + "unicode-width", ] [[package]] @@ -215,6 +355,15 @@ dependencies = [ "libc", ] +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if 1.0.0", +] + [[package]] name = "iovec" version = "0.1.4" @@ -225,10 +374,19 @@ dependencies = [ ] [[package]] -name = "itoa" -version = "1.0.6" +name = "itertools" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "kernel32-sys" @@ -254,24 +412,21 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.140" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "log" -version = "0.4.17" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if 1.0.0", -] +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" [[package]] name = "mio" @@ -318,9 +473,9 @@ dependencies = [ [[package]] name = "net2" -version = "0.2.38" +version = "0.2.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d0df99cfcd2530b2e694f6e17e7f37b8e26bb23983ac530c0c97408837c631" +checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" dependencies = [ "cfg-if 0.1.10", "libc", @@ -353,9 +508,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] @@ -367,13 +522,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] -name = "predicates" -version = "1.0.8" +name = "portable-atomic" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f49cfaf7fdaa3bfacc6fa3e7054e65148878354a5cfddcf661df4c851f8021df" +checksum = "31114a898e107c51bb1609ffaf55a0e011cf6a4d7f1170d0015a165082c0338b" + +[[package]] +name = "predicates" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09963355b9f467184c04017ced4a2ba2d75cbcb4e7462690d388233253d4b1a9" dependencies = [ - "difference", + "anstyle", + "difflib", "float-cmp", + "itertools", "normalize-line-endings", "predicates-core", "regex", @@ -397,36 +560,48 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.53" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.26" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ "bitflags", ] [[package]] name = "regex" -version = "1.7.2" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cce168fea28d3e05f158bda4576cf0c844d5045bc2cc3620fa0292ed5bb5814c" +checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" dependencies = [ "aho-corasick", "memchr", @@ -435,16 +610,17 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.29" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "rustlings" -version = "5.4.1" +version = "5.5.1" dependencies = [ "argh", "assert_cmd", + "clap", "console", "glob", "home", @@ -459,9 +635,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "same-file" @@ -474,29 +650,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.158" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.158" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.8", + "syn", ] [[package]] name = "serde_json" -version = "1.0.94" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" +checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" dependencies = [ "itoa", "ryu", @@ -504,30 +680,34 @@ dependencies = [ ] [[package]] -name = "slab" -version = "0.4.8" +name = "serde_spanned" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +dependencies = [ + "serde", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] -name = "syn" -version = "1.0.109" +name = "strsim" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "2.0.8" +version = "2.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9" +checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398" dependencies = [ "proc-macro2", "quote", @@ -542,18 +722,43 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "toml" -version = "0.5.11" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" dependencies = [ "serde", ] [[package]] -name = "unicode-ident" -version = "1.0.8" +name = "toml_edit" +version = "0.19.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "unicode-ident" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "unicode-width" @@ -561,6 +766,21 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + [[package]] name = "walkdir" version = "2.3.3" @@ -614,28 +834,22 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - [[package]] name = "windows-sys" version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ - "windows-targets", + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", ] [[package]] @@ -644,13 +858,28 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -659,42 +888,93 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_i686_gnu" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "winnow" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc" +dependencies = [ + "memchr", +] + [[package]] name = "ws2_32-sys" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index d22816ca..2c2a92b2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "rustlings" -version = "5.4.1" +description = "Small exercises to get you used to reading and writing Rust code!" +version = "5.5.1" authors = [ "Liv ", "Carol (Nichols || Goulding) ", @@ -9,21 +10,22 @@ edition = "2021" [dependencies] argh = "0.1" -indicatif = "0.16" +indicatif = "0.17.6" console = "0.15" notify = "4.0" -toml = "0.5" +toml = "0.7.6" regex = "1.5" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.81" home = "0.5.3" glob = "0.3.0" +clap = { version = "4.4.0", features = ["derive"] } [[bin]] name = "rustlings" path = "src/main.rs" [dev-dependencies] -assert_cmd = "0.11.0" -predicates = "1.0.1" +assert_cmd = "2.0.12" +predicates = "3.0.3" glob = "0.3.0" diff --git a/README.md b/README.md index be470fdb..300aee37 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ +
+ # rustlings 🦀❤️ +
+ 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! _...looking for the old, web-based version of Rustlings? Try [here](https://github.com/rust-lang/rustlings/tree/rustlings-1)_ @@ -14,7 +18,7 @@ Alternatively, for a first-time Rust learner, there are several other resources: _Note: If you're on MacOS, make sure you've installed Xcode and its developer tools by typing `xcode-select --install`._ _Note: If you're on Linux, make sure you've installed gcc. Deb: `sudo apt install gcc`. Yum: `sudo yum -y install gcc`._ -You will need to have Rust installed. You can get it by visiting https://rustup.rs. This'll also install Cargo, Rust's package/project manager. +You will need to have Rust installed. You can get it by visiting . This'll also install Cargo, Rust's package/project manager. ## MacOS/Linux @@ -23,6 +27,7 @@ Just run: ```bash curl -L https://raw.githubusercontent.com/rust-lang/rustlings/main/install.sh | bash ``` + Or if you want it to be installed to a different path: ```bash @@ -36,8 +41,8 @@ This will install Rustlings and give you access to the `rustlings` command. Run Basically: Clone the repository at the latest tag, finally run `nix develop` or `nix-shell`. ```bash -# find out the latest version at https://github.com/rust-lang/rustlings/releases/latest (on edit 5.4.1) -git clone -b 5.4.1 --depth 1 https://github.com/rust-lang/rustlings +# find out the latest version at https://github.com/rust-lang/rustlings/releases/latest (on edit 5.5.1) +git clone -b 5.5.1 --depth 1 https://github.com/rust-lang/rustlings cd rustlings # if nix version > 2.3 nix develop @@ -74,8 +79,8 @@ If you get a permission denied message, you might have to exclude the directory Basically: Clone the repository at the latest tag, run `cargo install --path .`. ```bash -# find out the latest version at https://github.com/rust-lang/rustlings/releases/latest (on edit 5.4.1) -git clone -b 5.4.1 --depth 1 https://github.com/rust-lang/rustlings +# find out the latest version at https://github.com/rust-lang/rustlings/releases/latest (on edit 5.5.1) +git clone -b 5.5.1 --depth 1 https://github.com/rust-lang/rustlings cd rustlings cargo install --force --path . ``` diff --git a/exercises/clippy/clippy1.rs b/exercises/clippy/clippy1.rs index bad46891..95c0141f 100644 --- a/exercises/clippy/clippy1.rs +++ b/exercises/clippy/clippy1.rs @@ -1,10 +1,13 @@ // clippy1.rs -// The Clippy tool is a collection of lints to analyze your code -// so you can catch common mistakes and improve your Rust code. // -// For these exercises the code will fail to compile when there are clippy warnings -// check clippy's suggestions from the output to solve the exercise. -// Execute `rustlings hint clippy1` or use the `hint` watch subcommand for a hint. +// The Clippy tool is a collection of lints to analyze your code so you can +// catch common mistakes and improve your Rust code. +// +// For these exercises the code will fail to compile when there are clippy +// warnings check clippy's suggestions from the output to solve the exercise. +// +// Execute `rustlings hint clippy1` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/clippy/clippy2.rs b/exercises/clippy/clippy2.rs index dac40dbe..9b87a0b7 100644 --- a/exercises/clippy/clippy2.rs +++ b/exercises/clippy/clippy2.rs @@ -1,5 +1,7 @@ // clippy2.rs -// Execute `rustlings hint clippy2` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint clippy2` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/clippy/clippy3.rs b/exercises/clippy/clippy3.rs index b0159ebe..35021f84 100644 --- a/exercises/clippy/clippy3.rs +++ b/exercises/clippy/clippy3.rs @@ -1,5 +1,8 @@ // clippy3.rs +// // Here's a couple more easy Clippy fixes, so you can see its utility. +// +// Execute `rustlings hint clippy3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/conversions/as_ref_mut.rs b/exercises/conversions/as_ref_mut.rs index e6a9d114..626a36c4 100644 --- a/exercises/conversions/as_ref_mut.rs +++ b/exercises/conversions/as_ref_mut.rs @@ -1,7 +1,11 @@ -// AsRef and AsMut allow for cheap reference-to-reference conversions. -// Read more 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. -// Execute `rustlings hint as_ref_mut` or use the `hint` watch subcommand for a hint. +// as_ref_mut.rs +// +// AsRef and AsMut allow for cheap reference-to-reference conversions. Read more +// 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. +// +// Execute `rustlings hint as_ref_mut` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/conversions/from_into.rs b/exercises/conversions/from_into.rs index 6c272c3b..60911f3e 100644 --- a/exercises/conversions/from_into.rs +++ b/exercises/conversions/from_into.rs @@ -1,7 +1,11 @@ -// The From trait is used for value-to-value conversions. -// If From is implemented correctly for a type, the Into trait should work conversely. -// You can read more about it at https://doc.rust-lang.org/std/convert/trait.From.html -// Execute `rustlings hint from_into` or use the `hint` watch subcommand for a hint. +// from_into.rs +// +// The From trait is used for value-to-value conversions. If From is implemented +// correctly for a type, the Into trait should work conversely. You can read +// more about it at https://doc.rust-lang.org/std/convert/trait.From.html +// +// Execute `rustlings hint from_into` or use the `hint` watch subcommand for a +// hint. #[derive(Debug)] struct Person { @@ -20,20 +24,21 @@ impl Default for Person { } } -// Your task is to complete this implementation -// in order for the line `let p = Person::from("Mark,20")` to compile -// Please note that you'll need to parse the age component into a `usize` -// with something like `"4".parse::()`. The outcome of this needs to -// be handled appropriately. +// Your task is to complete this implementation in order for the line `let p = +// Person::from("Mark,20")` to compile Please note that you'll need to parse the +// age component into a `usize` with something like `"4".parse::()`. The +// outcome of this needs to be handled appropriately. // // Steps: -// 1. If the length of the provided string is 0, then return the default of Person -// 2. Split the given string on the commas present in it -// 3. Extract the first element from the split operation and use it as the name -// 4. If the name is empty, then return the default of Person -// 5. Extract the other element from the split operation and parse it into a `usize` as the age -// If while parsing the age, something goes wrong, then return the default of Person -// Otherwise, then return an instantiated Person object with the results +// 1. If the length of the provided string is 0, then return the default of +// Person. +// 2. Split the given string on the commas present in it. +// 3. Extract the first element from the split operation and use it as the name. +// 4. If the name is empty, then return the default of Person. +// 5. Extract the other element from the split operation and parse it into a +// `usize` as the age. +// If while parsing the age, something goes wrong, then return the default of +// Person Otherwise, then return an instantiated Person object with the results // I AM NOT DONE @@ -77,7 +82,8 @@ mod tests { } #[test] fn test_bad_age() { - // Test that "Mark,twenty" will return the default person due to an error in parsing age + // Test that "Mark,twenty" will return the default person due to an + // error in parsing age let p = Person::from("Mark,twenty"); assert_eq!(p.name, "John"); assert_eq!(p.age, 30); @@ -121,14 +127,14 @@ mod tests { #[test] fn test_trailing_comma() { let p: Person = Person::from("Mike,32,"); - assert_eq!(p.name, "John"); - assert_eq!(p.age, 30); + assert_eq!(p.name, "Mike"); + assert_eq!(p.age, 32); } #[test] fn test_trailing_comma_and_some_string() { let p: Person = Person::from("Mike,32,man"); - assert_eq!(p.name, "John"); - assert_eq!(p.age, 30); + assert_eq!(p.name, "Mike"); + assert_eq!(p.age, 32); } } diff --git a/exercises/conversions/from_str.rs b/exercises/conversions/from_str.rs index fe168159..34472c32 100644 --- a/exercises/conversions/from_str.rs +++ b/exercises/conversions/from_str.rs @@ -1,10 +1,13 @@ // from_str.rs -// This is similar to from_into.rs, but this time we'll implement `FromStr` -// and return errors instead of falling back to a default value. -// Additionally, upon implementing FromStr, you can use the `parse` method -// on strings to generate an object of the implementor type. -// You can read more about it at https://doc.rust-lang.org/std/str/trait.FromStr.html -// Execute `rustlings hint from_str` or use the `hint` watch subcommand for a hint. +// +// This is similar to from_into.rs, but this time we'll implement `FromStr` and +// return errors instead of falling back to a default value. Additionally, upon +// implementing FromStr, you can use the `parse` method on strings to generate +// an object of the implementor type. You can read more about it at +// https://doc.rust-lang.org/std/str/trait.FromStr.html +// +// Execute `rustlings hint from_str` or use the `hint` watch subcommand for a +// hint. use std::num::ParseIntError; use std::str::FromStr; @@ -33,15 +36,18 @@ enum ParsePersonError { // Steps: // 1. If the length of the provided string is 0, an error should be returned // 2. Split the given string on the commas present in it -// 3. Only 2 elements should be returned from the split, otherwise return an error +// 3. Only 2 elements should be returned from the split, otherwise return an +// error // 4. Extract the first element from the split operation and use it as the name -// 5. Extract the other element from the split operation and parse it into a `usize` as the age -// with something like `"4".parse::()` -// 6. If while extracting the name and the age something goes wrong, an error should be returned +// 5. Extract the other element from the split operation and parse it into a +// `usize` as the age with something like `"4".parse::()` +// 6. If while extracting the name and the age something goes wrong, an error +// should be returned // If everything goes well, then return a Result of a Person object // -// As an aside: `Box` implements `From<&'_ str>`. This means that if you want to return a -// string error message, you can do so via just using return `Err("my error message".into())`. +// As an aside: `Box` implements `From<&'_ str>`. This means that if +// you want to return a string error message, you can do so via just using +// return `Err("my error message".into())`. impl FromStr for Person { type Err = ParsePersonError; diff --git a/exercises/conversions/try_from_into.rs b/exercises/conversions/try_from_into.rs index fa98bc90..32d6ef39 100644 --- a/exercises/conversions/try_from_into.rs +++ b/exercises/conversions/try_from_into.rs @@ -1,9 +1,13 @@ // try_from_into.rs -// TryFrom is a simple and safe type conversion that may fail in a controlled way under some circumstances. -// Basically, this is the same as From. The main difference is that this should return a Result type -// instead of the target type itself. -// You can read more about it at https://doc.rust-lang.org/std/convert/trait.TryFrom.html -// Execute `rustlings hint try_from_into` or use the `hint` watch subcommand for a hint. +// +// TryFrom is a simple and safe type conversion that may fail in a controlled +// way under some circumstances. Basically, this is the same as From. The main +// difference is that this should return a Result type instead of the target +// type itself. You can read more about it at +// https://doc.rust-lang.org/std/convert/trait.TryFrom.html +// +// Execute `rustlings hint try_from_into` or use the `hint` watch subcommand for +// a hint. use std::convert::{TryFrom, TryInto}; @@ -25,14 +29,13 @@ enum IntoColorError { // I AM NOT DONE -// Your task is to complete this implementation -// and return an Ok result of inner type Color. -// You need to create an implementation for a tuple of three integers, -// an array of three integers, and a slice of integers. +// Your task is to complete this implementation and return an Ok result of inner +// type Color. You need to create an implementation for a tuple of three +// integers, an array of three integers, and a slice of integers. // -// Note that the implementation for tuple and array will be checked at compile time, -// but the slice implementation needs to check the slice length! -// Also note that correct RGB color values must be integers in the 0..=255 range. +// Note that the implementation for tuple and array will be checked at compile +// time, but the slice implementation needs to check the slice length! Also note +// that correct RGB color values must be integers in the 0..=255 range. // Tuple implementation impl TryFrom<(i16, i16, i16)> for Color { diff --git a/exercises/conversions/using_as.rs b/exercises/conversions/using_as.rs index 8c9b7113..414cef3a 100644 --- a/exercises/conversions/using_as.rs +++ b/exercises/conversions/using_as.rs @@ -1,10 +1,14 @@ -// Type casting in Rust is done via the usage of the `as` operator. -// Please note that the `as` operator is not only used when type casting. -// It also helps with renaming imports. +// using_as.rs // -// The goal is to make sure that the division does not fail to compile -// and returns the proper type. -// Execute `rustlings hint using_as` or use the `hint` watch subcommand for a hint. +// Type casting in Rust is done via the usage of the `as` operator. Please note +// that the `as` operator is not only used when type casting. It also helps with +// renaming imports. +// +// The goal is to make sure that the division does not fail to compile and +// returns the proper type. +// +// Execute `rustlings hint using_as` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/enums/enums1.rs b/exercises/enums/enums1.rs index 511ba740..25525b25 100644 --- a/exercises/enums/enums1.rs +++ b/exercises/enums/enums1.rs @@ -1,4 +1,5 @@ // enums1.rs +// // No hints this time! ;) // I AM NOT DONE diff --git a/exercises/enums/enums2.rs b/exercises/enums/enums2.rs index 167a6b2e..df93fe0f 100644 --- a/exercises/enums/enums2.rs +++ b/exercises/enums/enums2.rs @@ -1,5 +1,7 @@ // enums2.rs -// Execute `rustlings hint enums2` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint enums2` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/enums/enums3.rs b/exercises/enums/enums3.rs index a2a9d586..98da1691 100644 --- a/exercises/enums/enums3.rs +++ b/exercises/enums/enums3.rs @@ -1,6 +1,9 @@ // enums3.rs +// // Address all the TODOs to make the tests pass! -// Execute `rustlings hint enums3` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint enums3` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE @@ -17,6 +20,7 @@ struct State { color: (u8, u8, u8), position: Point, quit: bool, + message: String } impl State { @@ -28,17 +32,17 @@ impl State { self.quit = true; } - fn echo(&self, s: String) { - println!("{}", s); - } + fn echo(&mut self, s: String) { self.message = s } fn move_position(&mut self, p: Point) { self.position = p; } fn process(&mut self, message: Message) { - // TODO: create a match expression to process the different message variants - // Remember: When passing a tuple as a function argument, you'll need extra parentheses: fn function((t, u, p, l, e)) + // TODO: create a match expression to process the different message + // variants + // Remember: When passing a tuple as a function argument, you'll need + // extra parentheses: fn function((t, u, p, l, e)) } } @@ -52,9 +56,10 @@ mod tests { quit: false, position: Point { x: 0, y: 0 }, color: (0, 0, 0), + message: "hello world".to_string(), }; state.process(Message::ChangeColor(255, 0, 255)); - state.process(Message::Echo(String::from("hello world"))); + state.process(Message::Echo(String::from("Hello world!"))); state.process(Message::Move(Point { x: 10, y: 15 })); state.process(Message::Quit); @@ -62,5 +67,6 @@ mod tests { assert_eq!(state.position.x, 10); assert_eq!(state.position.y, 15); assert_eq!(state.quit, true); + assert_eq!(state.message, "Hello world!"); } } diff --git a/exercises/error_handling/errors1.rs b/exercises/error_handling/errors1.rs index bcee9723..0ba59a57 100644 --- a/exercises/error_handling/errors1.rs +++ b/exercises/error_handling/errors1.rs @@ -1,9 +1,13 @@ // errors1.rs -// This function refuses to generate text to be printed on a nametag if -// you pass it an empty string. It'd be nicer if it explained what the problem -// was, instead of just sometimes returning `None`. Thankfully, Rust has a similar -// construct to `Option` that can be used to express error conditions. Let's use it! -// Execute `rustlings hint errors1` or use the `hint` watch subcommand for a hint. +// +// This function refuses to generate text to be printed on a nametag if you pass +// it an empty string. It'd be nicer if it explained what the problem was, +// instead of just sometimes returning `None`. Thankfully, Rust has a similar +// construct to `Option` that can be used to express error conditions. Let's use +// it! +// +// Execute `rustlings hint errors1` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/error_handling/errors2.rs b/exercises/error_handling/errors2.rs index 6971fcfb..d4a5477b 100644 --- a/exercises/error_handling/errors2.rs +++ b/exercises/error_handling/errors2.rs @@ -1,21 +1,23 @@ // errors2.rs +// // Say we're writing a game where you can buy items with tokens. All items cost // 5 tokens, and whenever you purchase items there is a processing fee of 1 -// token. A player of the game will type in how many items they want to buy, -// and the `total_cost` function will calculate the total cost of the tokens. -// Since the player typed in the quantity, though, we get it as a string-- and -// they might have typed anything, not just numbers! - +// token. A player of the game will type in how many items they want to buy, and +// the `total_cost` function will calculate the total cost of the tokens. Since +// the player typed in the quantity, though, we get it as a string-- and they +// might have typed anything, not just numbers! +// // Right now, this function isn't handling the error case at all (and isn't -// handling the success case properly either). What we want to do is: -// if we call the `parse` function on a string that is not a number, that -// function will return a `ParseIntError`, and in that case, we want to -// immediately return that error from our function and not try to multiply -// and add. - -// There are at least two ways to implement this that are both correct-- but -// one is a lot shorter! -// Execute `rustlings hint errors2` or use the `hint` watch subcommand for a hint. +// handling the success case properly either). What we want to do is: if we call +// the `total_cost` function on a string that is not a number, that function +// will return a `ParseIntError`, and in that case, we want to immediately +// return that error from our function and not try to multiply and add. +// +// There are at least two ways to implement this that are both correct-- but one +// is a lot shorter! +// +// Execute `rustlings hint errors2` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/error_handling/errors3.rs b/exercises/error_handling/errors3.rs index a2d2d190..d42d3b17 100644 --- a/exercises/error_handling/errors3.rs +++ b/exercises/error_handling/errors3.rs @@ -1,8 +1,11 @@ // errors3.rs +// // This is a program that is trying to use a completed version of the // `total_cost` function from the previous exercise. It's not working though! // Why not? What should we do to fix it? -// Execute `rustlings hint errors3` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint errors3` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/error_handling/errors4.rs b/exercises/error_handling/errors4.rs index 0efe8ccd..d6d6fcb6 100644 --- a/exercises/error_handling/errors4.rs +++ b/exercises/error_handling/errors4.rs @@ -1,5 +1,7 @@ // errors4.rs -// Execute `rustlings hint errors4` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint errors4` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE @@ -14,7 +16,7 @@ enum CreationError { impl PositiveNonzeroInteger { fn new(value: i64) -> Result { - // Hmm...? Why is this only returning an Ok value? + // Hmm... Why is this always returning an Ok value? Ok(PositiveNonzeroInteger(value as u64)) } } diff --git a/exercises/error_handling/errors5.rs b/exercises/error_handling/errors5.rs index eb5506cb..92461a7e 100644 --- a/exercises/error_handling/errors5.rs +++ b/exercises/error_handling/errors5.rs @@ -1,20 +1,26 @@ // errors5.rs - +// // This program uses an altered version of the code from errors4. - -// This exercise uses some concepts that we won't get to until later in the course, like `Box` and the -// `From` trait. It's not important to understand them in detail right now, but you can read ahead if you like. -// For now, think of the `Box` type as an "I want anything that does ???" type, which, given -// Rust's usual standards for runtime safety, should strike you as somewhat lenient! - -// 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 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. - -// What can we use to describe both errors? In other words, is there a trait which both errors implement? - -// Execute `rustlings hint errors5` or use the `hint` watch subcommand for a hint. +// +// This exercise uses some concepts that we won't get to until later in the +// course, like `Box` and the `From` trait. It's not important to understand +// them in detail right now, but you can read ahead if you like. For now, think +// of the `Box` type as an "I want anything that does ???" type, which, +// given Rust's usual standards for runtime safety, should strike you as +// somewhat lenient! +// +// 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 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. +// +// What can we use to describe both errors? In other words, is there a trait +// which both errors implement? +// +// Execute `rustlings hint errors5` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/error_handling/errors6.rs b/exercises/error_handling/errors6.rs index 8097b490..aaf0948e 100644 --- a/exercises/error_handling/errors6.rs +++ b/exercises/error_handling/errors6.rs @@ -1,12 +1,13 @@ // errors6.rs - +// // Using catch-all error types like `Box` isn't recommended // for library code, where callers might want to make decisions based on the -// error content, instead of printing it out or propagating it further. Here, -// we define a custom error type to make it possible for callers to decide -// what to do next when our function returns an error. - -// Execute `rustlings hint errors6` or use the `hint` watch subcommand for a hint. +// error content, instead of printing it out or propagating it further. Here, we +// define a custom error type to make it possible for callers to decide what to +// do next when our function returns an error. +// +// Execute `rustlings hint errors6` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/functions/functions1.rs b/exercises/functions/functions1.rs index 03d8af70..40ed9a07 100644 --- a/exercises/functions/functions1.rs +++ b/exercises/functions/functions1.rs @@ -1,5 +1,7 @@ // functions1.rs -// Execute `rustlings hint functions1` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint functions1` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/functions/functions2.rs b/exercises/functions/functions2.rs index 7d40a578..5154f34d 100644 --- a/exercises/functions/functions2.rs +++ b/exercises/functions/functions2.rs @@ -1,5 +1,7 @@ // functions2.rs -// Execute `rustlings hint functions2` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint functions2` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/functions/functions3.rs b/exercises/functions/functions3.rs index 3b9e585b..74f44d6d 100644 --- a/exercises/functions/functions3.rs +++ b/exercises/functions/functions3.rs @@ -1,5 +1,7 @@ // functions3.rs -// Execute `rustlings hint functions3` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint functions3` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/functions/functions4.rs b/exercises/functions/functions4.rs index 65d5be4f..77c4b2aa 100644 --- a/exercises/functions/functions4.rs +++ b/exercises/functions/functions4.rs @@ -1,11 +1,12 @@ // functions4.rs -// Execute `rustlings hint functions4` or use the `hint` watch subcommand for a hint. - -// This store is having a sale where if the price is an even number, you get -// 10 Rustbucks off, but if it's an odd number, it's 3 Rustbucks off. -// (Don't worry about the function bodies themselves, we're only interested -// in the signatures for now. If anything, this is a good way to peek ahead -// to future exercises!) +// +// This store is having a sale where if the price is an even number, you get 10 +// Rustbucks off, but if it's an odd number, it's 3 Rustbucks off. (Don't worry +// about the function bodies themselves, we're only interested in the signatures +// for now. If anything, this is a good way to peek ahead to future exercises!) +// +// Execute `rustlings hint functions4` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/functions/functions5.rs b/exercises/functions/functions5.rs index 5d762961..f1b63f48 100644 --- a/exercises/functions/functions5.rs +++ b/exercises/functions/functions5.rs @@ -1,5 +1,7 @@ // functions5.rs -// Execute `rustlings hint functions5` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint functions5` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/generics/generics1.rs b/exercises/generics/generics1.rs index 4c34ae47..35c1d2fe 100644 --- a/exercises/generics/generics1.rs +++ b/exercises/generics/generics1.rs @@ -1,7 +1,10 @@ -// This shopping list program isn't compiling! -// Use your knowledge of generics to fix it. - -// Execute `rustlings hint generics1` or use the `hint` watch subcommand for a hint. +// generics1.rs +// +// This shopping list program isn't compiling! Use your knowledge of generics to +// fix it. +// +// Execute `rustlings hint generics1` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/generics/generics2.rs b/exercises/generics/generics2.rs index aedbd55c..074cd938 100644 --- a/exercises/generics/generics2.rs +++ b/exercises/generics/generics2.rs @@ -1,7 +1,10 @@ +// generics2.rs +// // This powerful wrapper provides the ability to store a positive integer value. // Rewrite it using generics so that it supports wrapping ANY type. - -// Execute `rustlings hint generics2` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint generics2` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/hashmaps/hashmaps1.rs b/exercises/hashmaps/hashmaps1.rs index fd8dd2f8..80829eaa 100644 --- a/exercises/hashmaps/hashmaps1.rs +++ b/exercises/hashmaps/hashmaps1.rs @@ -1,14 +1,15 @@ // hashmaps1.rs -// 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 three different types of fruits (e.g apple, banana, mango) -// in the basket and the total count of all the fruits should be at -// least five. +// +// 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 three different +// types of fruits (e.g apple, banana, mango) in the basket and the total count +// of all the fruits should be at least five. // // Make me compile and pass the tests! // -// Execute `rustlings hint hashmaps1` or use the `hint` watch subcommand for a hint. +// Execute `rustlings hint hashmaps1` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/hashmaps/hashmaps2.rs b/exercises/hashmaps/hashmaps2.rs index a4f069a8..a5925690 100644 --- a/exercises/hashmaps/hashmaps2.rs +++ b/exercises/hashmaps/hashmaps2.rs @@ -1,17 +1,18 @@ // hashmaps2.rs -// We're collecting different fruits to bake a delicious fruit cake. -// For this, we have a basket, which we'll represent in the form of a hash -// map. The key represents the name of each fruit we collect and the value -// represents how many of that particular fruit we have collected. -// Three types of fruits - 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! +// +// We're collecting different fruits to bake a delicious fruit cake. For this, +// we have a basket, which we'll represent in the form of a hash map. The key +// represents the name of each fruit we collect and the value represents how +// many of that particular fruit we have collected. Three types of fruits - +// 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! // // Make me pass the tests! // -// Execute `rustlings hint hashmaps2` or use the `hint` watch subcommand for a hint. +// Execute `rustlings hint hashmaps2` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE @@ -36,9 +37,9 @@ fn fruit_basket(basket: &mut HashMap) { ]; for fruit in fruit_kinds { - // TODO: Insert new fruits if they are not already present in the basket. - // Note that you are not allowed to put any type of fruit that's already - // present! + // TODO: Insert new fruits if they are not already present in the + // basket. Note that you are not allowed to put any type of fruit that's + // already present! } } @@ -80,4 +81,13 @@ mod tests { let count = basket.values().sum::(); assert!(count > 11); } + + #[test] + fn all_fruit_types_in_basket() { + let mut basket = get_fruit_basket(); + fruit_basket(&mut basket); + for amount in basket.values() { + assert_ne!(amount, &0); + } + } } diff --git a/exercises/hashmaps/hashmaps3.rs b/exercises/hashmaps/hashmaps3.rs index ad3baa68..08e977c3 100644 --- a/exercises/hashmaps/hashmaps3.rs +++ b/exercises/hashmaps/hashmaps3.rs @@ -1,26 +1,25 @@ // hashmaps3.rs - -// A list of scores (one per line) of a soccer match is given. Each line -// is of the form : -// ,,, +// +// A list of scores (one per line) of a soccer match is given. Each line is of +// the form : ",,," // Example: England,France,4,2 (England scored 4 goals, France 2). - -// You have to build a scores table containing the name of the team, goals -// the team scored, and goals the team conceded. One approach to build -// the scores table is to use a Hashmap. The solution is partially -// written to use a Hashmap, complete it to pass the test. - +// +// You have to build a scores table containing the name of the team, goals the +// team scored, and goals the team conceded. One approach to build the scores +// table is to use a Hashmap. The solution is partially written to use a +// Hashmap, complete it to pass the test. +// // Make me pass the tests! - -// Execute `rustlings hint hashmaps3` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint hashmaps3` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE use std::collections::HashMap; -// A structure to store team name and its goal details. +// A structure to store the goal details of a team. struct Team { - name: String, goals_scored: u8, goals_conceded: u8, } diff --git a/exercises/if/if1.rs b/exercises/if/if1.rs index 587e03f8..4734d78f 100644 --- a/exercises/if/if1.rs +++ b/exercises/if/if1.rs @@ -1,4 +1,5 @@ // if1.rs +// // Execute `rustlings hint if1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE @@ -24,4 +25,9 @@ mod tests { fn fortytwo_is_bigger_than_thirtytwo() { assert_eq!(42, bigger(32, 42)); } + + #[test] + fn equal_numbers() { + assert_eq!(42, bigger(42, 42)); + } } diff --git a/exercises/if/if2.rs b/exercises/if/if2.rs index effddbb6..f512f13f 100644 --- a/exercises/if/if2.rs +++ b/exercises/if/if2.rs @@ -1,7 +1,8 @@ // if2.rs - +// // Step 1: Make me compile! // Step 2: Get the bar_for_fuzz and default_to_baz tests passing! +// // Execute `rustlings hint if2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/if/if3.rs b/exercises/if/if3.rs new file mode 100644 index 00000000..16962740 --- /dev/null +++ b/exercises/if/if3.rs @@ -0,0 +1,56 @@ +// if3.rs +// +// Execute `rustlings hint if3` or use the `hint` watch subcommand for a hint. + +// I AM NOT DONE + +pub fn animal_habitat(animal: &str) -> &'static str { + let identifier = if animal == "crab" { + 1 + } else if animal == "gopher" { + 2.0 + } else if animal == "snake" { + 3 + } else { + "Unknown" + }; + + // DO NOT CHANGE THIS STATEMENT BELOW + let habitat = if identifier == 1 { + "Beach" + } else if identifier == 2 { + "Burrow" + } else if identifier == 3 { + "Desert" + } else { + "Unknown" + }; + + habitat +} + +// No test changes needed. +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn gopher_lives_in_burrow() { + assert_eq!(animal_habitat("gopher"), "Burrow") + } + + #[test] + fn snake_lives_in_desert() { + assert_eq!(animal_habitat("snake"), "Desert") + } + + #[test] + fn crab_lives_on_beach() { + assert_eq!(animal_habitat("crab"), "Beach") + } + + #[test] + fn unknown_animal() { + assert_eq!(animal_habitat("dinosaur"), "Unknown") + } +} diff --git a/exercises/intro/intro1.rs b/exercises/intro/intro1.rs index cfc55c30..37fa0112 100644 --- a/exercises/intro/intro1.rs +++ b/exercises/intro/intro1.rs @@ -1,13 +1,17 @@ // intro1.rs +// // About this `I AM NOT DONE` thing: // 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, remove the `I AM NOT DONE` comment below. -// Execute `rustlings hint intro1` or use the `hint` watch subcommand for a hint. // -// If you're running this using `rustlings watch`: The exercise file will be reloaded -// when you change one of the lines below! Try adding a `println!` line, or try changing -// what it outputs in your terminal. Try removing a semicolon and see what happens! +// If you're running this using `rustlings watch`: The exercise file will be +// reloaded when you change one of the lines below! Try adding a `println!` +// line, or try changing what it outputs in your terminal. Try removing a +// semicolon and see what happens! +// +// Execute `rustlings hint intro1` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/intro/intro2.rs b/exercises/intro/intro2.rs index efc1af20..990b20f0 100644 --- a/exercises/intro/intro2.rs +++ b/exercises/intro/intro2.rs @@ -1,6 +1,9 @@ // intro2.rs +// // Make the code print a greeting to the world. -// Execute `rustlings hint intro2` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint intro2` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/iterators/iterators1.rs b/exercises/iterators/iterators1.rs index f9cc3b39..b3f698be 100644 --- a/exercises/iterators/iterators1.rs +++ b/exercises/iterators/iterators1.rs @@ -1,12 +1,13 @@ // iterators1.rs // -// Make me compile by filling in the `???`s +// When performing operations on elements within a collection, iterators are +// essential. This module helps you get familiar with the structure of using an +// iterator and how to go through elements within an iterable collection. // -// When performing operations on elements within a collection, iterators are essential. -// This module helps you get familiar with the structure of using an iterator and -// how to go through elements within an iterable collection. +// Make me compile by filling in the `???`s // -// Execute `rustlings hint iterators1` or use the `hint` watch subcommand for a hint. +// Execute `rustlings hint iterators1` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/iterators/iterators2.rs b/exercises/iterators/iterators2.rs index 29c53afb..dda82a08 100644 --- a/exercises/iterators/iterators2.rs +++ b/exercises/iterators/iterators2.rs @@ -1,7 +1,10 @@ // iterators2.rs +// // In this exercise, you'll learn some of the unique advantages that iterators // can offer. Follow the steps to complete the exercise. -// Execute `rustlings hint iterators2` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint iterators2` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/iterators/iterators3.rs b/exercises/iterators/iterators3.rs index c97a6258..29fa23a3 100644 --- a/exercises/iterators/iterators3.rs +++ b/exercises/iterators/iterators3.rs @@ -1,10 +1,13 @@ // iterators3.rs -// This is a bigger exercise than most of the others! You can do it! -// Here is your mission, should you choose to accept it: +// +// This is a bigger exercise than most of the others! You can do it! Here is +// your mission, should you choose to accept it: // 1. Complete the divide function to get the first four tests to pass. // 2. Get the remaining tests to pass by completing the result_with_list and // list_of_results functions. -// Execute `rustlings hint iterators3` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint iterators3` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE @@ -26,14 +29,16 @@ pub fn divide(a: i32, b: i32) -> Result { todo!(); } -// Complete the function and return a value of the correct type so the test passes. +// Complete the function and return a value of the correct type so the test +// passes. // Desired output: Ok([1, 11, 1426, 3]) fn result_with_list() -> () { let numbers = vec![27, 297, 38502, 81]; let division_results = numbers.into_iter().map(|n| divide(n, 27)); } -// Complete the function and return a value of the correct type so the test passes. +// Complete the function and return a value of the correct type so the test +// passes. // Desired output: [Ok(1), Ok(11), Ok(1426), Ok(3)] fn list_of_results() -> () { let numbers = vec![27, 297, 38502, 81]; diff --git a/exercises/iterators/iterators4.rs b/exercises/iterators/iterators4.rs index a02470ec..79e1692b 100644 --- a/exercises/iterators/iterators4.rs +++ b/exercises/iterators/iterators4.rs @@ -1,5 +1,7 @@ // iterators4.rs -// Execute `rustlings hint iterators4` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint iterators4` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/iterators/iterators5.rs b/exercises/iterators/iterators5.rs index 87097956..a062ee4c 100644 --- a/exercises/iterators/iterators5.rs +++ b/exercises/iterators/iterators5.rs @@ -1,4 +1,5 @@ // iterators5.rs +// // Let's define a simple model to track Rustlings exercise progress. Progress // will be modelled using a hash map. The name of the exercise is the key and // the progress is the value. Two counting functions were created to count the @@ -6,7 +7,9 @@ // functionality using iterators. Try not to use imperative loops (for, while). // Only the two iterator methods (count_iterator and count_collection_iterator) // need to be modified. -// Execute `rustlings hint iterators5` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint iterators5` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE @@ -65,12 +68,27 @@ mod tests { } #[test] - fn count_equals_for() { + fn count_some() { let map = get_map(); - assert_eq!( - count_for(&map, Progress::Complete), - count_iterator(&map, Progress::Complete) - ); + assert_eq!(1, count_iterator(&map, Progress::Some)); + } + + #[test] + fn count_none() { + let map = get_map(); + assert_eq!(2, count_iterator(&map, Progress::None)); + } + + #[test] + fn count_complete_equals_for() { + let map = get_map(); + let progress_states = vec![Progress::Complete, Progress::Some, Progress::None]; + for progress_state in progress_states { + assert_eq!( + count_for(&map, progress_state), + count_iterator(&map, progress_state) + ); + } } #[test] @@ -83,12 +101,28 @@ mod tests { } #[test] - fn count_collection_equals_for() { + fn count_collection_some() { let collection = get_vec_map(); - assert_eq!( - count_collection_for(&collection, Progress::Complete), - count_collection_iterator(&collection, Progress::Complete) - ); + assert_eq!(1, count_collection_iterator(&collection, Progress::Some)); + } + + #[test] + fn count_collection_none() { + let collection = get_vec_map(); + assert_eq!(4, count_collection_iterator(&collection, Progress::None)); + } + + #[test] + fn count_collection_equals_for() { + let progress_states = vec![Progress::Complete, Progress::Some, Progress::None]; + let collection = get_vec_map(); + + for progress_state in progress_states { + assert_eq!( + count_collection_for(&collection, progress_state), + count_collection_iterator(&collection, progress_state) + ); + } } fn get_map() -> HashMap { diff --git a/exercises/lifetimes/lifetimes1.rs b/exercises/lifetimes/lifetimes1.rs index 0236470d..87bde490 100644 --- a/exercises/lifetimes/lifetimes1.rs +++ b/exercises/lifetimes/lifetimes1.rs @@ -1,11 +1,12 @@ // lifetimes1.rs // // The Rust compiler needs to know how to check whether supplied references are -// valid, so that it can let the programmer know if a reference is at risk -// of going out of scope before it is used. Remember, references are borrows -// and do not own their own data. What if their owner goes out of scope? +// valid, so that it can let the programmer know if a reference is at risk of +// going out of scope before it is used. Remember, references are borrows and do +// not own their own data. What if their owner goes out of scope? // -// Execute `rustlings hint lifetimes1` or use the `hint` watch subcommand for a hint. +// Execute `rustlings hint lifetimes1` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/lifetimes/lifetimes2.rs b/exercises/lifetimes/lifetimes2.rs index b48feabc..4f3d8c18 100644 --- a/exercises/lifetimes/lifetimes2.rs +++ b/exercises/lifetimes/lifetimes2.rs @@ -1,10 +1,10 @@ // lifetimes2.rs // -// So if the compiler is just validating the references passed -// to the annotated parameters and the return type, what do -// we need to change? +// So if the compiler is just validating the references passed to the annotated +// parameters and the return type, what do we need to change? // -// Execute `rustlings hint lifetimes2` or use the `hint` watch subcommand for a hint. +// Execute `rustlings hint lifetimes2` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/lifetimes/lifetimes3.rs b/exercises/lifetimes/lifetimes3.rs index ea483708..9c59f9c0 100644 --- a/exercises/lifetimes/lifetimes3.rs +++ b/exercises/lifetimes/lifetimes3.rs @@ -2,7 +2,8 @@ // // Lifetimes are also needed when structs hold references. // -// Execute `rustlings hint lifetimes3` or use the `hint` watch subcommand for a hint. +// Execute `rustlings hint lifetimes3` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/macros/macros1.rs b/exercises/macros/macros1.rs index 634d0a70..678de6ee 100644 --- a/exercises/macros/macros1.rs +++ b/exercises/macros/macros1.rs @@ -1,5 +1,7 @@ // macros1.rs -// Execute `rustlings hint macros1` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint macros1` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/macros/macros2.rs b/exercises/macros/macros2.rs index f6092cab..788fc16a 100644 --- a/exercises/macros/macros2.rs +++ b/exercises/macros/macros2.rs @@ -1,5 +1,7 @@ // macros2.rs -// Execute `rustlings hint macros2` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint macros2` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/macros/macros3.rs b/exercises/macros/macros3.rs index 106f1c6d..b795c149 100644 --- a/exercises/macros/macros3.rs +++ b/exercises/macros/macros3.rs @@ -1,6 +1,9 @@ // macros3.rs +// // Make me compile, without taking the macro out of the module! -// Execute `rustlings hint macros3` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint macros3` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/macros/macros4.rs b/exercises/macros/macros4.rs index 4ee98035..71b45a09 100644 --- a/exercises/macros/macros4.rs +++ b/exercises/macros/macros4.rs @@ -1,5 +1,7 @@ // macros4.rs -// Execute `rustlings hint macros4` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint macros4` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/modules/modules1.rs b/exercises/modules/modules1.rs index 8dd0e402..9eb5a48b 100644 --- a/exercises/modules/modules1.rs +++ b/exercises/modules/modules1.rs @@ -1,5 +1,7 @@ // modules1.rs -// Execute `rustlings hint modules1` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint modules1` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/modules/modules2.rs b/exercises/modules/modules2.rs index c30a3897..04154543 100644 --- a/exercises/modules/modules2.rs +++ b/exercises/modules/modules2.rs @@ -1,7 +1,11 @@ // modules2.rs -// You can bring module paths into scopes and provide new names for them with the -// 'use' and 'as' keywords. Fix these 'use' statements to make the code compile. -// Execute `rustlings hint modules2` or use the `hint` watch subcommand for a hint. +// +// You can bring module paths into scopes and provide new names for them with +// the 'use' and 'as' keywords. Fix these 'use' statements to make the code +// compile. +// +// Execute `rustlings hint modules2` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/modules/modules3.rs b/exercises/modules/modules3.rs index 35e07990..f2bb0503 100644 --- a/exercises/modules/modules3.rs +++ b/exercises/modules/modules3.rs @@ -1,9 +1,12 @@ // modules3.rs -// You can use the 'use' keyword to bring module paths from modules from anywhere -// and especially from the Rust standard library into your scope. -// Bring SystemTime and UNIX_EPOCH -// from the std::time module. Bonus style points if you can do it with one line! -// Execute `rustlings hint modules3` or use the `hint` watch subcommand for a hint. +// +// You can use the 'use' keyword to bring module paths from modules from +// anywhere and especially from the Rust standard library into your scope. Bring +// SystemTime and UNIX_EPOCH from the std::time module. Bonus style points if +// you can do it with one line! +// +// Execute `rustlings hint modules3` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/move_semantics/move_semantics1.rs b/exercises/move_semantics/move_semantics1.rs index aac6dfc3..e0639375 100644 --- a/exercises/move_semantics/move_semantics1.rs +++ b/exercises/move_semantics/move_semantics1.rs @@ -1,26 +1,23 @@ // move_semantics1.rs -// Execute `rustlings hint move_semantics1` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint move_semantics1` or use the `hint` watch subcommand +// for a hint. // I AM NOT DONE +#[test] fn main() { - let vec0 = Vec::new(); + let vec0 = vec![22, 44, 66]; let vec1 = fill_vec(vec0); - println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); - - vec1.push(88); - - println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); + assert_eq!(vec1, vec![22, 44, 66, 88]); } fn fill_vec(vec: Vec) -> Vec { - let mut vec = vec; + let vec = vec; - vec.push(22); - vec.push(44); - vec.push(66); + vec.push(88); vec } diff --git a/exercises/move_semantics/move_semantics2.rs b/exercises/move_semantics/move_semantics2.rs index 68dbf021..baf6bcc9 100644 --- a/exercises/move_semantics/move_semantics2.rs +++ b/exercises/move_semantics/move_semantics2.rs @@ -1,32 +1,26 @@ // move_semantics2.rs -// Make me compile without changing line 13 or moving line 10! -// Execute `rustlings hint move_semantics2` or use the `hint` watch subcommand for a hint. - -// Expected output: -// vec0 has length 3 content `[22, 44, 66]` -// vec1 has length 4 content `[22, 44, 66, 88]` +// +// Make the test pass by finding a way to keep both Vecs separate! +// +// Execute `rustlings hint move_semantics2` or use the `hint` watch subcommand +// for a hint. // I AM NOT DONE +#[test] fn main() { - let vec0 = Vec::new(); + let vec0 = vec![22, 44, 66]; let mut vec1 = fill_vec(vec0); - // Do not change the following line! - println!("{} has length {} content `{:?}`", "vec0", vec0.len(), vec0); - - vec1.push(88); - - println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); + assert_eq!(vec0, vec![22, 44, 66]); + assert_eq!(vec1, vec![22, 44, 66, 88]); } fn fill_vec(vec: Vec) -> Vec { let mut vec = vec; - vec.push(22); - vec.push(44); - vec.push(66); + vec.push(88); vec } diff --git a/exercises/move_semantics/move_semantics3.rs b/exercises/move_semantics/move_semantics3.rs index eaa30e33..69e564ab 100644 --- a/exercises/move_semantics/move_semantics3.rs +++ b/exercises/move_semantics/move_semantics3.rs @@ -1,26 +1,24 @@ // move_semantics3.rs -// Make me compile without adding new lines-- just changing existing lines! -// (no lines with multiple semicolons necessary!) -// Execute `rustlings hint move_semantics3` or use the `hint` watch subcommand for a hint. +// +// Make me compile without adding new lines-- just changing existing lines! (no +// lines with multiple semicolons necessary!) +// +// Execute `rustlings hint move_semantics3` or use the `hint` watch subcommand +// for a hint. // I AM NOT DONE +#[test] fn main() { - let vec0 = Vec::new(); + let vec0 = vec![22, 44, 66]; let mut vec1 = fill_vec(vec0); - println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); - - vec1.push(88); - - println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); + assert_eq!(vec1, vec![22, 44, 66, 88]); } fn fill_vec(vec: Vec) -> Vec { - vec.push(22); - vec.push(44); - vec.push(66); + vec.push(88); vec } diff --git a/exercises/move_semantics/move_semantics4.rs b/exercises/move_semantics/move_semantics4.rs index 99834ec3..80b49dba 100644 --- a/exercises/move_semantics/move_semantics4.rs +++ b/exercises/move_semantics/move_semantics4.rs @@ -1,30 +1,29 @@ // move_semantics4.rs -// Refactor this code so that instead of passing `vec0` into the `fill_vec` function, -// the Vector gets created in the function itself and passed back to the main -// function. -// Execute `rustlings hint move_semantics4` or use the `hint` watch subcommand for a hint. +// +// Refactor this code so that instead of passing `vec0` into the `fill_vec` +// function, the Vector gets created in the function itself and passed back to +// the main function. +// +// Execute `rustlings hint move_semantics4` or use the `hint` watch subcommand +// for a hint. // I AM NOT DONE +#[test] fn main() { - let vec0 = Vec::new(); + let vec0 = vec![22, 44, 66]; let mut vec1 = fill_vec(vec0); - println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); - - vec1.push(88); - - println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1); + assert_eq!(vec1, vec![22, 44, 66, 88]); } -// `fill_vec()` no longer takes `vec: Vec` as argument +// `fill_vec()` no longer takes `vec: Vec` as argument - don't change this! fn fill_vec() -> Vec { + // Instead, let's create and fill the Vec in here - how do you do that? let mut vec = vec; - vec.push(22); - vec.push(44); - vec.push(66); + vec.push(88); vec } diff --git a/exercises/move_semantics/move_semantics5.rs b/exercises/move_semantics/move_semantics5.rs index 36eae127..68db09eb 100644 --- a/exercises/move_semantics/move_semantics5.rs +++ b/exercises/move_semantics/move_semantics5.rs @@ -1,7 +1,10 @@ // move_semantics5.rs -// Make me compile only by reordering the lines in `main()`, but without -// adding, changing or removing any of them. -// Execute `rustlings hint move_semantics5` or use the `hint` watch subcommand for a hint. +// +// Make me compile only by reordering the lines in `main()`, but without adding, +// changing or removing any of them. +// +// Execute `rustlings hint move_semantics5` or use the `hint` watch subcommand +// for a hint. // I AM NOT DONE diff --git a/exercises/move_semantics/move_semantics6.rs b/exercises/move_semantics/move_semantics6.rs index eb52a848..cace4ca6 100644 --- a/exercises/move_semantics/move_semantics6.rs +++ b/exercises/move_semantics/move_semantics6.rs @@ -1,6 +1,9 @@ // move_semantics6.rs -// Execute `rustlings hint move_semantics6` or use the `hint` watch subcommand for a hint. +// // You can't change anything except adding or removing references. +// +// Execute `rustlings hint move_semantics6` or use the `hint` watch subcommand +// for a hint. // I AM NOT DONE diff --git a/exercises/options/options1.rs b/exercises/options/options1.rs index 1f891b0e..e131b48b 100644 --- a/exercises/options/options1.rs +++ b/exercises/options/options1.rs @@ -1,5 +1,7 @@ // options1.rs -// Execute `rustlings hint options1` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint options1` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE @@ -7,8 +9,9 @@ // If it's before 10PM, there's 5 pieces left. At 10PM, someone eats them // all, so there'll be no more left :( fn maybe_icecream(time_of_day: u16) -> Option { - // We use the 24-hour system here, so 10PM is a value of 22 and 12AM is a value of 0 - // The Option output should gracefully handle cases where time_of_day > 23. + // We use the 24-hour system here, so 10PM is a value of 22 and 12AM is a + // value of 0 The Option output should gracefully handle cases where + // time_of_day > 23. // TODO: Complete the function body - remember to return an Option! ??? } @@ -28,7 +31,8 @@ mod tests { #[test] fn raw_value() { - // TODO: Fix this test. How do you get at the value contained in the Option? + // TODO: Fix this test. How do you get at the value contained in the + // Option? let icecreams = maybe_icecream(12); assert_eq!(icecreams, 5); } diff --git a/exercises/options/options2.rs b/exercises/options/options2.rs index 4e36443f..4d998e7d 100644 --- a/exercises/options/options2.rs +++ b/exercises/options/options2.rs @@ -1,5 +1,7 @@ // options2.rs -// Execute `rustlings hint options2` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint options2` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE @@ -18,17 +20,23 @@ mod tests { #[test] fn layered_option() { - let mut range = 10; - let mut optional_integers: Vec> = Vec::new(); - for i in 0..(range + 1) { + let range = 10; + let mut optional_integers: Vec> = vec![None]; + + for i in 1..(range + 1) { optional_integers.push(Some(i)); } - // TODO: make this a while let statement - remember that vector.pop also adds another layer of Option - // You can stack `Option`'s into while let and if let + let mut cursor = range; + + // TODO: make this a while let statement - remember that vector.pop also + // adds another layer of Option. You can stack `Option`s into + // while let and if let. integer = optional_integers.pop() { - assert_eq!(integer, range); - range -= 1; + assert_eq!(integer, cursor); + cursor -= 1; } + + assert_eq!(cursor, 0); } } diff --git a/exercises/options/options3.rs b/exercises/options/options3.rs index 3f995c52..23c15eab 100644 --- a/exercises/options/options3.rs +++ b/exercises/options/options3.rs @@ -1,5 +1,7 @@ // options3.rs -// Execute `rustlings hint options3` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint options3` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE @@ -13,7 +15,7 @@ fn main() { match y { Some(p) => println!("Co-ordinates are {},{} ", p.x, p.y), - _ => println!("no match"), + _ => panic!("no match!"), } y; // Fix without deleting this line. } diff --git a/exercises/primitive_types/primitive_types1.rs b/exercises/primitive_types/primitive_types1.rs index 09121392..e1cf52a2 100644 --- a/exercises/primitive_types/primitive_types1.rs +++ b/exercises/primitive_types/primitive_types1.rs @@ -1,6 +1,10 @@ // primitive_types1.rs -// Fill in the rest of the line that has code missing! -// No hints, there's no tricks, just get used to typing these :) +// +// Fill in the rest of the line that has code missing! No hints, there's no +// tricks, just get used to typing these :) +// +// Execute `rustlings hint primitive_types1` or use the `hint` watch subcommand +// for a hint. // I AM NOT DONE diff --git a/exercises/primitive_types/primitive_types2.rs b/exercises/primitive_types/primitive_types2.rs index 8730baab..fcc9705a 100644 --- a/exercises/primitive_types/primitive_types2.rs +++ b/exercises/primitive_types/primitive_types2.rs @@ -1,6 +1,10 @@ // primitive_types2.rs -// Fill in the rest of the line that has code missing! -// No hints, there's no tricks, just get used to typing these :) +// +// Fill in the rest of the line that has code missing! No hints, there's no +// tricks, just get used to typing these :) +// +// Execute `rustlings hint primitive_types2` or use the `hint` watch subcommand +// for a hint. // I AM NOT DONE diff --git a/exercises/primitive_types/primitive_types3.rs b/exercises/primitive_types/primitive_types3.rs index fa7d019a..06a7a621 100644 --- a/exercises/primitive_types/primitive_types3.rs +++ b/exercises/primitive_types/primitive_types3.rs @@ -1,6 +1,9 @@ // primitive_types3.rs +// // Create an array with at least 100 elements in it where the ??? is. -// Execute `rustlings hint primitive_types3` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint primitive_types3` or use the `hint` watch subcommand +// for a hint. // I AM NOT DONE diff --git a/exercises/primitive_types/primitive_types4.rs b/exercises/primitive_types/primitive_types4.rs index 71fa243c..d44d8776 100644 --- a/exercises/primitive_types/primitive_types4.rs +++ b/exercises/primitive_types/primitive_types4.rs @@ -1,6 +1,9 @@ // primitive_types4.rs +// // Get a slice out of Array a where the ??? is so that the test passes. -// Execute `rustlings hint primitive_types4` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint primitive_types4` or use the `hint` watch subcommand +// for a hint. // I AM NOT DONE diff --git a/exercises/primitive_types/primitive_types5.rs b/exercises/primitive_types/primitive_types5.rs index 4fd9141f..f646986e 100644 --- a/exercises/primitive_types/primitive_types5.rs +++ b/exercises/primitive_types/primitive_types5.rs @@ -1,6 +1,9 @@ // primitive_types5.rs +// // Destructure the `cat` tuple so that the println will work. -// Execute `rustlings hint primitive_types5` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint primitive_types5` or use the `hint` watch subcommand +// for a hint. // I AM NOT DONE diff --git a/exercises/primitive_types/primitive_types6.rs b/exercises/primitive_types/primitive_types6.rs index ddf8b423..07cc46c6 100644 --- a/exercises/primitive_types/primitive_types6.rs +++ b/exercises/primitive_types/primitive_types6.rs @@ -1,7 +1,10 @@ // primitive_types6.rs -// Use a tuple index to access the second element of `numbers`. -// You can put the expression for the second element where ??? is so that the test passes. -// Execute `rustlings hint primitive_types6` or use the `hint` watch subcommand for a hint. +// +// Use a tuple index to access the second element of `numbers`. You can put the +// expression for the second element where ??? is so that the test passes. +// +// Execute `rustlings hint primitive_types6` or use the `hint` watch subcommand +// for a hint. // I AM NOT DONE diff --git a/exercises/quiz1.rs b/exercises/quiz1.rs index dbb5cdc9..4ee5ada7 100644 --- a/exercises/quiz1.rs +++ b/exercises/quiz1.rs @@ -1,14 +1,17 @@ // quiz1.rs +// // This is a quiz for the following sections: // - Variables // - Functions // - If - +// // Mary is buying apples. The price of an apple is calculated as follows: // - An apple costs 2 rustbucks. // - If Mary buys more than 40 apples, each apple only costs 1 rustbuck! -// Write a function that calculates the price of an order of apples given -// the quantity bought. No hints this time! +// Write a function that calculates the price of an order of apples given the +// quantity bought. +// +// No hints this time ;) // I AM NOT DONE diff --git a/exercises/quiz2.rs b/exercises/quiz2.rs index 5c42dae0..29925caf 100644 --- a/exercises/quiz2.rs +++ b/exercises/quiz2.rs @@ -1,14 +1,15 @@ // quiz2.rs +// // This is a quiz for the following sections: // - Strings // - Vecs // - Move semantics // - Modules // - Enums - -// Let's build a little machine in the form of a function. -// As input, we're going to give a list of strings and commands. These commands -// determine what action is going to be applied to the string. It can either be: +// +// Let's build a little machine in the form of a function. As input, we're going +// to give a list of strings and commands. These commands determine what action +// is going to be applied to the string. It can either be: // - Uppercase the string // - Trim the string // - Append "bar" to the string a specified amount of times @@ -16,6 +17,7 @@ // - The input is going to be a Vector of a 2-length tuple, // the first element is the string, the second one is the command. // - The output element is going to be a Vector of strings. +// // No hints this time! // I AM NOT DONE diff --git a/exercises/quiz3.rs b/exercises/quiz3.rs index 15dc4699..3b01d313 100644 --- a/exercises/quiz3.rs +++ b/exercises/quiz3.rs @@ -1,17 +1,19 @@ // quiz3.rs +// // This quiz tests: // - Generics // - Traits -// An imaginary magical school has a new report card generation system written in Rust! -// Currently the system only supports creating report cards where the student's grade -// is represented numerically (e.g. 1.0 -> 5.5). -// However, the school also issues alphabetical grades (A+ -> F-) and needs -// to be able to print both types of report card! - +// +// An imaginary magical school has a new report card generation system written +// in Rust! Currently the system only supports creating report cards where the +// student's grade is represented numerically (e.g. 1.0 -> 5.5). However, the +// school also issues alphabetical grades (A+ -> F-) and needs to be able to +// print both types of report card! +// // Make the necessary code changes in the struct ReportCard and the impl block -// to support alphabetical report cards. Change the Grade in the second test to "A+" -// to show that your changes allow alphabetical grades. - +// to support alphabetical report cards. Change the Grade in the second test to +// "A+" to show that your changes allow alphabetical grades. +// // Execute `rustlings hint quiz3` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/smart_pointers/arc1.rs b/exercises/smart_pointers/arc1.rs index ffb306af..3526ddcb 100644 --- a/exercises/smart_pointers/arc1.rs +++ b/exercises/smart_pointers/arc1.rs @@ -1,21 +1,24 @@ // arc1.rs -// In this exercise, we are given a Vec of u32 called "numbers" with values ranging -// from 0 to 99 -- [ 0, 1, 2, ..., 98, 99 ] -// We would like to use this set of numbers within 8 different threads simultaneously. -// Each thread is going to get the sum of every eighth value, with an offset. +// +// In this exercise, we are given a Vec of u32 called "numbers" with values +// ranging from 0 to 99 -- [ 0, 1, 2, ..., 98, 99 ] We would like to use this +// set of numbers within 8 different threads simultaneously. Each thread is +// going to get the sum of every eighth value, with an offset. +// // The first thread (offset 0), will sum 0, 8, 16, ... // The second thread (offset 1), will sum 1, 9, 17, ... // The third thread (offset 2), will sum 2, 10, 18, ... // ... // The eighth thread (offset 7), will sum 7, 15, 23, ... - +// // Because we are using threads, our values need to be thread-safe. Therefore, // we are using Arc. We need to make a change in each of the two TODOs. - - +// // Make this code compile by filling in a value for `shared_numbers` where the // first TODO comment is, and create an initial binding for `child_numbers` -// where the second TODO comment is. Try not to create any copies of the `numbers` Vec! +// where the second TODO comment is. Try not to create any copies of the +// `numbers` Vec! +// // Execute `rustlings hint arc1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/smart_pointers/box1.rs b/exercises/smart_pointers/box1.rs index 66cf00f3..513e7daa 100644 --- a/exercises/smart_pointers/box1.rs +++ b/exercises/smart_pointers/box1.rs @@ -1,13 +1,15 @@ // box1.rs // -// At compile time, Rust needs to know how much space a type takes up. This becomes problematic -// for recursive types, where a value can have as part of itself another value of the same type. -// To get around the issue, we can use a `Box` - a smart pointer used to store data on the heap, -// which also allows us to wrap a recursive type. +// At compile time, Rust needs to know how much space a type takes up. This +// becomes problematic for recursive types, where a value can have as part of +// itself another value of the same type. To get around the issue, we can use a +// `Box` - a smart pointer used to store data on the heap, which also allows us +// to wrap a recursive type. // -// The recursive type we're implementing in this exercise is the `cons list` - a data structure -// frequently found in functional programming languages. Each item in a cons list contains two -// elements: the value of the current item and the next item. The last item is a value called `Nil`. +// The recursive type we're implementing in this exercise is the `cons list` - a +// data structure frequently found in functional programming languages. Each +// item in a cons list contains two elements: the value of the current item and +// the next item. The last item is a value called `Nil`. // // Step 1: use a `Box` in the enum definition to make the code compile // Step 2: create both empty and non-empty cons lists by replacing `todo!()` diff --git a/exercises/smart_pointers/cow1.rs b/exercises/smart_pointers/cow1.rs index 885138a7..5ab51152 100644 --- a/exercises/smart_pointers/cow1.rs +++ b/exercises/smart_pointers/cow1.rs @@ -1,12 +1,16 @@ // cow1.rs - -// This exercise explores the Cow, or Clone-On-Write type. -// Cow is a clone-on-write smart pointer. -// It can enclose and provide immutable access to borrowed data, and clone the data lazily when mutation or ownership is required. -// The type is designed to work with general borrowed data via the Borrow trait. +// +// This exercise explores the Cow, or Clone-On-Write type. Cow is a +// clone-on-write smart pointer. It can enclose and provide immutable access to +// borrowed data, and clone the data lazily when mutation or ownership is +// required. The type is designed to work with general borrowed data via the +// Borrow trait. // // This exercise is meant to show you what to expect when passing data to Cow. -// Fix the unit tests by checking for Cow::Owned(_) and Cow::Borrowed(_) at the TODO markers. +// Fix the unit tests by checking for Cow::Owned(_) and Cow::Borrowed(_) at the +// TODO markers. +// +// Execute `rustlings hint cow1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE @@ -50,9 +54,9 @@ mod tests { #[test] fn owned_no_mutation() -> Result<(), &'static str> { - // We can also pass `slice` without `&` so Cow owns it directly. - // In this case no mutation occurs and thus also no clone, - // but the result is still owned because it always was. + // We can also pass `slice` without `&` so Cow owns it directly. In this + // case no mutation occurs and thus also no clone, but the result is + // still owned because it was never borrowed or mutated. let slice = vec![0, 1, 2]; let mut input = Cow::from(slice); match abs_all(&mut input) { @@ -62,11 +66,11 @@ mod tests { #[test] fn owned_mutation() -> Result<(), &'static str> { - // Of course this is also the case if a mutation does occur. - // In this case the call to `to_mut()` returns a reference to - // the same data as before. + // Of course this is also the case if a mutation does occur. In this + // case the call to `to_mut()` returns a reference to the same data as + // before. let slice = vec![-1, 0, 1]; - let mut input = Cow::from(slice); + let mut input = Cow::from(slice).to_mut(); match abs_all(&mut input) { // TODO } diff --git a/exercises/smart_pointers/rc1.rs b/exercises/smart_pointers/rc1.rs index d62f3619..ad3f1ce2 100644 --- a/exercises/smart_pointers/rc1.rs +++ b/exercises/smart_pointers/rc1.rs @@ -1,9 +1,14 @@ // rc1.rs -// In this exercise, we want to express the concept of multiple owners via the Rc type. -// This is a model of our solar system - there is a Sun type and multiple Planets. -// The Planets take ownership of the sun, indicating that they revolve around the sun. - -// Make this code compile by using the proper Rc primitives to express that the sun has multiple owners. +// +// In this exercise, we want to express the concept of multiple owners via the +// Rc type. This is a model of our solar system - there is a Sun type and +// multiple Planets. The Planets take ownership of the sun, indicating that they +// revolve around the sun. +// +// Make this code compile by using the proper Rc primitives to express that the +// sun has multiple owners. +// +// Execute `rustlings hint rc1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/strings/strings1.rs b/exercises/strings/strings1.rs index 0de86a1d..f50e1fa9 100644 --- a/exercises/strings/strings1.rs +++ b/exercises/strings/strings1.rs @@ -1,6 +1,9 @@ // strings1.rs +// // Make me compile without changing the function signature! -// Execute `rustlings hint strings1` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint strings1` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/strings/strings2.rs b/exercises/strings/strings2.rs index 0c48ec95..4d95d16a 100644 --- a/exercises/strings/strings2.rs +++ b/exercises/strings/strings2.rs @@ -1,6 +1,9 @@ // strings2.rs +// // Make me compile without changing the function signature! -// Execute `rustlings hint strings2` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint strings2` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/strings/strings3.rs b/exercises/strings/strings3.rs index e2353aec..b29f9325 100644 --- a/exercises/strings/strings3.rs +++ b/exercises/strings/strings3.rs @@ -1,5 +1,7 @@ // strings3.rs -// Execute `rustlings hint strings3` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint strings3` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/strings/strings4.rs b/exercises/strings/strings4.rs index c410b562..e8c54acc 100644 --- a/exercises/strings/strings4.rs +++ b/exercises/strings/strings4.rs @@ -1,9 +1,10 @@ // strings4.rs - +// // Ok, here are a bunch of values-- some are `String`s, some are `&str`s. Your // task is to call one of these two functions on each value depending on what // you think each value is. That is, add either `string_slice` or `string` // before the parentheses on each line. If you're right, it will compile! +// // No hints this time! // I AM NOT DONE diff --git a/exercises/structs/structs1.rs b/exercises/structs/structs1.rs index 0d91c469..5fa5821c 100644 --- a/exercises/structs/structs1.rs +++ b/exercises/structs/structs1.rs @@ -1,6 +1,9 @@ // structs1.rs +// // Address all the TODOs to make the tests pass! -// Execute `rustlings hint structs1` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint structs1` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/structs/structs2.rs b/exercises/structs/structs2.rs index 32e311fa..328567f0 100644 --- a/exercises/structs/structs2.rs +++ b/exercises/structs/structs2.rs @@ -1,6 +1,9 @@ // structs2.rs +// // Address all the TODOs to make the tests pass! -// Execute `rustlings hint structs2` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint structs2` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/structs/structs3.rs b/exercises/structs/structs3.rs index 3536a457..7cda5af1 100644 --- a/exercises/structs/structs3.rs +++ b/exercises/structs/structs3.rs @@ -1,8 +1,11 @@ // structs3.rs +// // 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. // Make the code compile and the tests pass! -// Execute `rustlings hint structs3` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint structs3` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE @@ -10,13 +13,15 @@ struct Package { sender_country: String, recipient_country: String, - weight_in_grams: i32, + weight_in_grams: u32, } impl Package { - fn new(sender_country: String, recipient_country: String, weight_in_grams: i32) -> Package { - if weight_in_grams <= 0 { - panic!("Can not ship a weightless package.") + fn new(sender_country: String, recipient_country: String, weight_in_grams: u32) -> Package { + if weight_in_grams < 10 { + // This is not how you should handle errors in Rust, + // but we will learn about error handling later. + panic!("Can not ship a package with weight below 10 grams.") } else { Package { sender_country, @@ -30,7 +35,7 @@ impl Package { // Something goes here... } - fn get_fees(&self, cents_per_gram: i32) -> ??? { + fn get_fees(&self, cents_per_gram: u32) -> ??? { // Something goes here... } } @@ -45,7 +50,7 @@ mod tests { let sender_country = String::from("Spain"); let recipient_country = String::from("Austria"); - Package::new(sender_country, recipient_country, -2210); + Package::new(sender_country, recipient_country, 5); } #[test] diff --git a/exercises/tests/tests1.rs b/exercises/tests/tests1.rs index 8b6ea374..810277ac 100644 --- a/exercises/tests/tests1.rs +++ b/exercises/tests/tests1.rs @@ -1,11 +1,14 @@ // tests1.rs -// Tests are important to ensure that your code does what you think it should do. -// Tests can be run on this file with the following command: -// rustlings run tests1 - -// This test has a problem with it -- make the test compile! Make the test -// pass! Make the test fail! -// Execute `rustlings hint tests1` or use the `hint` watch subcommand for a hint. +// +// Tests are important to ensure that your code does what you think it should +// do. Tests can be run on this file with the following command: rustlings run +// tests1 +// +// This test has a problem with it -- make the test compile! Make the test pass! +// Make the test fail! +// +// Execute `rustlings hint tests1` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/tests/tests2.rs b/exercises/tests/tests2.rs index a5ac15b1..f8024e9f 100644 --- a/exercises/tests/tests2.rs +++ b/exercises/tests/tests2.rs @@ -1,7 +1,10 @@ // tests2.rs -// This test has a problem with it -- make the test compile! Make the test -// pass! Make the test fail! -// Execute `rustlings hint tests2` or use the `hint` watch subcommand for a hint. +// +// This test has a problem with it -- make the test compile! Make the test pass! +// Make the test fail! +// +// Execute `rustlings hint tests2` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/tests/tests3.rs b/exercises/tests/tests3.rs index 196a81a0..4013e384 100644 --- a/exercises/tests/tests3.rs +++ b/exercises/tests/tests3.rs @@ -1,8 +1,11 @@ // tests3.rs +// // This test isn't testing our function -- make it do that in such a way that -// the test passes. Then write a second test that tests whether we get the result -// we expect to get when we call `is_even(5)`. -// Execute `rustlings hint tests3` or use the `hint` watch subcommand for a hint. +// the test passes. Then write a second test that tests whether we get the +// result we expect to get when we call `is_even(5)`. +// +// Execute `rustlings hint tests3` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/tests/tests4.rs b/exercises/tests/tests4.rs index 1f34a2b2..935d0db1 100644 --- a/exercises/tests/tests4.rs +++ b/exercises/tests/tests4.rs @@ -1,6 +1,9 @@ // tests4.rs +// // Make sure that we're testing for the correct conditions! -// Execute `rustlings hint tests4` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint tests4` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/threads/README.md b/exercises/threads/README.md index d0866947..dbe66643 100644 --- a/exercises/threads/README.md +++ b/exercises/threads/README.md @@ -1,6 +1,6 @@ # Threads -In most current operating systems, an executed program’s code is run in a process, and the operating system manages multiple processes at once. +In most current operating systems, an executed program's code is run in a process, and the operating system manages multiple processes at once. Within your program, you can also have independent parts that run simultaneously. The features that run these independent parts are called threads. ## Further information diff --git a/exercises/threads/threads1.rs b/exercises/threads/threads1.rs index ae124eeb..80b6def3 100644 --- a/exercises/threads/threads1.rs +++ b/exercises/threads/threads1.rs @@ -1,10 +1,12 @@ // threads1.rs -// Execute `rustlings hint threads1` or use the `hint` watch subcommand for a hint. - -// 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 wait until all the spawned threads have finished and -// should collect their return values into a vector. +// +// 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 +// wait until all the spawned threads have finished and should collect their +// return values into a vector. +// +// Execute `rustlings hint threads1` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/threads/threads2.rs b/exercises/threads/threads2.rs index ada3d14a..62dad80d 100644 --- a/exercises/threads/threads2.rs +++ b/exercises/threads/threads2.rs @@ -1,7 +1,11 @@ // threads2.rs -// Execute `rustlings hint threads2` or use the `hint` watch subcommand for a hint. -// Building on the last exercise, we want all of the threads to complete their work but this time -// the spawned threads need to be in charge of updating a shared value: JobStatus.jobs_completed +// +// Building on the last exercise, we want all of the threads to complete their +// work but this time the spawned threads need to be in charge of updating a +// shared value: JobStatus.jobs_completed +// +// Execute `rustlings hint threads2` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE @@ -27,8 +31,9 @@ fn main() { } for handle in handles { handle.join().unwrap(); - // TODO: Print the value of the JobStatus.jobs_completed. Did you notice anything - // interesting in the output? Do you have to 'join' on all the handles? + // TODO: Print the value of the JobStatus.jobs_completed. Did you notice + // anything interesting in the output? Do you have to 'join' on all the + // handles? println!("jobs completed {}", ???); } } diff --git a/exercises/threads/threads3.rs b/exercises/threads/threads3.rs index 9e9f285a..db7d41ba 100644 --- a/exercises/threads/threads3.rs +++ b/exercises/threads/threads3.rs @@ -1,5 +1,7 @@ // threads3.rs -// Execute `rustlings hint threads3` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint threads3` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/traits/traits1.rs b/exercises/traits/traits1.rs index f5320a5a..37dfcbfe 100644 --- a/exercises/traits/traits1.rs +++ b/exercises/traits/traits1.rs @@ -1,13 +1,11 @@ // traits1.rs -// Time to implement some traits! // -// Your task is to implement the trait -// `AppendBar` for the type `String`. +// Time to implement some traits! Your task is to implement the trait +// `AppendBar` for the type `String`. The trait AppendBar has only one function, +// which appends "Bar" to any object implementing this trait. // -// The trait AppendBar has only one function, -// which appends "Bar" to any object -// implementing this trait. -// Execute `rustlings hint traits1` or use the `hint` watch subcommand for a hint. +// Execute `rustlings hint traits1` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/traits/traits2.rs b/exercises/traits/traits2.rs index 288b4983..3e35f8e1 100644 --- a/exercises/traits/traits2.rs +++ b/exercises/traits/traits2.rs @@ -1,14 +1,11 @@ // traits2.rs // -// Your task is to implement the trait -// `AppendBar` for a vector of strings. -// -// To implement this trait, consider for -// a moment what it means to 'append "Bar"' +// Your task is to implement the trait `AppendBar` for a vector of strings. To +// implement this trait, consider for a moment what it means to 'append "Bar"' // to a vector of strings. // -// No boiler plate code this time, -// you can do this! +// No boiler plate code this time, you can do this! +// // Execute `rustlings hint traits2` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/traits/traits3.rs b/exercises/traits/traits3.rs index 6d2fd6c3..4e2b06b0 100644 --- a/exercises/traits/traits3.rs +++ b/exercises/traits/traits3.rs @@ -1,11 +1,12 @@ // traits3.rs // -// Your task is to implement the Licensed trait for -// both structures and have them return the same -// information without writing the same function twice. +// Your task is to implement the Licensed trait for both structures and have +// them return the same information without writing the same function twice. // // Consider what you can add to the Licensed trait. -// Execute `rustlings hint traits3` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint traits3` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/traits/traits4.rs b/exercises/traits/traits4.rs index 6b541665..4bda3e57 100644 --- a/exercises/traits/traits4.rs +++ b/exercises/traits/traits4.rs @@ -1,8 +1,11 @@ // traits4.rs // // Your task is to replace the '??' sections so the code compiles. +// // Don't change any line other than the marked one. -// Execute `rustlings hint traits4` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint traits4` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/traits/traits5.rs b/exercises/traits/traits5.rs index 0fbca28a..df183805 100644 --- a/exercises/traits/traits5.rs +++ b/exercises/traits/traits5.rs @@ -1,8 +1,11 @@ // traits5.rs // // Your task is to replace the '??' sections so the code compiles. +// // Don't change any line other than the marked one. -// Execute `rustlings hint traits5` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint traits5` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/variables/variables1.rs b/exercises/variables/variables1.rs index f4d182ac..b3e089a5 100644 --- a/exercises/variables/variables1.rs +++ b/exercises/variables/variables1.rs @@ -1,6 +1,9 @@ // variables1.rs +// // Make me compile! -// Execute `rustlings hint variables1` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint variables1` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/variables/variables2.rs b/exercises/variables/variables2.rs index 641aeb8e..e1c23edf 100644 --- a/exercises/variables/variables2.rs +++ b/exercises/variables/variables2.rs @@ -1,5 +1,7 @@ // variables2.rs -// Execute `rustlings hint variables2` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint variables2` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/variables/variables3.rs b/exercises/variables/variables3.rs index 819b1bc7..86bed419 100644 --- a/exercises/variables/variables3.rs +++ b/exercises/variables/variables3.rs @@ -1,5 +1,7 @@ // variables3.rs -// Execute `rustlings hint variables3` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint variables3` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/variables/variables4.rs b/exercises/variables/variables4.rs index 54491b0a..5394f394 100644 --- a/exercises/variables/variables4.rs +++ b/exercises/variables/variables4.rs @@ -1,5 +1,7 @@ // variables4.rs -// Execute `rustlings hint variables4` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint variables4` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/variables/variables5.rs b/exercises/variables/variables5.rs index 0e670d2a..a29b38be 100644 --- a/exercises/variables/variables5.rs +++ b/exercises/variables/variables5.rs @@ -1,5 +1,7 @@ // variables5.rs -// Execute `rustlings hint variables5` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint variables5` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/variables/variables6.rs b/exercises/variables/variables6.rs index a8520122..853183ba 100644 --- a/exercises/variables/variables6.rs +++ b/exercises/variables/variables6.rs @@ -1,5 +1,7 @@ // variables6.rs -// Execute `rustlings hint variables6` or use the `hint` watch subcommand for a hint. +// +// Execute `rustlings hint variables6` or use the `hint` watch subcommand for a +// hint. // I AM NOT DONE diff --git a/exercises/vecs/vecs1.rs b/exercises/vecs/vecs1.rs index 4e8c4cbb..65b7a7f8 100644 --- a/exercises/vecs/vecs1.rs +++ b/exercises/vecs/vecs1.rs @@ -1,7 +1,10 @@ // vecs1.rs -// Your task is to create a `Vec` which holds the exact same elements -// as in the array `a`. +// +// Your task is to create a `Vec` which holds the exact same elements as in the +// array `a`. +// // Make me compile and pass the test! +// // Execute `rustlings hint vecs1` or use the `hint` watch subcommand for a hint. // I AM NOT DONE diff --git a/exercises/vecs/vecs2.rs b/exercises/vecs/vecs2.rs index 1ea26071..e92c970a 100644 --- a/exercises/vecs/vecs2.rs +++ b/exercises/vecs/vecs2.rs @@ -1,6 +1,7 @@ // vecs2.rs -// A Vec of even numbers is given. Your task is to complete the loop -// so that each number in the Vec is multiplied by 2. +// +// A Vec of even numbers is given. Your task is to complete the loop so that +// each number in the Vec is multiplied by 2. // // Make me pass the test! // diff --git a/flake.nix b/flake.nix index 5815a920..f65c2907 100644 --- a/flake.nix +++ b/flake.nix @@ -22,9 +22,10 @@ rustlings = pkgs.rustPlatform.buildRustPackage { name = "rustlings"; - version = "5.4.1"; + version = "5.5.1"; buildInputs = cargoBuildInputs; + nativeBuildInputs = [pkgs.git]; src = with pkgs.lib; cleanSourceWith { src = self; @@ -60,5 +61,18 @@ clippy ] ++ cargoBuildInputs; }; + apps = let + rustlings-app = { + type = "app"; + program = "${rustlings}/bin/rustlings"; + }; + in { + default = rustlings-app; + rustlings = rustlings-app; + }; + packages = { + inherit rustlings; + default = rustlings; + }; }); } diff --git a/info.toml b/info.toml index 8f391bae..c84dfa5f 100644 --- a/info.toml +++ b/info.toml @@ -22,8 +22,8 @@ name = "variables1" path = "exercises/variables/variables1.rs" mode = "compile" hint = """ -The declaration on line 8 is missing a keyword that is needed in Rust -to create a new variable binding.""" +The declaration in the first line in the main function is missing a keyword +that is needed in Rust to create a new variable binding.""" [[exercises]] name = "variables2" @@ -32,7 +32,7 @@ mode = "compile" hint = """ The compiler message is saying that Rust cannot infer the type that the variable binding `x` has with what is given here. -What happens if you annotate line 7 with a type annotation? +What happens if you annotate the first line in the main function with a type annotation? What if you give x a value? What if you do both? What type should x be, anyway? @@ -44,8 +44,9 @@ path = "exercises/variables/variables3.rs" mode = "compile" hint = """ Oops! In this exercise, we have a variable binding that we've created on -line 7, and we're trying to use it on line 8, but we haven't given it a -value. We can't print out something that isn't there; try giving x a value! +in the first line in the main function, and we're trying to use it in the next line, +but we haven't given it a value. +We can't print out something that isn't there; try giving x a value! This is an error that can cause bugs that's very easy to make in any programming language -- thankfully the Rust compiler has caught this for us!""" @@ -123,8 +124,8 @@ name = "functions4" path = "exercises/functions/functions4.rs" mode = "compile" hint = """ -The error message points to line 17 and says it expects a type after the -`->`. This is where the function's return type should be -- take a look at +The error message points to the function `sale_price` and says it expects a type +after the `->`. This is where the function's return type should be -- take a look at the `is_even` function for an example! Also: Did you figure out that, technically, u32 would be the more fitting type @@ -167,6 +168,13 @@ For that first compiler error, it's important in Rust that each conditional block returns the same type! To get the tests passing, you will need a couple conditions checking different input values.""" +[[exercises]] +name = "if3" +path = "exercises/if/if3.rs" +mode = "test" +hint = """ +In Rust, every arm of an `if` expression has to return the same type of value. Make sure the type is consistent across all arms.""" + # QUIZ 1 [[exercises]] @@ -209,7 +217,7 @@ mode = "test" 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 indices of the items in the Array +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 @@ -275,39 +283,37 @@ What do you think is the more commonly used pattern under Rust developers? [[exercises]] name = "move_semantics1" path = "exercises/move_semantics/move_semantics1.rs" -mode = "compile" +mode = "test" hint = """ -So you've got the "cannot borrow immutable local variable `vec1` as mutable" error on line 13, -right? The fix for this is going to be adding one keyword, and the addition is NOT on line 13 -where the error is. +So you've got the "cannot borrow immutable local variable `vec` as mutable" error on the line +where we push an element to the vector, right? +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). Also: Try accessing `vec0` after having called `fill_vec()`. See what happens!""" [[exercises]] name = "move_semantics2" path = "exercises/move_semantics/move_semantics2.rs" -mode = "compile" +mode = "test" hint = """ -So, `vec0` is passed into the `fill_vec` function as an argument. In Rust, -when an argument is passed to a function and it's not explicitly returned, -you can't use the original variable anymore. We call this "moving" a variable. -Variables that are moved into a function (or block scope) and aren't explicitly -returned get "dropped" at the end of that function. This is also what happens here. -There's a few ways to fix this, try them all if you want: -1. Make another, separate version of the data that's in `vec0` and pass that +When running this exercise for the first time, you'll notice an error about +"borrow of moved value". In Rust, when an argument is passed to a function and +it's not explicitly returned, you can't use the original variable anymore. +We call this "moving" a variable. When we pass `vec0` into `fill_vec`, it's being +"moved" into `vec1`, meaning we can't access `vec0` anymore after the fact. +Rust provides a couple of different ways to mitigate this issue, feel free to try them all: +1. You could make another, separate version of the data that's in `vec0` and pass that to `fill_vec` instead. 2. Make `fill_vec` borrow its argument instead of taking ownership of it, - and then copy the data within the function in order to return an owned - `Vec` -3. Make `fill_vec` *mutably* borrow a reference to its argument (which will need to be - mutable), modify it directly, then not return anything. Then you can get rid - of `vec1` entirely -- note that this will change what gets printed by the - first `println!`""" + and then copy the data within the function (`vec.clone()`) in order to return an owned + `Vec`. +""" [[exercises]] name = "move_semantics3" path = "exercises/move_semantics/move_semantics3.rs" -mode = "compile" +mode = "test" hint = """ The difference between this one and the previous ones is that the first line of `fn fill_vec` that had `let mut vec = vec;` is no longer there. You can, @@ -317,7 +323,7 @@ an existing binding to be a mutable binding instead of an immutable one :)""" [[exercises]] name = "move_semantics4" path = "exercises/move_semantics/move_semantics4.rs" -mode = "compile" +mode = "test" hint = """ Stop reading whenever you feel like you have enough direction :) Or try doing one step and then fixing the compiler errors that result! @@ -326,7 +332,7 @@ So the end goal is to: - so then `vec0` doesn't exist, so we can't pass it to `fill_vec` - `fill_vec` has had its signature changed, which our call should reflect - since we're not creating a new vec in `main` anymore, we need to create - a new vec in `fill_vec`, similarly to the way we did in `main`""" + a new vec in `fill_vec`, and fill it with the expected values""" [[exercises]] name = "move_semantics5" @@ -436,8 +442,8 @@ path = "exercises/strings/strings2.rs" mode = "compile" hint = """ Yes, it would be really easy to fix this by just changing the value bound to `word` to be a -string slice instead of a `String`, wouldn't it?? There is a way to add one character to line -9, though, that will coerce the `String` into a string slice. +string slice instead of a `String`, wouldn't it?? There is a way to add one character to the +if statement, though, that will coerce the `String` into a string slice. Side note: If you're interested in learning about how this kind of reference conversion works, you can jump ahead in the book and read this part in the smart pointers chapter: https://doc.rust-lang.org/stable/book/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods""" @@ -477,7 +483,8 @@ hint = """ The delicious_snacks module is trying to present an external interface that is different than its internal structure (the `fruits` and `veggies` modules and associated constants). Complete the `use` statements to fit the uses in main and -find the one keyword missing for both constants.""" +find the one keyword missing for both constants. +Learn more at https://doc.rust-lang.org/book/ch07-04-bringing-paths-into-scope-with-the-use-keyword.html#re-exporting-names-with-pub-use""" [[exercises]] name = "modules3" @@ -815,7 +822,6 @@ To handle that you need to add a special attribute to the test function. You can refer to the docs: https://doc.rust-lang.org/stable/book/ch11-01-writing-tests.html#checking-for-panics-with-should_panic""" - # STANDARD LIBRARY TYPES [[exercises]] @@ -895,9 +901,6 @@ hint = """ The documentation for the std::iter::Iterator trait contains numerous methods that would be helpful here. -Return 0 from count_collection_iterator to make the code compile in order to -test count_iterator. - The collection variable in count_collection_iterator is a slice of HashMaps. It needs to be converted into an iterator in order to use the iterator methods. @@ -906,67 +909,6 @@ The fold method can be useful in the count_collection_iterator function. For a further challenge, consult the documentation for Iterator to find a different method that could make your code more compact than using fold.""" -# THREADS - -[[exercises]] -name = "threads1" -path = "exercises/threads/threads1.rs" -mode = "compile" -hint = """ -`JoinHandle` is a struct that is returned from a spawned thread: -https://doc.rust-lang.org/std/thread/fn.spawn.html - -A challenge with multi-threaded applications is that the main thread can -finish before the spawned threads are completed. -https://doc.rust-lang.org/book/ch16-01-threads.html#waiting-for-all-threads-to-finish-using-join-handles - -Use the JoinHandles to wait for each thread to finish and collect their results. -https://doc.rust-lang.org/std/thread/struct.JoinHandle.html -""" - -[[exercises]] -name = "threads2" -path = "exercises/threads/threads2.rs" -mode = "compile" -hint = """ -`Arc` is an Atomic Reference Counted pointer that allows safe, shared access -to **immutable** data. But we want to *change* the number of `jobs_completed` -so we'll need to also use another type that will only allow one thread to -mutate the data at a time. Take a look at this section of the book: -https://doc.rust-lang.org/book/ch16-03-shared-state.html#atomic-reference-counting-with-arct -and keep reading if you'd like more hints :) - - -Do you now have an `Arc` `Mutex` `JobStatus` at the beginning of main? Like: -`let status = Arc::new(Mutex::new(JobStatus { jobs_completed: 0 }));` -Similar to the code in the example in the book that happens after the text -that says "We can use Arc to fix this.". If not, give that a try! If you -do and would like more hints, keep reading!! - - -Make sure neither of your threads are holding onto the lock of the mutex -while they are sleeping, since this will prevent the other thread from -being allowed to get the lock. Locks are automatically released when -they go out of scope. - -If you've learned from the sample solutions, I encourage you to come -back to this exercise and try it again in a few days to reinforce -what you've learned :)""" - -[[exercises]] -name = "threads3" -path = "exercises/threads/threads3.rs" -mode = "compile" -hint = """ -An alternate way to handle concurrency between threads is to use -a mpsc (multiple producer, single consumer) channel to communicate. -With both a sending end and a receiving end, it's possible to -send values in one thread and receive them in another. -Multiple producers are possible by using clone() to create a duplicate -of the original sending end. -See https://doc.rust-lang.org/book/ch16-02-message-passing.html for more info. -""" - # SMART POINTERS [[exercises]] @@ -1029,6 +971,67 @@ Check out https://doc.rust-lang.org/std/borrow/enum.Cow.html for documentation on the `Cow` type. """ +# THREADS + +[[exercises]] +name = "threads1" +path = "exercises/threads/threads1.rs" +mode = "compile" +hint = """ +`JoinHandle` is a struct that is returned from a spawned thread: +https://doc.rust-lang.org/std/thread/fn.spawn.html + +A challenge with multi-threaded applications is that the main thread can +finish before the spawned threads are completed. +https://doc.rust-lang.org/book/ch16-01-threads.html#waiting-for-all-threads-to-finish-using-join-handles + +Use the JoinHandles to wait for each thread to finish and collect their results. +https://doc.rust-lang.org/std/thread/struct.JoinHandle.html +""" + +[[exercises]] +name = "threads2" +path = "exercises/threads/threads2.rs" +mode = "compile" +hint = """ +`Arc` is an Atomic Reference Counted pointer that allows safe, shared access +to **immutable** data. But we want to *change* the number of `jobs_completed` +so we'll need to also use another type that will only allow one thread to +mutate the data at a time. Take a look at this section of the book: +https://doc.rust-lang.org/book/ch16-03-shared-state.html#atomic-reference-counting-with-arct +and keep reading if you'd like more hints :) + + +Do you now have an `Arc` `Mutex` `JobStatus` at the beginning of main? Like: +`let status = Arc::new(Mutex::new(JobStatus { jobs_completed: 0 }));` +Similar to the code in the example in the book that happens after the text +that says "Sharing a Mutex Between Multiple Threads". If not, give that a try! If you +do and would like more hints, keep reading!! + + +Make sure neither of your threads are holding onto the lock of the mutex +while they are sleeping, since this will prevent the other thread from +being allowed to get the lock. Locks are automatically released when +they go out of scope. + +If you've learned from the sample solutions, I encourage you to come +back to this exercise and try it again in a few days to reinforce +what you've learned :)""" + +[[exercises]] +name = "threads3" +path = "exercises/threads/threads3.rs" +mode = "compile" +hint = """ +An alternate way to handle concurrency between threads is to use +a mpsc (multiple producer, single consumer) channel to communicate. +With both a sending end and a receiving end, it's possible to +send values in one thread and receive them in another. +Multiple producers are possible by using clone() to create a duplicate +of the original sending end. +See https://doc.rust-lang.org/book/ch16-02-message-passing.html for more info. +""" + # MACROS [[exercises]] @@ -1171,4 +1174,4 @@ name = "as_ref_mut" path = "exercises/conversions/as_ref_mut.rs" mode = "test" hint = """ -Add AsRef as a trait bound to the functions.""" +Add AsRef or AsMut as a trait bound to the functions.""" diff --git a/install.ps1 b/install.ps1 index 97980c5b..7bab21f6 100644 --- a/install.ps1 +++ b/install.ps1 @@ -1,7 +1,7 @@ #!/usr/bin/env pwsh #Requires -Version 5 -param($path = "$pwd/rustlings") +param($path = "$home/rustlings") Write-Host "Let's get you set up with Rustlings!" @@ -91,4 +91,4 @@ if (!$clippy) { rustup component add clippy } -Write-Host "All done! Run 'rustlings' to get started." +Write-Host "All done! Navigate to $path and run 'rustlings' to get started!" diff --git a/oranda.json b/oranda.json new file mode 100644 index 00000000..603e474e --- /dev/null +++ b/oranda.json @@ -0,0 +1,25 @@ +{ + "project": { + "homepage": "https://rustlings.cool", + "repository": "https://github.com/rust-lang/rustlings" + }, + "marketing": { + "analytics": { + "plausible": { + "domain": "rustlings.cool" + } + } + }, + "components": { + "artifacts": { + "cargo_dist": false, + "package_managers": { + "preferred": { + "macos/linux/unix": "curl -L https://raw.githubusercontent.com/rust-lang/rustlings/main/install.sh | bash", + "windows": "Start-BitsTransfer -Source https://raw.githubusercontent.com/rust-lang/rustlings/main/install.ps1 -Destination $env:TMP/install_rustlings.ps1; Unblock-File $env:TMP/install_rustlings.ps1; Invoke-Expression $env:TMP/install_rustlings.ps1" + } + } + }, + "changelog": true + } +} diff --git a/src/exercise.rs b/src/exercise.rs index 2cde4e15..07251dba 100644 --- a/src/exercise.rs +++ b/src/exercise.rs @@ -110,12 +110,12 @@ impl Exercise { pub fn compile(&self) -> Result { let cmd = match self.mode { Mode::Compile => Command::new("rustc") - .args(&[self.path.to_str().unwrap(), "-o", &temp_file()]) + .args([self.path.to_str().unwrap(), "-o", &temp_file()]) .args(RUSTC_COLOR_ARGS) .args(RUSTC_EDITION_ARGS) .output(), Mode::Test => Command::new("rustc") - .args(&["--test", self.path.to_str().unwrap(), "-o", &temp_file()]) + .args(["--test", self.path.to_str().unwrap(), "-o", &temp_file()]) .args(RUSTC_COLOR_ARGS) .args(RUSTC_EDITION_ARGS) .output(), @@ -141,7 +141,7 @@ path = "{}.rs""#, // compilation failure, this would silently fail. But we expect // clippy to reflect the same failure while compiling later. Command::new("rustc") - .args(&[self.path.to_str().unwrap(), "-o", &temp_file()]) + .args([self.path.to_str().unwrap(), "-o", &temp_file()]) .args(RUSTC_COLOR_ARGS) .args(RUSTC_EDITION_ARGS) .output() @@ -151,14 +151,14 @@ path = "{}.rs""#, // This is already fixed on Clippy's master branch. See this issue to track merging into Cargo: // https://github.com/rust-lang/rust-clippy/issues/3837 Command::new("cargo") - .args(&["clean", "--manifest-path", CLIPPY_CARGO_TOML_PATH]) + .args(["clean", "--manifest-path", CLIPPY_CARGO_TOML_PATH]) .args(RUSTC_COLOR_ARGS) .output() .expect("Failed to run 'cargo clean'"); Command::new("cargo") - .args(&["clippy", "--manifest-path", CLIPPY_CARGO_TOML_PATH]) + .args(["clippy", "--manifest-path", CLIPPY_CARGO_TOML_PATH]) .args(RUSTC_COLOR_ARGS) - .args(&["--", "-D", "warnings", "-D", "clippy::float_cmp"]) + .args(["--", "-D", "warnings", "-D", "clippy::float_cmp"]) .output() } } @@ -183,7 +183,7 @@ path = "{}.rs""#, Mode::Test => "--show-output", _ => "", }; - let cmd = Command::new(&temp_file()) + let cmd = Command::new(temp_file()) .arg(arg) .output() .expect("Failed to run 'run' command"); @@ -260,7 +260,7 @@ impl Display for Exercise { #[inline] fn clean() { - let _ignored = remove_file(&temp_file()); + let _ignored = remove_file(temp_file()); } #[cfg(test)] @@ -270,7 +270,7 @@ mod test { #[test] fn test_clean() { - File::create(&temp_file()).unwrap(); + File::create(temp_file()).unwrap(); let exercise = Exercise { name: String::from("example"), path: PathBuf::from("tests/fixture/state/pending_exercise.rs"), diff --git a/src/main.rs b/src/main.rs index 704398e5..a4b764d7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ use crate::exercise::{Exercise, ExerciseList}; use crate::project::RustAnalyzerProject; use crate::run::{reset, run}; use crate::verify::verify; -use argh::FromArgs; +use clap::{Parser, Subcommand}; use console::Emoji; use notify::DebouncedEvent; use notify::{RecommendedWatcher, RecursiveMode, Watcher}; @@ -25,107 +25,69 @@ mod project; mod run; mod verify; -// In sync with crate version -const VERSION: &str = "5.4.1"; - -#[derive(FromArgs, PartialEq, Debug)] /// Rustlings is a collection of small exercises to get you used to writing and reading Rust code +#[derive(Parser)] +#[command(version)] struct Args { - /// show outputs from the test exercises - #[argh(switch)] + /// Show outputs from the test exercises + #[arg(long)] nocapture: bool, - /// show the executable version - #[argh(switch, short = 'v')] - version: bool, - #[argh(subcommand)] - nested: Option, + #[command(subcommand)] + command: Option, } -#[derive(FromArgs, PartialEq, Debug)] -#[argh(subcommand)] +#[derive(Subcommand)] enum Subcommands { - Verify(VerifyArgs), - Watch(WatchArgs), - Run(RunArgs), - Reset(ResetArgs), - Hint(HintArgs), - List(ListArgs), - Lsp(LspArgs), -} - -#[derive(FromArgs, PartialEq, Debug)] -#[argh(subcommand, name = "verify")] -/// Verifies all exercises according to the recommended order -struct VerifyArgs {} - -#[derive(FromArgs, PartialEq, Debug)] -#[argh(subcommand, name = "watch")] -/// Reruns `verify` when files were edited -struct WatchArgs {} - -#[derive(FromArgs, PartialEq, Debug)] -#[argh(subcommand, name = "run")] -/// Runs/Tests a single exercise -struct RunArgs { - #[argh(positional)] - /// the name of the exercise - name: String, -} - -#[derive(FromArgs, PartialEq, Debug)] -#[argh(subcommand, name = "reset")] -/// Resets a single exercise using "git stash -- " -struct ResetArgs { - #[argh(positional)] - /// the name of the exercise - name: String, -} - -#[derive(FromArgs, PartialEq, Debug)] -#[argh(subcommand, name = "hint")] -/// Returns a hint for the given exercise -struct HintArgs { - #[argh(positional)] - /// the name of the exercise - name: String, -} - -#[derive(FromArgs, PartialEq, Debug)] -#[argh(subcommand, name = "lsp")] -/// Enable rust-analyzer for exercises -struct LspArgs {} - -#[derive(FromArgs, PartialEq, Debug)] -#[argh(subcommand, name = "list")] -/// Lists the exercises available in Rustlings -struct ListArgs { - #[argh(switch, short = 'p')] - /// show only the paths of the exercises - paths: bool, - #[argh(switch, short = 'n')] - /// show only the names of the exercises - names: bool, - #[argh(option, short = 'f')] - /// provide a string to match exercise names - /// comma separated patterns are acceptable - filter: Option, - #[argh(switch, short = 'u')] - /// display only exercises not yet solved - unsolved: bool, - #[argh(switch, short = 's')] - /// display only exercises that have been solved - solved: bool, + /// Verify all exercises according to the recommended order + Verify, + /// Rerun `verify` when files were edited + Watch { + /// Show hints on success + #[arg(long)] + success_hints: bool, + }, + /// Run/Test a single exercise + Run { + /// The name of the exercise + name: String, + }, + /// Reset a single exercise using "git stash -- " + Reset { + /// The name of the exercise + name: String, + }, + /// Return a hint for the given exercise + Hint { + /// The name of the exercise + name: String, + }, + /// List the exercises available in Rustlings + List { + /// Show only the paths of the exercises + #[arg(short, long)] + paths: bool, + /// Show only the names of the exercises + #[arg(short, long)] + names: bool, + /// Provide a string to match exercise names. + /// Comma separated patterns are accepted + #[arg(short, long)] + filter: Option, + /// Display only exercises not yet solved + #[arg(short, long)] + unsolved: bool, + /// Display only exercises that have been solved + #[arg(short, long)] + solved: bool, + }, + /// Enable rust-analyzer for exercises + Lsp, } fn main() { - let args: Args = argh::from_env(); + let args = Args::parse(); - if args.version { - println!("v{VERSION}"); - std::process::exit(0); - } - - if args.nested.is_none() { + if args.command.is_none() { println!("\n{WELCOME}\n"); } @@ -149,23 +111,30 @@ fn main() { let exercises = toml::from_str::(toml_str).unwrap().exercises; let verbose = args.nocapture; - let command = args.nested.unwrap_or_else(|| { + let command = args.command.unwrap_or_else(|| { println!("{DEFAULT_OUT}\n"); std::process::exit(0); }); + match command { - Subcommands::List(subargs) => { - if !subargs.paths && !subargs.names { + Subcommands::List { + paths, + names, + filter, + unsolved, + solved, + } => { + if !paths && !names { println!("{:<17}\t{:<46}\t{:<7}", "Name", "Path", "Status"); } let mut exercises_done: u16 = 0; - let filters = subargs.filter.clone().unwrap_or_default().to_lowercase(); + let filters = filter.clone().unwrap_or_default().to_lowercase(); exercises.iter().for_each(|e| { let fname = format!("{}", e.path.display()); let filter_cond = filters .split(',') .filter(|f| !f.trim().is_empty()) - .any(|f| e.name.contains(&f) || fname.contains(&f)); + .any(|f| e.name.contains(f) || fname.contains(f)); let status = if e.looks_done() { exercises_done += 1; "Done" @@ -173,14 +142,14 @@ fn main() { "Pending" }; let solve_cond = { - (e.looks_done() && subargs.solved) - || (!e.looks_done() && subargs.unsolved) - || (!subargs.solved && !subargs.unsolved) + (e.looks_done() && solved) + || (!e.looks_done() && unsolved) + || (!solved && !unsolved) }; - if solve_cond && (filter_cond || subargs.filter.is_none()) { - let line = if subargs.paths { + if solve_cond && (filter_cond || filter.is_none()) { + let line = if paths { format!("{fname}\n") - } else if subargs.names { + } else if names { format!("{}\n", e.name) } else { format!("{:<17}\t{fname:<46}\t{status:<7}\n", e.name) @@ -210,30 +179,30 @@ fn main() { std::process::exit(0); } - Subcommands::Run(subargs) => { - let exercise = find_exercise(&subargs.name, &exercises); + Subcommands::Run { name } => { + let exercise = find_exercise(&name, &exercises); run(exercise, verbose).unwrap_or_else(|_| std::process::exit(1)); } - Subcommands::Reset(subargs) => { - let exercise = find_exercise(&subargs.name, &exercises); + Subcommands::Reset { name } => { + let exercise = find_exercise(&name, &exercises); reset(exercise).unwrap_or_else(|_| std::process::exit(1)); } - Subcommands::Hint(subargs) => { - let exercise = find_exercise(&subargs.name, &exercises); + Subcommands::Hint { name } => { + let exercise = find_exercise(&name, &exercises); println!("{}", exercise.hint); } - Subcommands::Verify(_subargs) => { - verify(&exercises, (0, exercises.len()), verbose) + Subcommands::Verify => { + verify(&exercises, (0, exercises.len()), verbose, false) .unwrap_or_else(|_| std::process::exit(1)); } - Subcommands::Lsp(_subargs) => { + Subcommands::Lsp => { let mut project = RustAnalyzerProject::new(); project .get_sysroot_src() @@ -252,7 +221,7 @@ fn main() { } } - Subcommands::Watch(_subargs) => match watch(&exercises, verbose) { + Subcommands::Watch { success_hints } => match watch(&exercises, verbose, success_hints) { Err(e) => { println!( "Error: Could not watch your progress. Error message was {:?}.", @@ -298,13 +267,21 @@ fn spawn_watch_shell( println!("Bye!"); } else if input.eq("help") { println!("Commands available to you in watch mode:"); - println!(" hint - prints the current exercise's hint"); - println!(" clear - clears the screen"); - println!(" quit - quits watch mode"); - println!(" help - displays this help message"); + println!(" hint - prints the current exercise's hint"); + println!(" clear - clears the screen"); + println!(" quit - quits watch mode"); + println!(" ! - executes a command, like `!rustc --explain E0381`"); + println!(" help - displays this help message"); println!(); println!("Watch mode automatically re-evaluates the current exercise"); println!("when you edit a file's contents.") + } else if let Some(cmd) = input.strip_prefix('!') { + let parts: Vec<&str> = cmd.split_whitespace().collect(); + if parts.is_empty() { + println!("no command provided"); + } else if let Err(e) = Command::new(parts[0]).args(&parts[1..]).status() { + println!("failed to execute command `{}`: {}", cmd, e); + } } else { println!("unknown command: {input}"); } @@ -340,7 +317,11 @@ enum WatchStatus { Unfinished, } -fn watch(exercises: &[Exercise], verbose: bool) -> notify::Result { +fn watch( + exercises: &[Exercise], + verbose: bool, + success_hints: bool, +) -> notify::Result { /* Clears the terminal with an ANSI escape code. Works in UNIX and newer Windows terminals. */ fn clear_screen() { @@ -356,7 +337,12 @@ fn watch(exercises: &[Exercise], verbose: bool) -> notify::Result { clear_screen(); let to_owned_hint = |t: &Exercise| t.hint.to_owned(); - let failed_exercise_hint = match verify(exercises.iter(), (0, exercises.len()), verbose) { + let failed_exercise_hint = match verify( + exercises.iter(), + (0, exercises.len()), + verbose, + success_hints, + ) { Ok(_) => return Ok(WatchStatus::Finished), Err(exercise) => Arc::new(Mutex::new(Some(to_owned_hint(exercise)))), }; @@ -378,7 +364,12 @@ fn watch(exercises: &[Exercise], verbose: bool) -> notify::Result { ); let num_done = exercises.iter().filter(|e| e.looks_done()).count(); clear_screen(); - match verify(pending_exercises, (num_done, exercises.len()), verbose) { + match verify( + pending_exercises, + (num_done, exercises.len()), + verbose, + success_hints, + ) { Ok(_) => return Ok(WatchStatus::Finished), Err(exercise) => { let mut failed_exercise_hint = failed_exercise_hint.lock().unwrap(); @@ -403,7 +394,7 @@ fn watch(exercises: &[Exercise], verbose: bool) -> notify::Result { fn rustc_exists() -> bool { Command::new("rustc") - .args(&["--version"]) + .args(["--version"]) .stdout(Stdio::null()) .spawn() .and_then(|mut child| child.wait()) @@ -439,7 +430,7 @@ started, here's a couple of notes about how Rustlings operates: Got all that? Great! To get started, run `rustlings watch` in order to get the first exercise. Make sure to have your editor open!"#; -const FENISH_LINE: &str = r#"+----------------------------------------------------+ +const FENISH_LINE: &str = r"+----------------------------------------------------+ | You made it to the Fe-nish line! | +-------------------------- ------------------------+ \\/ @@ -464,12 +455,12 @@ If you noticed any issues, please don't hesitate to report them to our repo. You can also contribute your own exercises to help the greater community! Before reporting an issue or contributing, please read our guidelines: -https://github.com/rust-lang/rustlings/blob/main/CONTRIBUTING.md"#; +https://github.com/rust-lang/rustlings/blob/main/CONTRIBUTING.md"; -const WELCOME: &str = r#" welcome to... +const WELCOME: &str = r" welcome to... _ _ _ _ __ _ _ ___| |_| (_)_ __ __ _ ___ | '__| | | / __| __| | | '_ \ / _` / __| | | | |_| \__ \ |_| | | | | | (_| \__ \ |_| \__,_|___/\__|_|_|_| |_|\__, |___/ - |___/"#; + |___/"; diff --git a/src/project.rs b/src/project.rs index 6e483504..bcbd7ada 100644 --- a/src/project.rs +++ b/src/project.rs @@ -2,6 +2,7 @@ use glob::glob; use serde::{Deserialize, Serialize}; use std::env; use std::error::Error; +use std::path::PathBuf; use std::process::Command; /// Contains the structure of resulting rust-project.json file @@ -38,11 +39,11 @@ impl RustAnalyzerProject { } /// If path contains .rs extension, add a crate to `rust-project.json` - fn path_to_json(&mut self, path: String) { - if let Some((_, ext)) = path.split_once('.') { + fn path_to_json(&mut self, path: PathBuf) -> Result<(), Box> { + if let Some(ext) = path.extension() { if ext == "rs" { self.crates.push(Crate { - root_module: path, + root_module: path.display().to_string(), edition: "2021".to_string(), deps: Vec::new(), // This allows rust_analyzer to work inside #[test] blocks @@ -50,15 +51,16 @@ impl RustAnalyzerProject { }) } } + + Ok(()) } /// Parse the exercises folder for .rs files, any matches will create /// a new `crate` in rust-project.json which allows rust-analyzer to /// treat it like a normal binary pub fn exercises_to_json(&mut self) -> Result<(), Box> { - for e in glob("./exercises/**/*")? { - let path = e?.to_string_lossy().to_string(); - self.path_to_json(path); + for path in glob("./exercises/**/*")? { + self.path_to_json(path?)?; } Ok(()) } @@ -84,7 +86,7 @@ impl RustAnalyzerProject { println!("Determined toolchain: {}\n", &toolchain); - self.sysroot_src = (std::path::Path::new(&*toolchain) + self.sysroot_src = (std::path::Path::new(toolchain) .join("lib") .join("rustlib") .join("src") diff --git a/src/run.rs b/src/run.rs index 1e2e56cf..e0ada4c5 100644 --- a/src/run.rs +++ b/src/run.rs @@ -1,4 +1,5 @@ use std::process::Command; +use std::time::Duration; use crate::exercise::{Exercise, Mode}; use crate::verify::test; @@ -36,7 +37,7 @@ pub fn reset(exercise: &Exercise) -> Result<(), ()> { fn compile_and_run(exercise: &Exercise) -> Result<(), ()> { let progress_bar = ProgressBar::new_spinner(); progress_bar.set_message(format!("Compiling {exercise}...")); - progress_bar.enable_steady_tick(100); + progress_bar.enable_steady_tick(Duration::from_millis(100)); let compilation_result = exercise.compile(); let compilation = match compilation_result { diff --git a/src/verify.rs b/src/verify.rs index 68ba6cef..8a2ad49f 100644 --- a/src/verify.rs +++ b/src/verify.rs @@ -1,7 +1,7 @@ use crate::exercise::{CompiledExercise, Exercise, Mode, State}; use console::style; use indicatif::{ProgressBar, ProgressStyle}; -use std::env; +use std::{env, time::Duration}; // Verify that the provided container of Exercise objects // can be compiled and run without any failures. @@ -12,22 +12,25 @@ pub fn verify<'a>( exercises: impl IntoIterator, progress: (usize, usize), verbose: bool, + success_hints: bool, ) -> Result<(), &'a Exercise> { let (num_done, total) = progress; let bar = ProgressBar::new(total as u64); let mut percentage = num_done as f32 / total as f32 * 100.0; - bar.set_style(ProgressStyle::default_bar() - .template("Progress: [{bar:60.green/red}] {pos}/{len} {msg}") - .progress_chars("#>-") + bar.set_style( + ProgressStyle::default_bar() + .template("Progress: [{bar:60.green/red}] {pos}/{len} {msg}") + .expect("Progressbar template should be valid!") + .progress_chars("#>-"), ); bar.set_position(num_done as u64); bar.set_message(format!("({:.1} %)", percentage)); for exercise in exercises { let compile_result = match exercise.mode { - Mode::Test => compile_and_test(exercise, RunMode::Interactive, verbose), - Mode::Compile => compile_and_run_interactively(exercise), - Mode::Clippy => compile_only(exercise), + Mode::Test => compile_and_test(exercise, RunMode::Interactive, verbose, success_hints), + Mode::Compile => compile_and_run_interactively(exercise, success_hints), + Mode::Clippy => compile_only(exercise, success_hints), }; if !compile_result.unwrap_or(false) { return Err(exercise); @@ -46,27 +49,27 @@ enum RunMode { // Compile and run the resulting test harness of the given Exercise pub fn test(exercise: &Exercise, verbose: bool) -> Result<(), ()> { - compile_and_test(exercise, RunMode::NonInteractive, verbose)?; + compile_and_test(exercise, RunMode::NonInteractive, verbose, false)?; Ok(()) } // Invoke the rust compiler without running the resulting binary -fn compile_only(exercise: &Exercise) -> Result { +fn compile_only(exercise: &Exercise, success_hints: bool) -> Result { let progress_bar = ProgressBar::new_spinner(); progress_bar.set_message(format!("Compiling {exercise}...")); - progress_bar.enable_steady_tick(100); + progress_bar.enable_steady_tick(Duration::from_millis(100)); let _ = compile(exercise, &progress_bar)?; progress_bar.finish_and_clear(); - Ok(prompt_for_completion(exercise, None)) + Ok(prompt_for_completion(exercise, None, success_hints)) } // Compile the given Exercise and run the resulting binary in an interactive mode -fn compile_and_run_interactively(exercise: &Exercise) -> Result { +fn compile_and_run_interactively(exercise: &Exercise, success_hints: bool) -> Result { let progress_bar = ProgressBar::new_spinner(); progress_bar.set_message(format!("Compiling {exercise}...")); - progress_bar.enable_steady_tick(100); + progress_bar.enable_steady_tick(Duration::from_millis(100)); let compilation = compile(exercise, &progress_bar)?; @@ -84,15 +87,24 @@ fn compile_and_run_interactively(exercise: &Exercise) -> Result { } }; - Ok(prompt_for_completion(exercise, Some(output.stdout))) + Ok(prompt_for_completion( + exercise, + Some(output.stdout), + success_hints, + )) } // Compile the given Exercise as a test harness and display // the output if verbose is set to true -fn compile_and_test(exercise: &Exercise, run_mode: RunMode, verbose: bool) -> Result { +fn compile_and_test( + exercise: &Exercise, + run_mode: RunMode, + verbose: bool, + success_hints: bool, +) -> Result { let progress_bar = ProgressBar::new_spinner(); progress_bar.set_message(format!("Testing {exercise}...")); - progress_bar.enable_steady_tick(100); + progress_bar.enable_steady_tick(Duration::from_millis(100)); let compilation = compile(exercise, &progress_bar)?; let result = compilation.run(); @@ -104,7 +116,7 @@ fn compile_and_test(exercise: &Exercise, run_mode: RunMode, verbose: bool) -> Re println!("{}", output.stdout); } if let RunMode::Interactive = run_mode { - Ok(prompt_for_completion(exercise, None)) + Ok(prompt_for_completion(exercise, None, success_hints)) } else { Ok(true) } @@ -122,9 +134,9 @@ fn compile_and_test(exercise: &Exercise, run_mode: RunMode, verbose: bool) -> Re // Compile the given Exercise and return an object with information // about the state of the compilation -fn compile<'a, 'b>( +fn compile<'a>( exercise: &'a Exercise, - progress_bar: &'b ProgressBar, + progress_bar: &ProgressBar, ) -> Result, ()> { let compilation_result = exercise.compile(); @@ -142,12 +154,15 @@ fn compile<'a, 'b>( } } -fn prompt_for_completion(exercise: &Exercise, prompt_output: Option) -> bool { +fn prompt_for_completion( + exercise: &Exercise, + prompt_output: Option, + success_hints: bool, +) -> bool { let context = match exercise.state() { State::Done => return true, State::Pending(context) => context, }; - match exercise.mode { Mode::Compile => success!("Successfully ran {}!", exercise), Mode::Test => success!("Successfully tested {}!", exercise), @@ -167,7 +182,6 @@ fn prompt_for_completion(exercise: &Exercise, prompt_output: Option) -> Mode::Test => "The code is compiling, and the tests pass!", Mode::Clippy => clippy_success_msg, }; - println!(); if no_emoji { println!("~*~ {success_msg} ~*~") @@ -183,6 +197,13 @@ fn prompt_for_completion(exercise: &Exercise, prompt_output: Option) -> println!("{}", separator()); println!(); } + if success_hints { + println!("Hints:"); + println!("{}", separator()); + println!("{}", exercise.hint); + println!("{}", separator()); + println!(); + } println!("You can keep working on this exercise,"); println!( diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 1a729232..d1694a39 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -44,7 +44,7 @@ fn verify_fails_if_some_fails() { fn run_single_compile_success() { Command::cargo_bin("rustlings") .unwrap() - .args(&["run", "compSuccess"]) + .args(["run", "compSuccess"]) .current_dir("tests/fixture/success/") .assert() .success(); @@ -54,7 +54,7 @@ fn run_single_compile_success() { fn run_single_compile_failure() { Command::cargo_bin("rustlings") .unwrap() - .args(&["run", "compFailure"]) + .args(["run", "compFailure"]) .current_dir("tests/fixture/failure/") .assert() .code(1); @@ -64,7 +64,7 @@ fn run_single_compile_failure() { fn run_single_test_success() { Command::cargo_bin("rustlings") .unwrap() - .args(&["run", "testSuccess"]) + .args(["run", "testSuccess"]) .current_dir("tests/fixture/success/") .assert() .success(); @@ -74,7 +74,7 @@ fn run_single_test_success() { fn run_single_test_failure() { Command::cargo_bin("rustlings") .unwrap() - .args(&["run", "testFailure"]) + .args(["run", "testFailure"]) .current_dir("tests/fixture/failure/") .assert() .code(1); @@ -84,7 +84,7 @@ fn run_single_test_failure() { fn run_single_test_not_passed() { Command::cargo_bin("rustlings") .unwrap() - .args(&["run", "testNotPassed.rs"]) + .args(["run", "testNotPassed.rs"]) .current_dir("tests/fixture/failure/") .assert() .code(1); @@ -97,14 +97,17 @@ fn run_single_test_no_filename() { .arg("run") .current_dir("tests/fixture/") .assert() - .code(1); + .code(2) + .stderr(predicates::str::contains( + "required arguments were not provided", + )); } #[test] fn run_single_test_no_exercise() { Command::cargo_bin("rustlings") .unwrap() - .args(&["run", "compNoExercise.rs"]) + .args(["run", "compNoExercise.rs"]) .current_dir("tests/fixture/failure") .assert() .code(1); @@ -114,7 +117,7 @@ fn run_single_test_no_exercise() { fn reset_single_exercise() { Command::cargo_bin("rustlings") .unwrap() - .args(&["reset", "intro1"]) + .args(["reset", "intro1"]) .assert() .code(0); } @@ -125,9 +128,9 @@ fn reset_no_exercise() { .unwrap() .arg("reset") .assert() - .code(1) + .code(2) .stderr(predicates::str::contains( - "positional arguments not provided", + "required arguments were not provided", )); } @@ -135,7 +138,7 @@ fn reset_no_exercise() { fn get_hint_for_single_test() { Command::cargo_bin("rustlings") .unwrap() - .args(&["hint", "testFailure"]) + .args(["hint", "testFailure"]) .current_dir("tests/fixture/failure") .assert() .code(0) @@ -171,7 +174,7 @@ fn all_exercises_require_confirmation() { fn run_compile_exercise_does_not_prompt() { Command::cargo_bin("rustlings") .unwrap() - .args(&["run", "pending_exercise"]) + .args(["run", "pending_exercise"]) .current_dir("tests/fixture/state") .assert() .code(0) @@ -182,7 +185,7 @@ fn run_compile_exercise_does_not_prompt() { fn run_test_exercise_does_not_prompt() { Command::cargo_bin("rustlings") .unwrap() - .args(&["run", "pending_test_exercise"]) + .args(["run", "pending_test_exercise"]) .current_dir("tests/fixture/state") .assert() .code(0) @@ -193,7 +196,7 @@ fn run_test_exercise_does_not_prompt() { fn run_single_test_success_with_output() { Command::cargo_bin("rustlings") .unwrap() - .args(&["--nocapture", "run", "testSuccess"]) + .args(["--nocapture", "run", "testSuccess"]) .current_dir("tests/fixture/success/") .assert() .code(0) @@ -204,7 +207,7 @@ fn run_single_test_success_with_output() { fn run_single_test_success_without_output() { Command::cargo_bin("rustlings") .unwrap() - .args(&["run", "testSuccess"]) + .args(["run", "testSuccess"]) .current_dir("tests/fixture/success/") .assert() .code(0) @@ -215,7 +218,7 @@ fn run_single_test_success_without_output() { fn run_rustlings_list() { Command::cargo_bin("rustlings") .unwrap() - .args(&["list"]) + .args(["list"]) .current_dir("tests/fixture/success") .assert() .success(); @@ -225,7 +228,7 @@ fn run_rustlings_list() { fn run_rustlings_list_no_pending() { Command::cargo_bin("rustlings") .unwrap() - .args(&["list"]) + .args(["list"]) .current_dir("tests/fixture/success") .assert() .success() @@ -236,7 +239,7 @@ fn run_rustlings_list_no_pending() { fn run_rustlings_list_both_done_and_pending() { Command::cargo_bin("rustlings") .unwrap() - .args(&["list"]) + .args(["list"]) .current_dir("tests/fixture/state") .assert() .success() @@ -247,7 +250,7 @@ fn run_rustlings_list_both_done_and_pending() { fn run_rustlings_list_without_pending() { Command::cargo_bin("rustlings") .unwrap() - .args(&["list", "--solved"]) + .args(["list", "--solved"]) .current_dir("tests/fixture/state") .assert() .success() @@ -258,7 +261,7 @@ fn run_rustlings_list_without_pending() { fn run_rustlings_list_without_done() { Command::cargo_bin("rustlings") .unwrap() - .args(&["list", "--unsolved"]) + .args(["list", "--unsolved"]) .current_dir("tests/fixture/state") .assert() .success()