Compare commits

...

458 commits

Author SHA1 Message Date
Mo 0f71e12235
Merge pull request #2011 from rust-lang/ci
Update CI
2024-07-03 18:02:43 +02:00
mo8it fa6b7d77b2 Run dev check only on Linux 2024-07-03 17:59:10 +02:00
mo8it a72c26bdc3 Fix solution of options1 for stable Rust 2024-07-03 17:53:30 +02:00
mo8it fe3292c170 Remove dtolnay/rust-toolchain 2024-07-03 17:52:44 +02:00
mo8it ad66fe0074 Update checkout in web.yml 2024-07-03 17:51:06 +02:00
mo8it df64893f2b Update CI 2024-07-03 17:49:41 +02:00
Mo e5bc8588e0
Merge pull request #2010 from rust-lang/oranda
Remove install page for now, README is enough
2024-07-03 16:27:37 +02:00
mo8it 23bc5d23fe Remove install page for now, README is enough 2024-07-03 16:23:23 +02:00
mo8it 28d2bb0432 chore: Release 2024-07-03 15:32:46 +02:00
mo8it 1c010a129e Update deps 2024-07-03 15:28:53 +02:00
mo8it f5ce4cf0a5 Merge branch 'v6' 2024-07-03 15:26:35 +02:00
mo8it ff3e6c05a5 Merge branch 'main' 2024-07-03 15:26:05 +02:00
mo8it 33dfe5331a Update CHANGELOG 2024-07-03 15:24:07 +02:00
Mo 888ad35d10
Merge pull request #2009 from Yung-Beef/patch-2
Update README.md
2024-07-03 01:04:19 +02:00
Yung Beef 4.2 fa452b3a93
Update README.md 2024-07-02 18:30:54 -03:00
mo8it 2f8fa469ac Small writing changes 2024-07-02 16:26:59 +02:00
mo8it d3a0c26999 Improve the placement of TODO comments 2024-07-02 16:26:28 +02:00
mo8it 95f10c8068 Update CHANGELOG 2024-07-02 16:10:42 +02:00
mo8it 9bb174e96e Add a guide for third-party exercises 2024-07-02 16:09:05 +02:00
mo8it 4c5573b09f Update CONTRIBUTING 2024-07-02 14:45:25 +02:00
mo8it 43eb014026 Update README 2024-07-02 14:45:19 +02:00
mo8it 2d792651ea chore: Release 2024-07-02 14:29:07 +02:00
mo8it 6cf75d569b Fix typos 2024-07-02 14:28:08 +02:00
mo8it 67ce9b9e56 Underline "next" 2024-07-02 01:50:05 +02:00
mo8it bcebbb9df6 Update deps 2024-07-02 01:45:55 +02:00
mo8it bdd76cdf77 Merge branch 'run-sols-in-parallel' 2024-07-02 01:43:22 +02:00
mo8it 825637f32c as_ref_mut solution 2024-07-02 01:35:38 +02:00
mo8it 8ef5d10da2 Import the error variants in the tests 2024-07-02 01:29:30 +02:00
mo8it 5217cdc5e2 try_from_into solution 2024-07-02 01:26:09 +02:00
mo8it e3c8c457ba from_str solution 2024-07-02 01:03:55 +02:00
mo8it cddaf4881e from_into solution 2024-07-01 22:09:48 +02:00
mo8it 428d64ffa0 using_as solution 2024-07-01 21:41:22 +02:00
mo8it 09c94bef2d clippy3 solution 2024-07-01 12:09:52 +02:00
mo8it a0e810b471 clippy2 solution 2024-07-01 11:55:18 +02:00
mo8it 78728d5238 clippy1 solution 2024-07-01 11:54:35 +02:00
mo8it cc2c0958c9 macros4 solution 2024-07-01 11:54:05 +02:00
mo8it 4cb15a4cda macros3 solution 2024-07-01 11:37:48 +02:00
mo8it 9845e046de macros2 solution 2024-07-01 11:31:37 +02:00
mo8it cf90364fd7 macros1 solution 2024-07-01 11:28:38 +02:00
mo8it a13e3cd07f threads3 solution 2024-07-01 11:23:40 +02:00
mo8it dfa2b44f71 threads2 solution 2024-07-01 11:11:11 +02:00
mo8it b000164eed threads1 solution 2024-07-01 10:59:33 +02:00
mo8it 663a03a17b cow1 solution 2024-06-29 02:07:56 +02:00
mo8it a943f5ba32 arc1 solution 2024-06-29 01:48:00 +02:00
mo8it f3842aa746 rc1 solution 2024-06-29 01:20:59 +02:00
mo8it 61c7eaed62 box1 solution 2024-06-28 21:24:35 +02:00
mo8it f53d458920 iterators5 solution 2024-06-28 16:11:14 +02:00
mo8it 2af437fd90 iterators4 solution 2024-06-28 15:31:15 +02:00
mo8it 56a9197f55 iterators3 solution 2024-06-28 15:00:13 +02:00
mo8it eddbb97934 iterators2 solution 2024-06-28 02:48:21 +02:00
mo8it 4f71f74b44 Use todo!() instead of ??? 2024-06-28 02:26:35 +02:00
mo8it cf9041c0e4 iterators1 solution 2024-06-28 02:07:56 +02:00
mo8it 746cf6863d Remove tests3 and add solution to tests4 2024-06-27 17:29:33 +02:00
mo8it 803e32dad2 tests2 solution 2024-06-27 16:40:26 +02:00
mo8it a4f8826301 tests1 solution 2024-06-27 16:29:03 +02:00
mo8it 6187216606 lifetimes3 solution 2024-06-27 16:15:53 +02:00
mo8it 275a854d6e lifetimes2 solution 2024-06-27 13:24:27 +02:00
mo8it 7efccc36b4 lifetimes1 solution 2024-06-27 13:24:21 +02:00
mo8it 64c2de95ca quiz3 solution 2024-06-27 13:01:52 +02:00
mo8it c170740423 Highlight change in traits4 solution 2024-06-27 12:29:35 +02:00
mo8it 45cfe86fb0 traits5 solution 2024-06-27 12:29:25 +02:00
mo8it db4d649e55 Remove move_semantics6 2024-06-27 12:27:53 +02:00
mo8it c0452d160b traits4 solution 2024-06-27 12:23:33 +02:00
mo8it b4b7ae63ad traits3 solution 2024-06-27 12:11:57 +02:00
mo8it c07209b635 Unify info.toml 2024-06-27 12:00:28 +02:00
mo8it 091e1e7f7a traits2 solution 2024-06-27 11:58:44 +02:00
mo8it 92f249a52c Merge branch 'main' 2024-06-27 11:30:42 +02:00
mo8it 789223cc9e traits1 solution 2024-06-27 03:04:57 +02:00
mo8it de3f846a53 generics2 solution 2024-06-27 02:25:11 +02:00
mo8it 46121b71cf generics1 rewrite and solution 2024-06-27 02:00:08 +02:00
mo8it b1daea1fe8 errors6 solution 2024-06-27 01:12:50 +02:00
mo8it 129884aff7 errors5 solution 2024-06-26 18:21:19 +02:00
mo8it 720b280bc1 Update deps 2024-06-26 16:59:13 +02:00
mo8it 9b7a5c041e errors4 solution 2024-06-26 15:54:18 +02:00
mo8it c46d8bdf95 errors3 solution 2024-06-26 15:44:33 +02:00
mo8it 050a23ce67 errors2 solution 2024-06-26 15:36:14 +02:00
mo8it 2afe6b38d3 Fix tests 2024-06-26 15:12:58 +02:00
mo8it 097f3c74ea errors1 solution 2024-06-26 15:06:29 +02:00
mo8it 25b5686dd2 options3 solution 2024-06-26 14:47:57 +02:00
mo8it a91888e79e option2 solution 2024-06-26 14:35:05 +02:00
mo8it c31e15c4cf options1 solution 2024-06-26 12:59:10 +02:00
mo8it 1694682aa4 Fix typos 2024-06-26 02:26:04 +02:00
mo8it 29bcb282da quiz2 solution 2024-06-26 02:25:59 +02:00
mo8it f1bd444792 hashmaps3 solution 2024-06-26 01:52:33 +02:00
mo8it fbc226a510 hashmaps2 solution 2024-06-24 16:50:03 +02:00
mo8it 5baa503bfc hashmaps1 solution 2024-06-24 13:20:50 +02:00
Mo 0cd96afe63
Merge pull request #1782 from danielsomerfield/main
Fix all_fruits_types_in_basket to fail if all fruit kinds are not  included
2024-06-24 13:00:53 +02:00
mo8it 3d540ed946 modules3 solution 2024-06-22 13:35:54 +02:00
mo8it 98cd00de63 modules2 solution 2024-06-22 13:24:06 +02:00
mo8it ecbe9b7324 modules1 solution 2024-06-22 13:12:39 +02:00
mo8it 879f0cd5c6 strings4 solution 2024-06-22 12:51:21 +02:00
mo8it 613ec23f84 strings 3 solution 2024-06-22 12:22:24 +02:00
mo8it f574905b8e strings2 solution 2024-06-22 12:14:04 +02:00
mo8it bd63ece47c string1 solution 2024-06-22 12:05:28 +02:00
mo8it 2901d85662 enums3 solution 2024-06-21 23:18:25 +02:00
mo8it 020711fa97 enums3 solution 2024-06-21 23:05:40 +02:00
mo8it a2dfbd86da enums1 solution 2024-06-21 23:00:38 +02:00
mo8it d6fd251a73 structs3 solution 2024-06-21 22:54:00 +02:00
mo8it 1264510fc0 structs2 solution 2024-06-21 22:31:06 +02:00
mo8it ef842d3a94 structs1 solution 2024-06-21 22:22:37 +02:00
mo8it d768353806 Fix typo 2024-06-21 18:29:00 +02:00
mo8it e4dbbbf5f5 Remove move_semantics4, add rest of move_semantics solutions 2024-06-21 18:14:19 +02:00
mo8it fd558065c7 move_semantics3 solution 2024-06-21 17:04:51 +02:00
mo8it 68142aff7f move_semantics2 solution 2024-06-21 17:02:50 +02:00
mo8it 946c29679e move_semantics1 solution 2024-06-21 16:16:52 +02:00
mo8it 6a79ada7f2 Add comment to vecs2 2024-06-21 15:06:50 +02:00
mo8it 835ec72622 vecs2 solution + significant change to have a better comparison between both methods 2024-06-21 14:52:11 +02:00
mo8it a9f0c7bf1f vecs1 solution 2024-06-20 01:00:06 +02:00
mo8it 0abcdeed42 primitive_types6 solution 2024-06-19 14:25:29 +02:00
mo8it 532c9ebb30 primitive_types5 solution 2024-06-19 14:17:06 +02:00
mo8it 2a1bc53771 Update deps 2024-06-19 14:03:06 +02:00
mo8it 5bf8d1fa1b Fix typos 2024-06-14 13:32:37 +02:00
mo8it 2ff1813746 Update deps 2024-06-14 13:32:02 +02:00
mo8it 42a3503906 Run solutions in parallel 2024-06-10 17:42:11 +02:00
mo8it 98db579014 primitive_types4 solution 2024-06-08 23:42:15 +02:00
mo8it 0338b1cbdf primitive_types3 solution 2024-06-08 21:43:38 +02:00
mo8it e1051724c3 primitive_types2 solution 2024-06-08 21:35:44 +02:00
mo8it 0e4136d31e Update deps 2024-06-08 21:19:16 +02:00
mo8it f8d38320cd Fix typos 2024-06-06 01:59:09 +02:00
mo8it 42bd0b8b75 Update deps 2024-06-06 01:58:05 +02:00
mo8it 08ac11ff22 Add --require-solutions option to dev check 2024-06-02 00:11:41 +02:00
mo8it 6ae4a979f4 Check for unexpected files in the solutions dir 2024-06-02 00:03:48 +02:00
mo8it a3ada0eee8 Print the exercise solution on check 2024-06-01 21:51:45 +02:00
mo8it 50530fa3cf Don't try to check a solution that doesn't exist 2024-06-01 21:50:11 +02:00
mo8it 611f9d8722 Check that all solutions run successfully 2024-06-01 21:48:15 +02:00
mo8it 8e9c99ae5b Change condition order 2024-06-01 15:10:43 +02:00
mo8it c324ea10df Update deps 2024-06-01 15:10:17 +02:00
mo8it 1984a8d38e Update Cargo.toml with the solution bins 2024-06-01 15:01:27 +02:00
mo8it 84a818dbda Update the bins buffer capacity 2024-06-01 15:01:18 +02:00
mo8it beb7b24e8e Add solutions to bins 2024-05-25 18:19:30 +02:00
mo8it 990c68efcb primitive_types1 solution 2024-05-25 16:31:21 +02:00
mo8it 8d4145038d Update deps 2024-05-25 16:15:35 +02:00
mo8it f2c3dcab3a quiz1 solution 2024-05-22 16:35:57 +02:00
mo8it 73e84f8379 if3 solution 2024-05-22 15:54:35 +02:00
mo8it eafb157d60 if2 solution 2024-05-22 15:16:50 +02:00
mo8it 7cdf6b7942 Add missing semicolons 2024-05-22 15:13:18 +02:00
mo8it c8ad6c3960 if1 solution 2024-05-22 15:04:21 +02:00
mo8it 3bb71c6b0c Remove unneeded pub 2024-05-22 15:04:12 +02:00
mo8it d0b843d6c4 Add solutions to functions 2024-05-21 02:43:18 +02:00
mo8it 0f4c42d54e Add solutions to intro and variables 2024-05-21 01:47:57 +02:00
mo8it bde2524c3b Update deps 2024-05-20 18:11:19 +02:00
mo8it cf3f6fd6a1 Fix typo 2024-05-14 01:50:03 +02:00
mo8it c8481d35c1 Done documentation 2024-05-14 01:49:22 +02:00
mo8it 96a44f3dcf Make it more clear that only one char is expected 2024-05-14 01:23:58 +02:00
mo8it 0ae66d1860 Remove inline 2024-05-14 00:55:07 +02:00
mo8it 700605ff35 Document init 2024-05-14 00:35:12 +02:00
mo8it a67e63cce0 Document info_file 2024-05-13 22:02:45 +02:00
mo8it d48e86b154 Use public comments for public items 2024-05-13 21:40:40 +02:00
mo8it 39a19f9450 Document exercise 2024-05-13 21:36:20 +02:00
mo8it 2dfc7cdb1a Document embedded 2024-05-13 21:07:04 +02:00
mo8it 0add5ac240 chore: Release 2024-05-13 17:14:11 +02:00
mo8it 5a1d95028c Update version in README 2024-05-13 17:14:00 +02:00
mo8it e80e91faf2 Thanks Clippy :) 2024-05-13 17:12:58 +02:00
mo8it 4ae3fcc3ca Don't skip exercises on file changes 2024-05-13 17:06:11 +02:00
mo8it 17a2d42ffd Better variable naming 2024-05-13 16:44:48 +02:00
mo8it a7bc6d53a5 Only send Unrecognized on ENTER if the last input wasn't valid 2024-05-13 16:39:38 +02:00
mo8it 56eb4a5d65 chore: Release 2024-05-13 04:11:29 +02:00
mo8it f6cf6c611c Fix Windows terminal links 2024-05-13 04:11:11 +02:00
mo8it 7a74a72dc8 Update beta version in README 2024-05-13 02:48:42 +02:00
mo8it a4da216a5c chore: Release 2024-05-13 02:46:26 +02:00
mo8it 8b2d9ed503 Use PartialEq instead of matches! 2024-05-13 02:45:12 +02:00
mo8it d2b5906be2 No more word input 2024-05-13 02:37:32 +02:00
mo8it f9e35a4344 Improve input handling 2024-05-13 02:32:25 +02:00
mo8it 0525739046 Fix invisible input on Windows 2024-05-13 02:20:04 +02:00
mo8it 11fda5d70f Move info.toml to rustlings-macros/
This improves the experience for contributors on Windows becuase
Windows can't deal with git symbolic links out of the box…
2024-05-13 01:25:38 +02:00
mo8it d9df809838 Optimize embedded dirs 2024-05-12 17:40:53 +02:00
mo8it da9f97b0e0 Update deps 2024-05-12 01:35:30 +02:00
mo8it 2d0497bf3b Fix errors 2024-05-02 17:08:39 +02:00
mo8it 5e7afce019 Document dev 2024-05-01 19:47:35 +02:00
mo8it 74180ba1cc Check for tests while test=false 2024-05-01 19:16:59 +02:00
mo8it d425dbe203 Test run_cmd 2024-05-01 18:08:18 +02:00
mo8it 32415e1e6c Document cmd 2024-05-01 17:55:49 +02:00
mo8it 8e178ac60d Document and test cargo_toml 2024-04-30 02:48:56 +02:00
mo8it 3ae6c208b2 Disable the pretty format because of --show-output 2024-04-30 02:43:51 +02:00
mo8it 563727f47f test next_pending_exercise_ind 2024-04-30 02:14:20 +02:00
mo8it 2b7ac91505 Add press_enter_prompt 2024-04-30 01:46:57 +02:00
mo8it 52c0f5b39e Fix clearing the terminal 2024-04-30 01:41:08 +02:00
mo8it fef66b80ad Implement From<ExerciseInfo> for Exercise 2024-04-30 01:39:31 +02:00
mo8it b6f40f2ec8 Document main and app_state 2024-04-29 17:01:47 +02:00
mo8it 7f73219041 chore: Release 2024-04-29 00:36:50 +02:00
mo8it 196d3c1a98 Bump version 2024-04-29 00:36:13 +02:00
mo8it 8c60ac267e Add working environment section 2024-04-29 00:26:53 +02:00
mo8it 3c7e7368b2 Add solutions to the initialized .gitignore 2024-04-28 23:25:44 +02:00
mo8it 593f0e0916 Revert escaping with ESC in list to be able to clear the message 2024-04-28 23:22:11 +02:00
mo8it 1508938fed Highlight the active filter 2024-04-28 23:21:13 +02:00
mo8it aedeff8b24 Reorder the footer keys 2024-04-27 23:45:26 +02:00
mo8it 75e2804c83 Esacpe the list with ESC 2024-04-27 23:42:09 +02:00
mo8it c45d2c3255 Remove the I AM NOT DONE check 2024-04-27 23:38:38 +02:00
mo8it ea40804371 Put long version in () 2024-04-27 23:38:26 +02:00
mo8it ee2b772dd5 Update intro1 hint 2024-04-27 23:38:05 +02:00
mo8it 62a2c1a6d9 Put long version in () 2024-04-27 23:37:44 +02:00
mo8it de0befef9c Update intro1 2024-04-27 23:37:17 +02:00
mo8it 5658998c0c Update welcome and final messages 2024-04-27 23:24:09 +02:00
mo8it 89e0f64279 chore: Release 2024-04-27 17:35:08 +02:00
mo8it edea76b5b9 Bump version 2024-04-27 17:34:39 +02:00
mo8it 016e6a014e Update serde 2024-04-27 17:32:42 +02:00
mo8it cdeb8ce229 Fix initialization 2024-04-27 17:31:51 +02:00
mo8it 12504b01e9 Disable unneeded features in deps 2024-04-27 04:32:06 +02:00
mo8it c3a92b1248 Update deps 2024-04-27 04:21:29 +02:00
mo8it 181c81f016 chore: Release 2024-04-27 04:17:24 +02:00
mo8it cb7ce006b5 Bump version 2024-04-27 04:17:10 +02:00
mo8it 2150d629b1 Use --show-output instead of --nocapture 2024-04-27 04:15:16 +02:00
mo8it c82c367324 Respect the target-dir config and show tests' output 2024-04-27 04:14:59 +02:00
mo8it dc5c72bc19 Update README.md 2024-04-26 03:44:16 +02:00
mo8it 0ce5d9d4d7 Update README.md 2024-04-26 03:39:38 +02:00
mo8it 37fcbeb596 Add indentation for details 2024-04-26 03:29:05 +02:00
mo8it 2f071c97b0 Update README.md 2024-04-26 03:25:31 +02:00
mo8it 9664f4357c Use HTML in the summary 2024-04-26 03:20:34 +02:00
mo8it 74ae506603 Update README 2024-04-26 03:17:35 +02:00
mo8it 2965867338 Add click to expand 2024-04-26 02:02:14 +02:00
mo8it e63e668d86 Use <details> 2024-04-26 02:00:42 +02:00
mo8it b7289e59aa Put --locked in the troubleshooting section 2024-04-26 01:55:44 +02:00
mo8it be4dfe8be0 Add hint about updating Rust 2024-04-26 01:49:36 +02:00
mo8it e230ffcf03 Update the contributing guide 2024-04-26 01:19:52 +02:00
mo8it 0d7b036137 chore: Release 2024-04-25 21:07:41 +02:00
mo8it 078142c43c Update dev/Cargo.toml 2024-04-25 21:07:10 +02:00
mo8it 5920a58e83 Include dev/Cargo.toml 2024-04-25 19:58:55 +02:00
mo8it aaea5b490f chore: Release 2024-04-25 19:54:59 +02:00
mo8it 8d45cdb09d Fix missing info.toml in the macros crate 2024-04-25 19:54:03 +02:00
mo8it a4e623ea94 Fix releasing rustlings 2024-04-25 19:33:24 +02:00
mo8it 5595e1c397 chore: Release 2024-04-25 19:32:10 +02:00
mo8it ca41f9e2df Prepare for using cargo-release 2024-04-25 19:02:07 +02:00
mo8it 177e2870c5 Edit comment 2024-04-25 16:30:01 +02:00
mo8it 3ce3235294 Show warnings and errors in the tests 2024-04-25 16:08:07 +02:00
mo8it c51f1b3f31 Thanks Clippy :D 2024-04-25 15:58:46 +02:00
mo8it 8bf8b19a5d Improve output after initialization 2024-04-25 15:51:12 +02:00
mo8it 6d1d42d2dd Try to run git init 2024-04-25 15:41:52 +02:00
mo8it 212c82c6f6 Don't ignore .vscode/extensions.json when developing third-party exercises 2024-04-25 15:34:58 +02:00
mo8it fcefa3d614 Name the exercises' package exercises 2024-04-25 15:33:24 +02:00
mo8it b3b4b7d59c Update initialized .gitignore 2024-04-25 15:23:24 +02:00
mo8it 29abaee4ec Update dep 2024-04-25 15:22:14 +02:00
mo8it c7c8d99680 Moar responsive :P 2024-04-25 15:22:11 +02:00
mo8it c1d28b502e Format test file :P 2024-04-25 14:51:14 +02:00
mo8it 14fe248b4b Optimize the notify event handler 2024-04-25 14:44:12 +02:00
Mo 88f27a5377
Merge pull request #1959 from rust-lang/output
Improve output
2024-04-25 14:43:28 +02:00
mo8it 1f1a62d83e Raise the output capacity 2024-04-25 14:43:02 +02:00
mo8it 428998a4cf Quicker response to file changes 2024-04-25 03:28:44 +02:00
mo8it d26f47dddd Fix tests 2024-04-25 03:27:41 +02:00
mo8it 2af0cd9cce Replace mode by test and strict_clippy 2024-04-25 03:25:45 +02:00
mo8it f92d45fa68 Use write macros instead of write_fmt 2024-04-25 02:03:26 +02:00
mo8it 67fa017742 Use os_pipe 2024-04-25 01:56:01 +02:00
mo8it d8c2ab8349 Fix tests 2024-04-24 16:26:48 +02:00
mo8it 0df0be8352 Update Cargo.lock 2024-04-24 16:26:34 +02:00
mo8it 8ebd2f9df2 Update Cargo.toml files 2024-04-24 16:15:14 +02:00
mo8it 4ef345e706 Update dependency 2024-04-24 15:58:34 +02:00
mo8it 0a2d4dae5a Merge branch 'main' 2024-04-24 15:48:29 +02:00
Mo 53fdb9044d
Merge pull request #1955 from rust-lang/solutions
Solutions
2024-04-24 02:56:20 +02:00
mo8it 8a085a0a85 Dump solution and show its path 2024-04-24 02:52:30 +02:00
mo8it edf5762612 Preallocate path 2024-04-24 01:17:39 +02:00
mo8it ef02c6c6ab Use the embedded info.toml in debug mode 2024-04-24 00:58:52 +02:00
mo8it e4ee2cd548 Don't write solutions in debug mode 2024-04-24 00:48:58 +02:00
mo8it b77007887c Write the solution file on done 2024-04-24 00:47:46 +02:00
mo8it 2dac8e509b Refactor embedded files to add solutions 2024-04-23 19:18:25 +02:00
mo8it e5a19a4c33 Update deps 2024-04-23 15:32:07 +02:00
mo8it 5349f0e8d4 Add README to the quizzes directory 2024-04-23 15:32:01 +02:00
mo8it ad8e544483 Move quizzes 2024-04-22 01:07:36 +02:00
mo8it 86684b7fc9 Document dev commands 2024-04-22 00:45:16 +02:00
mo8it 4ce2714da1 Add --no-git 2024-04-22 00:38:34 +02:00
mo8it e93a99e19e Third-party exercises should be in a separate Git repo 2024-04-22 00:34:55 +02:00
mo8it 61a84a2c11 dev init -> dev new PATH 2024-04-21 23:43:49 +02:00
mo8it 30040d7778 Add a disclaimer to the state file 2024-04-21 23:39:44 +02:00
mo8it e3b9124b85 Add a confirmation prompt to the init subcommand 2024-04-21 23:24:10 +02:00
mo8it 642c3bd37e Fix the generated Cargo.toml after rustlings init 2024-04-21 20:22:01 +02:00
mo8it 49e4a1fab0 Catch the usage of the old method 2024-04-21 19:34:55 +02:00
mo8it 04d36996dd Update deps 2024-04-21 19:27:00 +02:00
mo8it f1a60780b9 Rename constant 2024-04-21 19:26:19 +02:00
mo8it d83c91edc6 Ignore all lock files but the one in root 2024-04-21 18:20:15 +02:00
mo8it a2be6754bf Make the exercise name option for the hint subcommand 2024-04-18 17:17:39 +02:00
mo8it daa090981a Update README 2024-04-18 17:17:21 +02:00
mo8it aaf183142e Bring back the thanks to contributors ❤️ 2024-04-18 16:17:33 +02:00
Mo 7525ecd8c1
Merge pull request #1952 from rust-lang/remove-all-contributors
Remove all contributors
2024-04-18 13:12:08 +02:00
mo8it 09d8bc83ff Remove README reference 2024-04-18 13:08:02 +02:00
mo8it cc35a8431f Remove "All-Contributors" 2024-04-18 13:07:07 +02:00
Mo 819dea2500
Merge pull request #1949 from rust-lang/third-party-exercises
Support for third-party exercises
2024-04-18 13:02:35 +02:00
mo8it 01e6732e4d Improve resetting 2024-04-18 12:41:17 +02:00
mo8it f04089b8bc Only take a reference 2024-04-18 11:40:54 +02:00
mo8it 2566f9aaf6 Place mods under all imports 2024-04-18 11:31:08 +02:00
mo8it 1eac00e89a Disable init command during development 2024-04-18 11:28:28 +02:00
mo8it 2e9b9a9f13 Move constant 2024-04-18 11:21:39 +02:00
mo8it 9f5be60b40 Use git stash to reset third-party exercises 2024-04-18 11:20:51 +02:00
mo8it d64836f317 Avoid an unneeded syscall 2024-04-18 01:49:32 +02:00
mo8it 634e17a5ab Fix tests 2024-04-17 23:37:31 +02:00
mo8it 2f810a4da6 Clean up and unify exercises 2024-04-17 23:34:27 +02:00
mo8it cb9f1ac9ce Require a main function in all exercises 2024-04-17 22:46:21 +02:00
mo8it d83cc69afe Trim before checking if the hint is empty 2024-04-17 19:16:48 +02:00
mo8it d6bb27ec20 Check for empty field values 2024-04-17 19:12:10 +02:00
mo8it d42a6e7415 Print the path of the missing file 2024-04-17 18:59:40 +02:00
mo8it b9167e9299 Remove redundant checks 2024-04-17 18:19:28 +02:00
mo8it 28ec0f864a Check the info file 2024-04-17 18:19:08 +02:00
mo8it 7005d8a400 Fix typo 2024-04-17 16:11:44 +02:00
mo8it 7f433ae28f Check the format version in dev check 2024-04-17 16:09:25 +02:00
mo8it a2506f154b Update serde 2024-04-17 15:56:24 +02:00
mo8it 501b973c25 Add "dev update" 2024-04-17 15:55:50 +02:00
mo8it 30636e7cf3 Use colors inside the test 2024-04-16 21:46:07 +02:00
mo8it d322bcfcec Add description 2024-04-16 04:04:45 +02:00
mo8it 0ac5aa7af2 Fix typo 2024-04-16 04:00:42 +02:00
mo8it f9be652b3b Ready to publish 2024-04-16 03:56:08 +02:00
mo8it 932f6b53a9 Add myself to the list of authors :) 2024-04-16 03:47:09 +02:00
mo8it 4d9eb35ad7 Prepare for publishing the first alpha version 2024-04-16 03:46:04 +02:00
mo8it 86d716cf8a Add comment about keeping dependencies 2024-04-16 03:43:34 +02:00
mo8it 87db9129bc Add the mode field 2024-04-16 03:37:58 +02:00
mo8it 6566c5904f Tell about updating Cargo.toml 2024-04-16 03:35:23 +02:00
mo8it aa813fbce1 Update Cargo.toml on dev check 2024-04-16 03:30:28 +02:00
mo8it d1ebbaa6f6 Add format_version to test info.toml files 2024-04-16 03:18:22 +02:00
mo8it c07cf5bffe Fix typo 2024-04-16 03:18:06 +02:00
mo8it df448c069c Fix running dev commands 2024-04-16 03:15:14 +02:00
mo8it 25e7696565 Done dev init 2024-04-16 03:08:45 +02:00
mo8it 92777c0a44 Add the format version 2024-04-16 01:22:54 +02:00
mo8it 7ebc260924 Scetch the dev subcommand 2024-04-15 23:54:57 +02:00
mo8it f5eaa578b9 Update deps 2024-04-15 23:35:30 +02:00
mo8it 6f04570dd0 Revert "Implement third-party exercises trust handling"
This reverts commit 15ca847c37.
See https://rust-lang.zulipchat.com/#narrow/stream/334454-rustlings/topic/Proposal.3A.20Third-party.20exercises/near/433183449
2024-04-15 03:36:12 +02:00
mo8it 15ca847c37 Implement third-party exercises trust handling 2024-04-15 02:11:27 +02:00
mo8it c613b70363 Print the trimmed final message 2024-04-14 17:28:01 +02:00
Mo dc02c38a94
Merge pull request #1942 from rust-lang/tui
TUI
2024-04-14 17:13:32 +02:00
mo8it 7526c6b1f9 Update POST_INIT_MSG 2024-04-14 17:11:27 +02:00
mo8it 1cbabc3d28 Add the manual-run option 2024-04-14 17:10:53 +02:00
mo8it bd10b154fe Clear the terminal after showing the welcome message 2024-04-14 16:07:17 +02:00
mo8it 070a780d7f Trim the final message 2024-04-14 16:04:05 +02:00
mo8it 8aef915ee7 Show the welcome message 2024-04-14 16:03:49 +02:00
mo8it 3da860927d Use push instead of extend_from_slice on chars 2024-04-14 14:53:32 +02:00
mo8it 1c90575b9f Update deps 2024-04-14 05:13:50 +02:00
mo8it 9dcc4b7df5 Simplify the state file 2024-04-14 05:13:27 +02:00
mo8it 9831cbb139 Fix tests 2024-04-14 03:13:33 +02:00
mo8it bee62c89de Add terminal links 2024-04-14 02:41:19 +02:00
mo8it 5c0073a948 Tolerate changes in the state file 2024-04-14 01:15:43 +02:00
mo8it 2a26dfcb00 Remove unused ContextLine 2024-04-13 15:30:35 +02:00
mo8it 24539666af Show the final message 2024-04-12 20:06:56 +02:00
mo8it 757723a7e8 Add missing newline 2024-04-12 19:30:36 +02:00
mo8it ff4c752984 Print FAILED 2024-04-12 19:30:29 +02:00
mo8it 06d1089714 Set pending on fail in run mode 2024-04-12 19:24:26 +02:00
mo8it 6e827da570 It doesn't take minutes :P 2024-04-12 19:18:16 +02:00
mo8it 279ebdc153 Remove the modifier filter in the list mode 2024-04-12 19:16:52 +02:00
mo8it 9b0eeb815a Fix Display for Exercise 2024-04-12 19:07:17 +02:00
mo8it 44824718b2 Remove unused import 2024-04-12 18:58:01 +02:00
mo8it 8bd03093eb Add newline at the end of the generated .gitignore 2024-04-12 18:57:39 +02:00
mo8it d5a6dee1b3 Handle the case when all exercises are done 2024-04-12 18:57:04 +02:00
mo8it a534de0312 Implement going to the next exercise 2024-04-12 15:27:29 +02:00
mo8it 98c5088a39 Update deps 2024-04-12 14:52:50 +02:00
mo8it 6807e63c5f Show done message 2024-04-12 02:45:54 +02:00
mo8it 2a95a3e966 Deal with long strings 2024-04-12 01:24:01 +02:00
mo8it 1e3745ccdf Update winnow 2024-04-12 00:58:26 +02:00
mo8it d8160f9113 Remove outdated installation methods 2024-04-12 00:56:40 +02:00
mo8it 6494a8c50b Remove the watch subcommand 2024-04-11 16:54:27 +02:00
mo8it 864cfa725b Remove outdated tests 2024-04-11 15:10:15 +02:00
mo8it e79bc727f0 Don't listen on keys with modifiers 2024-04-11 15:08:46 +02:00
mo8it 2e1a87d7d3 Take care of filters when resolving the selected exercise 2024-04-11 14:58:56 +02:00
mo8it f53a0e8700 Panic if there are no exercises 2024-04-11 14:39:19 +02:00
mo8it 470dc65956 Fix selected when there are no rows 2024-04-11 14:35:30 +02:00
mo8it 686143100f Update intro1 2024-04-11 02:55:58 +02:00
mo8it c3933904f6 Update deps 2024-04-11 02:51:50 +02:00
mo8it 65849629f5 Remove glob 2024-04-11 02:51:23 +02:00
mo8it fa1f239a70 Remove "I AM NOT DONE" and the verify mode and add AppState 2024-04-11 02:51:02 +02:00
mo8it 4bb6bda9f6 Separate event handlers 2024-04-10 16:02:12 +02:00
mo8it 256c4013b7 Keep hint displayed after resizing the terminal 2024-04-10 15:56:38 +02:00
mo8it 27e9520665 Add deny_unknown_fields 2024-04-10 14:40:49 +02:00
mo8it b3642b0219 Remove todo 2024-04-10 14:35:42 +02:00
mo8it 193e0a03b2 Use light blue for the message 2024-04-10 14:31:08 +02:00
mo8it a59acf8835 Show the current exercise path 2024-04-10 14:29:31 +02:00
mo8it 62e92476e6 Fix typo 2024-04-10 04:10:05 +02:00
mo8it 6255efe8b2 Show the invalid command to avoid confusion after resizing the terminal 2024-04-10 04:08:40 +02:00
mo8it a46d66134b Fix shift of first output line 2024-04-10 03:56:41 +02:00
mo8it f034899c7f Capture terminal resize events 2024-04-10 03:54:48 +02:00
mo8it c9a5fa6097 Accept repeat keyboard events 2024-04-10 02:19:14 +02:00
mo8it d1a965f019 Make the list mode part of the watch mode 2024-04-10 02:12:50 +02:00
mo8it 533a009257 Show the progress in the progress bar, not the current exercise index 2024-04-10 00:51:41 +02:00
mo8it 4a80bf6441 Colorize the progress bar 2024-04-10 00:42:32 +02:00
mo8it c8d217ad50 Fix showing stdout and stderr 2024-04-09 22:20:12 +02:00
mo8it a8ddc07a9a Add "exercises" to the end of the progress bar 2024-04-09 22:15:41 +02:00
mo8it af85f2036c Print a newline before the progress bar 2024-04-09 22:06:55 +02:00
mo8it ff6c15f9c1 Don't try to join the input thread 2024-04-09 22:04:10 +02:00
mo8it 4110ae21af Handle notify errors 2024-04-09 21:46:55 +02:00
mo8it b15e0a279b Use shrink to fit before leaking the vector 2024-04-09 21:23:02 +02:00
mo8it 787bec9875 Use exercises as leaked 2024-04-09 21:16:27 +02:00
mo8it f0ce2c1afa Improve event handling in the watch mode 2024-04-09 21:07:53 +02:00
mo8it 850c1d0234 Add progress bar to list 2024-04-09 19:37:39 +02:00
mo8it ee7d976283 Use a green color on successful run 2024-04-09 17:15:12 +02:00
mo8it d0fcd8ae8a Use a color for the message 2024-04-08 03:21:13 +02:00
mo8it 7c46e7ac69 Simplify building rows.
No more lifetimes championship :(
2024-04-08 03:16:38 +02:00
mo8it 1db5de9653 Fix selection after applying filters 2024-04-08 03:08:05 +02:00
mo8it b5fc06bd56 Show more exercises before the selected one 2024-04-08 02:46:35 +02:00
mo8it 7c4d33654f Implement done/pending filters 2024-04-08 02:41:48 +02:00
mo8it 05729b27a0 Set a list offset 2024-04-08 01:49:38 +02:00
mo8it 0bf3f7e01f Lowercase "filter" in help footer 2024-04-08 01:34:41 +02:00
mo8it bd5503a0d3 Show message on reset 2024-04-08 01:33:11 +02:00
mo8it 25e855a009 Merge imports 2024-04-08 00:36:26 +02:00
mo8it c2501ae733 Remove list tests because of the TUI 2024-04-08 00:36:10 +02:00
mo8it 3a4f2bebb4 Remove test because of defaulting to watch mode 2024-04-08 00:35:51 +02:00
mo8it 394ca402a8 Remove the info_toml_content field 2024-04-07 23:57:54 +02:00
mo8it db25cc9157 Ignore .rustlings-state.json 2024-04-07 23:54:32 +02:00
mo8it 93f8d1610d Some renamings 2024-04-07 23:37:40 +02:00
mo8it 99c9ab467b Implement resetting 2024-04-07 22:43:59 +02:00
mo8it db43efe3ec Update .gitignore 2024-04-07 22:40:50 +02:00
mo8it 9a4ee47c52 Separate WatchState 2024-04-07 19:29:16 +02:00
mo8it 0a674a158d Separate UiState 2024-04-07 19:05:29 +02:00
mo8it 3bd26c7a24 State -> StateFile 2024-04-07 19:01:08 +02:00
mo8it 8c31d38fa1 Better variable name 2024-04-07 17:57:20 +02:00
mo8it d988054ad8 Add UiState 2024-04-07 16:33:00 +02:00
mo8it 2db86833a9 Fix lifetimes 2024-04-07 13:12:40 +02:00
mo8it b0a4750624 Implement "continue at" 2024-04-07 04:59:22 +02:00
mo8it 4f69285375 Shorten the help footer 2024-04-07 04:39:03 +02:00
mo8it e640b4a1ff Add "Next" column 2024-04-07 04:36:27 +02:00
mo8it 7f5a18fa34 Show help message 2024-04-07 04:19:50 +02:00
mo8it c4897139ae Prevent unneeded redraws 2024-04-07 03:41:23 +02:00
mo8it 372290a796 Done navigation 2024-04-07 03:38:18 +02:00
mo8it 729385362c Update deps 2024-04-07 03:03:59 +02:00
mo8it f6db88aca8 Started with list 2024-04-07 03:03:37 +02:00
mo8it 0819bbe21f Can't use Ratatui for the watch mode :( 2024-04-07 01:17:53 +02:00
mo8it 18342b3aa3 Verify starting with some index 2024-04-07 01:16:56 +02:00
mo8it c2daad8340 Return an error instead of exiting 2024-04-07 01:15:47 +02:00
mo8it de9a0ed522 Update state 2024-04-06 01:46:22 +02:00
mo8it 06e7216c83 Elimintate an itermediate variable 2024-04-06 01:46:09 +02:00
mo8it 60155294e9 Rename packages 2024-04-06 01:45:54 +02:00
mo8it 3f2d41de9e Start with the state 2024-04-05 03:05:07 +02:00
mo8it b0f19fd862 Start with the TUI 2024-04-05 03:04:53 +02:00
mo8it 0bf51c6a0d Ignore .ignore 2024-04-05 00:59:21 +02:00
mo8it 1d2c2cffd2 Remove .gitattributes 2024-04-05 00:59:13 +02:00
mo8it 157fe016e5 Remove ui.rs 2024-04-05 00:49:22 +02:00
mo8it 5a233398eb Fix tests 2024-04-05 00:44:43 +02:00
mo8it 919ba88413 Use the pretty format when testing even with -q 2024-04-05 00:43:36 +02:00
mo8it 445441ce25 Make gen-dev-cargo-toml a separate package
so that `cargo install` only installs `rustlings`
2024-04-04 23:16:57 +02:00
mo8it 34375b2ebf Clean up as a preparation for the TUI 2024-04-04 21:06:11 +02:00
mo8it 9ea744a710 Remove deps not needed in the TUI 2024-04-04 20:27:30 +02:00
mo8it 2b6f9fb6a7 Add Ratatui 2024-04-04 20:21:55 +02:00
Mo 8c8f30d8ce
Merge pull request #1931 from mo8it/standalone-binary
Standalone binary
2024-04-04 15:48:07 +02:00
mo8it b6c434c445 Remove optional version field 2024-04-04 15:45:53 +02:00
mo8it 569a68eb73 Minify generated Cargo.toml 2024-04-04 15:44:48 +02:00
mo8it 1885ece2dc Merge branch 'main' 2024-04-04 15:31:59 +02:00
mo8it 190945352a Add comments about dev/Cargo.toml 2024-04-01 18:52:43 +02:00
mo8it def8d2c569 Add VerifyState 2024-04-01 18:38:01 +02:00
mo8it fdd7de00bd Improvements to verify 2024-04-01 18:21:56 +02:00
mo8it 2f30eac27f Remove unneeded .iter() 2024-04-01 17:36:42 +02:00
mo8it 14f3585816 Make cargo run work 2024-04-01 02:11:52 +02:00
mo8it 8ad18de54c Use var_os to avoid conversion to String 2024-03-31 20:11:08 +02:00
mo8it 7560aec66b Inline reset 2024-03-31 20:08:23 +02:00
mo8it fb32d0b86f Remove redundant test 2024-03-31 18:59:07 +02:00
mo8it 7090fffeae Fix tests 2024-03-31 18:59:01 +02:00
mo8it c1de4d46aa Some improvements to error handling 2024-03-31 18:25:54 +02:00
mo8it 82b563f165 Use Cargo instead of rustc 2024-03-31 16:55:33 +02:00
mo8it b711dd692a Add .gitignore 2024-03-31 02:04:41 +01:00
mo8it 1e1f031713 Fix path comparison 2024-03-31 00:49:19 +01:00
mo8it b5e17c965d Add an error message when a file is not embedded 2024-03-30 21:15:11 +01:00
mo8it 23f0fae1c8 Show a success message after resetting 2024-03-30 21:13:28 +01:00
mo8it 79ca821e26 Fix tests 2024-03-30 20:48:30 +01:00
mo8it fe7d775818 Remove the installation scripts 2024-03-30 18:52:49 +01:00
mo8it 8e3cc9d70c Improve printed information 2024-03-29 01:52:05 +01:00
mo8it 2b01811fe9 Fix typo 2024-03-29 01:51:22 +01:00
mo8it a561a0f7f0 Avoid reinitialization by mistake 2024-03-29 01:51:08 +01:00
mo8it 36a8e3ac0e Replace rust-project.json with Cargo.toml 2024-03-29 01:29:41 +01:00
mo8it 0f18d599e9 Add panic = "abort" 2024-03-29 01:25:32 +01:00
mo8it 3959570221 Bump version to v6 2024-03-29 01:25:21 +01:00
mo8it 3ff9b0cd2a POC done 2024-03-28 22:11:16 +01:00
mo8it 5b4103bbac Remove unneeded ./ from relative paths 2024-03-28 21:10:31 +01:00
mo8it d5ed749e9f Add embedded.rs 2024-03-28 21:06:36 +01:00
mo8it 39bdd086a7 Use concat explicitly from std 2024-03-28 18:18:20 +01:00
mo8it dd025391f2 Make everything static 2024-03-28 17:52:51 +01:00
mo8it e5efc68a91 Done macro 2024-03-28 17:34:48 +01:00
Daniel Somerfield 62afbb034f Move test array to be in test module as vec 2024-03-27 20:37:19 -07:00
Daniel Somerfield 8bfe2ec71e Fix all_fruits_types_in_basket to fail if all fruit kinds are not included 2023-11-21 14:02:26 -08:00
267 changed files with 9473 additions and 7925 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,8 +0,0 @@
{
"image": "mcr.microsoft.com/devcontainers/rust:1",
"updateContentCommand": ["cargo", "build"],
"postAttachCommand": ["rustlings", "watch"],
"remoteEnv": {
"PATH": "${containerEnv:PATH}:${containerWorkspaceFolder}/target/debug"
}
}

2
.gitattributes vendored
View file

@ -1,2 +0,0 @@
* text=auto
*.sh text eol=lf

View file

@ -18,25 +18,26 @@ jobs:
fmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- uses: DavidAnson/markdownlint-cli2-action@v9
- uses: actions/checkout@v4
- uses: DavidAnson/markdownlint-cli2-action@v16
with:
globs: "exercises/**/*.md"
- name: Run cargo fmt
run: |
cargo fmt --all -- --check
run: cargo fmt --all -- --check
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@stable
- uses: actions/checkout@v4
- uses: swatinem/rust-cache@v2
- name: Run cargo test
run: |
cargo test
run: cargo test
dev-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: swatinem/rust-cache@v2
- name: Run rustlings dev check
run: cargo run -- dev check

View file

@ -54,10 +54,9 @@ jobs:
runs-on: ubuntu-latest
steps:
# Setup
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: dtolnay/rust-toolchain@stable
- uses: swatinem/rust-cache@v2
# If you use any mdbook plugins, here's the place to install them!

33
.gitignore vendored
View file

@ -1,18 +1,23 @@
*.swp
# Cargo
target/
**/*.rs.bk
.DS_Store
*.pdb
exercises/22_clippy/Cargo.toml
exercises/22_clippy/Cargo.lock
rust-project.json
.idea
.vscode/*
!.vscode/extensions.json
*.iml
*.o
Cargo.lock
!/Cargo.lock
# State file
.rustlings-state.txt
# oranda
public/
.netlify
# OS
.DS_Store
.direnv/
# Local Netlify folder
.netlify
# Editor
*.swp
.idea
*.iml
# Ignore file for editors like Helix
.ignore

View file

@ -1,7 +0,0 @@
tasks:
- init: /workspace/rustlings/install.sh
command: /workspace/.cargo/bin/rustlings watch
vscode:
extensions:
- rust-lang.rust-analyzer@0.3.1348

7
.typos.toml Normal file
View file

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

View file

@ -1,5 +0,0 @@
{
"recommendations": [
"rust-lang.rust-analyzer"
]
}

View file

@ -1,398 +0,0 @@
## Authors
This file lists the people that have contributed to this project.
Excluded from this list are @carols10cents and @diannasoreil, the principal
authors.
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tbody>
<tr>
<td align="center" valign="top" width="12.5%"><a href="http://carol-nichols.com"><img src="https://avatars2.githubusercontent.com/u/193874?v=4?s=100" width="100px;" alt="Carol (Nichols &#124;&#124; Goulding)"/><br /><sub><b>Carol (Nichols &#124;&#124; Goulding)</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=carols10cents" title="Code">💻</a> <a href="#content-carols10cents" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://twitter.com/QuietMisdreavus"><img src="https://avatars2.githubusercontent.com/u/5217170?v=4?s=100" width="100px;" alt="QuietMisdreavus"/><br /><sub><b>QuietMisdreavus</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=QuietMisdreavus" title="Code">💻</a> <a href="#content-QuietMisdreavus" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/robertlugg"><img src="https://avatars0.githubusercontent.com/u/6054540?v=4?s=100" width="100px;" alt="Robert M Lugg"/><br /><sub><b>Robert M Lugg</b></sub></a><br /><a href="#content-robertlugg" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://hynek.me/about/"><img src="https://avatars3.githubusercontent.com/u/41240?v=4?s=100" width="100px;" alt="Hynek Schlawack"/><br /><sub><b>Hynek Schlawack</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=hynek" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://spacekookie.de"><img src="https://avatars0.githubusercontent.com/u/7669898?v=4?s=100" width="100px;" alt="Katharina Fey"/><br /><sub><b>Katharina Fey</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=spacekookie" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/lukabavdaz"><img src="https://avatars0.githubusercontent.com/u/9624558?v=4?s=100" width="100px;" alt="lukabavdaz"/><br /><sub><b>lukabavdaz</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=lukabavdaz" title="Code">💻</a> <a href="#content-lukabavdaz" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://vestera.as"><img src="https://avatars2.githubusercontent.com/u/4187449?v=4?s=100" width="100px;" alt="Erik Vesteraas"/><br /><sub><b>Erik Vesteraas</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=evestera" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/Delet0r"><img src="https://avatars1.githubusercontent.com/u/23195618?v=4?s=100" width="100px;" alt="delet0r"/><br /><sub><b>delet0r</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=Delet0r" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="http://phinary.ca"><img src="https://avatars1.githubusercontent.com/u/10522375?v=4?s=100" width="100px;" alt="Shaun Bennett"/><br /><sub><b>Shaun Bennett</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=shaunbennett" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/abagshaw"><img src="https://avatars2.githubusercontent.com/u/8594541?v=4?s=100" width="100px;" alt="Andrew Bagshaw"/><br /><sub><b>Andrew Bagshaw</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=abagshaw" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://ai6ua.net/"><img src="https://avatars2.githubusercontent.com/u/175578?v=4?s=100" width="100px;" alt="Kyle Isom"/><br /><sub><b>Kyle Isom</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=kisom" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/ColinPitrat"><img src="https://avatars3.githubusercontent.com/u/1541863?v=4?s=100" width="100px;" alt="Colin Pitrat"/><br /><sub><b>Colin Pitrat</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=ColinPitrat" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://zacanger.com"><img src="https://avatars3.githubusercontent.com/u/12520493?v=4?s=100" width="100px;" alt="Zac Anger"/><br /><sub><b>Zac Anger</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=zacanger" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/mgeier"><img src="https://avatars1.githubusercontent.com/u/705404?v=4?s=100" width="100px;" alt="Matthias Geier"/><br /><sub><b>Matthias Geier</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=mgeier" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/cjpearce"><img src="https://avatars1.githubusercontent.com/u/3453268?v=4?s=100" width="100px;" alt="Chris Pearce"/><br /><sub><b>Chris Pearce</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=cjpearce" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://yvan-sraka.github.io"><img src="https://avatars2.githubusercontent.com/u/705213?v=4?s=100" width="100px;" alt="Yvan Sraka"/><br /><sub><b>Yvan Sraka</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=yvan-sraka" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/dendi239"><img src="https://avatars3.githubusercontent.com/u/16478650?v=4?s=100" width="100px;" alt="Denys Smirnov"/><br /><sub><b>Denys Smirnov</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=dendi239" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/eddyp"><img src="https://avatars2.githubusercontent.com/u/123772?v=4?s=100" width="100px;" alt="eddyp"/><br /><sub><b>eddyp</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=eddyp" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://about.me/BrianKung"><img src="https://avatars1.githubusercontent.com/u/2836167?v=4?s=100" width="100px;" alt="Brian Kung"/><br /><sub><b>Brian Kung</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=briankung" title="Code">💻</a> <a href="#content-briankung" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://rcousineau.gitlab.io"><img src="https://avatars3.githubusercontent.com/u/281039?v=4?s=100" width="100px;" alt="Russell"/><br /><sub><b>Russell</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=miller-time" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://danwilhelm.com"><img src="https://avatars3.githubusercontent.com/u/6137185?v=4?s=100" width="100px;" alt="Dan Wilhelm"/><br /><sub><b>Dan Wilhelm</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=danwilhelm" title="Documentation">📖</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/Jesse-Cameron"><img src="https://avatars3.githubusercontent.com/u/3723654?v=4?s=100" width="100px;" alt="Jesse"/><br /><sub><b>Jesse</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=Jesse-Cameron" title="Code">💻</a> <a href="#content-Jesse-Cameron" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/MrFroop"><img src="https://avatars3.githubusercontent.com/u/196700?v=4?s=100" width="100px;" alt="Fredrik Jambrén"/><br /><sub><b>Fredrik Jambrén</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=MrFroop" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/petemcfarlane"><img src="https://avatars3.githubusercontent.com/u/3472717?v=4?s=100" width="100px;" alt="Pete McFarlane"/><br /><sub><b>Pete McFarlane</b></sub></a><br /><a href="#content-petemcfarlane" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/nkanderson"><img src="https://avatars0.githubusercontent.com/u/4128825?v=4?s=100" width="100px;" alt="nkanderson"/><br /><sub><b>nkanderson</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=nkanderson" title="Code">💻</a> <a href="#content-nkanderson" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/ajaxm"><img src="https://avatars0.githubusercontent.com/u/13360138?v=4?s=100" width="100px;" alt="Ajax M"/><br /><sub><b>Ajax M</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=ajaxm" title="Documentation">📖</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://dylnuge.com"><img src="https://avatars2.githubusercontent.com/u/118624?v=4?s=100" width="100px;" alt="Dylan Nugent"/><br /><sub><b>Dylan Nugent</b></sub></a><br /><a href="#content-Dylnuge" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/vyaslav"><img src="https://avatars0.githubusercontent.com/u/1385427?v=4?s=100" width="100px;" alt="vyaslav"/><br /><sub><b>vyaslav</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=vyaslav" title="Code">💻</a> <a href="#content-vyaslav" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://join.sfxd.org"><img src="https://avatars1.githubusercontent.com/u/17297466?v=4?s=100" width="100px;" alt="George"/><br /><sub><b>George</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=gdoenlen" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/nyxtom"><img src="https://avatars2.githubusercontent.com/u/222763?v=4?s=100" width="100px;" alt="Thomas Holloway"/><br /><sub><b>Thomas Holloway</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=nyxtom" title="Code">💻</a> <a href="#content-nyxtom" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/workingjubilee"><img src="https://avatars1.githubusercontent.com/u/46493976?v=4?s=100" width="100px;" alt="Jubilee"/><br /><sub><b>Jubilee</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=workingjubilee" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/WofWca"><img src="https://avatars1.githubusercontent.com/u/39462442?v=4?s=100" width="100px;" alt="WofWca"/><br /><sub><b>WofWca</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=WofWca" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/jrvidal"><img src="https://avatars0.githubusercontent.com/u/1636604?v=4?s=100" width="100px;" alt="Roberto Vidal"/><br /><sub><b>Roberto Vidal</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=jrvidal" title="Code">💻</a> <a href="https://github.com/rust-lang/rustlings/commits?author=jrvidal" title="Documentation">📖</a> <a href="#ideas-jrvidal" title="Ideas, Planning, & Feedback">🤔</a> <a href="#maintenance-jrvidal" title="Maintenance">🚧</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/jensim"><img src="https://avatars0.githubusercontent.com/u/3663856?v=4?s=100" width="100px;" alt="Jens"/><br /><sub><b>Jens</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=jensim" title="Documentation">📖</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://rahatah.me/d"><img src="https://avatars3.githubusercontent.com/u/3174006?v=4?s=100" width="100px;" alt="Rahat Ahmed"/><br /><sub><b>Rahat Ahmed</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=rahatarmanahmed" title="Documentation">📖</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/AbdouSeck"><img src="https://avatars2.githubusercontent.com/u/6490055?v=4?s=100" width="100px;" alt="Abdou Seck"/><br /><sub><b>Abdou Seck</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=AbdouSeck" title="Code">💻</a> <a href="#content-AbdouSeck" title="Content">🖋</a> <a href="https://github.com/rust-lang/rustlings/pulls?q=is%3Apr+reviewed-by%3AAbdouSeck" title="Reviewed Pull Requests">👀</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://codehearts.com"><img src="https://avatars0.githubusercontent.com/u/2885412?v=4?s=100" width="100px;" alt="Katie"/><br /><sub><b>Katie</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=codehearts" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/Socratides"><img src="https://avatars3.githubusercontent.com/u/27732983?v=4?s=100" width="100px;" alt="Socrates"/><br /><sub><b>Socrates</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=Socratides" title="Documentation">📖</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/gnodarse"><img src="https://avatars3.githubusercontent.com/u/46761795?v=4?s=100" width="100px;" alt="gnodarse"/><br /><sub><b>gnodarse</b></sub></a><br /><a href="#content-gnodarse" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/harrisonmetz"><img src="https://avatars1.githubusercontent.com/u/7883408?v=4?s=100" width="100px;" alt="Harrison Metzger"/><br /><sub><b>Harrison Metzger</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=harrisonmetz" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/TorbenJ"><img src="https://avatars2.githubusercontent.com/u/9077102?v=4?s=100" width="100px;" alt="Torben Jonas"/><br /><sub><b>Torben Jonas</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=TorbenJ" title="Code">💻</a> <a href="#content-TorbenJ" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://paulbissex.com/"><img src="https://avatars0.githubusercontent.com/u/641?v=4?s=100" width="100px;" alt="Paul Bissex"/><br /><sub><b>Paul Bissex</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=pbx" title="Documentation">📖</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/sjmann"><img src="https://avatars0.githubusercontent.com/u/6589896?v=4?s=100" width="100px;" alt="Steven Mann"/><br /><sub><b>Steven Mann</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=sjmann" title="Code">💻</a> <a href="#content-sjmann" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://smmdb.net/"><img src="https://avatars2.githubusercontent.com/u/5855071?v=4?s=100" width="100px;" alt="Mario Reder"/><br /><sub><b>Mario Reder</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=Tarnadas" title="Code">💻</a> <a href="#content-Tarnadas" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://keybase.io/skim"><img src="https://avatars0.githubusercontent.com/u/47347?v=4?s=100" width="100px;" alt="skim"/><br /><sub><b>skim</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=sl4m" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/sanjaykdragon"><img src="https://avatars1.githubusercontent.com/u/10261698?v=4?s=100" width="100px;" alt="Sanjay K"/><br /><sub><b>Sanjay K</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=sanjaykdragon" title="Code">💻</a> <a href="#content-sanjaykdragon" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://www.rohanjain.in"><img src="https://avatars1.githubusercontent.com/u/343499?v=4?s=100" width="100px;" alt="Rohan Jain"/><br /><sub><b>Rohan Jain</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=crodjer" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://www.saidaspen.se"><img src="https://avatars1.githubusercontent.com/u/7727687?v=4?s=100" width="100px;" alt="Said Aspen"/><br /><sub><b>Said Aspen</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=saidaspen" title="Code">💻</a> <a href="#content-saidaspen" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/uce"><img src="https://avatars3.githubusercontent.com/u/1756620?v=4?s=100" width="100px;" alt="Ufuk Celebi"/><br /><sub><b>Ufuk Celebi</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=uce" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/lebedevsergey"><img src="https://avatars2.githubusercontent.com/u/7325764?v=4?s=100" width="100px;" alt="lebedevsergey"/><br /><sub><b>lebedevsergey</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=lebedevsergey" title="Documentation">📖</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/avrong"><img src="https://avatars2.githubusercontent.com/u/6342851?v=4?s=100" width="100px;" alt="Aleksei Trifonov"/><br /><sub><b>Aleksei Trifonov</b></sub></a><br /><a href="#content-avrong" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://drn.ie"><img src="https://avatars2.githubusercontent.com/u/411136?v=4?s=100" width="100px;" alt="Darren Meehan"/><br /><sub><b>Darren Meehan</b></sub></a><br /><a href="#content-Darrenmeehan" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/jihchi"><img src="https://avatars1.githubusercontent.com/u/87983?v=4?s=100" width="100px;" alt="Jihchi Lee"/><br /><sub><b>Jihchi Lee</b></sub></a><br /><a href="#content-jihchi" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/bertonha"><img src="https://avatars3.githubusercontent.com/u/1225902?v=4?s=100" width="100px;" alt="Christofer Bertonha"/><br /><sub><b>Christofer Bertonha</b></sub></a><br /><a href="#content-bertonha" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/apatniv"><img src="https://avatars2.githubusercontent.com/u/22565917?v=4?s=100" width="100px;" alt="Vivek Bharath Akupatni"/><br /><sub><b>Vivek Bharath Akupatni</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=apatniv" title="Code">💻</a> <a href="https://github.com/rust-lang/rustlings/commits?author=apatniv" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/DiD92"><img src="https://avatars3.githubusercontent.com/u/6002416?v=4?s=100" width="100px;" alt="Dídac Sementé Fernández"/><br /><sub><b>Dídac Sementé Fernández</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=DiD92" title="Code">💻</a> <a href="#content-DiD92" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/wrobstory"><img src="https://avatars3.githubusercontent.com/u/2601457?v=4?s=100" width="100px;" alt="Rob Story"/><br /><sub><b>Rob Story</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=wrobstory" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/siobhanjacobson"><img src="https://avatars2.githubusercontent.com/u/28983835?v=4?s=100" width="100px;" alt="Siobhan Jacobson"/><br /><sub><b>Siobhan Jacobson</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=siobhanjacobson" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://www.linkedin.com/in/evancarroll/"><img src="https://avatars2.githubusercontent.com/u/19922?v=4?s=100" width="100px;" alt="Evan Carroll"/><br /><sub><b>Evan Carroll</b></sub></a><br /><a href="#content-EvanCarroll" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://www.jawaadmahmood.com"><img src="https://avatars3.githubusercontent.com/u/95606?v=4?s=100" width="100px;" alt="Jawaad Mahmood"/><br /><sub><b>Jawaad Mahmood</b></sub></a><br /><a href="#content-jmahmood" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/GaurangTandon"><img src="https://avatars1.githubusercontent.com/u/6308683?v=4?s=100" width="100px;" alt="Gaurang Tandon"/><br /><sub><b>Gaurang Tandon</b></sub></a><br /><a href="#content-GaurangTandon" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/dev-cyprium"><img src="https://avatars1.githubusercontent.com/u/6002628?v=4?s=100" width="100px;" alt="Stefan Kupresak"/><br /><sub><b>Stefan Kupresak</b></sub></a><br /><a href="#content-dev-cyprium" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/greg-el"><img src="https://avatars3.githubusercontent.com/u/45019882?v=4?s=100" width="100px;" alt="Greg Leonard"/><br /><sub><b>Greg Leonard</b></sub></a><br /><a href="#content-greg-el" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://ryanpcmcquen.org"><img src="https://avatars3.githubusercontent.com/u/772937?v=4?s=100" width="100px;" alt="Ryan McQuen"/><br /><sub><b>Ryan McQuen</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=ryanpcmcquen" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/AnnikaCodes"><img src="https://avatars3.githubusercontent.com/u/56906084?v=4?s=100" width="100px;" alt="Annika"/><br /><sub><b>Annika</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/pulls?q=is%3Apr+reviewed-by%3AAnnikaCodes" title="Reviewed Pull Requests">👀</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://darnuria.eu"><img src="https://avatars1.githubusercontent.com/u/2827553?v=4?s=100" width="100px;" alt="Axel Viala"/><br /><sub><b>Axel Viala</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=darnuria" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://sazid.github.io"><img src="https://avatars1.githubusercontent.com/u/2370167?v=4?s=100" width="100px;" alt="Mohammed Sazid Al Rashid"/><br /><sub><b>Mohammed Sazid Al Rashid</b></sub></a><br /><a href="#content-sazid" title="Content">🖋</a> <a href="https://github.com/rust-lang/rustlings/commits?author=sazid" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://codingthemsoftly.com"><img src="https://avatars1.githubusercontent.com/u/17479099?v=4?s=100" width="100px;" alt="Caleb Webber"/><br /><sub><b>Caleb Webber</b></sub></a><br /><a href="#maintenance-seeplusplus" title="Maintenance">🚧</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/pcn"><img src="https://avatars2.githubusercontent.com/u/1056756?v=4?s=100" width="100px;" alt="Peter N"/><br /><sub><b>Peter N</b></sub></a><br /><a href="#maintenance-pcn" title="Maintenance">🚧</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/seancad"><img src="https://avatars1.githubusercontent.com/u/47405611?v=4?s=100" width="100px;" alt="seancad"/><br /><sub><b>seancad</b></sub></a><br /><a href="#maintenance-seancad" title="Maintenance">🚧</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://willhayworth.com"><img src="https://avatars3.githubusercontent.com/u/181174?v=4?s=100" width="100px;" alt="Will Hayworth"/><br /><sub><b>Will Hayworth</b></sub></a><br /><a href="#content-wsh" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/chrizel"><img src="https://avatars3.githubusercontent.com/u/20802?v=4?s=100" width="100px;" alt="Christian Zeller"/><br /><sub><b>Christian Zeller</b></sub></a><br /><a href="#content-chrizel" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/jfchevrette"><img src="https://avatars.githubusercontent.com/u/3001?v=4?s=100" width="100px;" alt="Jean-Francois Chevrette"/><br /><sub><b>Jean-Francois Chevrette</b></sub></a><br /><a href="#content-jfchevrette" title="Content">🖋</a> <a href="https://github.com/rust-lang/rustlings/commits?author=jfchevrette" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/jbaber"><img src="https://avatars.githubusercontent.com/u/1908117?v=4?s=100" width="100px;" alt="John Baber-Lucero"/><br /><sub><b>John Baber-Lucero</b></sub></a><br /><a href="#content-jbaber" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/tal-zvon"><img src="https://avatars.githubusercontent.com/u/3195851?v=4?s=100" width="100px;" alt="Tal"/><br /><sub><b>Tal</b></sub></a><br /><a href="#content-tal-zvon" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/apogeeoak"><img src="https://avatars.githubusercontent.com/u/59737221?v=4?s=100" width="100px;" alt="apogeeoak"/><br /><sub><b>apogeeoak</b></sub></a><br /><a href="#content-apogeeoak" title="Content">🖋</a> <a href="https://github.com/rust-lang/rustlings/commits?author=apogeeoak" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://www.garfieldtech.com/"><img src="https://avatars.githubusercontent.com/u/254863?v=4?s=100" width="100px;" alt="Larry Garfield"/><br /><sub><b>Larry Garfield</b></sub></a><br /><a href="#content-Crell" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/circumspect"><img src="https://avatars.githubusercontent.com/u/40770208?v=4?s=100" width="100px;" alt="circumspect"/><br /><sub><b>circumspect</b></sub></a><br /><a href="#content-circumspect" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/cjwyett"><img src="https://avatars.githubusercontent.com/u/34195737?v=4?s=100" width="100px;" alt="Cyrus Wyett"/><br /><sub><b>Cyrus Wyett</b></sub></a><br /><a href="#content-cjwyett" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/cadolphs"><img src="https://avatars.githubusercontent.com/u/13894820?v=4?s=100" width="100px;" alt="cadolphs"/><br /><sub><b>cadolphs</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=cadolphs" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://www.haveneer.com"><img src="https://avatars.githubusercontent.com/u/26146722?v=4?s=100" width="100px;" alt="Pascal H."/><br /><sub><b>Pascal H.</b></sub></a><br /><a href="#content-hpwxf" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://twitter.com/chapeupreto"><img src="https://avatars.githubusercontent.com/u/834048?v=4?s=100" width="100px;" alt="Rod Elias"/><br /><sub><b>Rod Elias</b></sub></a><br /><a href="#content-chapeupreto" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/blerchy"><img src="https://avatars.githubusercontent.com/u/2555355?v=4?s=100" width="100px;" alt="Matt Lebl"/><br /><sub><b>Matt Lebl</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=blerchy" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://flakolefluk.dev"><img src="https://avatars.githubusercontent.com/u/11986564?v=4?s=100" width="100px;" alt="Ignacio Le Fluk"/><br /><sub><b>Ignacio Le Fluk</b></sub></a><br /><a href="#content-flakolefluk" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/tlyu"><img src="https://avatars.githubusercontent.com/u/431873?v=4?s=100" width="100px;" alt="Taylor Yu"/><br /><sub><b>Taylor Yu</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=tlyu" title="Code">💻</a> <a href="#content-tlyu" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://zerotask.github.io"><img src="https://avatars.githubusercontent.com/u/20150243?v=4?s=100" width="100px;" alt="Patrick Hintermayer"/><br /><sub><b>Patrick Hintermayer</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=Zerotask" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://petkopavlovski.com/"><img src="https://avatars.githubusercontent.com/u/32264020?v=4?s=100" width="100px;" alt="Pete Pavlovski"/><br /><sub><b>Pete Pavlovski</b></sub></a><br /><a href="#content-arthas168" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/k12ish"><img src="https://avatars.githubusercontent.com/u/45272873?v=4?s=100" width="100px;" alt="k12ish"/><br /><sub><b>k12ish</b></sub></a><br /><a href="#content-k12ish" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/hongshaoyang"><img src="https://avatars.githubusercontent.com/u/19281800?v=4?s=100" width="100px;" alt="Shao Yang Hong"/><br /><sub><b>Shao Yang Hong</b></sub></a><br /><a href="#content-hongshaoyang" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/bmacer"><img src="https://avatars.githubusercontent.com/u/13931806?v=4?s=100" width="100px;" alt="Brandon Macer"/><br /><sub><b>Brandon Macer</b></sub></a><br /><a href="#content-bmacer" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/stoiandan"><img src="https://avatars.githubusercontent.com/u/10388612?v=4?s=100" width="100px;" alt="Stoian Dan"/><br /><sub><b>Stoian Dan</b></sub></a><br /><a href="#content-stoiandan" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://about.me/pjdelport"><img src="https://avatars.githubusercontent.com/u/630271?v=4?s=100" width="100px;" alt="Pi Delport"/><br /><sub><b>Pi Delport</b></sub></a><br /><a href="#content-PiDelport" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/sateeshkumarb"><img src="https://avatars.githubusercontent.com/u/429263?v=4?s=100" width="100px;" alt="Sateesh "/><br /><sub><b>Sateesh </b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=sateeshkumarb" title="Code">💻</a> <a href="#content-sateeshkumarb" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/kayuapi"><img src="https://avatars.githubusercontent.com/u/10304328?v=4?s=100" width="100px;" alt="ZC"/><br /><sub><b>ZC</b></sub></a><br /><a href="#content-kayuapi" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/hyperparabolic"><img src="https://avatars.githubusercontent.com/u/12348474?v=4?s=100" width="100px;" alt="hyperparabolic"/><br /><sub><b>hyperparabolic</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=hyperparabolic" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://www.net4visions.at"><img src="https://avatars.githubusercontent.com/u/5228369?v=4?s=100" width="100px;" alt="arlecchino"/><br /><sub><b>arlecchino</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=kolbma" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://richthofen.io/"><img src="https://avatars.githubusercontent.com/u/7576730?v=4?s=100" width="100px;" alt="Richthofen"/><br /><sub><b>Richthofen</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=jazzplato" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/cseltol"><img src="https://avatars.githubusercontent.com/u/64264529?v=4?s=100" width="100px;" alt="Ivan Nerazumov"/><br /><sub><b>Ivan Nerazumov</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=cseltol" title="Documentation">📖</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/lauralindzey"><img src="https://avatars.githubusercontent.com/u/65185744?v=4?s=100" width="100px;" alt="lauralindzey"/><br /><sub><b>lauralindzey</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=lauralindzey" title="Documentation">📖</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/sinharaksh1t"><img src="https://avatars.githubusercontent.com/u/28585848?v=4?s=100" width="100px;" alt="Rakshit Sinha"/><br /><sub><b>Rakshit Sinha</b></sub></a><br /><a href="#content-sinharaksh1t" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/dbednar230"><img src="https://avatars.githubusercontent.com/u/54457902?v=4?s=100" width="100px;" alt="Damian"/><br /><sub><b>Damian</b></sub></a><br /><a href="#content-dbednar230" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://benarmstead.co.uk"><img src="https://avatars.githubusercontent.com/u/70973680?v=4?s=100" width="100px;" alt="Ben Armstead"/><br /><sub><b>Ben Armstead</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=benarmstead" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/anuk909"><img src="https://avatars.githubusercontent.com/u/34924662?v=4?s=100" width="100px;" alt="anuk909"/><br /><sub><b>anuk909</b></sub></a><br /><a href="#content-anuk909" title="Content">🖋</a> <a href="https://github.com/rust-lang/rustlings/commits?author=anuk909" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://granddaifuku.com/"><img src="https://avatars.githubusercontent.com/u/49578068?v=4?s=100" width="100px;" alt="granddaifuku"/><br /><sub><b>granddaifuku</b></sub></a><br /><a href="#content-granddaifuku" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://weilet.me"><img src="https://avatars.githubusercontent.com/u/32561597?v=4?s=100" width="100px;" alt="Weilet"/><br /><sub><b>Weilet</b></sub></a><br /><a href="#content-Weilet" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/Millione"><img src="https://avatars.githubusercontent.com/u/38575932?v=4?s=100" width="100px;" alt="LIU JIE"/><br /><sub><b>LIU JIE</b></sub></a><br /><a href="#content-Millione" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/abusch"><img src="https://avatars.githubusercontent.com/u/506344?v=4?s=100" width="100px;" alt="Antoine Büsch"/><br /><sub><b>Antoine Büsch</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=abusch" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://frogtd.com/"><img src="https://avatars.githubusercontent.com/u/31412003?v=4?s=100" width="100px;" alt="frogtd"/><br /><sub><b>frogtd</b></sub></a><br /><a href="#content-frogtd" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/EmisonLu"><img src="https://avatars.githubusercontent.com/u/54395432?v=4?s=100" width="100px;" alt="Zhenghao Lu"/><br /><sub><b>Zhenghao Lu</b></sub></a><br /><a href="#content-EmisonLu" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://soundtrackyourbrand.com"><img src="https://avatars.githubusercontent.com/u/762956?v=4?s=100" width="100px;" alt="Fredrik Enestad"/><br /><sub><b>Fredrik Enestad</b></sub></a><br /><a href="#content-fredr" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://xuesong.pydevops.com"><img src="https://avatars.githubusercontent.com/u/18476085?v=4?s=100" width="100px;" alt="xuesong"/><br /><sub><b>xuesong</b></sub></a><br /><a href="#content-xuesongbj" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/MpdWalsh"><img src="https://avatars.githubusercontent.com/u/48160144?v=4?s=100" width="100px;" alt="Michael Walsh"/><br /><sub><b>Michael Walsh</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=MpdWalsh" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/alirezaghey"><img src="https://avatars.githubusercontent.com/u/26653424?v=4?s=100" width="100px;" alt="alirezaghey"/><br /><sub><b>alirezaghey</b></sub></a><br /><a href="#content-alirezaghey" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/frvannes16"><img src="https://avatars.githubusercontent.com/u/3188475?v=4?s=100" width="100px;" alt="Franklin van Nes"/><br /><sub><b>Franklin van Nes</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=frvannes16" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://nekonako.github.io"><img src="https://avatars.githubusercontent.com/u/46141275?v=4?s=100" width="100px;" alt="nekonako"/><br /><sub><b>nekonako</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=nekonako" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/tan-zx"><img src="https://avatars.githubusercontent.com/u/67887489?v=4?s=100" width="100px;" alt="ZX"/><br /><sub><b>ZX</b></sub></a><br /><a href="#content-tan-zx" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/sundevilyang"><img src="https://avatars.githubusercontent.com/u/1499214?v=4?s=100" width="100px;" alt="Yang Wen"/><br /><sub><b>Yang Wen</b></sub></a><br /><a href="#content-sundevilyang" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://brandon-high.com"><img src="https://avatars.githubusercontent.com/u/759848?v=4?s=100" width="100px;" alt="Brandon High"/><br /><sub><b>Brandon High</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=highb" title="Documentation">📖</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/x-hgg-x"><img src="https://avatars.githubusercontent.com/u/39058530?v=4?s=100" width="100px;" alt="x-hgg-x"/><br /><sub><b>x-hgg-x</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=x-hgg-x" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://kisaragieffective.github.io"><img src="https://avatars.githubusercontent.com/u/48310258?v=4?s=100" width="100px;" alt="Kisaragi"/><br /><sub><b>Kisaragi</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=KisaragiEffective" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/Kallu-A"><img src="https://avatars.githubusercontent.com/u/73198738?v=4?s=100" width="100px;" alt="Lucas Aries"/><br /><sub><b>Lucas Aries</b></sub></a><br /><a href="#content-Kallu-A" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/ragreenburg"><img src="https://avatars.githubusercontent.com/u/24358100?v=4?s=100" width="100px;" alt="ragreenburg"/><br /><sub><b>ragreenburg</b></sub></a><br /><a href="#content-ragreenburg" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/stevenfukase"><img src="https://avatars.githubusercontent.com/u/66785624?v=4?s=100" width="100px;" alt="stevenfukase"/><br /><sub><b>stevenfukase</b></sub></a><br /><a href="#content-stevenfukase" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/J-S-Kim"><img src="https://avatars.githubusercontent.com/u/17569303?v=4?s=100" width="100px;" alt="J-S-Kim"/><br /><sub><b>J-S-Kim</b></sub></a><br /><a href="#content-J-S-Kim" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/Fointard"><img src="https://avatars.githubusercontent.com/u/9333398?v=4?s=100" width="100px;" alt="Fointard"/><br /><sub><b>Fointard</b></sub></a><br /><a href="#content-Fointard" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/rytheo"><img src="https://avatars.githubusercontent.com/u/22184325?v=4?s=100" width="100px;" alt="Ryan Lowe"/><br /><sub><b>Ryan Lowe</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=rytheo" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://www.dashen.tech"><img src="https://avatars.githubusercontent.com/u/15921519?v=4?s=100" width="100px;" alt="cui fliter"/><br /><sub><b>cui fliter</b></sub></a><br /><a href="#content-cuishuang" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/luskwater"><img src="https://avatars.githubusercontent.com/u/42529?v=4?s=100" width="100px;" alt="Ron Lusk"/><br /><sub><b>Ron Lusk</b></sub></a><br /><a href="#content-luskwater" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="http://liby.github.io/liby/"><img src="https://avatars.githubusercontent.com/u/38807139?v=4?s=100" width="100px;" alt="Bryan Lee"/><br /><sub><b>Bryan Lee</b></sub></a><br /><a href="#content-liby" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://nandaja.space"><img src="https://avatars.githubusercontent.com/u/2624550?v=4?s=100" width="100px;" alt="Nandaja Varma"/><br /><sub><b>Nandaja Varma</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=nandajavarma" title="Documentation">📖</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/merelymyself"><img src="https://avatars.githubusercontent.com/u/88221256?v=4?s=100" width="100px;" alt="pwygab"/><br /><sub><b>pwygab</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=merelymyself" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://linkedin.com/in/lucasgrvarela"><img src="https://avatars.githubusercontent.com/u/37870368?v=4?s=100" width="100px;" alt="Lucas Grigolon Varela"/><br /><sub><b>Lucas Grigolon Varela</b></sub></a><br /><a href="#content-lucasgrvarela" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/bufo24"><img src="https://avatars.githubusercontent.com/u/32884105?v=4?s=100" width="100px;" alt="Bufo"/><br /><sub><b>Bufo</b></sub></a><br /><a href="#content-bufo24" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://rustnote.com"><img src="https://avatars.githubusercontent.com/u/77730378?v=4?s=100" width="100px;" alt="Jack Clayton"/><br /><sub><b>Jack Clayton</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=jackos" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/klkl0808"><img src="https://avatars.githubusercontent.com/u/24694249?v=4?s=100" width="100px;" alt="Konstantin"/><br /><sub><b>Konstantin</b></sub></a><br /><a href="#content-klkl0808" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/0pling"><img src="https://avatars.githubusercontent.com/u/104090344?v=4?s=100" width="100px;" alt="0pling"/><br /><sub><b>0pling</b></sub></a><br /><a href="#content-0pling" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/KatanaFluorescent"><img src="https://avatars.githubusercontent.com/u/60199077?v=4?s=100" width="100px;" alt="KatanaFluorescent"/><br /><sub><b>KatanaFluorescent</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=KatanaFluorescent" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/Drew-Morris"><img src="https://avatars.githubusercontent.com/u/95818166?v=4?s=100" width="100px;" alt="Drew Morris"/><br /><sub><b>Drew Morris</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=Drew-Morris" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/camperdue42"><img src="https://avatars.githubusercontent.com/u/43047763?v=4?s=100" width="100px;" alt="camperdue42"/><br /><sub><b>camperdue42</b></sub></a><br /><a href="#content-camperdue42" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/YsuOS"><img src="https://avatars.githubusercontent.com/u/30138661?v=4?s=100" width="100px;" alt="YsuOS"/><br /><sub><b>YsuOS</b></sub></a><br /><a href="#content-YsuOS" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://lichess.org/@/StevenEmily"><img src="https://avatars.githubusercontent.com/u/58114641?v=4?s=100" width="100px;" alt="Steven Nguyen"/><br /><sub><b>Steven Nguyen</b></sub></a><br /><a href="#content-icecream17" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://noahcairns.dev"><img src="https://avatars.githubusercontent.com/u/94420090?v=4?s=100" width="100px;" alt="nacairns1"/><br /><sub><b>nacairns1</b></sub></a><br /><a href="#content-nacairns1" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/pgjbz"><img src="https://avatars.githubusercontent.com/u/22059237?v=4?s=100" width="100px;" alt="Paulo Gabriel Justino Bezerra"/><br /><sub><b>Paulo Gabriel Justino Bezerra</b></sub></a><br /><a href="#content-pgjbz" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/jaystile"><img src="https://avatars.githubusercontent.com/u/46078028?v=4?s=100" width="100px;" alt="Jason"/><br /><sub><b>Jason</b></sub></a><br /><a href="#content-jaystile" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://exdx.github.io"><img src="https://avatars.githubusercontent.com/u/31546601?v=4?s=100" width="100px;" alt="exdx"/><br /><sub><b>exdx</b></sub></a><br /><a href="#content-exdx" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/Jzow"><img src="https://avatars.githubusercontent.com/u/68860495?v=4?s=100" width="100px;" alt="James Zow"/><br /><sub><b>James Zow</b></sub></a><br /><a href="#content-Jzow" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://jamesabromley.wordpress.com/"><img src="https://avatars.githubusercontent.com/u/2474334?v=4?s=100" width="100px;" alt="James Bromley"/><br /><sub><b>James Bromley</b></sub></a><br /><a href="#content-jayber" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/swhiteCQC"><img src="https://avatars.githubusercontent.com/u/77438466?v=4?s=100" width="100px;" alt="swhiteCQC"/><br /><sub><b>swhiteCQC</b></sub></a><br /><a href="#content-swhiteCQC" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/neilpate"><img src="https://avatars.githubusercontent.com/u/7802334?v=4?s=100" width="100px;" alt="Neil Pate"/><br /><sub><b>Neil Pate</b></sub></a><br /><a href="#content-neilpate" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://wojexe.com"><img src="https://avatars.githubusercontent.com/u/21208490?v=4?s=100" width="100px;" alt="wojexe"/><br /><sub><b>wojexe</b></sub></a><br /><a href="#content-wojexe" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/Tostapunk"><img src="https://avatars.githubusercontent.com/u/25140297?v=4?s=100" width="100px;" alt="Mattia Schiavon"/><br /><sub><b>Mattia Schiavon</b></sub></a><br /><a href="#content-Tostapunk" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://toucantoco.com"><img src="https://avatars.githubusercontent.com/u/18406791?v=4?s=100" width="100px;" alt="Eric Jolibois"/><br /><sub><b>Eric Jolibois</b></sub></a><br /><a href="#content-PrettyWood" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="http://edwinchang.vercel.app"><img src="https://avatars.githubusercontent.com/u/88263098?v=4?s=100" width="100px;" alt="Edwin Chang"/><br /><sub><b>Edwin Chang</b></sub></a><br /><a href="#content-EdwinChang24" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://saikat.dev/"><img src="https://avatars.githubusercontent.com/u/7412443?v=4?s=100" width="100px;" alt="Saikat Das"/><br /><sub><b>Saikat Das</b></sub></a><br /><a href="#content-saikatdas0790" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/thatlittleboy"><img src="https://avatars.githubusercontent.com/u/30731072?v=4?s=100" width="100px;" alt="Jeremy Goh"/><br /><sub><b>Jeremy Goh</b></sub></a><br /><a href="#content-thatlittleboy" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/Lioness100"><img src="https://avatars.githubusercontent.com/u/65814829?v=4?s=100" width="100px;" alt="Lioness100"/><br /><sub><b>Lioness100</b></sub></a><br /><a href="#content-Lioness100" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/tvkn"><img src="https://avatars.githubusercontent.com/u/79277926?v=4?s=100" width="100px;" alt="Tristan Nicholls"/><br /><sub><b>Tristan Nicholls</b></sub></a><br /><a href="#content-tvkn" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://clairewang.net"><img src="https://avatars.githubusercontent.com/u/9344258?v=4?s=100" width="100px;" alt="Claire"/><br /><sub><b>Claire</b></sub></a><br /><a href="#content-clairew" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/Mouwrice"><img src="https://avatars.githubusercontent.com/u/56763273?v=4?s=100" width="100px;" alt="Maurice Van Wassenhove"/><br /><sub><b>Maurice Van Wassenhove</b></sub></a><br /><a href="#content-Mouwrice" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://jmthree.com"><img src="https://avatars.githubusercontent.com/u/77524?v=4?s=100" width="100px;" alt="John Mendelewski"/><br /><sub><b>John Mendelewski</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=johnmendel" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="http://fakhoury.xyz"><img src="https://avatars.githubusercontent.com/u/20828724?v=4?s=100" width="100px;" alt="Brian Fakhoury"/><br /><sub><b>Brian Fakhoury</b></sub></a><br /><a href="#content-brianfakhoury" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/markusboehme"><img src="https://avatars.githubusercontent.com/u/5074759?v=4?s=100" width="100px;" alt="Markus Boehme"/><br /><sub><b>Markus Boehme</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=markusboehme" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/nico-vromans"><img src="https://avatars.githubusercontent.com/u/48183857?v=4?s=100" width="100px;" alt="Nico Vromans"/><br /><sub><b>Nico Vromans</b></sub></a><br /><a href="#content-nico-vromans" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/vostok92"><img src="https://avatars.githubusercontent.com/u/540339?v=4?s=100" width="100px;" alt="vostok92"/><br /><sub><b>vostok92</b></sub></a><br /><a href="#content-vostok92" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://magnusrodseth.vercel.app"><img src="https://avatars.githubusercontent.com/u/59113973?v=4?s=100" width="100px;" alt="Magnus Rødseth"/><br /><sub><b>Magnus Rødseth</b></sub></a><br /><a href="#content-magnusrodseth" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/rubiesonthesky"><img src="https://avatars.githubusercontent.com/u/2591240?v=4?s=100" width="100px;" alt="rubiesonthesky"/><br /><sub><b>rubiesonthesky</b></sub></a><br /><a href="#content-rubiesonthesky" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://www.gabrielbianconi.com/"><img src="https://avatars.githubusercontent.com/u/1275491?v=4?s=100" width="100px;" alt="Gabriel Bianconi"/><br /><sub><b>Gabriel Bianconi</b></sub></a><br /><a href="#content-GabrielBianconi" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/Kodylow"><img src="https://avatars.githubusercontent.com/u/74332828?v=4?s=100" width="100px;" alt="Kody Low"/><br /><sub><b>Kody Low</b></sub></a><br /><a href="#content-Kodylow" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/rzrymiak"><img src="https://avatars.githubusercontent.com/u/106121613?v=4?s=100" width="100px;" alt="rzrymiak"/><br /><sub><b>rzrymiak</b></sub></a><br /><a href="#content-rzrymiak" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/miguelraz"><img src="https://avatars.githubusercontent.com/u/13056181?v=4?s=100" width="100px;" alt="Miguel Raz Guzmán Macedo"/><br /><sub><b>Miguel Raz Guzmán Macedo</b></sub></a><br /><a href="#content-miguelraz" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/memark"><img src="https://avatars.githubusercontent.com/u/318504?v=4?s=100" width="100px;" alt="Magnus Markling"/><br /><sub><b>Magnus Markling</b></sub></a><br /><a href="#content-memark" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/gasparitiago"><img src="https://avatars.githubusercontent.com/u/3237254?v=4?s=100" width="100px;" alt="Tiago De Gaspari"/><br /><sub><b>Tiago De Gaspari</b></sub></a><br /><a href="#content-gasparitiago" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/skaunov"><img src="https://avatars.githubusercontent.com/u/65976143?v=4?s=100" width="100px;" alt="skaunov"/><br /><sub><b>skaunov</b></sub></a><br /><a href="#content-skaunov" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://caljacobson.dev"><img src="https://avatars.githubusercontent.com/u/9152032?v=4?s=100" width="100px;" alt="Cal Jacobson"/><br /><sub><b>Cal Jacobson</b></sub></a><br /><a href="#content-cj81499" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/duchonic"><img src="https://avatars.githubusercontent.com/u/34117620?v=4?s=100" width="100px;" alt="Duchoud Nicolas"/><br /><sub><b>Duchoud Nicolas</b></sub></a><br /><a href="#content-duchonic" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/gfaugere"><img src="https://avatars.githubusercontent.com/u/11901979?v=4?s=100" width="100px;" alt="Gaëtan Faugère"/><br /><sub><b>Gaëtan Faugère</b></sub></a><br /><a href="#tool-gfaugere" title="Tools">🔧</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/bhbuehler"><img src="https://avatars.githubusercontent.com/u/25541343?v=4?s=100" width="100px;" alt="bhbuehler"/><br /><sub><b>bhbuehler</b></sub></a><br /><a href="#content-bhbuehler" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/nyurik"><img src="https://avatars.githubusercontent.com/u/1641515?v=4?s=100" width="100px;" alt="Yuri Astrakhan"/><br /><sub><b>Yuri Astrakhan</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=nyurik" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://azzamsa.com"><img src="https://avatars.githubusercontent.com/u/17734314?v=4?s=100" width="100px;" alt="azzamsa"/><br /><sub><b>azzamsa</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=azzamsa" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/mvanschellebeeck"><img src="https://avatars.githubusercontent.com/u/17671052?v=4?s=100" width="100px;" alt="mvanschellebeeck"/><br /><sub><b>mvanschellebeeck</b></sub></a><br /><a href="#content-mvanschellebeeck" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/aaarkid"><img src="https://avatars.githubusercontent.com/u/39987510?v=4?s=100" width="100px;" alt="Arkid"/><br /><sub><b>Arkid</b></sub></a><br /><a href="#content-aaarkid" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://tfpk.dev"><img src="https://avatars.githubusercontent.com/u/10906982?v=4?s=100" width="100px;" alt="Tom Kunc"/><br /><sub><b>Tom Kunc</b></sub></a><br /><a href="#content-tfpk" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/mfurak"><img src="https://avatars.githubusercontent.com/u/38523093?v=4?s=100" width="100px;" alt="Marek Furák"/><br /><sub><b>Marek Furák</b></sub></a><br /><a href="#content-mfurak" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://winter.cafe"><img src="https://avatars.githubusercontent.com/u/78392041?v=4?s=100" width="100px;" alt="Winter"/><br /><sub><b>Winter</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=winterqt" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://moritzboeh.me"><img src="https://avatars.githubusercontent.com/u/42215704?v=4?s=100" width="100px;" alt="Moritz Böhme"/><br /><sub><b>Moritz Böhme</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=MoritzBoehme" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/craymel"><img src="https://avatars.githubusercontent.com/u/71062756?v=4?s=100" width="100px;" alt="craymel"/><br /><sub><b>craymel</b></sub></a><br /><a href="#content-craymel" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/tkburis"><img src="https://avatars.githubusercontent.com/u/20501289?v=4?s=100" width="100px;" alt="TK Buristrakul"/><br /><sub><b>TK Buristrakul</b></sub></a><br /><a href="#content-tkburis" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/HerschelW"><img src="https://avatars.githubusercontent.com/u/17935816?v=4?s=100" width="100px;" alt="Kent Worthington"/><br /><sub><b>Kent Worthington</b></sub></a><br /><a href="#content-HerschelW" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/seporterfield"><img src="https://avatars.githubusercontent.com/u/107010978?v=4?s=100" width="100px;" alt="seporterfield"/><br /><sub><b>seporterfield</b></sub></a><br /><a href="#content-seporterfield" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://www.linkedin.com/in/dbarrosop"><img src="https://avatars.githubusercontent.com/u/6246622?v=4?s=100" width="100px;" alt="David Barroso"/><br /><sub><b>David Barroso</b></sub></a><br /><a href="#infra-dbarrosop" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://distanz.ch"><img src="https://avatars.githubusercontent.com/u/539708?v=4?s=100" width="100px;" alt="Tobias Klauser"/><br /><sub><b>Tobias Klauser</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=tklauser" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/0xMySt1c"><img src="https://avatars.githubusercontent.com/u/101825630?v=4?s=100" width="100px;" alt="0xMySt1c"/><br /><sub><b>0xMySt1c</b></sub></a><br /><a href="#tool-0xMySt1c" title="Tools">🔧</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/AxolotlTears"><img src="https://avatars.githubusercontent.com/u/87157047?v=4?s=100" width="100px;" alt="Ten"/><br /><sub><b>Ten</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=AxolotlTears" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://h4x5p4c3.xyz"><img src="https://avatars.githubusercontent.com/u/66133688?v=4?s=100" width="100px;" alt="jones martin"/><br /><sub><b>jones martin</b></sub></a><br /><a href="#content-h4x5p4c3" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/cloppingemu"><img src="https://avatars.githubusercontent.com/u/12227963?v=4?s=100" width="100px;" alt="cloppingemu"/><br /><sub><b>cloppingemu</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=cloppingemu" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://github.com/zeromicro/go-zero"><img src="https://avatars.githubusercontent.com/u/1918356?v=4?s=100" width="100px;" alt="Kevin Wan"/><br /><sub><b>Kevin Wan</b></sub></a><br /><a href="#content-kevwan" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://kurowasaruby.cn"><img src="https://avatars.githubusercontent.com/u/43495006?v=4?s=100" width="100px;" alt="Ruby"/><br /><sub><b>Ruby</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=wjwrh" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/alexandergill"><img src="https://avatars.githubusercontent.com/u/7033716?v=4?s=100" width="100px;" alt="Alexander Gill"/><br /><sub><b>Alexander Gill</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=alexandergill" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://www.linkedin.com/in/jarrod-sanders/"><img src="https://avatars.githubusercontent.com/u/50600614?v=4?s=100" width="100px;" alt="Jarrod Sanders"/><br /><sub><b>Jarrod Sanders</b></sub></a><br /><a href="#content-kawaiiPlat" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/platformer"><img src="https://avatars.githubusercontent.com/u/40146328?v=4?s=100" width="100px;" alt="Andrew Sen"/><br /><sub><b>Andrew Sen</b></sub></a><br /><a href="#content-platformer" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://grzegorz-zur.com/"><img src="https://avatars.githubusercontent.com/u/5297583?v=4?s=100" width="100px;" alt="Grzegorz Żur"/><br /><sub><b>Grzegorz Żur</b></sub></a><br /><a href="#content-grzegorz-zur" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/black-puppydog"><img src="https://avatars.githubusercontent.com/u/189241?v=4?s=100" width="100px;" alt="Daan Wynen"/><br /><sub><b>Daan Wynen</b></sub></a><br /><a href="#content-black-puppydog" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/Anush008"><img src="https://avatars.githubusercontent.com/u/46051506?v=4?s=100" width="100px;" alt="Anush"/><br /><sub><b>Anush</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=Anush008" title="Documentation">📖</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/shgew"><img src="https://avatars.githubusercontent.com/u/5584672?v=4?s=100" width="100px;" alt="Gleb Shevchenko"/><br /><sub><b>Gleb Shevchenko</b></sub></a><br /><a href="#content-shgew" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/mdmundo"><img src="https://avatars.githubusercontent.com/u/60408300?v=4?s=100" width="100px;" alt="Edmundo Paulino"/><br /><sub><b>Edmundo Paulino</b></sub></a><br /><a href="#infra-mdmundo" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/eroullit"><img src="https://avatars.githubusercontent.com/u/301795?v=4?s=100" width="100px;" alt="Emmanuel Roullit"/><br /><sub><b>Emmanuel Roullit</b></sub></a><br /><a href="#infra-eroullit" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://nidhalmessaoudi.herokuapp.com"><img src="https://avatars.githubusercontent.com/u/63377412?v=4?s=100" width="100px;" alt="Nidhal Messaoudi"/><br /><sub><b>Nidhal Messaoudi</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=nidhalmessaoudi" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/MahdiBM"><img src="https://avatars.githubusercontent.com/u/54685446?v=4?s=100" width="100px;" alt="Mahdi Bahrami"/><br /><sub><b>Mahdi Bahrami</b></sub></a><br /><a href="#tool-MahdiBM" title="Tools">🔧</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/Nagidal"><img src="https://avatars.githubusercontent.com/u/7075397?v=4?s=100" width="100px;" alt="Nagidal"/><br /><sub><b>Nagidal</b></sub></a><br /><a href="#content-Nagidal" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://adabrew.com"><img src="https://avatars.githubusercontent.com/u/25161597?v=4?s=100" width="100px;" alt="Adam Brewer"/><br /><sub><b>Adam Brewer</b></sub></a><br /><a href="#content-adamhb123" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/eugkhp"><img src="https://avatars.githubusercontent.com/u/25910599?v=4?s=100" width="100px;" alt="Eugene"/><br /><sub><b>Eugene</b></sub></a><br /><a href="#tool-eugkhp" title="Tools">🔧</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://social.linux.pizza/@navicore"><img src="https://avatars.githubusercontent.com/u/110999?v=4?s=100" width="100px;" alt="Ed Sweeney"/><br /><sub><b>Ed Sweeney</b></sub></a><br /><a href="#content-navicore" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/javihernant"><img src="https://avatars.githubusercontent.com/u/73640929?v=4?s=100" width="100px;" alt="javihernant"/><br /><sub><b>javihernant</b></sub></a><br /><a href="#content-javihernant" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/VegardMatthey"><img src="https://avatars.githubusercontent.com/u/59250656?v=4?s=100" width="100px;" alt="Vegard"/><br /><sub><b>Vegard</b></sub></a><br /><a href="#content-VegardMatthey" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/ryanwhitehouse"><img src="https://avatars.githubusercontent.com/u/13400784?v=4?s=100" width="100px;" alt="Ryan Whitehouse"/><br /><sub><b>Ryan Whitehouse</b></sub></a><br /><a href="#content-ryanwhitehouse" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/guoard"><img src="https://avatars.githubusercontent.com/u/65511355?v=4?s=100" width="100px;" alt="Ali Afsharzadeh"/><br /><sub><b>Ali Afsharzadeh</b></sub></a><br /><a href="#content-guoard" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="http://keogami.ml"><img src="https://avatars.githubusercontent.com/u/41939011?v=4?s=100" width="100px;" alt="Keogami"/><br /><sub><b>Keogami</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=keogami" title="Documentation">📖</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/ahresse"><img src="https://avatars.githubusercontent.com/u/28402488?v=4?s=100" width="100px;" alt="Alexandre Esse"/><br /><sub><b>Alexandre Esse</b></sub></a><br /><a href="#content-ahresse" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://resilient.tech"><img src="https://avatars.githubusercontent.com/u/16315650?v=4?s=100" width="100px;" alt="Sagar Vora"/><br /><sub><b>Sagar Vora</b></sub></a><br /><a href="#content-sagarvora" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/poneciak57"><img src="https://avatars.githubusercontent.com/u/94321164?v=4?s=100" width="100px;" alt="Kacper Poneta"/><br /><sub><b>Kacper Poneta</b></sub></a><br /><a href="#content-poneciak57" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://ktheory.com/"><img src="https://avatars.githubusercontent.com/u/975?v=4?s=100" width="100px;" alt="Aaron Suggs"/><br /><sub><b>Aaron Suggs</b></sub></a><br /><a href="#content-ktheory" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/alexwh"><img src="https://avatars.githubusercontent.com/u/1723612?v=4?s=100" width="100px;" alt="Alex"/><br /><sub><b>Alex</b></sub></a><br /><a href="#content-alexwh" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/stornquist"><img src="https://avatars.githubusercontent.com/u/42915664?v=4?s=100" width="100px;" alt="Sebastian Törnquist"/><br /><sub><b>Sebastian Törnquist</b></sub></a><br /><a href="#content-stornquist" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://smlavine.com"><img src="https://avatars.githubusercontent.com/u/33563640?v=4?s=100" width="100px;" alt="Sebastian LaVine"/><br /><sub><b>Sebastian LaVine</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=smlavine" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="http://www.alangerber.us"><img src="https://avatars.githubusercontent.com/u/201313?v=4?s=100" width="100px;" alt="Alan Gerber"/><br /><sub><b>Alan Gerber</b></sub></a><br /><a href="#content-akgerber" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://esotuvaka.github.io"><img src="https://avatars.githubusercontent.com/u/104941850?v=4?s=100" width="100px;" alt="Eric"/><br /><sub><b>Eric</b></sub></a><br /><a href="#content-esotuvaka" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/az0977776"><img src="https://avatars.githubusercontent.com/u/9172038?v=4?s=100" width="100px;" alt="Aaron Wang"/><br /><sub><b>Aaron Wang</b></sub></a><br /><a href="#content-az0977776" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/nmay231"><img src="https://avatars.githubusercontent.com/u/35386821?v=4?s=100" width="100px;" alt="Noah"/><br /><sub><b>Noah</b></sub></a><br /><a href="#content-nmay231" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/rb5014"><img src="https://avatars.githubusercontent.com/u/105397317?v=4?s=100" width="100px;" alt="rb5014"/><br /><sub><b>rb5014</b></sub></a><br /><a href="#content-rb5014" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/deedy5"><img src="https://avatars.githubusercontent.com/u/65482418?v=4?s=100" width="100px;" alt="deedy5"/><br /><sub><b>deedy5</b></sub></a><br /><a href="#content-deedy5" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/lionel-rowe"><img src="https://avatars.githubusercontent.com/u/26078826?v=4?s=100" width="100px;" alt="lionel-rowe"/><br /><sub><b>lionel-rowe</b></sub></a><br /><a href="#content-lionel-rowe" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/Ben2917"><img src="https://avatars.githubusercontent.com/u/10279994?v=4?s=100" width="100px;" alt="Ben"/><br /><sub><b>Ben</b></sub></a><br /><a href="#content-Ben2917" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/b1ue64"><img src="https://avatars.githubusercontent.com/u/77976308?v=4?s=100" width="100px;" alt="b1ue64"/><br /><sub><b>b1ue64</b></sub></a><br /><a href="#content-b1ue64" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/lazywalker"><img src="https://avatars.githubusercontent.com/u/53956?v=4?s=100" width="100px;" alt="lazywalker"/><br /><sub><b>lazywalker</b></sub></a><br /><a href="#content-lazywalker" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/proofconstruction"><img src="https://avatars.githubusercontent.com/u/74747193?v=4?s=100" width="100px;" alt="proofconstruction"/><br /><sub><b>proofconstruction</b></sub></a><br /><a href="#infra-proofconstruction" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://www.youtube.com/channel/UCQCjA6qUutAtWqkCA4Z36CQ"><img src="https://avatars.githubusercontent.com/u/16007179?v=4?s=100" width="100px;" alt="IVIURRAY"/><br /><sub><b>IVIURRAY</b></sub></a><br /><a href="#content-IVIURRAY" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/b-apperlo"><img src="https://avatars.githubusercontent.com/u/91734527?v=4?s=100" width="100px;" alt="Bert Apperlo"/><br /><sub><b>Bert Apperlo</b></sub></a><br /><a href="#content-b-apperlo" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://fwdekker.com/"><img src="https://avatars.githubusercontent.com/u/13442533?v=4?s=100" width="100px;" alt="Florine W. Dekker"/><br /><sub><b>Florine W. Dekker</b></sub></a><br /><a href="#content-FWDekker" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/luhem7"><img src="https://avatars.githubusercontent.com/u/4008215?v=4?s=100" width="100px;" alt="Mehul Gangavelli"/><br /><sub><b>Mehul Gangavelli</b></sub></a><br /><a href="#content-luhem7" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/Frosthage"><img src="https://avatars.githubusercontent.com/u/14823314?v=4?s=100" width="100px;" alt="Mikael Frosthage"/><br /><sub><b>Mikael Frosthage</b></sub></a><br /><a href="#content-Frosthage" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://robertfry.xyz"><img src="https://avatars.githubusercontent.com/u/43712054?v=4?s=100" width="100px;" alt="Robert Fry"/><br /><sub><b>Robert Fry</b></sub></a><br /><a href="#content-robertefry" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/tajo48"><img src="https://avatars.githubusercontent.com/u/55502906?v=4?s=100" width="100px;" alt="tajo48"/><br /><sub><b>tajo48</b></sub></a><br /><a href="#content-tajo48" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://anishchhetri.com.np"><img src="https://avatars.githubusercontent.com/u/98446102?v=4?s=100" width="100px;" alt="Anish"/><br /><sub><b>Anish</b></sub></a><br /><a href="#content-novanish" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/vnprc"><img src="https://avatars.githubusercontent.com/u/9425366?v=4?s=100" width="100px;" alt="vnprc"/><br /><sub><b>vnprc</b></sub></a><br /><a href="#content-vnprc" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://androecia.net"><img src="https://avatars.githubusercontent.com/u/61999256?v=4?s=100" width="100px;" alt="Joshua Carlson"/><br /><sub><b>Joshua Carlson</b></sub></a><br /><a href="#content-jrcarl624" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://johndesilencio.me"><img src="https://avatars.githubusercontent.com/u/20136554?v=4?s=100" width="100px;" alt="Nicholas R. Smith"/><br /><sub><b>Nicholas R. Smith</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=johnDeSilencio" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://alexfertel.me"><img src="https://avatars.githubusercontent.com/u/22298999?v=4?s=100" width="100px;" alt="Alexander González"/><br /><sub><b>Alexander González</b></sub></a><br /><a href="#content-alexfertel" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/softarn"><img src="https://avatars.githubusercontent.com/u/517619?v=4?s=100" width="100px;" alt="Marcus Höjvall"/><br /><sub><b>Marcus Höjvall</b></sub></a><br /><a href="#content-softarn" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/barlevalon"><img src="https://avatars.githubusercontent.com/u/3397911?v=4?s=100" width="100px;" alt="Alon Hearter"/><br /><sub><b>Alon Hearter</b></sub></a><br /><a href="#content-barlevalon" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/shirts"><img src="https://avatars.githubusercontent.com/u/4952151?v=4?s=100" width="100px;" alt="shirts"/><br /><sub><b>shirts</b></sub></a><br /><a href="#content-shirts" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/eLVas"><img src="https://avatars.githubusercontent.com/u/6797156?v=4?s=100" width="100px;" alt="Ivan Vasiunyk"/><br /><sub><b>Ivan Vasiunyk</b></sub></a><br /><a href="#content-eLVas" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://mo8it.com"><img src="https://avatars.githubusercontent.com/u/76752051?v=4?s=100" width="100px;" alt="Mo"/><br /><sub><b>Mo</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=mo8it" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/x10an14"><img src="https://avatars.githubusercontent.com/u/710608?v=4?s=100" width="100px;" alt="x10an14"/><br /><sub><b>x10an14</b></sub></a><br /><a href="#infra-x10an14" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/gabay"><img src="https://avatars.githubusercontent.com/u/5773610?v=4?s=100" width="100px;" alt="Roi Gabay"/><br /><sub><b>Roi Gabay</b></sub></a><br /><a href="#content-gabay" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/mkovaxx"><img src="https://avatars.githubusercontent.com/u/481354?v=4?s=100" width="100px;" alt="Máté Kovács"/><br /><sub><b>Máté Kovács</b></sub></a><br /><a href="#content-mkovaxx" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://szabgab.com/"><img src="https://avatars.githubusercontent.com/u/48833?v=4?s=100" width="100px;" alt="Gábor Szabó"/><br /><sub><b>Gábor Szabó</b></sub></a><br /><a href="#content-szabgab" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://moduslaborandi.net"><img src="https://avatars.githubusercontent.com/u/3340793?v=4?s=100" width="100px;" alt="Yamila Moreno"/><br /><sub><b>Yamila Moreno</b></sub></a><br /><a href="#content-yamila-moreno" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/willhack"><img src="https://avatars.githubusercontent.com/u/18036720?v=4?s=100" width="100px;" alt="Will Hack"/><br /><sub><b>Will Hack</b></sub></a><br /><a href="#content-willhack" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://cancompute.tech"><img src="https://avatars.githubusercontent.com/u/2052646?v=4?s=100" width="100px;" alt="Michael"/><br /><sub><b>Michael</b></sub></a><br /><a href="#content-bean5" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://www.sadiqpk.org"><img src="https://avatars.githubusercontent.com/u/1289514?v=4?s=100" width="100px;" alt="Mohammed Sadiq"/><br /><sub><b>Mohammed Sadiq</b></sub></a><br /><a href="#content-pksadiq" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/Jak-Ch-ll"><img src="https://avatars.githubusercontent.com/u/56225668?v=4?s=100" width="100px;" alt="Jakob"/><br /><sub><b>Jakob</b></sub></a><br /><a href="#content-Jak-Ch-ll" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://oscarbonilla.com"><img src="https://avatars.githubusercontent.com/u/4950?v=4?s=100" width="100px;" alt="Oscar Bonilla"/><br /><sub><b>Oscar Bonilla</b></sub></a><br /><a href="#content-ob" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/husjon"><img src="https://avatars.githubusercontent.com/u/554229?v=4?s=100" width="100px;" alt="Jon Erling Hustadnes"/><br /><sub><b>Jon Erling Hustadnes</b></sub></a><br /><a href="#content-husjon" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/CobaltCause"><img src="https://avatars.githubusercontent.com/u/7003738?v=4?s=100" width="100px;" alt="Charles Hall"/><br /><sub><b>Charles Hall</b></sub></a><br /><a href="#infra-CobaltCause" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/krmpotic"><img src="https://avatars.githubusercontent.com/u/10350645?v=4?s=100" width="100px;" alt="Luka Krmpotić"/><br /><sub><b>Luka Krmpotić</b></sub></a><br /><a href="#content-krmpotic" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/jurglic"><img src="https://avatars.githubusercontent.com/u/112600?v=4?s=100" width="100px;" alt="Jurglic"/><br /><sub><b>Jurglic</b></sub></a><br /><a href="#content-jurglic" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/OfirLauber"><img src="https://avatars.githubusercontent.com/u/5631030?v=4?s=100" width="100px;" alt="Ofir Lauber"/><br /><sub><b>Ofir Lauber</b></sub></a><br /><a href="#content-OfirLauber" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/offbyone"><img src="https://avatars.githubusercontent.com/u/181693?v=4?s=100" width="100px;" alt="Chris Rose"/><br /><sub><b>Chris Rose</b></sub></a><br /><a href="#infra-offbyone" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/dieterplex"><img src="https://avatars.githubusercontent.com/u/507502?v=4?s=100" width="100px;" alt="d1t2"/><br /><sub><b>d1t2</b></sub></a><br /><a href="#infra-dieterplex" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/docwilco"><img src="https://avatars.githubusercontent.com/u/66911096?v=4?s=100" width="100px;" alt="docwilco"/><br /><sub><b>docwilco</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=docwilco" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://www.linkedin.com/in/matthew-nield1/"><img src="https://avatars.githubusercontent.com/u/64328730?v=4?s=100" width="100px;" alt="Matt Nield"/><br /><sub><b>Matt Nield</b></sub></a><br /><a href="#content-matthewjnield" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/TheBearodactyl"><img src="https://avatars.githubusercontent.com/u/114454115?v=4?s=100" width="100px;" alt="The Bearodactyl"/><br /><sub><b>The Bearodactyl</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=TheBearodactyl" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/markgreene74"><img src="https://avatars.githubusercontent.com/u/18945890?v=4?s=100" width="100px;" alt="markgreene74"/><br /><sub><b>markgreene74</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=markgreene74" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/VeeDeltaVee"><img src="https://avatars.githubusercontent.com/u/45564258?v=4?s=100" width="100px;" alt="Versha Dhankar"/><br /><sub><b>Versha Dhankar</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=VeeDeltaVee" title="Documentation">📖</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://0atman.com"><img src="https://avatars.githubusercontent.com/u/114097?v=4?s=100" width="100px;" alt="Tristram Oaten"/><br /><sub><b>Tristram Oaten</b></sub></a><br /><a href="#content-0atman" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/danieltinazzi"><img src="https://avatars.githubusercontent.com/u/11833533?v=4?s=100" width="100px;" alt="Daniel Tinazzi"/><br /><sub><b>Daniel Tinazzi</b></sub></a><br /><a href="#content-danieltinazzi" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/raymon-roos"><img src="https://avatars.githubusercontent.com/u/38888470?v=4?s=100" width="100px;" alt="Raymon Roos"/><br /><sub><b>Raymon Roos</b></sub></a><br /><a href="#content-raymon-roos" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/matthri"><img src="https://avatars.githubusercontent.com/u/67913999?v=4?s=100" width="100px;" alt="Matthias"/><br /><sub><b>Matthias</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=matthri" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/neuschaefer"><img src="https://avatars.githubusercontent.com/u/1021512?v=4?s=100" width="100px;" alt="J. Neuschäfer"/><br /><sub><b>J. Neuschäfer</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=neuschaefer" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://scooterhacking.org"><img src="https://avatars.githubusercontent.com/u/58905488?v=4?s=100" width="100px;" alt="Bastian Pedersen"/><br /><sub><b>Bastian Pedersen</b></sub></a><br /><a href="#content-bastianpedersen" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/gerases"><img src="https://avatars.githubusercontent.com/u/8953623?v=4?s=100" width="100px;" alt="gerases"/><br /><sub><b>gerases</b></sub></a><br /><a href="#content-gerases" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/AnonimAnonim2245"><img src="https://avatars.githubusercontent.com/u/98339220?v=4?s=100" width="100px;" alt="Luca Plian"/><br /><sub><b>Luca Plian</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=AnonimAnonim2245" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://reifenrath.dev/"><img src="https://avatars.githubusercontent.com/u/18126097?v=4?s=100" width="100px;" alt="René Reifenrath"/><br /><sub><b>René Reifenrath</b></sub></a><br /><a href="#content-reifenrath-dev" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/peterneave"><img src="https://avatars.githubusercontent.com/u/7982708?v=4?s=100" width="100px;" alt="Peter Neave"/><br /><sub><b>Peter Neave</b></sub></a><br /><a href="#infra-peterneave" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://www.janb1.com"><img src="https://avatars.githubusercontent.com/u/5552248?v=4?s=100" width="100px;" alt="Jan"/><br /><sub><b>Jan</b></sub></a><br /><a href="#content-JanB1" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="http://www.kylev.com/"><img src="https://avatars.githubusercontent.com/u/46888?v=4?s=100" width="100px;" alt="Kyle VanderBeek"/><br /><sub><b>Kyle VanderBeek</b></sub></a><br /><a href="#infra-kylev" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/pavedroad"><img src="https://avatars.githubusercontent.com/u/138004431?v=4?s=100" width="100px;" alt="pavedroad"/><br /><sub><b>pavedroad</b></sub></a><br /><a href="#content-pavedroad" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/hyphena"><img src="https://avatars.githubusercontent.com/u/26529488?v=4?s=100" width="100px;" alt="luna"/><br /><sub><b>luna</b></sub></a><br /><a href="#content-hyphena" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/evanmiller2112"><img src="https://avatars.githubusercontent.com/u/28488957?v=4?s=100" width="100px;" alt="Evan Miller"/><br /><sub><b>Evan Miller</b></sub></a><br /><a href="#content-evanmiller2112" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/luvchurchill"><img src="https://avatars.githubusercontent.com/u/46406654?v=4?s=100" width="100px;" alt="luvchurchill"/><br /><sub><b>luvchurchill</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=luvchurchill" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://leverimmy.top/"><img src="https://avatars.githubusercontent.com/u/47663913?v=4?s=100" width="100px;" alt="Ze-en Xiong"/><br /><sub><b>Ze-en Xiong</b></sub></a><br /><a href="#content-LeverImmy" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/parnavh"><img src="https://avatars.githubusercontent.com/u/45985534?v=4?s=100" width="100px;" alt="Parnav Harinathan"/><br /><sub><b>Parnav Harinathan</b></sub></a><br /><a href="#content-parnavh" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/0Ahmed-0"><img src="https://avatars.githubusercontent.com/u/111569638?v=4?s=100" width="100px;" alt="0Ahmed-0"/><br /><sub><b>0Ahmed-0</b></sub></a><br /><a href="#content-0Ahmed-0" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/guizo792"><img src="https://avatars.githubusercontent.com/u/95940388?v=4?s=100" width="100px;" alt="guizo792"/><br /><sub><b>guizo792</b></sub></a><br /><a href="#content-guizo792" title="Content">🖋</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/kazu728"><img src="https://avatars.githubusercontent.com/u/34614358?v=4?s=100" width="100px;" alt="Kazuki Matsuo"/><br /><sub><b>Kazuki Matsuo</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=kazu728" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/paul-leydier"><img src="https://avatars.githubusercontent.com/u/75126792?v=4?s=100" width="100px;" alt="Paul Leydier"/><br /><sub><b>Paul Leydier</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=paul-leydier" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="12.5%"><a href="http://wznmickey.com"><img src="https://avatars.githubusercontent.com/u/44784663?v=4?s=100" width="100px;" alt="wznmickey"/><br /><sub><b>wznmickey</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=wznmickey" title="Documentation">📖</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/NicolasRoelandt"><img src="https://avatars.githubusercontent.com/u/8594193?v=4?s=100" width="100px;" alt="NicolasRoelandt"/><br /><sub><b>NicolasRoelandt</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=NicolasRoelandt" title="Documentation">📖</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://github.com/jbouganim-parallel"><img src="https://avatars.githubusercontent.com/u/150748285?v=4?s=100" width="100px;" alt="Josh Bouganim"/><br /><sub><b>Josh Bouganim</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=jbouganim-parallel" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://loshz.com"><img src="https://avatars.githubusercontent.com/u/3449337?v=4?s=100" width="100px;" alt="Dan"/><br /><sub><b>Dan</b></sub></a><br /><a href="https://github.com/rust-lang/rustlings/commits?author=loshz" title="Code">💻</a></td>
<td align="center" valign="top" width="12.5%"><a href="https://yunshu.site"><img src="https://avatars.githubusercontent.com/u/53544726?v=4?s=100" width="100px;" alt="YunShu"/><br /><sub><b>YunShu</b></sub></a><br /><a href="#content-Selflocking" title="Content">🖋</a></td>
</tr>
</tbody>
</table>
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!

View file

@ -1,4 +1,72 @@
<a name="6.0.0"></a>
## 6.0.0 (2024-07-03)
This release is the result of a complete rewrite to deliver a ton of new features and improvements ✨
The most important changes are highlighted below.
### Installation
The installation has been simplified a lot!
To install Rustlings after installing Rust, all what you need to do now is running the following command:
```bash
cargo install rustlings
```
Yes, this means that Rustlings is now on [crates.io](https://crates.io/crates/rustlings) 🎉
You can read about the motivations of this change in [this issue](https://github.com/rust-lang/rustlings/issues/1919).
### UI/UX
- The UI is now responsive when the terminal is resized.
- The progress bar was moved to the bottom so that you can always see your progress and the current exercise to work on.
- The current exercise path is now a terminal link. It will open the exercise file in your default editor when you click on it.
- A small prompt is now always shown at the bottom. It allows you to choose an action by entering a character. For example, entering `h` will show you the hint of the current exercise.
- The comment "I AM NOT DONE!" doesn't exist anymore. Instead of needing to remove it to go to the next exercise, you need to enter `n` in the terminal.
### List mode
A list mode was added using [Ratatui](https://ratatui.rs).
You can enter it by entering `l` in the watch mode.
It offers the following features:
- Browse all exercises and see their state (pending/done).
- Filter exercises based on their state (pending/done).
- Continue at another exercise. This allows you to skip some exercises or go back to previous ones.
- Reset an exercise so you can start over and revert your changes.
### Solutions
After finishing an exercise, a solution file will be available and Rustlings will show you its path in green.
This allows you to compare your solution with an idiomatic solution and maybe learn about other ways to solve a problem.
While writing the solutions, all exercises have been polished 🌟
For example, every exercise now contains `TODO` comments to highlight what the user needs to change and where.
### LSP support out of the box
Instead of creating a `project.json` file using `rustlings lsp`, Rustlings now works with a `Cargo.toml` file out of the box.
No actions are needed to activate the language server `rust-analyzer`.
This should avoid issues related to the language server or to running exercises, especially the ones with Clippy.
### Clippy
Clippy lints are now shown on all exercises, not only the Clippy exercises 📎
Make Clippy your friend from early on 🥰
### Third party exercises
Rustlings now supports third-party exercises!
Do you want to create your own set of Rustlings exercises to focus on some specific topic?
Or do you want to translate the original Rustlings exercises?
Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXERCISES.md)!
<a name="5.6.1"></a>
## 5.6.1 (2023-09-18)
#### Changed
@ -15,6 +83,7 @@
- `enums3`: Fixed formatting with `rustfmt`.
<a name="5.6.0"></a>
## 5.6.0 (2023-09-04)
#### Added
@ -55,6 +124,7 @@
- Improved CI workflows, we're now testing on multiple platforms at once.
<a name="5.5.1"></a>
## 5.5.1 (2023-05-17)
#### Fixed
@ -62,6 +132,7 @@
- Reverted `rust-project.json` path generation due to an upstream `rust-analyzer` fix.
<a name="5.5.0"></a>
## 5.5.0 (2023-05-17)
#### Added
@ -97,6 +168,7 @@
- Split quick installation section into two code blocks
<a name="5.4.1"></a>
## 5.4.1 (2023-03-10)
#### Changed

View file

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

459
Cargo.lock generated
View file

@ -2,6 +2,18 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "ahash"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
"cfg-if",
"once_cell",
"version_check",
"zerocopy",
]
[[package]]
name = "aho-corasick"
version = "1.1.3"
@ -11,6 +23,12 @@ dependencies = [
"memchr",
]
[[package]]
name = "allocator-api2"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
[[package]]
name = "anstream"
version = "0.6.14"
@ -110,6 +128,21 @@ dependencies = [
"serde",
]
[[package]]
name = "cassowary"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
[[package]]
name = "castaway"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a17ed5635fc8536268e5d4de1e22e81ac34419e5f052d4d51f4e01dcc263fcc"
dependencies = [
"rustversion",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
@ -118,9 +151,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "4.5.7"
version = "4.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f"
checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d"
dependencies = [
"clap_builder",
"clap_derive",
@ -128,9 +161,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.7"
version = "4.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f"
checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708"
dependencies = [
"anstream",
"anstyle",
@ -140,9 +173,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.5.5"
version = "4.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6"
checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085"
dependencies = [
"heck",
"proc-macro2",
@ -163,16 +196,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
[[package]]
name = "console"
version = "0.15.8"
name = "compact_str"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f"
dependencies = [
"encode_unicode",
"lazy_static",
"libc",
"unicode-width",
"windows-sys 0.52.0",
"castaway",
"cfg-if",
"itoa",
"ryu",
"static_assertions",
]
[[package]]
@ -190,6 +223,31 @@ version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
[[package]]
name = "crossterm"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df"
dependencies = [
"bitflags 2.6.0",
"crossterm_winapi",
"libc",
"mio",
"parking_lot",
"signal-hook",
"signal-hook-mio",
"winapi",
]
[[package]]
name = "crossterm_winapi"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
dependencies = [
"winapi",
]
[[package]]
name = "difflib"
version = "0.4.0"
@ -208,28 +266,12 @@ version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "encode_unicode"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "filetime"
version = "0.2.23"
@ -238,7 +280,7 @@ checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"redox_syscall 0.4.1",
"windows-sys 0.52.0",
]
@ -260,17 +302,15 @@ dependencies = [
"libc",
]
[[package]]
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "hashbrown"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
dependencies = [
"ahash",
"allocator-api2",
]
[[package]]
name = "heck"
@ -278,15 +318,6 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "home"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "indexmap"
version = "2.2.6"
@ -297,19 +328,6 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "indicatif"
version = "0.17.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3"
dependencies = [
"console",
"instant",
"number_prefix",
"portable-atomic",
"unicode-width",
]
[[package]]
name = "inotify"
version = "0.9.6"
@ -330,21 +348,30 @@ dependencies = [
"libc",
]
[[package]]
name = "instant"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
dependencies = [
"cfg-if",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
[[package]]
name = "itertools"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.11"
@ -371,12 +398,6 @@ dependencies = [
"libc",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
version = "0.2.155"
@ -384,16 +405,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "linux-raw-sys"
version = "0.4.14"
name = "lock_api"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.21"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "lru"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc"
dependencies = [
"hashbrown",
]
[[package]]
name = "memchr"
@ -444,7 +478,6 @@ version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d40b221972a1fc5ef4d858a2f671fb34c75983eb385463dff3780eeff6a9d43"
dependencies = [
"crossbeam-channel",
"log",
"notify",
]
@ -459,16 +492,49 @@ dependencies = [
]
[[package]]
name = "number_prefix"
version = "0.4.0"
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "portable-atomic"
version = "1.6.0"
name = "os_pipe"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
checksum = "29d73ba8daf8fac13b0501d1abeddcfe21ba7401ada61a819144b6c2a4f32209"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "parking_lot"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [
"cfg-if",
"libc",
"redox_syscall 0.5.2",
"smallvec",
"windows-targets 0.52.5",
]
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "predicates"
@ -518,6 +584,27 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "ratatui"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d16546c5b5962abf8ce6e2881e722b4e0ae3b6f1a08a26ae3573c55853ca68d3"
dependencies = [
"bitflags 2.6.0",
"cassowary",
"compact_str",
"crossterm",
"itertools 0.13.0",
"lru",
"paste",
"stability",
"strum",
"strum_macros",
"unicode-segmentation",
"unicode-truncate",
"unicode-width",
]
[[package]]
name = "redox_syscall"
version = "0.4.1"
@ -527,6 +614,15 @@ dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "redox_syscall"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd"
dependencies = [
"bitflags 2.6.0",
]
[[package]]
name = "regex"
version = "1.10.5"
@ -556,39 +652,40 @@ version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
[[package]]
name = "rustix"
version = "0.38.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
dependencies = [
"bitflags 2.6.0",
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.52.0",
]
[[package]]
name = "rustlings"
version = "5.6.1"
version = "6.0.0"
dependencies = [
"anyhow",
"assert_cmd",
"clap",
"console",
"glob",
"indicatif",
"crossterm",
"hashbrown",
"notify-debouncer-mini",
"os_pipe",
"predicates",
"ratatui",
"rustlings-macros",
"serde",
"serde_json",
"shlex",
"toml_edit",
"which",
"winnow",
]
[[package]]
name = "rustlings-macros"
version = "6.0.0"
dependencies = [
"quote",
"serde",
"toml_edit",
]
[[package]]
name = "rustversion"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
[[package]]
name = "ryu"
version = "1.0.18"
@ -604,6 +701,12 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.203"
@ -626,9 +729,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.118"
version = "1.0.120"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4"
checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5"
dependencies = [
"itoa",
"ryu",
@ -645,10 +748,56 @@ dependencies = [
]
[[package]]
name = "shlex"
version = "1.3.0"
name = "signal-hook"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
dependencies = [
"libc",
"signal-hook-registry",
]
[[package]]
name = "signal-hook-mio"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af"
dependencies = [
"libc",
"mio",
"signal-hook",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
dependencies = [
"libc",
]
[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "stability"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ff9eaf853dec4c8802325d8b6d3dffa86cc707fd7a1a4cdbf416e13b061787a"
dependencies = [
"quote",
"syn",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "strsim"
@ -656,6 +805,28 @@ version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "strum"
version = "0.26.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
dependencies = [
"strum_macros",
]
[[package]]
name = "strum_macros"
version = "0.26.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
dependencies = [
"heck",
"proc-macro2",
"quote",
"rustversion",
"syn",
]
[[package]]
name = "syn"
version = "2.0.68"
@ -701,6 +872,22 @@ version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-segmentation"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
[[package]]
name = "unicode-truncate"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5fbabedabe362c618c714dbefda9927b5afc8e2a8102f47f081089a9019226"
dependencies = [
"itertools 0.12.1",
"unicode-width",
]
[[package]]
name = "unicode-width"
version = "0.1.13"
@ -713,6 +900,12 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wait-timeout"
version = "0.2.0"
@ -739,17 +932,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "which"
version = "6.0.1"
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8211e4f58a2b2805adfbefbc07bab82958fc91e3836339b1ab7ae32465dce0d7"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"either",
"home",
"rustix",
"winsafe",
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.8"
@ -759,6 +956,12 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.48.0"
@ -908,7 +1111,21 @@ dependencies = [
]
[[package]]
name = "winsafe"
version = "0.0.19"
name = "zerocopy"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

View file

@ -1,31 +1,72 @@
[workspace]
resolver = "2"
exclude = [
"tests/fixture/failure",
"tests/fixture/state",
"tests/fixture/success",
"dev",
]
[workspace.package]
version = "6.0.0"
authors = [
"Liv <mokou@fastmail.com>",
"Mo Bitar <mo8it@proton.me>",
# Alumni
"Carol (Nichols || Goulding) <carol.nichols@gmail.com>",
]
repository = "https://github.com/rust-lang/rustlings"
license = "MIT"
edition = "2021"
[workspace.dependencies]
serde = { version = "1.0.203", features = ["derive"] }
toml_edit = { version = "0.22.14", default-features = false, features = ["parse", "serde"] }
[package]
name = "rustlings"
description = "Small exercises to get you used to reading and writing Rust code!"
version = "5.6.1"
authors = [
"Liv <mokou@fastmail.com>",
"Carol (Nichols || Goulding) <carol.nichols@gmail.com>",
version.workspace = true
authors.workspace = true
repository.workspace = true
license.workspace = true
edition.workspace = true
keywords = [
"exercise",
"learning",
]
include = [
"/src/",
"/exercises/",
"/solutions/",
# A symlink to be able to include `dev/Cargo.toml` although `dev` is excluded.
"/dev-Cargo.toml",
"/README.md",
"/LICENSE",
]
edition = "2021"
[dependencies]
anyhow = "1.0.86"
clap = { version = "4.5.7", features = ["derive"] }
console = "0.15.8"
indicatif = "0.17.8"
notify-debouncer-mini = "0.4.1"
serde_json = "1.0.118"
serde = { version = "1.0.203", features = ["derive"] }
shlex = "1.3.0"
toml_edit = { version = "0.22.14", default-features = false, features = ["parse", "serde"] }
which = "6.0.1"
winnow = "0.6.13"
[[bin]]
name = "rustlings"
path = "src/main.rs"
clap = { version = "4.5.8", features = ["derive"] }
crossterm = "0.27.0"
hashbrown = "0.14.5"
notify-debouncer-mini = { version = "0.4.1", default-features = false }
os_pipe = "1.2.0"
ratatui = { version = "0.27.0", default-features = false, features = ["crossterm"] }
rustlings-macros = { path = "rustlings-macros", version = "=6.0.0" }
serde_json = "1.0.120"
serde.workspace = true
toml_edit.workspace = true
[dev-dependencies]
assert_cmd = "2.0.14"
glob = "0.3.0"
predicates = "3.1.0"
[profile.release]
panic = "abort"
[profile.dev]
panic = "abort"
[package.metadata.release]
pre-release-hook = ["./release-hook.sh"]

197
README.md
View file

@ -1,178 +1,143 @@
<div class="oranda-hide">
# rustlings 🦀❤️
# Rustlings 🦀❤️
</div>
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!
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!
Alternatively, for a first-time Rust learner, there are several other resources:
It is recommended to do the Rustlings exercises in parallel to reading [the official Rust book](https://doc.rust-lang.org/book/), the most comprehensive resource for learning Rust 📚️
- [The Book](https://doc.rust-lang.org/book/index.html) - The most comprehensive resource for learning Rust, but a bit theoretical sometimes. You will be using this along with Rustlings!
- [Rust By Example](https://doc.rust-lang.org/rust-by-example/index.html) - Learn Rust by solving little exercises! It's almost like `rustlings`, but online
[Rust By Example](https://doc.rust-lang.org/rust-by-example/) is another recommended resource that you might find helpful.
It contains code examples and exercises similar to Rustlings, but online.
## Getting Started
_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`._
### Installing Rust
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.
Before installing Rustlings, you need to have _Rust installed_.
Visit [www.rust-lang.org/tools/install](https://www.rust-lang.org/tools/install) for further instructions on installing Rust.
This'll also install _Cargo_, Rust's package/project manager.
## MacOS/Linux
> 🐧 If you're on Linux, make sure you've installed `gcc` (for a linker).
>
> Deb: `sudo apt install gcc`.
> Dnf: `sudo dnf install gcc`.
Just run:
> 🍎 If you're on MacOS, make sure you've installed Xcode and its developer tools by running `xcode-select --install`.
### Installing Rustlings
The following command will download and compile Rustlings:
```bash
curl -L https://raw.githubusercontent.com/rust-lang/rustlings/main/install.sh | bash
cargo install rustlings
```
Or if you want it to be installed to a different path:
<details>
<summary><strong>If the installation fails…</strong> (<em>click to expand</em>)</summary>
- Make sure you have the latest Rust version by running `rustup update`
- Try adding the `--locked` flag: `cargo install rustlings --locked`
- Otherwise, please [report the issue](https://github.com/rust-lang/rustlings/issues/new)
</details>
### Initialization
After installing Rustlings, run the following command to initialize the `rustlings/` directory:
```bash
curl -L https://raw.githubusercontent.com/rust-lang/rustlings/main/install.sh | bash -s mypath/
rustlings init
```
This will install Rustlings and give you access to the `rustlings` command. Run it to get started!
### Nix
Basically: Clone the repository at the latest tag, finally run `nix develop` or `nix-shell`.
Now, go into the newly initialized directory and launch Rustlings for further instructions on getting started with the exercises:
```bash
# find out the latest version at https://github.com/rust-lang/rustlings/releases/latest (on edit 5.6.1)
git clone -b 5.6.1 --depth 1 https://github.com/rust-lang/rustlings
cd rustlings
# if nix version > 2.3
nix develop
# if nix version <= 2.3
nix-shell
cd rustlings/
rustlings
```
## Windows
## Working environment
In PowerShell (Run as Administrator), set `ExecutionPolicy` to `RemoteSigned`:
### Editor
```ps1
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
```
Our general recommendation is [VS Code](https://code.visualstudio.com/) with the [rust-analyzer plugin](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer).
But any editor that supports [rust-analyzer](https://rust-analyzer.github.io/) should be enough for working on the exercises.
Then, you can run:
### Terminal
```ps1
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
```
While working with Rustlings, please use a modern terminal for the best user experience.
The default terminal on Linux and Mac should be sufficient.
On Windows, we recommend the [Windows Terminal](https://aka.ms/terminal).
To install Rustlings. Same as on MacOS/Linux, you will have access to the `rustlings` command after it. Keep in mind that this works best in PowerShell, and any other terminals may give you errors.
If you get a permission denied message, you might have to exclude the directory where you cloned Rustlings in your antivirus.
## Browser
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/rust-lang/rustlings)
[![Open Rustlings On Codespaces](https://github.com/codespaces/badge.svg)](https://github.com/codespaces/new/?repo=rust-lang%2Frustlings&ref=main)
## Manually
Basically: Clone the repository at the latest tag, run `cargo install --locked --path .`.
```bash
# find out the latest version at https://github.com/rust-lang/rustlings/releases/latest (on edit 5.6.1)
git clone -b 5.6.1 --depth 1 https://github.com/rust-lang/rustlings
cd rustlings
cargo install --locked --force --path .
```
If there are installation errors, ensure that your toolchain is up to date. For the latest, run:
```bash
rustup update
```
Then, same as above, run `rustlings` to get started.
If you use VS Code, the builtin terminal should also be fine.
## Doing exercises
The exercises are sorted by topic and can be found in the subdirectory `rustlings/exercises/<topic>`. For every topic there is an additional README file with some resources to get you started on the topic. We really recommend that you have a look at them before you start.
The exercises are sorted by topic and can be found in the subdirectory `exercises/<topic>`.
For every topic, there is an additional `README.md` file with some resources to get you started on the topic.
We highly recommend that you have a look at them before you start 📚️
The task is simple. Most exercises contain an error that keeps them from compiling, and it's up to you to fix it! Some exercises are also run as tests, but rustlings handles them all the same. To run the exercises in the recommended order, execute:
Most exercises contain an error that keeps them from compiling, and it's up to you to fix it!
Some exercises contain tests that need to pass for the exercise to be done ✅
```bash
rustlings watch
```
Search for `TODO` and `todo!()` to find out what you need to change.
Ask for hints by entering `h` in the _watch mode_ 💡
This will try to verify the completion of every exercise in a predetermined order (what we think is best for newcomers). It will also rerun automatically every time you change a file in the `exercises/` directory. If you want to only run it once, you can use:
### Watch Mode
```bash
rustlings verify
```
After [initialization](#initialization), Rustlings can be launched by simply running the command `rustlings`.
This will do the same as watch, but it'll quit after running.
This will start the _watch mode_ which walks you through the exercises in a predefined order (what we think is best for newcomers).
It will rerun the current exercise automatically every time you change the exercise's file in the `exercises/` directory.
In case you want to go by your own order, or want to only verify a single exercise, you can run:
<details>
<summary><strong>If detecting file changes in the <code>exercises/</code> directory fails…</strong> (<em>click to expand</em>)</summary>
```bash
rustlings run myExercise1
```
> You can add the **`--manual-run`** flag (`rustlings --manual-run`) to manually rerun the current exercise by entering `r` in the watch mode.
>
> Please [report the issue](https://github.com/rust-lang/rustlings/issues/new) with some information about your operating system and whether you run Rustlings in a container or virtual machine (e.g. WSL).
Or simply use the following command to run the next unsolved exercise in the course:
</details>
```bash
rustlings run next
```
### Exercise List
In case you get stuck, you can run the following command to get a hint for your
exercise:
In the [watch mode](#watch-mode) (after launching `rustlings`), you can enter `l` to open the interactive exercise list.
```bash
rustlings hint myExercise1
```
The list allows you to…
You can also get the hint for the next unsolved exercise with the following command:
- See the status of all exercises (done or pending)
- `c`: Continue at another exercise (temporarily skip some exercises or go back to a previous one)
- `r`: Reset status and file of an exercise (you need to _reload/reopen_ its file in your editor afterwards)
```bash
rustlings hint next
```
To check your progress, you can run the following command:
```bash
rustlings list
```
## Testing yourself
After every couple of sections, there will be a quiz that'll test your knowledge on a bunch of sections at once. These quizzes are found in `exercises/quizN.rs`.
## Enabling `rust-analyzer`
Run the command `rustlings lsp` which will generate a `rust-project.json` at the root of the project, this allows [rust-analyzer](https://rust-analyzer.github.io/) to parse each exercise.
See the footer of the list for all possible keys.
## Continuing On
Once you've completed Rustlings, put your new knowledge to good use! Continue practicing your Rust skills by building your own projects, contributing to Rustlings, or finding other open-source projects to contribute to.
Once you've completed Rustlings, put your new knowledge to good use!
Continue practicing your Rust skills by building your own projects, contributing to Rustlings, or finding other open-source projects to contribute to.
## Third-Party Exercises
Do you want to create your own set of Rustlings exercises to focus on some specific topic?
Or do you want to translate the original Rustlings exercises?
Then follow the link to the guide about [third-party exercises](THIRD_PARTY_EXERCISES.md)!
## Uninstalling Rustlings
If you want to remove Rustlings from your system, there are two steps. First, you'll need to remove the exercises folder that the install script created
for you:
```bash
rm -rf rustlings # or your custom folder name, if you chose and or renamed it
```
Second, run `cargo uninstall` to remove the `rustlings` binary:
If you want to remove Rustlings from your system, run the following command:
```bash
cargo uninstall rustlings
```
Now you should be done!
## Contributing
See [CONTRIBUTING.md](https://github.com/rust-lang/rustlings/blob/main/CONTRIBUTING.md).
See [CONTRIBUTING.md](https://github.com/rust-lang/rustlings/blob/main/CONTRIBUTING.md) 🔗
## Contributors ✨
Thanks goes to the wonderful people listed in [AUTHORS.md](https://github.com/rust-lang/rustlings/blob/main/AUTHORS.md) 🎉
Thanks to [all the wonderful contributors](https://github.com/rust-lang/rustlings/graphs/contributors) 🎉

53
THIRD_PARTY_EXERCISES.md Normal file
View file

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

1
dev-Cargo.toml Symbolic link
View file

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

197
dev/Cargo.toml Normal file
View file

@ -0,0 +1,197 @@
# Don't edit the `bin` list manually! It is updated by `cargo run -- dev update`. This comment line will be stripped in `rustlings init`.
bin = [
{ name = "intro1", path = "../exercises/00_intro/intro1.rs" },
{ name = "intro1_sol", path = "../solutions/00_intro/intro1.rs" },
{ name = "intro2", path = "../exercises/00_intro/intro2.rs" },
{ name = "intro2_sol", path = "../solutions/00_intro/intro2.rs" },
{ name = "variables1", path = "../exercises/01_variables/variables1.rs" },
{ name = "variables1_sol", path = "../solutions/01_variables/variables1.rs" },
{ name = "variables2", path = "../exercises/01_variables/variables2.rs" },
{ name = "variables2_sol", path = "../solutions/01_variables/variables2.rs" },
{ name = "variables3", path = "../exercises/01_variables/variables3.rs" },
{ name = "variables3_sol", path = "../solutions/01_variables/variables3.rs" },
{ name = "variables4", path = "../exercises/01_variables/variables4.rs" },
{ name = "variables4_sol", path = "../solutions/01_variables/variables4.rs" },
{ name = "variables5", path = "../exercises/01_variables/variables5.rs" },
{ name = "variables5_sol", path = "../solutions/01_variables/variables5.rs" },
{ name = "variables6", path = "../exercises/01_variables/variables6.rs" },
{ name = "variables6_sol", path = "../solutions/01_variables/variables6.rs" },
{ name = "functions1", path = "../exercises/02_functions/functions1.rs" },
{ name = "functions1_sol", path = "../solutions/02_functions/functions1.rs" },
{ name = "functions2", path = "../exercises/02_functions/functions2.rs" },
{ name = "functions2_sol", path = "../solutions/02_functions/functions2.rs" },
{ name = "functions3", path = "../exercises/02_functions/functions3.rs" },
{ name = "functions3_sol", path = "../solutions/02_functions/functions3.rs" },
{ name = "functions4", path = "../exercises/02_functions/functions4.rs" },
{ name = "functions4_sol", path = "../solutions/02_functions/functions4.rs" },
{ name = "functions5", path = "../exercises/02_functions/functions5.rs" },
{ name = "functions5_sol", path = "../solutions/02_functions/functions5.rs" },
{ name = "if1", path = "../exercises/03_if/if1.rs" },
{ name = "if1_sol", path = "../solutions/03_if/if1.rs" },
{ name = "if2", path = "../exercises/03_if/if2.rs" },
{ name = "if2_sol", path = "../solutions/03_if/if2.rs" },
{ name = "if3", path = "../exercises/03_if/if3.rs" },
{ name = "if3_sol", path = "../solutions/03_if/if3.rs" },
{ name = "quiz1", path = "../exercises/quizzes/quiz1.rs" },
{ name = "quiz1_sol", path = "../solutions/quizzes/quiz1.rs" },
{ name = "primitive_types1", path = "../exercises/04_primitive_types/primitive_types1.rs" },
{ name = "primitive_types1_sol", path = "../solutions/04_primitive_types/primitive_types1.rs" },
{ name = "primitive_types2", path = "../exercises/04_primitive_types/primitive_types2.rs" },
{ name = "primitive_types2_sol", path = "../solutions/04_primitive_types/primitive_types2.rs" },
{ name = "primitive_types3", path = "../exercises/04_primitive_types/primitive_types3.rs" },
{ name = "primitive_types3_sol", path = "../solutions/04_primitive_types/primitive_types3.rs" },
{ name = "primitive_types4", path = "../exercises/04_primitive_types/primitive_types4.rs" },
{ name = "primitive_types4_sol", path = "../solutions/04_primitive_types/primitive_types4.rs" },
{ name = "primitive_types5", path = "../exercises/04_primitive_types/primitive_types5.rs" },
{ name = "primitive_types5_sol", path = "../solutions/04_primitive_types/primitive_types5.rs" },
{ name = "primitive_types6", path = "../exercises/04_primitive_types/primitive_types6.rs" },
{ name = "primitive_types6_sol", path = "../solutions/04_primitive_types/primitive_types6.rs" },
{ name = "vecs1", path = "../exercises/05_vecs/vecs1.rs" },
{ name = "vecs1_sol", path = "../solutions/05_vecs/vecs1.rs" },
{ name = "vecs2", path = "../exercises/05_vecs/vecs2.rs" },
{ name = "vecs2_sol", path = "../solutions/05_vecs/vecs2.rs" },
{ name = "move_semantics1", path = "../exercises/06_move_semantics/move_semantics1.rs" },
{ name = "move_semantics1_sol", path = "../solutions/06_move_semantics/move_semantics1.rs" },
{ name = "move_semantics2", path = "../exercises/06_move_semantics/move_semantics2.rs" },
{ name = "move_semantics2_sol", path = "../solutions/06_move_semantics/move_semantics2.rs" },
{ name = "move_semantics3", path = "../exercises/06_move_semantics/move_semantics3.rs" },
{ name = "move_semantics3_sol", path = "../solutions/06_move_semantics/move_semantics3.rs" },
{ name = "move_semantics4", path = "../exercises/06_move_semantics/move_semantics4.rs" },
{ name = "move_semantics4_sol", path = "../solutions/06_move_semantics/move_semantics4.rs" },
{ name = "move_semantics5", path = "../exercises/06_move_semantics/move_semantics5.rs" },
{ name = "move_semantics5_sol", path = "../solutions/06_move_semantics/move_semantics5.rs" },
{ name = "structs1", path = "../exercises/07_structs/structs1.rs" },
{ name = "structs1_sol", path = "../solutions/07_structs/structs1.rs" },
{ name = "structs2", path = "../exercises/07_structs/structs2.rs" },
{ name = "structs2_sol", path = "../solutions/07_structs/structs2.rs" },
{ name = "structs3", path = "../exercises/07_structs/structs3.rs" },
{ name = "structs3_sol", path = "../solutions/07_structs/structs3.rs" },
{ name = "enums1", path = "../exercises/08_enums/enums1.rs" },
{ name = "enums1_sol", path = "../solutions/08_enums/enums1.rs" },
{ name = "enums2", path = "../exercises/08_enums/enums2.rs" },
{ name = "enums2_sol", path = "../solutions/08_enums/enums2.rs" },
{ name = "enums3", path = "../exercises/08_enums/enums3.rs" },
{ name = "enums3_sol", path = "../solutions/08_enums/enums3.rs" },
{ name = "strings1", path = "../exercises/09_strings/strings1.rs" },
{ name = "strings1_sol", path = "../solutions/09_strings/strings1.rs" },
{ name = "strings2", path = "../exercises/09_strings/strings2.rs" },
{ name = "strings2_sol", path = "../solutions/09_strings/strings2.rs" },
{ name = "strings3", path = "../exercises/09_strings/strings3.rs" },
{ name = "strings3_sol", path = "../solutions/09_strings/strings3.rs" },
{ name = "strings4", path = "../exercises/09_strings/strings4.rs" },
{ name = "strings4_sol", path = "../solutions/09_strings/strings4.rs" },
{ name = "modules1", path = "../exercises/10_modules/modules1.rs" },
{ name = "modules1_sol", path = "../solutions/10_modules/modules1.rs" },
{ name = "modules2", path = "../exercises/10_modules/modules2.rs" },
{ name = "modules2_sol", path = "../solutions/10_modules/modules2.rs" },
{ name = "modules3", path = "../exercises/10_modules/modules3.rs" },
{ name = "modules3_sol", path = "../solutions/10_modules/modules3.rs" },
{ name = "hashmaps1", path = "../exercises/11_hashmaps/hashmaps1.rs" },
{ name = "hashmaps1_sol", path = "../solutions/11_hashmaps/hashmaps1.rs" },
{ name = "hashmaps2", path = "../exercises/11_hashmaps/hashmaps2.rs" },
{ name = "hashmaps2_sol", path = "../solutions/11_hashmaps/hashmaps2.rs" },
{ name = "hashmaps3", path = "../exercises/11_hashmaps/hashmaps3.rs" },
{ name = "hashmaps3_sol", path = "../solutions/11_hashmaps/hashmaps3.rs" },
{ name = "quiz2", path = "../exercises/quizzes/quiz2.rs" },
{ name = "quiz2_sol", path = "../solutions/quizzes/quiz2.rs" },
{ name = "options1", path = "../exercises/12_options/options1.rs" },
{ name = "options1_sol", path = "../solutions/12_options/options1.rs" },
{ name = "options2", path = "../exercises/12_options/options2.rs" },
{ name = "options2_sol", path = "../solutions/12_options/options2.rs" },
{ name = "options3", path = "../exercises/12_options/options3.rs" },
{ name = "options3_sol", path = "../solutions/12_options/options3.rs" },
{ name = "errors1", path = "../exercises/13_error_handling/errors1.rs" },
{ name = "errors1_sol", path = "../solutions/13_error_handling/errors1.rs" },
{ name = "errors2", path = "../exercises/13_error_handling/errors2.rs" },
{ name = "errors2_sol", path = "../solutions/13_error_handling/errors2.rs" },
{ name = "errors3", path = "../exercises/13_error_handling/errors3.rs" },
{ name = "errors3_sol", path = "../solutions/13_error_handling/errors3.rs" },
{ name = "errors4", path = "../exercises/13_error_handling/errors4.rs" },
{ name = "errors4_sol", path = "../solutions/13_error_handling/errors4.rs" },
{ name = "errors5", path = "../exercises/13_error_handling/errors5.rs" },
{ name = "errors5_sol", path = "../solutions/13_error_handling/errors5.rs" },
{ name = "errors6", path = "../exercises/13_error_handling/errors6.rs" },
{ name = "errors6_sol", path = "../solutions/13_error_handling/errors6.rs" },
{ name = "generics1", path = "../exercises/14_generics/generics1.rs" },
{ name = "generics1_sol", path = "../solutions/14_generics/generics1.rs" },
{ name = "generics2", path = "../exercises/14_generics/generics2.rs" },
{ name = "generics2_sol", path = "../solutions/14_generics/generics2.rs" },
{ name = "traits1", path = "../exercises/15_traits/traits1.rs" },
{ name = "traits1_sol", path = "../solutions/15_traits/traits1.rs" },
{ name = "traits2", path = "../exercises/15_traits/traits2.rs" },
{ name = "traits2_sol", path = "../solutions/15_traits/traits2.rs" },
{ name = "traits3", path = "../exercises/15_traits/traits3.rs" },
{ name = "traits3_sol", path = "../solutions/15_traits/traits3.rs" },
{ name = "traits4", path = "../exercises/15_traits/traits4.rs" },
{ name = "traits4_sol", path = "../solutions/15_traits/traits4.rs" },
{ name = "traits5", path = "../exercises/15_traits/traits5.rs" },
{ name = "traits5_sol", path = "../solutions/15_traits/traits5.rs" },
{ name = "quiz3", path = "../exercises/quizzes/quiz3.rs" },
{ name = "quiz3_sol", path = "../solutions/quizzes/quiz3.rs" },
{ name = "lifetimes1", path = "../exercises/16_lifetimes/lifetimes1.rs" },
{ name = "lifetimes1_sol", path = "../solutions/16_lifetimes/lifetimes1.rs" },
{ name = "lifetimes2", path = "../exercises/16_lifetimes/lifetimes2.rs" },
{ name = "lifetimes2_sol", path = "../solutions/16_lifetimes/lifetimes2.rs" },
{ name = "lifetimes3", path = "../exercises/16_lifetimes/lifetimes3.rs" },
{ name = "lifetimes3_sol", path = "../solutions/16_lifetimes/lifetimes3.rs" },
{ name = "tests1", path = "../exercises/17_tests/tests1.rs" },
{ name = "tests1_sol", path = "../solutions/17_tests/tests1.rs" },
{ name = "tests2", path = "../exercises/17_tests/tests2.rs" },
{ name = "tests2_sol", path = "../solutions/17_tests/tests2.rs" },
{ name = "tests3", path = "../exercises/17_tests/tests3.rs" },
{ name = "tests3_sol", path = "../solutions/17_tests/tests3.rs" },
{ name = "iterators1", path = "../exercises/18_iterators/iterators1.rs" },
{ name = "iterators1_sol", path = "../solutions/18_iterators/iterators1.rs" },
{ name = "iterators2", path = "../exercises/18_iterators/iterators2.rs" },
{ name = "iterators2_sol", path = "../solutions/18_iterators/iterators2.rs" },
{ name = "iterators3", path = "../exercises/18_iterators/iterators3.rs" },
{ name = "iterators3_sol", path = "../solutions/18_iterators/iterators3.rs" },
{ name = "iterators4", path = "../exercises/18_iterators/iterators4.rs" },
{ name = "iterators4_sol", path = "../solutions/18_iterators/iterators4.rs" },
{ name = "iterators5", path = "../exercises/18_iterators/iterators5.rs" },
{ name = "iterators5_sol", path = "../solutions/18_iterators/iterators5.rs" },
{ name = "box1", path = "../exercises/19_smart_pointers/box1.rs" },
{ name = "box1_sol", path = "../solutions/19_smart_pointers/box1.rs" },
{ name = "rc1", path = "../exercises/19_smart_pointers/rc1.rs" },
{ name = "rc1_sol", path = "../solutions/19_smart_pointers/rc1.rs" },
{ name = "arc1", path = "../exercises/19_smart_pointers/arc1.rs" },
{ name = "arc1_sol", path = "../solutions/19_smart_pointers/arc1.rs" },
{ name = "cow1", path = "../exercises/19_smart_pointers/cow1.rs" },
{ name = "cow1_sol", path = "../solutions/19_smart_pointers/cow1.rs" },
{ name = "threads1", path = "../exercises/20_threads/threads1.rs" },
{ name = "threads1_sol", path = "../solutions/20_threads/threads1.rs" },
{ name = "threads2", path = "../exercises/20_threads/threads2.rs" },
{ name = "threads2_sol", path = "../solutions/20_threads/threads2.rs" },
{ name = "threads3", path = "../exercises/20_threads/threads3.rs" },
{ name = "threads3_sol", path = "../solutions/20_threads/threads3.rs" },
{ name = "macros1", path = "../exercises/21_macros/macros1.rs" },
{ name = "macros1_sol", path = "../solutions/21_macros/macros1.rs" },
{ name = "macros2", path = "../exercises/21_macros/macros2.rs" },
{ name = "macros2_sol", path = "../solutions/21_macros/macros2.rs" },
{ name = "macros3", path = "../exercises/21_macros/macros3.rs" },
{ name = "macros3_sol", path = "../solutions/21_macros/macros3.rs" },
{ name = "macros4", path = "../exercises/21_macros/macros4.rs" },
{ name = "macros4_sol", path = "../solutions/21_macros/macros4.rs" },
{ name = "clippy1", path = "../exercises/22_clippy/clippy1.rs" },
{ name = "clippy1_sol", path = "../solutions/22_clippy/clippy1.rs" },
{ name = "clippy2", path = "../exercises/22_clippy/clippy2.rs" },
{ name = "clippy2_sol", path = "../solutions/22_clippy/clippy2.rs" },
{ name = "clippy3", path = "../exercises/22_clippy/clippy3.rs" },
{ name = "clippy3_sol", path = "../solutions/22_clippy/clippy3.rs" },
{ name = "using_as", path = "../exercises/23_conversions/using_as.rs" },
{ name = "using_as_sol", path = "../solutions/23_conversions/using_as.rs" },
{ name = "from_into", path = "../exercises/23_conversions/from_into.rs" },
{ name = "from_into_sol", path = "../solutions/23_conversions/from_into.rs" },
{ name = "from_str", path = "../exercises/23_conversions/from_str.rs" },
{ name = "from_str_sol", path = "../solutions/23_conversions/from_str.rs" },
{ name = "try_from_into", path = "../exercises/23_conversions/try_from_into.rs" },
{ name = "try_from_into_sol", path = "../solutions/23_conversions/try_from_into.rs" },
{ name = "as_ref_mut", path = "../exercises/23_conversions/as_ref_mut.rs" },
{ name = "as_ref_mut_sol", path = "../solutions/23_conversions/as_ref_mut.rs" },
]
[package]
name = "exercises"
edition = "2021"
# Don't publish the exercises on crates.io!
publish = false

1
dev/rustlings-repo.txt Normal file
View file

@ -0,0 +1 @@
This file is used to check if the user tries to run Rustlings in the repository (the method before v6)

View file

@ -1,19 +1,10 @@
// intro1.rs
// TODO: We sometimes encourage you to keep trying things on a given exercise,
// even after you already figured it out. If you got everything working and feel
// ready for the next exercise, enter `n` in the terminal.
//
// 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.
//
// 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
// The exercise file will be reloaded when you change one of the lines below!
// Try adding a new `println!`.
// Try removing a semicolon and see what happens in the terminal!
fn main() {
println!("Hello and");
@ -29,13 +20,7 @@ fn main() {
println!("or logic error. The central concept behind Rustlings is to fix these errors and");
println!("solve the exercises. Good luck!");
println!();
println!("The source for this exercise is in `exercises/00_intro/intro1.rs`. Have a look!");
println!(
"Going forward, the source of the exercises will always be in the success/failure output."
);
println!();
println!(
"If you want to use rust-analyzer, Rust's LSP implementation, make sure your editor is set"
);
println!("up, and then run `rustlings lsp` before continuing.")
println!("The file of this exercise is `exercises/00_intro/intro1.rs`. Have a look!");
println!("The current exercise path will be always shown under the progress bar.");
println!("You can click on the path to open the exercise file in your editor.");
}

View file

@ -1,12 +1,4 @@
// intro2.rs
//
// Make the code print a greeting to the world.
//
// Execute `rustlings hint intro2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
printline!("Hello there!")
// TODO: Fix the code to print "Hello world!".
printline!("Hello world!");
}

View file

@ -1,13 +1,6 @@
// variables1.rs
//
// Make me compile!
//
// Execute `rustlings hint variables1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
// TODO: Add missing keyword.
x = 5;
println!("x has the value {}", x);
println!("x has the value {x}");
}

View file

@ -1,12 +1,7 @@
// variables2.rs
//
// Execute `rustlings hint variables2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
// TODO: Change the line below to fix the compiler error.
let x;
if x == 10 {
println!("x is ten!");
} else {

View file

@ -1,11 +1,6 @@
// variables3.rs
//
// Execute `rustlings hint variables3` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
// TODO: Change the line below to fix the compiler error.
let x: i32;
println!("Number {}", x);
println!("Number {x}");
}

View file

@ -1,13 +1,8 @@
// variables4.rs
//
// Execute `rustlings hint variables4` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
// TODO: Fix the compiler error.
fn main() {
let x = 3;
println!("Number {}", x);
x = 5; // don't change this line
println!("Number {}", x);
println!("Number {x}");
x = 5; // Don't change this line
println!("Number {x}");
}

View file

@ -1,13 +1,8 @@
// variables5.rs
//
// Execute `rustlings hint variables5` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
let number = "T-H-R-E-E"; // don't change this line
println!("Spell a Number : {}", number);
number = 3; // don't rename this variable
let number = "T-H-R-E-E"; // Don't change this line
println!("Spell a number: {}", number);
// TODO: Fix the compiler error by changing the line below without renaming the variable.
number = 3;
println!("Number plus two is: {}", number + 2);
}

View file

@ -1,11 +1,6 @@
// variables6.rs
//
// Execute `rustlings hint variables6` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
// TODO: Change the line below to fix the compiler error.
const NUMBER = 3;
fn main() {
println!("Number {}", NUMBER);
println!("Number: {NUMBER}");
}

View file

@ -1,10 +1,5 @@
// functions1.rs
//
// Execute `rustlings hint functions1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
// TODO: Add some function with the name `call_me` without arguments or a return value.
fn main() {
call_me();
call_me(); // Don't change this line
}

View file

@ -1,16 +1,10 @@
// functions2.rs
//
// Execute `rustlings hint functions2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
call_me(3);
}
// TODO: Add the missing type of the argument `num` after the colon `:`.
fn call_me(num:) {
for i in 0..num {
println!("Ring! Call number {}", i + 1);
}
}
fn main() {
call_me(3);
}

View file

@ -1,16 +1,10 @@
// functions3.rs
//
// Execute `rustlings hint functions3` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
call_me();
}
fn call_me(num: u32) {
for i in 0..num {
println!("Ring! Call number {}", i + 1);
}
}
fn main() {
// TODO: Fix the function call.
call_me();
}

View file

@ -1,21 +1,14 @@
// functions4.rs
//
// 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.
// Rustbucks off, but if it's an odd number, it's 3 Rustbucks off.
// Don't worry about the function bodies themselves, we are only interested in
// the signatures for now.
// I AM NOT DONE
fn main() {
let original_price = 51;
println!("Your sale price is {}", sale_price(original_price));
fn is_even(num: i64) -> bool {
num % 2 == 0
}
fn sale_price(price: i32) -> {
// TODO: Fix the function signature.
fn sale_price(price: i64) -> {
if is_even(price) {
price - 10
} else {
@ -23,6 +16,7 @@ fn sale_price(price: i32) -> {
}
}
fn is_even(num: i32) -> bool {
num % 2 == 0
fn main() {
let original_price = 51;
println!("Your sale price is {}", sale_price(original_price));
}

View file

@ -1,15 +1,9 @@
// functions5.rs
//
// Execute `rustlings hint functions5` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
let answer = square(3);
println!("The square of 3 is {}", answer);
}
// TODO: Fix the function body without changing the signature.
fn square(num: i32) -> i32 {
num * num;
}
fn main() {
let answer = square(3);
println!("The square of 3 is {answer}");
}

View file

@ -1,17 +1,15 @@
// if1.rs
//
// Execute `rustlings hint if1` or use the `hint` watch subcommand for a hint.
// I AM NOT DONE
pub fn bigger(a: i32, b: i32) -> i32 {
// Complete this function to return the bigger number!
fn bigger(a: i32, b: i32) -> i32 {
// TODO: Complete this function to return the bigger number!
// If both numbers are equal, any of them can be returned.
// Do not use:
// - another function call
// - additional variables
}
fn main() {
// You can optionally experiment here.
}
// Don't mind this for now :)
#[cfg(test)]
mod tests {

View file

@ -1,13 +1,5 @@
// 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
pub fn foo_if_fizz(fizzish: &str) -> &str {
// TODO: Fix the compiler error on this function.
fn foo_if_fizz(fizzish: &str) -> &str {
if fizzish == "fizz" {
"foo"
} else {
@ -15,23 +7,29 @@ pub fn foo_if_fizz(fizzish: &str) -> &str {
}
}
// No test changes needed!
fn main() {
// You can optionally experiment here.
}
// TODO: Read the tests to understand the desired behavior.
// Make all tests pass without changing them.
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn foo_for_fizz() {
assert_eq!(foo_if_fizz("fizz"), "foo")
// This means that calling `foo_if_fizz` with the argument "fizz" should return "foo".
assert_eq!(foo_if_fizz("fizz"), "foo");
}
#[test]
fn bar_for_fuzz() {
assert_eq!(foo_if_fizz("fuzz"), "bar")
assert_eq!(foo_if_fizz("fuzz"), "bar");
}
#[test]
fn default_to_baz() {
assert_eq!(foo_if_fizz("literally anything"), "baz")
assert_eq!(foo_if_fizz("literally anything"), "baz");
}
}

View file

@ -1,10 +1,5 @@
// 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 {
fn animal_habitat(animal: &str) -> &str {
// TODO: Fix the compiler error in the statement below.
let identifier = if animal == "crab" {
1
} else if animal == "gopher" {
@ -15,8 +10,8 @@ pub fn animal_habitat(animal: &str) -> &'static str {
"Unknown"
};
// DO NOT CHANGE THIS STATEMENT BELOW
let habitat = if identifier == 1 {
// Don't change the expression below!
if identifier == 1 {
"Beach"
} else if identifier == 2 {
"Burrow"
@ -24,12 +19,14 @@ pub fn animal_habitat(animal: &str) -> &'static str {
"Desert"
} else {
"Unknown"
};
habitat
}
}
// No test changes needed.
fn main() {
// You can optionally experiment here.
}
// Don't change the tests!
#[cfg(test)]
mod tests {
use super::*;

View file

@ -1,19 +1,14 @@
// 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 :)
// I AM NOT DONE
fn main() {
// Booleans (`bool`)
fn main() {
let is_morning = true;
if is_morning {
println!("Good morning!");
}
let // Finish the rest of this line like the example! Or make it be false!
// TODO: Define a boolean variable with the name `is_evening` before the `if` statement below.
// The value of the variable should be the negation (opposite) of `is_morning`.
// let …
if is_evening {
println!("Good evening!");
}

View file

@ -1,13 +1,6 @@
// 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 :)
// I AM NOT DONE
fn main() {
// Characters (`char`)
fn main() {
// Note the _single_ quotes, these are different from the double quotes
// you've been seeing around.
let my_first_initial = 'C';
@ -19,9 +12,12 @@ fn main() {
println!("Neither alphabetic nor numeric!");
}
let // Finish this line like the example! What's your favorite character?
// Try a letter, try a number, try a special character, try a character
// from a different language than your own, try an emoji!
// TODO: Analogous to the example before, declare a variable called `your_character`
// below with your favorite character.
// Try a letter, try a digit (in single quotes), try a special character, try a character
// from a different language than your own, try an emoji 😉
// let your_character = '';
if your_character.is_alphabetic() {
println!("Alphabetical!");
} else if your_character.is_numeric() {

View file

@ -1,19 +1,11 @@
// 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.
// I AM NOT DONE
fn main() {
let a = ???
// TODO: Create an array called `a` with at least 100 elements in it.
// let a = ???
if a.len() >= 100 {
println!("Wow, that's a big array!");
} else {
println!("Meh, I eat arrays like that for breakfast.");
panic!("Array not big enough, more elements needed")
panic!("Array not big enough, more elements needed");
}
}

View file

@ -1,17 +1,16 @@
// 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.
// I AM NOT DONE
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
#[test]
fn slice_out_of_array() {
let a = [1, 2, 3, 4, 5];
let nice_slice = ???
// TODO: Get a slice called `nice_slice` out of the array `a` so that the test passes.
// let nice_slice = ???
assert_eq!([2, 3, 4], nice_slice)
assert_eq!([2, 3, 4], nice_slice);
}
}

View file

@ -1,15 +1,8 @@
// 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.
// I AM NOT DONE
fn main() {
let cat = ("Furry McFurson", 3.5);
let /* your pattern here */ = cat;
println!("{} is {} years old.", name, age);
// TODO: Destructure the `cat` tuple in one statement so that the println works.
// let /* your pattern here */ = cat;
println!("{name} is {age} years old");
}

View file

@ -1,19 +1,17 @@
// 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.
// I AM NOT DONE
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
#[test]
fn indexing_tuple() {
let numbers = (1, 2, 3);
// Replace below ??? with the tuple indexing syntax.
let second = ???;
assert_eq!(2, second,
"This is not the 2nd number in the tuple!")
// TODO: Use a tuple index to access the second element of `numbers`
// and assign it to a variable called `second`.
// let second = ???;
assert_eq!(second, 2, "This is not the 2nd number in the tuple!");
}
}

View file

@ -1,21 +1,17 @@
// vecs1.rs
//
// 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
fn array_and_vec() -> ([i32; 4], Vec<i32>) {
let a = [10, 20, 30, 40]; // a plain array
let v = // TODO: declare your vector here with the macro for vectors
let a = [10, 20, 30, 40]; // Array
// TODO: Create a vector called `v` which contains the exact same elements as in the array `a`.
// Use the vector macro.
// let v = ???;
(a, v)
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
@ -23,6 +19,6 @@ mod tests {
#[test]
fn test_array_and_vec_similarity() {
let (a, v) = array_and_vec();
assert_eq!(a, v[..]);
assert_eq!(a, *v);
}
}

View file

@ -1,31 +1,36 @@
// 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.
//
// Make me pass the test!
//
// Execute `rustlings hint vecs2` or use the `hint` watch subcommand for a hint.
fn vec_loop(input: &[i32]) -> Vec<i32> {
let mut output = Vec::new();
// I AM NOT DONE
fn vec_loop(mut v: Vec<i32>) -> Vec<i32> {
for element in v.iter_mut() {
// TODO: Fill this up so that each element in the Vec `v` is
// multiplied by 2.
???
for element in input {
// TODO: Multiply each element in the `input` slice by 2 and push it to
// the `output` vector.
}
// At this point, `v` should be equal to [4, 8, 12, 16, 20].
v
output
}
fn vec_map(v: &Vec<i32>) -> Vec<i32> {
v.iter().map(|element| {
// TODO: Do the same thing as above - but instead of mutating the
// Vec, you can just return the new number!
???
}).collect()
fn vec_map_example(input: &[i32]) -> Vec<i32> {
// An example of collecting a vector after mapping.
// We map each element of the `input` slice to its value plus 1.
// If the input is `[1, 2, 3]`, the output is `[2, 3, 4]`.
input.iter().map(|element| element + 1).collect()
}
fn vec_map(input: &[i32]) -> Vec<i32> {
// TODO: Here, we also want to multiply each element in the `input` slice
// by 2, but with iterator mapping instead of manually pushing into an empty
// vector.
// See the example in the function `vec_map_example` above.
input
.iter()
.map(|element| {
// ???
})
.collect()
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
@ -34,17 +39,22 @@ mod tests {
#[test]
fn test_vec_loop() {
let v: Vec<i32> = (1..).filter(|x| x % 2 == 0).take(5).collect();
let ans = vec_loop(v.clone());
let input = [2, 4, 6, 8, 10];
let ans = vec_loop(&input);
assert_eq!(ans, [4, 8, 12, 16, 20]);
}
assert_eq!(ans, v.iter().map(|x| x * 2).collect::<Vec<i32>>());
#[test]
fn test_vec_map_example() {
let input = [1, 2, 3];
let ans = vec_map_example(&input);
assert_eq!(ans, [2, 3, 4]);
}
#[test]
fn test_vec_map() {
let v: Vec<i32> = (1..).filter(|x| x % 2 == 0).take(5).collect();
let ans = vec_map(&v);
assert_eq!(ans, v.iter().map(|x| x * 2).collect::<Vec<i32>>());
let input = [2, 4, 6, 8, 10];
let ans = vec_map(&input);
assert_eq!(ans, [4, 8, 12, 16, 20]);
}
}

View file

@ -1,19 +1,4 @@
// move_semantics1.rs
//
// Execute `rustlings hint move_semantics1` or use the `hint` watch subcommand
// for a hint.
// I AM NOT DONE
#[test]
fn main() {
let vec0 = vec![22, 44, 66];
let vec1 = fill_vec(vec0);
assert_eq!(vec1, vec![22, 44, 66, 88]);
}
// TODO: Fix the compiler error in this function.
fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
let vec = vec;
@ -21,3 +6,19 @@ fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
vec
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn move_semantics1() {
let vec0 = vec![22, 44, 66];
let vec1 = fill_vec(vec0);
assert_eq!(vec1, vec![22, 44, 66, 88]);
}
}

View file

@ -1,22 +1,3 @@
// move_semantics2.rs
//
// 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![22, 44, 66];
let vec1 = fill_vec(vec0);
assert_eq!(vec0, vec![22, 44, 66]);
assert_eq!(vec1, vec![22, 44, 66, 88]);
}
fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
let mut vec = vec;
@ -24,3 +5,24 @@ fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
vec
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
// TODO: Make both vectors `vec0` and `vec1` accessible at the same time to
// fix the compiler error in the test.
#[test]
fn move_semantics2() {
let vec0 = vec![22, 44, 66];
let vec1 = fill_vec(vec0);
assert_eq!(vec0, [22, 44, 66]);
assert_eq!(vec1, [22, 44, 66, 88]);
}
}

View file

@ -1,24 +1,22 @@
// 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.
// I AM NOT DONE
#[test]
fn main() {
let vec0 = vec![22, 44, 66];
let vec1 = fill_vec(vec0);
assert_eq!(vec1, vec![22, 44, 66, 88]);
}
// TODO: Fix the compiler error in the function without adding any new line.
fn fill_vec(vec: Vec<i32>) -> Vec<i32> {
vec.push(88);
vec
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn move_semantics3() {
let vec0 = vec![22, 44, 66];
let vec1 = fill_vec(vec0);
assert_eq!(vec1, [22, 44, 66, 88]);
}
}

View file

@ -1,29 +1,18 @@
// 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.
// I AM NOT DONE
#[test]
fn main() {
let vec0 = vec![22, 44, 66];
let vec1 = fill_vec(vec0);
assert_eq!(vec1, vec![22, 44, 66, 88]);
// You can optionally experiment here.
}
// `fill_vec()` no longer takes `vec: Vec<i32>` as argument - don't change this!
fn fill_vec() -> Vec<i32> {
// Instead, let's create and fill the Vec in here - how do you do that?
let mut vec = vec;
vec.push(88);
vec
#[cfg(test)]
mod tests {
// TODO: Fix the compiler errors only by reordering the lines in the test.
// Don't add, change or remove any line.
#[test]
fn move_semantics5() {
let mut x = 100;
let y = &mut x;
let z = &mut x;
*y += 100;
*z += 1000;
assert_eq!(x, 1200);
}
}

View file

@ -1,19 +1,22 @@
// 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.
// TODO: Fix the compiler errors without changing anything except adding or
// removing references (the character `&`).
// I AM NOT DONE
#[test]
fn main() {
let mut x = 100;
let y = &mut x;
let z = &mut x;
*y += 100;
*z += 1000;
assert_eq!(x, 1200);
let data = "Rust is great!".to_string();
get_char(data);
string_uppercase(&data);
}
// Shouldn't take ownership
fn get_char(data: String) -> char {
data.chars().last().unwrap()
}
// Should take ownership
fn string_uppercase(mut data: &String) {
data = &data.to_uppercase();
println!("{data}");
}

View file

@ -1,28 +0,0 @@
// move_semantics6.rs
//
// 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
fn main() {
let data = "Rust is great!".to_string();
get_char(data);
string_uppercase(&data);
}
// Should not take ownership
fn get_char(data: String) -> char {
data.chars().last().unwrap()
}
// Should take ownership
fn string_uppercase(mut data: &String) {
data = &data.to_uppercase();
println!("{}", data);
}

View file

@ -1,28 +1,24 @@
// structs1.rs
//
// Address all the TODOs to make the tests pass!
//
// Execute `rustlings hint structs1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
struct ColorClassicStruct {
// TODO: Something goes here
struct ColorRegularStruct {
// TODO: Add the fields that the test `regular_structs` expects.
// What types should the fields have? What are the minimum and maximum values for RGB colors?
}
struct ColorTupleStruct(/* TODO: Something goes here */);
struct ColorTupleStruct(/* TODO: Add the fields that the test `tuple_structs` expects */);
#[derive(Debug)]
struct UnitLikeStruct;
struct UnitStruct;
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn classic_c_structs() {
// TODO: Instantiate a classic c struct!
fn regular_structs() {
// TODO: Instantiate a regular struct.
// let green =
assert_eq!(green.red, 0);
@ -32,7 +28,7 @@ mod tests {
#[test]
fn tuple_structs() {
// TODO: Instantiate a tuple struct!
// TODO: Instantiate a tuple struct.
// let green =
assert_eq!(green.0, 0);
@ -42,10 +38,10 @@ mod tests {
#[test]
fn unit_structs() {
// TODO: Instantiate a unit-like struct!
// let unit_like_struct =
let message = format!("{:?}s are fun!", unit_like_struct);
// TODO: Instantiate a unit struct.
// let unit_struct =
let message = format!("{unit_struct:?}s are fun!");
assert_eq!(message, "UnitLikeStructs are fun!");
assert_eq!(message, "UnitStructs are fun!");
}
}

View file

@ -1,12 +1,3 @@
// structs2.rs
//
// Address all the TODOs to make the tests pass!
//
// Execute `rustlings hint structs2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
#[derive(Debug)]
struct Order {
name: String,
@ -30,6 +21,10 @@ fn create_order_template() -> Order {
}
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
@ -37,8 +32,10 @@ mod tests {
#[test]
fn your_order() {
let order_template = create_order_template();
// TODO: Create your own order using the update syntax and template above!
// let your_order =
assert_eq!(your_order.name, "Hacker in Rust");
assert_eq!(your_order.year, order_template.year);
assert_eq!(your_order.made_by_phone, order_template.made_by_phone);

View file

@ -1,13 +1,5 @@
// 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.
// I AM NOT DONE
// defined the `Package` struct and we want to test some logic attached to it.
#[derive(Debug)]
struct Package {
@ -17,27 +9,34 @@ struct Package {
}
impl Package {
fn new(sender_country: String, recipient_country: String, weight_in_grams: u32) -> Package {
fn new(sender_country: String, recipient_country: String, weight_in_grams: u32) -> Self {
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 {
// This isn't how you should handle errors in Rust, but we will
// learn about error handling later.
panic!("Can't ship a package with weight below 10 grams");
}
Self {
sender_country,
recipient_country,
weight_in_grams,
}
}
// TODO: Add the correct return type to the function signature.
fn is_international(&self) {
// TODO: Read the tests that use this method to find out when a package
// is considered international.
}
fn is_international(&self) -> ??? {
// Something goes here...
// TODO: Add the correct return type to the function signature.
fn get_fees(&self, cents_per_gram: u32) {
// TODO: Calculate the package's fees.
}
}
fn get_fees(&self, cents_per_gram: u32) -> ??? {
// Something goes here...
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]

View file

@ -1,12 +1,6 @@
// enums1.rs
//
// No hints this time! ;)
// I AM NOT DONE
#[derive(Debug)]
enum Message {
// TODO: define a few types of messages as used below
// TODO: Define a few types of messages as used below.
}
fn main() {

View file

@ -1,13 +1,6 @@
// enums2.rs
//
// Execute `rustlings hint enums2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
#[derive(Debug)]
enum Message {
// TODO: define the different variants used below
// TODO: Define the different variants used below.
}
impl Message {

View file

@ -1,14 +1,5 @@
// enums3.rs
//
// Address all the TODOs to make the tests pass!
//
// Execute `rustlings hint enums3` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
enum Message {
// TODO: implement the message variant types based on their usage below
// TODO: Implement the message variant types based on their usage below.
}
struct Point {
@ -33,20 +24,24 @@ impl State {
}
fn echo(&mut self, s: String) {
self.message = s
self.message = s;
}
fn move_position(&mut self, p: Point) {
self.position = p;
fn move_position(&mut self, point: Point) {
self.position = point;
}
fn process(&mut self, message: Message) {
// TODO: create a match expression to process the different message variants
// 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))
// e.g. `foo((t, u, p, l, e))`
}
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
@ -57,8 +52,9 @@ mod tests {
quit: false,
position: Point { x: 0, y: 0 },
color: (0, 0, 0),
message: "hello world".to_string(),
message: String::from("hello world"),
};
state.process(Message::ChangeColor(255, 0, 255));
state.process(Message::Echo(String::from("Hello world!")));
state.process(Message::Move(Point { x: 10, y: 15 }));
@ -67,7 +63,7 @@ mod tests {
assert_eq!(state.color, (255, 0, 255));
assert_eq!(state.position.x, 10);
assert_eq!(state.position.y, 15);
assert_eq!(state.quit, true);
assert!(state.quit);
assert_eq!(state.message, "Hello world!");
}
}

View file

@ -1,17 +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.
// I AM NOT DONE
fn main() {
let answer = current_favorite_color();
println!("My current favorite color is {}", answer);
}
// TODO: Fix the compiler error without changing the function signature.
fn current_favorite_color() -> String {
"blue"
}
fn main() {
let answer = current_favorite_color();
println!("My current favorite color is {answer}");
}

View file

@ -1,21 +1,14 @@
// strings2.rs
//
// Make me compile without changing the function signature!
//
// Execute `rustlings hint strings2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
// TODO: Fix the compiler error in the `main` function without changing this function.
fn is_a_color_word(attempt: &str) -> bool {
attempt == "green" || attempt == "blue" || attempt == "red"
}
fn main() {
let word = String::from("green"); // Try not changing this line :)
let word = String::from("green"); // Don't change this line.
if is_a_color_word(word) {
println!("That is a color word I know!");
} else {
println!("That is not a color word I know.");
}
}
fn is_a_color_word(attempt: &str) -> bool {
attempt == "green" || attempt == "blue" || attempt == "red"
}

View file

@ -1,23 +1,17 @@
// strings3.rs
//
// Execute `rustlings hint strings3` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn trim_me(input: &str) -> String {
// TODO: Remove whitespace from both ends of a string!
???
fn trim_me(input: &str) -> &str {
// TODO: Remove whitespace from both ends of a string.
}
fn compose_me(input: &str) -> String {
// TODO: Add " world!" to the string! There are multiple ways to do this!
???
// TODO: Add " world!" to the string! There are multiple ways to do this.
}
fn replace_me(input: &str) -> String {
// TODO: Replace "cars" in the string with "balloons"!
???
// TODO: Replace "cars" in the string with "balloons".
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
@ -39,7 +33,13 @@ mod tests {
#[test]
fn replace_a_string() {
assert_eq!(replace_me("I think cars are cool"), "I think balloons are cool");
assert_eq!(replace_me("I love to look at cars"), "I love to look at balloons");
assert_eq!(
replace_me("I think cars are cool"),
"I think balloons are cool",
);
assert_eq!(
replace_me("I love to look at cars"),
"I love to look at balloons",
);
}
}

View file

@ -1,30 +1,36 @@
// 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
// Calls of this function should be replaced with calls of `string_slice` or `string`.
fn placeholder() {}
fn string_slice(arg: &str) {
println!("{}", arg);
println!("{arg}");
}
fn string(arg: String) {
println!("{}", arg);
println!("{arg}");
}
// TODO: Here are a bunch of values - some are `String`, some are `&str`.
// Your task is to replace `placeholder(…)` with either `string_slice(…)`
// or `string(…)` depending on what you think each value is.
fn main() {
???("blue");
???("red".to_string());
???(String::from("hi"));
???("rust is fun!".to_owned());
???("nice weather".into());
???(format!("Interpolation {}", "Station"));
???(&String::from("abc")[0..1]);
???(" hello there ".trim());
???("Happy Monday!".to_string().replace("Mon", "Tues"));
???("mY sHiFt KeY iS sTiCkY".to_lowercase());
placeholder("blue");
placeholder("red".to_string());
placeholder(String::from("hi"));
placeholder("rust is fun!".to_owned());
placeholder("nice weather".into());
placeholder(format!("Interpolation {}", "Station"));
// WARNING: This is byte indexing, not character indexing.
// Character indexing can be done using `s.chars().nth(INDEX)`.
placeholder(&String::from("abc")[0..1]);
placeholder(" hello there ".trim());
placeholder("Happy Monday!".replace("Mon", "Tues"));
placeholder("mY sHiFt KeY iS sTiCkY".to_lowercase());
}

View file

@ -1,10 +1,4 @@
// modules1.rs
//
// Execute `rustlings hint modules1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
// TODO: Fix the compiler error about calling a private function.
mod sausage_factory {
// Don't let anybody outside of this module see this!
fn get_secret_recipe() -> String {

View file

@ -1,27 +1,19 @@
// 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.
// I AM NOT DONE
// the `use` and `as` keywords.
mod delicious_snacks {
// TODO: Fix these use statements
use self::fruits::PEAR as ???
use self::veggies::CUCUMBER as ???
// TODO: Add the following two `use` statements after fixing them.
// use self::fruits::PEAR as ???;
// use self::veggies::CUCUMBER as ???;
mod fruits {
pub const PEAR: &'static str = "Pear";
pub const APPLE: &'static str = "Apple";
pub const PEAR: &str = "Pear";
pub const APPLE: &str = "Apple";
}
mod veggies {
pub const CUCUMBER: &'static str = "Cucumber";
pub const CARROT: &'static str = "Carrot";
pub const CUCUMBER: &str = "Cucumber";
pub const CARROT: &str = "Carrot";
}
}
@ -29,6 +21,6 @@ fn main() {
println!(
"favorite snacks: {} and {}",
delicious_snacks::fruit,
delicious_snacks::veggie
delicious_snacks::veggie,
);
}

View file

@ -1,17 +1,9 @@
// 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 standard library into your scope.
// I AM NOT DONE
// TODO: Complete this use statement
use ???
// TODO: Bring `SystemTime` and `UNIX_EPOCH` from the `std::time` module into
// your scope. Bonus style points if you can do it with one line!
// use ???;
fn main() {
match SystemTime::now().duration_since(UNIX_EPOCH) {

View file

@ -1,31 +1,27 @@
// 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
// particular fruit is in the basket. You have to put at least 3 different
// types of fruits (e.g. apple, banana, mango) in the basket and the total count
// 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.
// I AM NOT DONE
// of all the fruits should be at least 5.
use std::collections::HashMap;
fn fruit_basket() -> HashMap<String, u32> {
let mut basket = // TODO: declare your hash map here.
// TODO: Declare the hash map.
// let mut basket =
// Two bananas are already given for you :)
basket.insert(String::from("banana"), 2);
// TODO: Put more fruits in your basket here.
// TODO: Put more fruits in your basket.
basket
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;

View file

@ -1,5 +1,3 @@
// 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
@ -8,17 +6,10 @@
// 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.
// I AM NOT DONE
use std::collections::HashMap;
#[derive(Hash, PartialEq, Eq)]
#[derive(Hash, PartialEq, Eq, Debug)]
enum Fruit {
Apple,
Banana,
@ -28,7 +19,7 @@ enum Fruit {
}
fn fruit_basket(basket: &mut HashMap<Fruit, u32>) {
let fruit_kinds = vec![
let fruit_kinds = [
Fruit::Apple,
Fruit::Banana,
Fruit::Mango,
@ -43,18 +34,18 @@ fn fruit_basket(basket: &mut HashMap<Fruit, u32>) {
}
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
// Don't modify this function!
fn get_fruit_basket() -> HashMap<Fruit, u32> {
let mut basket = HashMap::<Fruit, u32>::new();
basket.insert(Fruit::Apple, 4);
basket.insert(Fruit::Mango, 2);
basket.insert(Fruit::Lychee, 5);
basket
let content = [(Fruit::Apple, 4), (Fruit::Mango, 2), (Fruit::Lychee, 5)];
HashMap::from_iter(content)
}
#[test]
@ -84,10 +75,22 @@ mod tests {
#[test]
fn all_fruit_types_in_basket() {
let fruit_kinds = [
Fruit::Apple,
Fruit::Banana,
Fruit::Mango,
Fruit::Lychee,
Fruit::Pineapple,
];
let mut basket = get_fruit_basket();
fruit_basket(&mut basket);
for amount in basket.values() {
assert_ne!(amount, &0);
for fruit_kind in fruit_kinds {
let Some(amount) = basket.get(&fruit_kind) else {
panic!("Fruit kind {fruit_kind:?} was not found in basket");
};
assert!(*amount > 0);
}
}
}

View file

@ -1,87 +1,77 @@
// hashmaps3.rs
//
// A list of scores (one per line) of a soccer match is given. Each line is of
// the form : "<team_1_name>,<team_2_name>,<team_1_goals>,<team_2_goals>"
// Example: England,France,4,2 (England scored 4 goals, France 2).
// the form "<team_1_name>,<team_2_name>,<team_1_goals>,<team_2_goals>"
// Example: "England,France,4,2" (England scored 4 goals, France 2).
//
// You have to build a scores table containing the name of the team, the total
// number of goals the team scored, and the total number of 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.
// I AM NOT DONE
// conceded.
use std::collections::HashMap;
// A structure to store the goal details of a team.
#[derive(Default)]
struct Team {
goals_scored: u8,
goals_conceded: u8,
}
fn build_scores_table(results: String) -> HashMap<String, Team> {
fn build_scores_table(results: &str) -> HashMap<&str, Team> {
// The name of the team is the key and its associated struct is the value.
let mut scores: HashMap<String, Team> = HashMap::new();
let mut scores = HashMap::new();
for r in results.lines() {
let v: Vec<&str> = r.split(',').collect();
let team_1_name = v[0].to_string();
let team_1_score: u8 = v[2].parse().unwrap();
let team_2_name = v[1].to_string();
let team_2_score: u8 = v[3].parse().unwrap();
// TODO: Populate the scores table with details extracted from the
// current line. Keep in mind that goals scored by team_1
// will be the number of goals conceded by team_2, and similarly
// goals scored by team_2 will be the number of goals conceded by
// team_1.
for line in results.lines() {
let mut split_iterator = line.split(',');
// NOTE: We use `unwrap` because we didn't deal with error handling yet.
let team_1_name = split_iterator.next().unwrap();
let team_2_name = split_iterator.next().unwrap();
let team_1_score: u8 = split_iterator.next().unwrap().parse().unwrap();
let team_2_score: u8 = split_iterator.next().unwrap().parse().unwrap();
// TODO: Populate the scores table with the extracted details.
// Keep in mind that goals scored by team 1 will be the number of goals
// conceded by team 2. Similarly, goals scored by team 2 will be the
// number of goals conceded by team 1.
}
scores
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
fn get_results() -> String {
let results = "".to_string()
+ "England,France,4,2\n"
+ "France,Italy,3,1\n"
+ "Poland,Spain,2,0\n"
+ "Germany,England,2,1\n";
results
}
const RESULTS: &str = "England,France,4,2
France,Italy,3,1
Poland,Spain,2,0
Germany,England,2,1
England,Spain,1,0";
#[test]
fn build_scores() {
let scores = build_scores_table(get_results());
let scores = build_scores_table(RESULTS);
let mut keys: Vec<&String> = scores.keys().collect();
keys.sort();
assert_eq!(
keys,
vec!["England", "France", "Germany", "Italy", "Poland", "Spain"]
);
assert!(["England", "France", "Germany", "Italy", "Poland", "Spain"]
.into_iter()
.all(|team_name| scores.contains_key(team_name)));
}
#[test]
fn validate_team_score_1() {
let scores = build_scores_table(get_results());
let scores = build_scores_table(RESULTS);
let team = scores.get("England").unwrap();
assert_eq!(team.goals_scored, 5);
assert_eq!(team.goals_scored, 6);
assert_eq!(team.goals_conceded, 4);
}
#[test]
fn validate_team_score_2() {
let scores = build_scores_table(get_results());
let scores = build_scores_table(RESULTS);
let team = scores.get("Spain").unwrap();
assert_eq!(team.goals_scored, 0);
assert_eq!(team.goals_conceded, 2);
assert_eq!(team.goals_conceded, 3);
}
}

View file

@ -1,25 +1,27 @@
// options1.rs
//
// Execute `rustlings hint options1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
// This function returns how much icecream there is left in the fridge.
// If it's before 10PM, there's 5 scoops left. At 10PM, someone eats it
// all, so there'll be no more left :(
fn maybe_icecream(time_of_day: u16) -> Option<u16> {
// 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!
???
// If it's before 22:00 (24-hour system), then 5 scoops are left. At 22:00,
// someone eats it all, so no icecream is left (value 0). Return `None` if
// `hour_of_day` is higher than 23.
fn maybe_icecream(hour_of_day: u16) -> Option<u16> {
// TODO: Complete the function body.
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn raw_value() {
// TODO: Fix this test. How do you get the value contained in the
// Option?
let icecreams = maybe_icecream(12);
assert_eq!(icecreams, 5);
}
#[test]
fn check_icecream() {
assert_eq!(maybe_icecream(0), Some(5));
@ -27,14 +29,7 @@ mod tests {
assert_eq!(maybe_icecream(18), Some(5));
assert_eq!(maybe_icecream(22), Some(0));
assert_eq!(maybe_icecream(23), Some(0));
assert_eq!(maybe_icecream(24), None);
assert_eq!(maybe_icecream(25), None);
}
#[test]
fn raw_value() {
// TODO: Fix this test. How do you get at the value contained in the
// Option?
let icecreams = maybe_icecream(12);
assert_eq!(icecreams, 5);
}
}

View file

@ -1,9 +1,6 @@
// options2.rs
//
// Execute `rustlings hint options2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
@ -12,7 +9,7 @@ mod tests {
let target = "rustlings";
let optional_target = Some(target);
// TODO: Make this an if let statement whose value is "Some" type
// TODO: Make this an if-let statement whose value is `Some`.
word = optional_target {
assert_eq!(word, target);
}
@ -23,15 +20,15 @@ mod tests {
let range = 10;
let mut optional_integers: Vec<Option<i8>> = vec![None];
for i in 1..(range + 1) {
for i in 1..=range {
optional_integers.push(Some(i));
}
let mut cursor = range;
// TODO: make this a while let statement - remember that vector.pop also
// adds another layer of Option<T>. You can stack `Option<T>`s into
// while let and if let.
// TODO: Make this a while-let statement. Remember that `Vec::pop()`
// adds another layer of `Option`. You can do nested pattern matching
// in if-let and while-let statements.
integer = optional_integers.pop() {
assert_eq!(integer, cursor);
cursor -= 1;

View file

@ -1,21 +1,17 @@
// options3.rs
//
// Execute `rustlings hint options3` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
fn main() {
let y: Option<Point> = Some(Point { x: 100, y: 200 });
let optional_point = Some(Point { x: 100, y: 200 });
match y {
// TODO: Fix the compiler error by adding something to this match statement.
match optional_point {
Some(p) => println!("Co-ordinates are {},{}", p.x, p.y),
_ => panic!("no match!"),
_ => panic!("No match!"),
}
y; // Fix without deleting this line.
println!("{optional_point:?}"); // Don't change this line.
}

View file

@ -1,25 +1,22 @@
// 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.
// I AM NOT DONE
pub fn generate_nametag_text(name: String) -> Option<String> {
// TODO: 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 returning `None`. Thankfully, Rust has a similar
// construct to `Option` that can be used to express error conditions. Change
// the function signature and body to return `Result<String, String>` instead
// of `Option<String>`.
fn generate_nametag_text(name: String) -> Option<String> {
if name.is_empty() {
// Empty names aren't allowed.
None
} else {
Some(format!("Hi! My name is {}", name))
Some(format!("Hi! My name is {name}"))
}
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
@ -27,17 +24,18 @@ mod tests {
#[test]
fn generates_nametag_text_for_a_nonempty_name() {
assert_eq!(
generate_nametag_text("Beyoncé".into()),
Ok("Hi! My name is Beyoncé".into())
generate_nametag_text("Beyoncé".to_string()).as_deref(),
Ok("Hi! My name is Beyoncé"),
);
}
#[test]
fn explains_why_generating_nametag_text_fails() {
assert_eq!(
generate_nametag_text("".into()),
// Don't change this line
Err("`name` was empty; it must be nonempty.".into())
generate_nametag_text(String::new())
.as_ref()
.map_err(|e| e.as_str()),
Err("Empty names aren't allowed"),
);
}
}

View file

@ -1,39 +1,39 @@
// 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 items. Since
// the player typed in the quantity, though, we get it as a string-- and they
// might have typed anything, not just numbers!
// the player typed in the quantity, we get it as a string. 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
// 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.
// will return a `ParseIntError`. 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
// 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
use std::num::ParseIntError;
pub fn total_cost(item_quantity: &str) -> Result<i32, ParseIntError> {
fn total_cost(item_quantity: &str) -> Result<i32, ParseIntError> {
let processing_fee = 1;
let cost_per_item = 5;
// TODO: Handle the error case as described above.
let qty = item_quantity.parse::<i32>();
Ok(qty * cost_per_item + processing_fee)
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
use std::num::IntErrorKind;
#[test]
fn item_quantity_is_a_valid_number() {
@ -43,8 +43,8 @@ mod tests {
#[test]
fn item_quantity_is_an_invalid_number() {
assert_eq!(
total_cost("beep boop").unwrap_err().to_string(),
"invalid digit found in string"
total_cost("beep boop").unwrap_err().kind(),
&IntErrorKind::InvalidDigit,
);
}
}

View file

@ -1,16 +1,20 @@
// 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.
// I AM NOT DONE
use std::num::ParseIntError;
// Don't change this function.
fn total_cost(item_quantity: &str) -> Result<i32, ParseIntError> {
let processing_fee = 1;
let cost_per_item = 5;
let qty = item_quantity.parse::<i32>()?;
Ok(qty * cost_per_item + processing_fee)
}
// TODO: Fix the compiler error by changing the signature and body of the
// `main` function.
fn main() {
let mut tokens = 100;
let pretend_user_input = "8";
@ -21,14 +25,6 @@ fn main() {
println!("You can't afford that many!");
} else {
tokens -= cost;
println!("You now have {} tokens.", tokens);
println!("You now have {tokens} tokens.");
}
}
pub fn total_cost(item_quantity: &str) -> Result<i32, ParseIntError> {
let processing_fee = 1;
let cost_per_item = 5;
let qty = item_quantity.parse::<i32>()?;
Ok(qty * cost_per_item + processing_fee)
}

View file

@ -1,32 +1,37 @@
// errors4.rs
//
// Execute `rustlings hint errors4` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
#[derive(PartialEq, Debug)]
struct PositiveNonzeroInteger(u64);
#[derive(PartialEq, Debug)]
enum CreationError {
Negative,
Zero,
}
#[derive(PartialEq, Debug)]
struct PositiveNonzeroInteger(u64);
impl PositiveNonzeroInteger {
fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> {
// Hmm... Why is this always returning an Ok value?
Ok(PositiveNonzeroInteger(value as u64))
fn new(value: i64) -> Result<Self, CreationError> {
// TODO: This function shouldn't always return an `Ok`.
Ok(Self(value as u64))
}
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_creation() {
assert!(PositiveNonzeroInteger::new(10).is_ok());
assert_eq!(
Err(CreationError::Negative),
PositiveNonzeroInteger::new(-10)
PositiveNonzeroInteger::new(10),
Ok(PositiveNonzeroInteger(10)),
);
assert_eq!(Err(CreationError::Zero), PositiveNonzeroInteger::new(0));
assert_eq!(
PositiveNonzeroInteger::new(-10),
Err(CreationError::Negative),
);
assert_eq!(PositiveNonzeroInteger::new(0), Err(CreationError::Zero));
}
}

View file

@ -1,45 +1,18 @@
// 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<dyn ???>` type as an "I want anything that does ???" type, which,
// given Rust's usual standards for runtime safety, should strike you as
// somewhat lenient!
// This exercise is an altered version of the `errors4` exercise. It 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<dyn ???>` type as
// an "I want anything that does ???" type.
//
// In short, this particular use case for boxes is for when you want to own a
// value and you care only that it is a type which implements a particular
// trait. To do so, The Box is declared as of type Box<dyn Trait> where Trait 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.
// trait. To do so, The `Box` is declared as of type `Box<dyn Trait>` where
// `Trait` is the trait the compiler looks for on any value used in that
// context. For this exercise, that context is the potential errors which
// can be returned in a `Result`.
// I AM NOT DONE
use std::error;
use std::error::Error;
use std::fmt;
use std::num::ParseIntError;
// TODO: update the return type of `main()` to make this compile.
fn main() -> Result<(), Box<dyn ???>> {
let pretend_user_input = "42";
let x: i64 = pretend_user_input.parse()?;
println!("output={:?}", PositiveNonzeroInteger::new(x)?);
Ok(())
}
// Don't change anything below this line.
#[derive(PartialEq, Debug)]
struct PositiveNonzeroInteger(u64);
#[derive(PartialEq, Debug)]
enum CreationError {
@ -47,17 +20,7 @@ enum CreationError {
Zero,
}
impl PositiveNonzeroInteger {
fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> {
match value {
x if x < 0 => Err(CreationError::Negative),
x if x == 0 => Err(CreationError::Zero),
x => Ok(PositiveNonzeroInteger(x as u64)),
}
}
}
// This is required so that `CreationError` can implement `error::Error`.
// This is required so that `CreationError` can implement `Error`.
impl fmt::Display for CreationError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let description = match *self {
@ -68,4 +31,26 @@ impl fmt::Display for CreationError {
}
}
impl error::Error for CreationError {}
impl Error for CreationError {}
#[derive(PartialEq, Debug)]
struct PositiveNonzeroInteger(u64);
impl PositiveNonzeroInteger {
fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> {
match value {
0 => Err(CreationError::Zero),
x if x < 0 => Err(CreationError::Negative),
x => Ok(PositiveNonzeroInteger(x as u64)),
}
}
}
// TODO: Add the correct return type `Result<(), Box<dyn ???>>`. What can we
// use to describe both errors? Is there a trait which both errors implement?
fn main() {
let pretend_user_input = "42";
let x: i64 = pretend_user_input.parse()?;
println!("output={:?}", PositiveNonzeroInteger::new(x)?);
Ok(())
}

View file

@ -1,94 +1,90 @@
// errors6.rs
//
// Using catch-all error types like `Box<dyn error::Error>` 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.
// I AM NOT DONE
// Using catch-all error types like `Box<dyn Error>` 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.
use std::num::ParseIntError;
// This is a custom error type that we will be using in `parse_pos_nonzero()`.
#[derive(PartialEq, Debug)]
enum ParsePosNonzeroError {
Creation(CreationError),
ParseInt(ParseIntError),
}
impl ParsePosNonzeroError {
fn from_creation(err: CreationError) -> ParsePosNonzeroError {
ParsePosNonzeroError::Creation(err)
}
// TODO: add another error conversion function here.
// fn from_parseint...
}
fn parse_pos_nonzero(s: &str) -> Result<PositiveNonzeroInteger, ParsePosNonzeroError> {
// TODO: change this to return an appropriate error instead of panicking
// when `parse()` returns an error.
let x: i64 = s.parse().unwrap();
PositiveNonzeroInteger::new(x).map_err(ParsePosNonzeroError::from_creation)
}
// Don't change anything below this line.
#[derive(PartialEq, Debug)]
struct PositiveNonzeroInteger(u64);
#[derive(PartialEq, Debug)]
enum CreationError {
Negative,
Zero,
}
// A custom error type that we will be using in `PositiveNonzeroInteger::parse`.
#[derive(PartialEq, Debug)]
enum ParsePosNonzeroError {
Creation(CreationError),
ParseInt(ParseIntError),
}
impl ParsePosNonzeroError {
fn from_creation(err: CreationError) -> Self {
Self::Creation(err)
}
// TODO: Add another error conversion function here.
// fn from_parseint(???) -> Self { ??? }
}
#[derive(PartialEq, Debug)]
struct PositiveNonzeroInteger(u64);
impl PositiveNonzeroInteger {
fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> {
fn new(value: i64) -> Result<Self, CreationError> {
match value {
x if x < 0 => Err(CreationError::Negative),
x if x == 0 => Err(CreationError::Zero),
x => Ok(PositiveNonzeroInteger(x as u64)),
x => Ok(Self(x as u64)),
}
}
fn parse(s: &str) -> Result<Self, ParsePosNonzeroError> {
// TODO: change this to return an appropriate error instead of panicking
// when `parse()` returns an error.
let x: i64 = s.parse().unwrap();
Self::new(x).map_err(ParsePosNonzeroError::from_creation)
}
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod test {
use super::*;
use std::num::IntErrorKind;
#[test]
fn test_parse_error() {
// We can't construct a ParseIntError, so we have to pattern match.
assert!(matches!(
parse_pos_nonzero("not a number"),
Err(ParsePosNonzeroError::ParseInt(_))
PositiveNonzeroInteger::parse("not a number"),
Err(ParsePosNonzeroError::ParseInt(_)),
));
}
#[test]
fn test_negative() {
assert_eq!(
parse_pos_nonzero("-555"),
Err(ParsePosNonzeroError::Creation(CreationError::Negative))
PositiveNonzeroInteger::parse("-555"),
Err(ParsePosNonzeroError::Creation(CreationError::Negative)),
);
}
#[test]
fn test_zero() {
assert_eq!(
parse_pos_nonzero("0"),
Err(ParsePosNonzeroError::Creation(CreationError::Zero))
PositiveNonzeroInteger::parse("0"),
Err(ParsePosNonzeroError::Creation(CreationError::Zero)),
);
}
#[test]
fn test_positive() {
let x = PositiveNonzeroInteger::new(42);
assert!(x.is_ok());
assert_eq!(parse_pos_nonzero("42"), Ok(x.unwrap()));
let x = PositiveNonzeroInteger::new(42).unwrap();
assert_eq!(x.0, 42);
assert_eq!(PositiveNonzeroInteger::parse("42"), Ok(x));
}
}

View file

@ -1,7 +1,7 @@
# Generics
Generics is the topic of generalizing types and functionalities to broader cases.
This is extremely useful for reducing code duplication in many ways, but can call for rather involving syntax.
This is extremely useful for reducing code duplication in many ways, but can call for some rather involved syntax.
Namely, being generic requires taking great care to specify over which types a generic type is actually considered valid.
The simplest and most common use of generics is for type parameters.

View file

@ -1,14 +1,18 @@
// 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
// `Vec<T>` is generic over the type `T`. In most cases, the compiler is able to
// infer `T`, for example after pushing a value with a concrete type to the vector.
// But in this exercise, the compiler needs some help through a type annotation.
fn main() {
let mut shopping_list: Vec<?> = Vec::new();
shopping_list.push("milk");
// TODO: Fix the compiler error by annotating the type of the vector
// `Vec<T>`. Choose `T` as some integer type that can be created from
// `u8` and `i8`.
let mut numbers = Vec::new();
// Don't change the lines below.
let n1: u8 = 42;
numbers.push(n1.into());
let n2: i8 = -1;
numbers.push(n2.into());
println!("{numbers:?}");
}

View file

@ -1,23 +1,20 @@
// 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.
// I AM NOT DONE
// TODO: Rewrite it using a generic so that it supports wrapping ANY type.
struct Wrapper {
value: u32,
}
// TODO: Adapt the struct's implementation to be generic over the wrapped value.
impl Wrapper {
pub fn new(value: u32) -> Self {
fn new(value: u32) -> Self {
Wrapper { value }
}
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;

View file

@ -1,26 +1,17 @@
// traits1.rs
//
// 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.
//
// Execute `rustlings hint traits1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
// The trait `AppendBar` has only one function which appends "Bar" to any object
// implementing this trait.
trait AppendBar {
fn append_bar(self) -> Self;
}
impl AppendBar for String {
// TODO: Implement `AppendBar` for type `String`.
// TODO: Implement `AppendBar` for the type `String`.
}
fn main() {
let s = String::from("Foo");
let s = s.append_bar();
println!("s: {}", s);
println!("s: {s}");
}
#[cfg(test)]
@ -29,14 +20,11 @@ mod tests {
#[test]
fn is_foo_bar() {
assert_eq!(String::from("Foo").append_bar(), String::from("FooBar"));
assert_eq!(String::from("Foo").append_bar(), "FooBar");
}
#[test]
fn is_bar_bar() {
assert_eq!(
String::from("").append_bar().append_bar(),
String::from("BarBar")
);
assert_eq!(String::from("").append_bar().append_bar(), "BarBar");
}
}

View file

@ -1,20 +1,13 @@
// 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"'
// to a vector of strings.
//
// 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
trait AppendBar {
fn append_bar(self) -> Self;
}
// TODO: Implement trait `AppendBar` for a vector of strings.
// TODO: Implement the trait `AppendBar` for a vector of strings.
// `append_bar` should push the string "Bar" into the vector.
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
@ -23,7 +16,7 @@ mod tests {
#[test]
fn is_vec_pop_eq_bar() {
let mut foo = vec![String::from("Foo")].append_bar();
assert_eq!(foo.pop().unwrap(), String::from("Bar"));
assert_eq!(foo.pop().unwrap(), String::from("Foo"));
assert_eq!(foo.pop().unwrap(), "Bar");
assert_eq!(foo.pop().unwrap(), "Foo");
}
}

View file

@ -1,16 +1,8 @@
// 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.
//
// Consider what you can add to the Licensed trait.
//
// Execute `rustlings hint traits3` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
pub trait Licensed {
trait Licensed {
// TODO: Add a default implementation for `licensing_info` so that
// implementors like the two structs below can share that default behavior
// without repeating the function.
// The default license information should be the string "Default license".
fn licensing_info(&self) -> String;
}
@ -22,8 +14,12 @@ struct OtherSoftware {
version_number: String,
}
impl Licensed for SomeSoftware {} // Don't edit this line
impl Licensed for OtherSoftware {} // Don't edit this line
impl Licensed for SomeSoftware {} // Don't edit this line.
impl Licensed for OtherSoftware {} // Don't edit this line.
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
@ -31,7 +27,7 @@ mod tests {
#[test]
fn is_licensing_info_the_same() {
let licensing_info = String::from("Some information");
let licensing_info = "Default license";
let some_software = SomeSoftware { version_number: 1 };
let other_software = OtherSoftware {
version_number: "v2.0.0".to_string(),

View file

@ -1,30 +1,22 @@
// 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.
// I AM NOT DONE
pub trait Licensed {
trait Licensed {
fn licensing_info(&self) -> String {
"some information".to_string()
"Default license".to_string()
}
}
struct SomeSoftware {}
struct OtherSoftware {}
struct SomeSoftware;
struct OtherSoftware;
impl Licensed for SomeSoftware {}
impl Licensed for OtherSoftware {}
// YOU MAY ONLY CHANGE THE NEXT LINE
fn compare_license_types(software: ??, software_two: ??) -> bool {
software.licensing_info() == software_two.licensing_info()
// TODO: Fix the compiler error by only changing the signature of this function.
fn compare_license_types(software1: ???, software2: ???) -> bool {
software1.licensing_info() == software2.licensing_info()
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
@ -33,17 +25,11 @@ mod tests {
#[test]
fn compare_license_information() {
let some_software = SomeSoftware {};
let other_software = OtherSoftware {};
assert!(compare_license_types(some_software, other_software));
assert!(compare_license_types(SomeSoftware, OtherSoftware));
}
#[test]
fn compare_license_information_backwards() {
let some_software = SomeSoftware {};
let other_software = OtherSoftware {};
assert!(compare_license_types(other_software, some_software));
assert!(compare_license_types(OtherSoftware, SomeSoftware));
}
}

View file

@ -1,40 +1,39 @@
// 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.
// I AM NOT DONE
pub trait SomeTrait {
trait SomeTrait {
fn some_function(&self) -> bool {
true
}
}
pub trait OtherTrait {
trait OtherTrait {
fn other_function(&self) -> bool {
true
}
}
struct SomeStruct {}
struct OtherStruct {}
struct SomeStruct;
impl SomeTrait for SomeStruct {}
impl OtherTrait for SomeStruct {}
struct OtherStruct;
impl SomeTrait for OtherStruct {}
impl OtherTrait for OtherStruct {}
// YOU MAY ONLY CHANGE THE NEXT LINE
fn some_func(item: ??) -> bool {
// TODO: Fix the compiler error by only changing the signature of this function.
fn some_func(item: ???) -> bool {
item.some_function() && item.other_function()
}
fn main() {
some_func(SomeStruct {});
some_func(OtherStruct {});
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_some_func() {
assert!(some_func(SomeStruct));
assert!(some_func(OtherStruct));
}
}

View file

@ -1,15 +1,9 @@
// 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?
//
// Execute `rustlings hint lifetimes1` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
// TODO: Fix the compiler error by updating the function signature.
fn longest(x: &str, y: &str) -> &str {
if x.len() > y.len() {
x
@ -19,9 +13,16 @@ fn longest(x: &str, y: &str) -> &str {
}
fn main() {
let string1 = String::from("abcd");
let string2 = "xyz";
let result = longest(string1.as_str(), string2);
println!("The longest string is '{}'", result);
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_longest() {
assert_eq!(longest("abcd", "123"), "abcd");
assert_eq!(longest("abc", "1234"), "1234");
}
}

View file

@ -1,13 +1,4 @@
// 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?
//
// Execute `rustlings hint lifetimes2` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
// Don't change this function.
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
@ -17,11 +8,13 @@ fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
}
fn main() {
// TODO: Fix the compiler error by moving one line.
let string1 = String::from("long string is long");
let result;
{
let string2 = String::from("xyz");
result = longest(string1.as_str(), string2.as_str());
result = longest(&string1, &string2);
}
println!("The longest string is '{}'", result);
println!("The longest string is '{result}'");
}

View file

@ -1,21 +1,16 @@
// lifetimes3.rs
//
// Lifetimes are also needed when structs hold references.
//
// Execute `rustlings hint lifetimes3` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
// TODO: Fix the compiler errors about the struct.
struct Book {
author: &str,
title: &str,
}
fn main() {
let name = String::from("Jill Smith");
let title = String::from("Fish Flying");
let book = Book { author: &name, title: &title };
let book = Book {
author: "George Orwell",
title: "1984",
};
println!("{} by {}", book.title, book.author);
}

View file

@ -1,21 +1,23 @@
// 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.
// do.
// I AM NOT DONE
fn is_even(n: i64) -> bool {
n % 2 == 0
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
// TODO: Import `is_even`. You can use a wildcard to import everything in
// the outer module.
#[test]
fn you_can_assert() {
// TODO: Test the function `is_even` with some values.
assert!();
assert!();
}
}

View file

@ -1,17 +1,23 @@
// 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.
// Calculates the power of 2 using a bit shift.
// `1 << n` is equivalent to "2 to the power of n".
fn power_of_2(n: u8) -> u64 {
1 << n
}
// I AM NOT DONE
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn you_can_assert_eq() {
// TODO: Test the function `power_of_2` with some values.
assert_eq!();
assert_eq!();
assert_eq!();
assert_eq!();
}
}

View file

@ -1,16 +1,23 @@
// 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.
struct Rectangle {
width: i32,
height: i32,
}
// I AM NOT DONE
impl Rectangle {
// Don't change this function.
fn new(width: i32, height: i32) -> Self {
if width <= 0 || height <= 0 {
// Returning a `Result` would be better here. But we want to learn
// how to test functions that can panic.
panic!("Rectangle width and height can't be negative");
}
pub fn is_even(num: i32) -> bool {
num % 2 == 0
Rectangle { width, height }
}
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
@ -18,12 +25,25 @@ mod tests {
use super::*;
#[test]
fn is_true_when_even() {
assert!();
fn correct_width_and_height() {
// TODO: This test should check if the rectangle has the size that we
// pass to its constructor.
let rect = Rectangle::new(10, 20);
assert_eq!(todo!(), 10); // Check width
assert_eq!(todo!(), 20); // Check height
}
// TODO: This test should check if the program panics when we try to create
// a rectangle with negative width.
#[test]
fn is_false_when_odd() {
assert!();
fn negative_width() {
let _rect = Rectangle::new(-10, 10);
}
// TODO: This test should check if the program panics when we try to create
// a rectangle with negative height.
#[test]
fn negative_height() {
let _rect = Rectangle::new(10, -10);
}
}

View file

@ -1,48 +0,0 @@
// 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.
// I AM NOT DONE
struct Rectangle {
width: i32,
height: i32
}
impl Rectangle {
// Only change the test functions themselves
pub fn new(width: i32, height: i32) -> Self {
if width <= 0 || height <= 0 {
panic!("Rectangle width and height cannot be negative!")
}
Rectangle {width, height}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn correct_width_and_height() {
// This test should check if the rectangle is the size that we pass into its constructor
let rect = Rectangle::new(10, 20);
assert_eq!(???, 10); // check width
assert_eq!(???, 20); // check height
}
#[test]
fn negative_width() {
// This test should check if program panics when we try to create rectangle with negative width
let _rect = Rectangle::new(-10, 10);
}
#[test]
fn negative_height() {
// This test should check if program panics when we try to create rectangle with negative height
let _rect = Rectangle::new(10, -10);
}
}

View file

@ -1,26 +1,25 @@
// iterators1.rs
//
// 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.
// I AM NOT DONE
#[test]
fn main() {
let my_fav_fruits = vec!["banana", "custard apple", "avocado", "peach", "raspberry"];
let mut my_iterable_fav_fruits = ???; // TODO: Step 1
assert_eq!(my_iterable_fav_fruits.next(), Some(&"banana"));
assert_eq!(my_iterable_fav_fruits.next(), ???); // TODO: Step 2
assert_eq!(my_iterable_fav_fruits.next(), Some(&"avocado"));
assert_eq!(my_iterable_fav_fruits.next(), ???); // TODO: Step 3
assert_eq!(my_iterable_fav_fruits.next(), Some(&"raspberry"));
assert_eq!(my_iterable_fav_fruits.next(), ???); // TODO: Step 4
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
#[test]
fn iterators() {
let my_fav_fruits = ["banana", "custard apple", "avocado", "peach", "raspberry"];
// TODO: Create an iterator over the array.
let mut fav_fruits_iterator = todo!();
assert_eq!(fav_fruits_iterator.next(), Some(&"banana"));
assert_eq!(fav_fruits_iterator.next(), todo!()); // TODO: Replace `todo!()`
assert_eq!(fav_fruits_iterator.next(), Some(&"avocado"));
assert_eq!(fav_fruits_iterator.next(), todo!()); // TODO: Replace `todo!()`
assert_eq!(fav_fruits_iterator.next(), Some(&"raspberry"));
assert_eq!(fav_fruits_iterator.next(), todo!()); // TODO: Replace `todo!()`
}
}

View file

@ -1,38 +1,32 @@
// 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.
// can offer.
// I AM NOT DONE
// Step 1.
// Complete the `capitalize_first` function.
// TODO: Complete the `capitalize_first` function.
// "hello" -> "Hello"
pub fn capitalize_first(input: &str) -> String {
let mut c = input.chars();
match c.next() {
fn capitalize_first(input: &str) -> String {
let mut chars = input.chars();
match chars.next() {
None => String::new(),
Some(first) => ???,
Some(first) => todo!(),
}
}
// Step 2.
// Apply the `capitalize_first` function to a slice of string slices.
// TODO: Apply the `capitalize_first` function to a slice of string slices.
// Return a vector of strings.
// ["hello", "world"] -> ["Hello", "World"]
pub fn capitalize_words_vector(words: &[&str]) -> Vec<String> {
vec![]
fn capitalize_words_vector(words: &[&str]) -> Vec<String> {
// ???
}
// Step 3.
// Apply the `capitalize_first` function again to a slice of string slices.
// Return a single string.
// TODO: Apply the `capitalize_first` function again to a slice of string
// slices. Return a single string.
// ["hello", " ", "world"] -> "Hello World"
pub fn capitalize_words_string(words: &[&str]) -> String {
String::new()
fn capitalize_words_string(words: &[&str]) -> String {
// ???
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]

View file

@ -1,50 +1,33 @@
// 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:
// 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.
// I AM NOT DONE
#[derive(Debug, PartialEq, Eq)]
pub enum DivisionError {
NotDivisible(NotDivisibleError),
enum DivisionError {
DivideByZero,
NotDivisible,
}
#[derive(Debug, PartialEq, Eq)]
pub struct NotDivisibleError {
dividend: i32,
divisor: i32,
}
// Calculate `a` divided by `b` if `a` is evenly divisible by `b`.
// TODO: Calculate `a` divided by `b` if `a` is evenly divisible by `b`.
// Otherwise, return a suitable error.
pub fn divide(a: i32, b: i32) -> Result<i32, DivisionError> {
fn divide(a: i32, b: i32) -> Result<i32, DivisionError> {
todo!();
}
// 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];
// TODO: Add the correct return type and complete the function body.
// Desired output: `Ok([1, 11, 1426, 3])`
fn result_with_list() {
let numbers = [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.
// Desired output: [Ok(1), Ok(11), Ok(1426), Ok(3)]
fn list_of_results() -> () {
let numbers = vec![27, 297, 38502, 81];
// TODO: Add the correct return type and complete the function body.
// Desired output: `[Ok(1), Ok(11), Ok(1426), Ok(3)]`
fn list_of_results() {
let numbers = [27, 297, 38502, 81];
let division_results = numbers.into_iter().map(|n| divide(n, 27));
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
@ -55,19 +38,13 @@ mod tests {
}
#[test]
fn test_not_divisible() {
assert_eq!(
divide(81, 6),
Err(DivisionError::NotDivisible(NotDivisibleError {
dividend: 81,
divisor: 6
}))
);
fn test_divide_by_0() {
assert_eq!(divide(81, 0), Err(DivisionError::DivideByZero));
}
#[test]
fn test_divide_by_0() {
assert_eq!(divide(81, 0), Err(DivisionError::DivideByZero));
fn test_not_divisible() {
assert_eq!(divide(81, 6), Err(DivisionError::NotDivisible));
}
#[test]
@ -77,14 +54,11 @@ mod tests {
#[test]
fn test_result_with_list() {
assert_eq!(format!("{:?}", result_with_list()), "Ok([1, 11, 1426, 3])");
assert_eq!(result_with_list().unwarp(), [1, 11, 1426, 3]);
}
#[test]
fn test_list_of_results() {
assert_eq!(
format!("{:?}", list_of_results()),
"[Ok(1), Ok(11), Ok(1426), Ok(3)]"
);
assert_eq!(list_of_results(), [Ok(1), Ok(11), Ok(1426), Ok(3)]);
}
}

View file

@ -1,20 +1,16 @@
// iterators4.rs
//
// Execute `rustlings hint iterators4` or use the `hint` watch subcommand for a
// hint.
// I AM NOT DONE
pub fn factorial(num: u64) -> u64 {
// Complete this function to return the factorial of num
fn factorial(num: u8) -> u64 {
// TODO: Complete this function to return the factorial of `num`.
// Do not use:
// - early returns (using the `return` keyword explicitly)
// Try not to use:
// - imperative style loops (for, while)
// - imperative style loops (for/while)
// - additional variables
// For an extra challenge, don't use:
// - recursion
// Execute `rustlings hint iterators4` for hints.
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
@ -23,20 +19,20 @@ mod tests {
#[test]
fn factorial_of_0() {
assert_eq!(1, factorial(0));
assert_eq!(factorial(0), 1);
}
#[test]
fn factorial_of_1() {
assert_eq!(1, factorial(1));
assert_eq!(factorial(1), 1);
}
#[test]
fn factorial_of_2() {
assert_eq!(2, factorial(2));
assert_eq!(factorial(2), 2);
}
#[test]
fn factorial_of_4() {
assert_eq!(24, factorial(4));
assert_eq!(factorial(4), 24);
}
}

View file

@ -1,17 +1,8 @@
// iterators5.rs
//
// Let's define a simple model to track Rustlings exercise progress. Progress
// 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
// number of exercises with a given progress. Recreate this counting
// 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.
// I AM NOT DONE
// functionality using iterators. Try to not use imperative loops (for/while).
use std::collections::HashMap;
@ -25,24 +16,25 @@ enum Progress {
fn count_for(map: &HashMap<String, Progress>, value: Progress) -> usize {
let mut count = 0;
for val in map.values() {
if val == &value {
if *val == value {
count += 1;
}
}
count
}
// TODO: Implement the functionality of `count_for` but with an iterator instead
// of a `for` loop.
fn count_iterator(map: &HashMap<String, Progress>, value: Progress) -> usize {
// map is a hashmap with String keys and Progress values.
// map = { "variables1": Complete, "from_str": None, ... }
todo!();
// `map` is a hash map with `String` keys and `Progress` values.
// map = { "variables1": Complete, "from_str": None, … }
}
fn count_collection_for(collection: &[HashMap<String, Progress>], value: Progress) -> usize {
let mut count = 0;
for map in collection {
for val in map.values() {
if val == &value {
if *val == value {
count += 1;
}
}
@ -50,81 +42,22 @@ fn count_collection_for(collection: &[HashMap<String, Progress>], value: Progres
count
}
// TODO: Implement the functionality of `count_collection_for` but with an
// iterator instead of a `for` loop.
fn count_collection_iterator(collection: &[HashMap<String, Progress>], value: Progress) -> usize {
// collection is a slice of hashmaps.
// collection = [{ "variables1": Complete, "from_str": None, ... },
// { "variables2": Complete, ... }, ... ]
todo!();
// `collection` is a slice of hash maps.
// collection = [{ "variables1": Complete, "from_str": None, … },
// { "variables2": Complete, … }, … ]
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn count_complete() {
let map = get_map();
assert_eq!(3, count_iterator(&map, Progress::Complete));
}
#[test]
fn count_some() {
let map = get_map();
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]
fn count_collection_complete() {
let collection = get_vec_map();
assert_eq!(
6,
count_collection_iterator(&collection, Progress::Complete)
);
}
#[test]
fn count_collection_some() {
let collection = get_vec_map();
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<String, Progress> {
use Progress::*;
@ -153,4 +86,68 @@ mod tests {
vec![map, other]
}
#[test]
fn count_complete() {
let map = get_map();
assert_eq!(count_iterator(&map, Progress::Complete), 3);
}
#[test]
fn count_some() {
let map = get_map();
assert_eq!(count_iterator(&map, Progress::Some), 1);
}
#[test]
fn count_none() {
let map = get_map();
assert_eq!(count_iterator(&map, Progress::None), 2);
}
#[test]
fn count_complete_equals_for() {
let map = get_map();
let progress_states = [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]
fn count_collection_complete() {
let collection = get_vec_map();
assert_eq!(
count_collection_iterator(&collection, Progress::Complete),
6,
);
}
#[test]
fn count_collection_some() {
let collection = get_vec_map();
assert_eq!(count_collection_iterator(&collection, Progress::Some), 1);
}
#[test]
fn count_collection_none() {
let collection = get_vec_map();
assert_eq!(count_collection_iterator(&collection, Progress::None), 4);
}
#[test]
fn count_collection_equals_for() {
let collection = get_vec_map();
let progress_states = [Progress::Complete, Progress::Some, Progress::None];
for progress_state in progress_states {
assert_eq!(
count_collection_for(&collection, progress_state),
count_collection_iterator(&collection, progress_state),
);
}
}
}

View file

@ -1,45 +1,42 @@
// arc1.rs
// In this exercise, we are given a `Vec` of u32 called `numbers` with values
// ranging from 0 to 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, ...
// 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!
//
// Execute `rustlings hint arc1` or use the `hint` watch subcommand for a hint.
// we are using `Arc`.
// I AM NOT DONE
#![forbid(unused_imports)] // Do not change this, (or the next) line.
use std::sync::Arc;
use std::thread;
// Don't change the lines below.
#![forbid(unused_imports)]
use std::{sync::Arc, thread};
fn main() {
let numbers: Vec<_> = (0..100u32).collect();
let shared_numbers = // TODO
let mut joinhandles = Vec::new();
// TODO: Define `shared_numbers` by using `Arc`.
// let shared_numbers = ???;
let mut join_handles = Vec::new();
for offset in 0..8 {
let child_numbers = // TODO
joinhandles.push(thread::spawn(move || {
// TODO: Define `child_numbers` using `shared_numbers`.
// let child_numbers = ???;
let handle = thread::spawn(move || {
let sum: u32 = child_numbers.iter().filter(|&&n| n % 8 == offset).sum();
println!("Sum of offset {} is {}", offset, sum);
}));
println!("Sum of offset {offset} is {sum}");
});
join_handles.push(handle);
}
for handle in joinhandles.into_iter() {
for handle in join_handles.into_iter() {
handle.join().unwrap();
}
}

View file

@ -1,58 +1,50 @@
// 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.
//
// The recursive type we're implementing in this exercise is the `cons list` - a
// 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
// 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!()`
//
// Note: the tests should not be changed
//
// Execute `rustlings hint box1` or use the `hint` watch subcommand for a hint.
// I AM NOT DONE
// TODO: Use a `Box` in the enum definition to make the code compile.
#[derive(PartialEq, Debug)]
pub enum List {
enum List {
Cons(i32, List),
Nil,
}
// TODO: Create an empty cons list.
fn create_empty_list() -> List {
todo!()
}
// TODO: Create a non-empty cons list.
fn create_non_empty_list() -> List {
todo!()
}
fn main() {
println!("This is an empty cons list: {:?}", create_empty_list());
println!(
"This is a non-empty cons list: {:?}",
create_non_empty_list()
create_non_empty_list(),
);
}
pub fn create_empty_list() -> List {
todo!()
}
pub fn create_non_empty_list() -> List {
todo!()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_create_empty_list() {
assert_eq!(List::Nil, create_empty_list())
assert_eq!(create_empty_list(), List::Nil);
}
#[test]
fn test_create_non_empty_list() {
assert_ne!(create_empty_list(), create_non_empty_list())
assert_ne!(create_empty_list(), create_non_empty_list());
}
}

View file

@ -1,30 +1,22 @@
// 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 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.
//
// Execute `rustlings hint cow1` or use the `hint` watch subcommand for a hint.
// I AM NOT DONE
// This exercise explores the `Cow` (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.
use std::borrow::Cow;
fn abs_all<'a, 'b>(input: &'a mut Cow<'b, [i32]>) -> &'a mut Cow<'b, [i32]> {
for i in 0..input.len() {
let v = input[i];
if v < 0 {
fn abs_all(input: &mut Cow<[i32]>) {
for ind in 0..input.len() {
let value = input[ind];
if value < 0 {
// Clones into a vector if not already owned.
input.to_mut()[i] = -v;
input.to_mut()[ind] = -value;
}
}
input
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
@ -32,47 +24,45 @@ mod tests {
use super::*;
#[test]
fn reference_mutation() -> Result<(), &'static str> {
fn reference_mutation() {
// Clone occurs because `input` needs to be mutated.
let slice = [-1, 0, 1];
let mut input = Cow::from(&slice[..]);
match abs_all(&mut input) {
Cow::Owned(_) => Ok(()),
_ => Err("Expected owned value"),
}
let vec = vec![-1, 0, 1];
let mut input = Cow::from(&vec);
abs_all(&mut input);
assert!(matches!(input, Cow::Owned(_)));
}
#[test]
fn reference_no_mutation() -> Result<(), &'static str> {
fn reference_no_mutation() {
// No clone occurs because `input` doesn't need to be mutated.
let slice = [0, 1, 2];
let mut input = Cow::from(&slice[..]);
match abs_all(&mut input) {
// TODO
}
let vec = vec![0, 1, 2];
let mut input = Cow::from(&vec);
abs_all(&mut input);
// TODO: Replace `todo!()` with `Cow::Owned(_)` or `Cow::Borrowed(_)`.
assert!(matches!(input, todo!()));
}
#[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
fn owned_no_mutation() {
// We can also pass `vec` 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) {
// TODO
}
let vec = vec![0, 1, 2];
let mut input = Cow::from(vec);
abs_all(&mut input);
// TODO: Replace `todo!()` with `Cow::Owned(_)` or `Cow::Borrowed(_)`.
assert!(matches!(input, todo!()));
}
#[test]
fn owned_mutation() -> Result<(), &'static str> {
fn owned_mutation() {
// Of course this is also the case if a mutation does occur. In this
// case the call to `to_mut()` in the abs_all() function returns a
// case, the call to `to_mut()` in the `abs_all` function returns a
// reference to the same data as before.
let slice = vec![-1, 0, 1];
let mut input = Cow::from(slice);
match abs_all(&mut input) {
// TODO
}
let vec = vec![-1, 0, 1];
let mut input = Cow::from(vec);
abs_all(&mut input);
// TODO: Replace `todo!()` with `Cow::Owned(_)` or `Cow::Borrowed(_)`.
assert!(matches!(input, todo!()));
}
}

View file

@ -1,21 +1,12 @@
// rc1.rs
//
// In this exercise, we want to express the concept of multiple owners via the
// Rc<T> 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
// `Rc<T>` type. This is a model of our solar system - there is a `Sun` type and
// multiple `Planet`s. The planets take ownership of the sun, indicating that
// they revolve around the sun.
use std::rc::Rc;
#[derive(Debug)]
struct Sun {}
struct Sun;
#[derive(Debug)]
enum Planet {
@ -31,13 +22,21 @@ enum Planet {
impl Planet {
fn details(&self) {
println!("Hi from {:?}!", self)
println!("Hi from {self:?}!");
}
}
#[test]
fn main() {
let sun = Rc::new(Sun {});
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn rc1() {
let sun = Rc::new(Sun);
println!("reference count = {}", Rc::strong_count(&sun)); // 1 reference
let mercury = Planet::Mercury(Rc::clone(&sun));
@ -61,17 +60,17 @@ fn main() {
jupiter.details();
// TODO
let saturn = Planet::Saturn(Rc::new(Sun {}));
let saturn = Planet::Saturn(Rc::new(Sun));
println!("reference count = {}", Rc::strong_count(&sun)); // 7 references
saturn.details();
// TODO
let uranus = Planet::Uranus(Rc::new(Sun {}));
let uranus = Planet::Uranus(Rc::new(Sun));
println!("reference count = {}", Rc::strong_count(&sun)); // 8 references
uranus.details();
// TODO
let neptune = Planet::Neptune(Rc::new(Sun {}));
let neptune = Planet::Neptune(Rc::new(Sun));
println!("reference count = {}", Rc::strong_count(&sun)); // 9 references
neptune.details();
@ -103,3 +102,4 @@ fn main() {
assert_eq!(Rc::strong_count(&sun), 1);
}
}

View file

@ -1,40 +1,37 @@
// threads1.rs
//
// 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
use std::thread;
use std::time::{Duration, Instant};
use std::{
thread,
time::{Duration, Instant},
};
fn main() {
let mut handles = vec![];
let mut handles = Vec::new();
for i in 0..10 {
handles.push(thread::spawn(move || {
let handle = thread::spawn(move || {
let start = Instant::now();
thread::sleep(Duration::from_millis(250));
println!("thread {} is complete", i);
println!("Thread {i} done");
start.elapsed().as_millis()
}));
});
handles.push(handle);
}
let mut results: Vec<u128> = vec![];
let mut results = Vec::new();
for handle in handles {
// TODO: a struct is returned from thread::spawn, can you use it?
// TODO: Collect the results of all threads into the `results` vector.
// Use the `JoinHandle` struct which is returned by `thread::spawn`.
}
if results.len() != 10 {
panic!("Oh no! All the spawned threads did not finish!");
panic!("Oh no! Some thread isn't done yet!");
}
println!();
for (i, result) in results.into_iter().enumerate() {
println!("thread {} took {}ms", i, result);
println!("Thread {i} took {result}ms");
}
}

View file

@ -1,42 +1,34 @@
// threads2.rs
//
// 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.
// work. But this time, the spawned threads need to be in charge of updating a
// shared value: `JobStatus.jobs_done`
// I AM NOT DONE
use std::sync::Arc;
use std::thread;
use std::time::Duration;
use std::{sync::Arc, thread, time::Duration};
struct JobStatus {
jobs_completed: u32,
jobs_done: u32,
}
fn main() {
// TODO: `Arc` isn't enough if you want a **mutable** shared state
let status = Arc::new(JobStatus { jobs_completed: 0 });
// TODO: `Arc` isn't enough if you want a **mutable** shared state.
let status = Arc::new(JobStatus { jobs_done: 0 });
let mut handles = vec![];
let mut handles = Vec::new();
for _ in 0..10 {
let status_shared = Arc::clone(&status);
let handle = thread::spawn(move || {
thread::sleep(Duration::from_millis(250));
// TODO: You must take an action before you update a shared value
status_shared.jobs_completed += 1;
// TODO: You must take an action before you update a shared value.
status_shared.jobs_done += 1;
});
handles.push(handle);
}
// Waiting for all jobs to complete
// Waiting for all jobs to complete.
for handle in handles {
handle.join().unwrap();
}
// TODO: Print the value of `JobStatus.jobs_completed`
println!("Jobs completed: {}", ???);
// TODO: Print the value of `JobStatus.jobs_done`.
println!("Jobs done: {}", todo!());
}

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