1
0
mirror of https://github.com/rust-lang/rustlings.git synced 2025-12-26 00:11:49 +02:00

Compare commits

...

513 Commits
3.0.0 ... 4.6.0

Author SHA1 Message Date
ana
d57c183028 release: 4.6.0 2021-09-25 11:23:05 +02:00
diannasoriel
c2ed98deb3 Merge pull request #781 from tlyu/advanced-errs
feature: advanced errors
2021-09-25 11:18:55 +02:00
Taylor Yu
abd6b70c72 feat: add advanced_errs2
New exercise to demonstrate traits that make it easier for other code
to consume our custom error types.
2021-09-25 11:18:23 +02:00
Taylor Yu
882d535ba8 feat: add advanced_errs1
New section and exercise to demonstrate the `From` trait for errors
and its usefulness with the `?` operator.
2021-09-25 11:18:21 +02:00
diannasoriel
0de45ccdb7 Merge pull request #851 from rust-lang/all-contributors/add-frogtd
docs: add frogtd as a contributor for content
2021-09-25 10:53:13 +02:00
allcontributors[bot]
ab5ecbee7a docs: update .all-contributorsrc [skip ci] 2021-09-25 08:53:05 +00:00
allcontributors[bot]
e106d7a4f4 docs: update README.md [skip ci] 2021-09-25 08:53:04 +00:00
frogtd
d75759e829 fix(move_semantics5): change &mut *y to &mut x (#814)
Instead of having to explain why 
```rs
let mut x = 100; 
let y = &mut x;
let mut z_owned = *y;
let z = &mut z_owned;
*y += 100;
*z += 1000;
```
and 
```rs
let mut x = 100; 
let y = &mut x;
let z = &mut *y;
*y += 100;
*z += 1000;
```
are different, you still get the point across about having only one mutable reference.
As it stands, this exercise does too much (dereferencing and having only one mutable reference), and by doing so confuses people.

Example of someone being confused by this:
<https://discord.com/channels/273534239310479360/273541522815713281/872689531428692040>
2021-09-25 10:52:18 +02:00
diannasoriel
db9d7a907d Merge pull request #850 from rust-lang/all-contributors/add-abusch
docs: add abusch as a contributor for code
2021-09-25 10:48:04 +02:00
allcontributors[bot]
a1b9c50f36 docs: update .all-contributorsrc [skip ci] 2021-09-25 08:47:56 +00:00
allcontributors[bot]
c4b59aa593 docs: update README.md [skip ci] 2021-09-25 08:47:55 +00:00
diannasoriel
4a18bdeefe Merge pull request #843 from abusch/quit_command
feat: Add "quit" command to `rustlings watch`
2021-09-25 10:47:36 +02:00
Antoine Busch
1caef0b434 feat: Add "quit" command to rustlings watch
closes: #842
2021-09-24 23:55:55 +10:00
diannasoriel
ae56cba9c8 Merge pull request #846 from rust-lang/feat/add-more-watch-commands
feat: add more watch commands
2021-09-24 13:05:04 +02:00
ana
3352b5a4d3 chore: improve println! usage 2021-09-24 13:04:30 +02:00
diannasoriel
24762434ff Merge pull request #849 from rust-lang/all-contributors/add-Millione
docs: add Millione as a contributor for content
2021-09-21 11:50:41 +02:00
allcontributors[bot]
e9c0ca6be2 docs: update .all-contributorsrc [skip ci] 2021-09-21 09:50:32 +00:00
allcontributors[bot]
9ef63c0b9b docs: update README.md [skip ci] 2021-09-21 09:50:31 +00:00
LIU JIE
06d5c0973a fix(cli): typo in exercise.rs (#848) 2021-09-21 11:50:15 +02:00
diannasoriel
8d82856233 Merge pull request #847 from rust-lang/all-contributors/add-Weilet
docs: add Weilet as a contributor for content
2021-09-21 10:44:15 +02:00
allcontributors[bot]
9ddd4ca33a docs: update .all-contributorsrc [skip ci] 2021-09-21 08:44:04 +00:00
allcontributors[bot]
fe726f5bca docs: update README.md [skip ci] 2021-09-21 08:44:03 +00:00
Weilet
0a11bad714 feat(quiz1): add default function name in comment (#838) 2021-09-21 10:43:44 +02:00
ana
a7dc080b95 feat: add more watch commands
Includes:
- quit, to quit the shell instead of having to press Cmd/Ctrl-C or Cmd/Ctrl-D
- help, to display an overview of all the commands available in watch mode.

Closes #842.
2021-09-21 10:36:11 +02:00
diannasoriel
74af578beb Merge pull request #840 from MikAoJk/main
Added in ignore for .iml files
2021-09-09 15:54:57 +02:00
joakim.kartveit
6efa7d5d15 Added ignore for .iml files 2021-09-09 15:53:05 +02:00
diannasoriel
a6774100d4 Merge pull request #836 from rust-lang/all-contributors/add-granddaifuku
docs: add granddaifuku as a contributor for content
2021-09-06 16:33:15 +02:00
allcontributors[bot]
de22b13273 docs: update .all-contributorsrc [skip ci] 2021-09-06 14:33:05 +00:00
allcontributors[bot]
6c41adef63 docs: update README.md [skip ci] 2021-09-06 14:33:03 +00:00
granddaifuku
1c3beb0a59 fix(modules2): fix typo (#835) 2021-09-06 16:32:39 +02:00
diannasoriel
e4e9e4c963 Merge pull request #834 from rust-lang/all-contributors/add-anuk909
docs: add anuk909 as a contributor for content, code
2021-09-03 10:41:51 +02:00
allcontributors[bot]
44d8047249 docs: update .all-contributorsrc [skip ci] 2021-09-03 08:41:43 +00:00
allcontributors[bot]
5423f1be29 docs: update README.md [skip ci] 2021-09-03 08:41:42 +00:00
anuk909
dfd2fab4f3 feat(modules): update exercises, add modules3 (#822)
Co-authored-by: diannasoriel <mokou@fastmail.com>
2021-09-03 10:41:12 +02:00
diannasoriel
96fc301764 chore(quiz1): revert wording 2021-08-26 10:30:18 +02:00
diannasoriel
5bdb5de855 Merge pull request #830 from rust-lang/all-contributors/add-benarmstead
docs: add benarmstead as a contributor for code
2021-08-24 14:06:55 +02:00
allcontributors[bot]
a64dbdcc04 docs: update .all-contributorsrc [skip ci] 2021-08-24 12:06:45 +00:00
allcontributors[bot]
2f0ff258b1 docs: update README.md [skip ci] 2021-08-24 12:06:44 +00:00
Ben Armstead
1cd9328a58 fix(cli): remove unnecessary borrows (#829)
* Update dependencies

* Format better and remove unnecessary borrows
2021-08-24 14:06:30 +02:00
diannasoriel
ec527824b4 Merge pull request #828 from rust-lang/all-contributors/add-dbednar230
docs: add dbednar230 as a contributor for content
2021-08-24 10:49:50 +02:00
allcontributors[bot]
380587f120 docs: update .all-contributorsrc [skip ci] 2021-08-24 08:49:24 +00:00
allcontributors[bot]
ba8f97f418 docs: update README.md [skip ci] 2021-08-24 08:49:23 +00:00
Damian
03131a3d35 fix(quiz1): Fix inconsistent wording (#826)
The second test expects the function to return 80 when there is an order of 40 apples, but the current wording implies returning 40 will pass as well
2021-08-24 10:48:51 +02:00
ana
df25684cb7 fix(move_semantics5): Clarify instructions 2021-07-29 12:37:15 +02:00
fmoko
8e313cffaa Merge pull request #732 from apogeeoak/iterators5
chore(iterators5): Minor formatting improvements.
2021-07-09 12:24:42 +02:00
fmoko
6948905716 Merge pull request #737 from ghost/correct-small-typo
Correct small typo in exercises/conversions/from_str.rs
2021-07-08 11:07:21 +02:00
ana
ba087ce64a release: 4.5.0
Signed-off-by: ana <ana@ana.st>
2021-07-07 22:23:52 +02:00
fmoko
3b03865a62 Merge pull request #801 from rust-lang/all-contributors/add-sinharaksh1t
docs: add sinharaksh1t as a contributor for content
2021-07-07 22:20:02 +02:00
allcontributors[bot]
33fa274bbf docs: update .all-contributorsrc [skip ci] 2021-07-07 20:19:48 +00:00
allcontributors[bot]
23f700dc23 docs: update README.md [skip ci] 2021-07-07 20:19:47 +00:00
Rakshit Sinha
d876649616 fix(quiz1): Updated question description (#794)
Co-authored-by: Rakshit Sinha <rakshit.sinha@oracle.com>
2021-07-07 22:18:33 +02:00
fmoko
e4c14ac76e Merge pull request #800 from rust-lang/all-contributors/add-lauralindzey
docs: add lauralindzey as a contributor for doc
2021-07-07 22:17:12 +02:00
allcontributors[bot]
b438049c39 docs: update .all-contributorsrc [skip ci] 2021-07-07 20:17:04 +00:00
allcontributors[bot]
b017579577 docs: update README.md [skip ci] 2021-07-07 20:17:03 +00:00
fmoko
c8e4b357a3 Merge pull request #795 from lauralindzey/docs/section-mapping
docs: Update exercise to chapter mapping for HashMap
2021-07-07 22:16:45 +02:00
lauralindzey
8774e47dc3 docs: Update collections README with HashMap link 2021-07-06 01:31:27 -07:00
Laura Lindzey
e422ab1507 docs: Update exercise to chapter mapping for HashMap 2021-07-05 23:07:34 -07:00
marisa
cdd8e19716 Merge pull request #792 from rust-lang/all-contributors/add-cseltol
docs: add cseltol as a contributor for doc
2021-07-05 18:57:05 +02:00
allcontributors[bot]
91d86a1de9 docs: update .all-contributorsrc [skip ci] 2021-07-05 16:56:57 +00:00
allcontributors[bot]
6a10f900b4 docs: update README.md [skip ci] 2021-07-05 16:56:56 +00:00
marisa
9b9a89c79a Merge pull request #668 from cseltol/main
fix(installation): first PowerShell command
2021-07-05 18:56:34 +02:00
marisa
123e6426d1 Merge pull request #789 from kolbma/exercise-clippy1-hint-390
chore: clippy1 hint enhancement
2021-06-30 12:10:02 +02:00
marisa
427ec6b2e4 Merge pull request #790 from rust-lang/all-contributors/add-jazzplato
docs: add jazzplato as a contributor for code
2021-06-30 12:06:16 +02:00
allcontributors[bot]
03dcb582e6 docs: update .all-contributorsrc [skip ci] 2021-06-30 10:06:07 +00:00
allcontributors[bot]
1043a06124 docs: update README.md [skip ci] 2021-06-30 10:06:06 +00:00
Richthofen
d20e413a68 feat(cli): Add "next" to run the next unsolved exercise. (#785)
* Add "run next" to run the next unsolved exercise.

* Fix a grammar error in the message.

* Update README.md with the suggested change

Co-authored-by: marisa <mokou@fastmail.com>

* Update the README.md for "rustlings hint next".

Co-authored-by: marisa <mokou@fastmail.com>
2021-06-30 12:05:49 +02:00
arlecchino
9bf4c5e8df chore: clippy1 hint enhancement
Added some explanation and links about floating point representation and to use the clippy suggestion. (fixes #390)
2021-06-29 20:47:32 +02:00
marisa
633303d4b8 Merge pull request #787 from kolbma/exercise-iterator3-hint
chore: Update hint of iterators3
2021-06-29 13:49:17 +02:00
arlecchino
a4a1098766 Update info.toml
Co-authored-by: marisa <mokou@fastmail.com>
2021-06-29 13:41:16 +02:00
marisa
0bd459dcac Merge pull request #788 from rust-lang/all-contributors/add-kolbma
docs: add kolbma as a contributor for doc
2021-06-29 12:46:49 +02:00
allcontributors[bot]
3b4514b686 docs: update .all-contributorsrc [skip ci] 2021-06-29 10:46:41 +00:00
allcontributors[bot]
2e05606edc docs: update README.md [skip ci] 2021-06-29 10:46:40 +00:00
marisa
c8c1b87a01 Merge pull request #786 from kolbma/git-clone-release-tag
docs: Faster git clone command
2021-06-29 12:46:28 +02:00
arlecchino
34ea029df8 chore: Update hint of iterators3
`collect()` needs some hint for standard_library_types/iterators3 exercise with doc link for understanding different return types via `FromIterator`.
2021-06-29 12:03:18 +02:00
arlecchino
3a4433d5a2 docs: Faster git clone command
Clone only release tag without history
2021-06-28 17:08:53 +02:00
Taylor Yu
2dc93cadda fix(from_str, try_from_into): custom error types
Remove the use of trait objects as errors from `from_str` and
`try_from_into`; they seem to have caused a lot of confusion in
practice. (Also, it's considered best practice to use custom error
types instead of boxed errors in library code.) Instead, use custom
error enums, and update hints accordingly. Hints also provide
some guidance about converting errors, which could be covered
more completely in a future advanced errors section.

Also move from_str to directly after the similar exercise `from_into`,
for the sake of familiarity when solving.
2021-06-24 21:33:41 -05:00
marisa
de6c45ad24 Merge pull request #779 from rust-lang/all-contributors/add-hyperparabolic
docs: add hyperparabolic as a contributor for code
2021-06-24 14:18:02 +02:00
allcontributors[bot]
fadade8592 docs: update .all-contributorsrc [skip ci] 2021-06-24 12:17:32 +00:00
allcontributors[bot]
d91044f3a2 docs: update README.md [skip ci] 2021-06-24 12:17:31 +00:00
marisa
a3ea37b76e Merge pull request #771 from tlyu/iterators5-trait-tweak
fix(iterators5): derive Clone, Copy
2021-06-24 14:17:05 +02:00
marisa
ec63cadadb Merge pull request #772 from tlyu/errors-rework
feature: improve error_handling exercises
2021-06-24 14:12:34 +02:00
marisa
84d8305730 Merge pull request #778 from rust-lang/all-contributors/add-kayuapi
docs: add kayuapi as a contributor for content
2021-06-24 14:10:33 +02:00
allcontributors[bot]
73777980f1 docs: update .all-contributorsrc [skip ci] 2021-06-24 12:10:24 +00:00
allcontributors[bot]
75788b1148 docs: update README.md [skip ci] 2021-06-24 12:10:23 +00:00
marisa
dd9b2ddc89 Merge pull request #773 from kayuapi/patch-1
fix(variables5): confine the answer further
2021-06-24 14:10:02 +02:00
Taylor Yu
b7ddd09fab address review feedback
Adjust error text and naming to conform with best practices.
Use `map_err()` instead of `or()`. Wrap lower-level errors instead of
ignoring their details.

Also, don't "cheat" by bypassing the `new()` function in tests.

Fix a dangling reference in the try_from_into hints.
2021-06-09 23:27:53 -05:00
ZC
48ffcbd2c4 fix(variables5): confine the answer further
let mut number = 3; can lead to a correct answer, so the comment helps to direct the users to the intended answer.
2021-06-07 18:22:55 +08:00
Taylor Yu
68d3ac567c feature: improve error_handling exercises
Add new exercises errors5 and errors6, to introduce boxed errors and
custom error enums more gently. Delete errorsn, because it tried to do
too much too soon.
2021-06-06 23:08:57 -05:00
Taylor Yu
50ab289da6 fix: rename result1 to errors4
Also put it in the ERROR HANDLING section where it probably belongs.
2021-06-06 23:08:54 -05:00
Taylor Yu
4e079fdd08 chore(iterators5): conciseness hint 2021-06-06 17:45:35 -05:00
Taylor Yu
91fc9e3118 fix(iterators5): derive Clone, Copy
To allow more flexibility in solutions, derive `Clone` and `Copy`
for `Progress`.
2021-06-06 17:38:02 -05:00
marisa
a2f0401c4c Merge pull request #762 from tlyu/move-semantics5-fixes
fix: move_semantics5 hints
2021-05-23 15:41:56 +02:00
Taylor Yu
1b85828548 fix: move_semantics5 hints
Improve the hints for move_semantics5, as well as the explanatory
comments in the code.

Previously, it was not clear what possible changes were allowed.
It seems that reordering the statements might be the intended solution.
The previous comment about not "adding newlines" doesn't make sense,
so treating it as "adding new lines" makes it more clear.
2021-05-22 22:09:58 -05:00
Taylor Yu
4c46e5e1a3 chore: minor typos in move_semantics5 hints 2021-05-22 21:56:14 -05:00
marisa
4da9e7ee29 Merge pull request #758 from rust-lang/all-contributors/add-sateeshkumarb
docs: add sateeshkumarb as a contributor
2021-05-17 14:11:15 +02:00
allcontributors[bot]
72e615aa7a docs: update .all-contributorsrc [skip ci] 2021-05-17 12:11:05 +00:00
allcontributors[bot]
cd02abc481 docs: update README.md [skip ci] 2021-05-17 12:11:04 +00:00
Sateesh
399ab328d8 feat: Add move_semantics5 exercise. (#746)
* feat: Add move_semantics5 exercise.

* feat: Add option3 exercise

* Address review comments. Fix typos, sentence formatting.

* Remove unwanted newline.

* Address review comments: make comment inline, fix format in print.
2021-05-17 14:10:40 +02:00
marisa
809ec2ce01 Merge pull request #755 from tlyu/dyn-error-hints
fix(try_from_into, from_str): hints for dyn Error
2021-05-17 14:09:44 +02:00
Taylor Yu
11d2cf0d60 fix(try_from_into, from_str): hints for dyn Error
Add hints about how to return the correct type for functions that
return `Result<_, Box<dyn Error>`. Some feedback from Discord suggests
that people run into trouble with that.
2021-05-15 14:01:17 -05:00
marisa
dbb2624403 Merge pull request #751 from juanprq/main
fix: remove trailing whitespace
2021-05-13 17:20:47 +02:00
Juan Pablo Ramirez
4d4fa77459 fix: remove trailing whitespaces from iterators1 2021-05-12 10:20:07 -05:00
Juan Pablo Ramirez
3145794084 fix: add hints to generics1 and generics2 exercises 2021-05-11 14:50:05 -05:00
Juan Pablo Ramirez
d9b69bd1a0 fix: remove trailing whitespace 2021-05-09 17:58:54 -05:00
marisa
7cd635fa84 Merge pull request #740 from rust-lang/all-contributors/add-PiDelport
docs: add PiDelport as a contributor
2021-05-01 12:12:51 +02:00
allcontributors[bot]
ce40e201f0 docs: update .all-contributorsrc [skip ci] 2021-05-01 10:12:43 +00:00
allcontributors[bot]
404f3ef465 docs: update README.md [skip ci] 2021-05-01 10:12:42 +00:00
marisa
e1be594fdd Merge pull request #739 from PiDelport/patch-1
style(standard_library_types): stray line break
2021-05-01 12:12:29 +02:00
Pi Delport
9569c9a9e7 style(standard_library_types): stray line break 2021-04-29 23:31:26 +02:00
Martin HART
8794b40bc6 Merge branch 'correct-small-typo' of github.com:martinhartxyz/rustlings into correct-small-typo 2021-04-27 21:12:44 +02:00
Martin HART
86cc85295a fix: Correct small typo in exercises/conversions/from_str.rs 2021-04-27 21:11:40 +02:00
Martin HART
166a53946c Correct small typo in exercises/conversions/from_str.rs 2021-04-27 20:22:13 +02:00
marisa
91530f5716 Merge pull request #736 from maartentibau/quiz1_add_explicit_test_40
chore: Update quiz1.rs add explicit test for 40
2021-04-27 10:20:50 +02:00
Maarten Tibau
650b1dee54 chore: Update quiz1.rs add explicit test for 40 2021-04-25 19:02:50 +02:00
apogeeoak
7f0d2c2bf0 chore(iterators5): Minor formatting improvements. 2021-04-24 12:42:06 -04:00
marisa
6b6dc9dd48 Merge pull request #731 from rust-lang/all-contributors/add-stoiandan
docs: add stoiandan as a contributor
2021-04-24 17:36:48 +02:00
allcontributors[bot]
3a9ec4192d docs: update .all-contributorsrc [skip ci] 2021-04-24 15:36:39 +00:00
allcontributors[bot]
4f7dbbd2c3 docs: update README.md [skip ci] 2021-04-24 15:36:38 +00:00
marisa
8c37db1a23 Merge pull request #730 from stoiandan/main
updated README.md; specify need for admin rights
2021-04-24 17:36:19 +02:00
Dan Stoian
c6b7ad8878 updated README.md; specify need for admin rights 2021-04-24 18:32:13 +03:00
mokou
84461c20cb release: 4.4.0 2021-04-24 11:57:00 +02:00
marisa
3cddda56fc Merge pull request #725 from Zerotask/add-hint-corresponding-readme
chore(watch): add hint for the exercises README.md
2021-04-24 11:46:25 +02:00
marisa
37f3069a67 Merge pull request #724 from Zerotask/update-dependencies
chore(deps): update cargo dependencies
2021-04-24 11:45:56 +02:00
marisa
2b2fbe918e Merge pull request #723 from Zerotask/update-exercises-readme
docs(exercises): consistent excersises README.md files
2021-04-24 11:45:37 +02:00
Zerotask
cf42ddc449 chore(watch): add hint for the exercises README.md
rustlings watch will now show an additional hint for the corresponding README.me
2021-04-23 20:28:55 +02:00
Zerotask
eefa656232 chore(deps): update cargo dependencies 2021-04-23 20:07:32 +02:00
Zerotask
249ad44cc0 docs(exercises): updated all exercises readme files
all exercises readme files now have a unified structure and a description
2021-04-23 19:54:31 +02:00
marisa
54804e344d Merge pull request #721 from Zerotask/add-further-help-for-generics3
docs(generics): add bounds help
2021-04-23 15:05:00 +02:00
marisa
1c334de6fd Merge pull request #718 from Zerotask/add-further-help-to-error-excersis
docs(errors): add additional help for Result/Boxing
2021-04-23 15:04:47 +02:00
Zerotask
f253103a31 docs(generics): add bounds help
add help for bounds provided by the rust by example book
2021-04-22 22:11:04 +02:00
Zerotask
1120db57a6 docs(errors): add additional help for Result/Boxing
add additional help information provided by the rust by example book
2021-04-22 21:32:29 +02:00
marisa
afa661cff4 Merge pull request #715 from rust-lang/feat/declap
feat: Replace clap with argh
2021-04-21 16:33:07 +02:00
mokou
347f30bd86 fix(main): Let find_exercise work with borrows 2021-04-21 16:21:56 +02:00
marisa
127773f3f5 Merge pull request #717 from rust-lang/all-contributors/add-bmacer
docs: add bmacer as a contributor
2021-04-21 14:50:37 +02:00
allcontributors[bot]
8d0490bd70 docs: update .all-contributorsrc [skip ci] 2021-04-21 12:50:27 +00:00
allcontributors[bot]
293dfb35d5 docs: update README.md [skip ci] 2021-04-21 12:50:26 +00:00
Brandon Macer
81be404487 feat(arc1): Add more details to description and hint (#710)
Co-authored-by: bmacer <bmacer@cisco.com>
Co-authored-by: marisa <mokou@fastmail.com>
Co-authored-by: Roberto Vidal <vidal.roberto.j@gmail.com>
2021-04-21 14:50:03 +02:00
mokou
6177b6e126 chore: Fix integration tests 2021-04-21 14:47:53 +02:00
marisa
79cc657917 Merge pull request #646 from apogeeoak/iterator
Added iterators5.rs exercise.
2021-04-21 10:10:50 +02:00
mokou
7928122fce feat: Replace clap with argh
I’ve been wanting to do this for a while, but always procrastinated on it. We’ve been using Clap since the 2.0 rewrite, but Clap is known to be a fairly heavy library. Since Rustlings is usually peoples’ first contact with a Rust compilation, I think it’s in our best interests that this complation is as fast as possible. In effect, replacing Clap with the smaller, structopt-style `argh` reduces the amount of crates needing to be compiled from 82 to 60.

I also think this makes the code way easier to read, we don’t need to use Clap’s methods anymore, but can switch over to using pure Rust methods, e.g., switches are booleans, options are Option<String>s or the like, and subcommands are just structs.
2021-04-21 10:08:26 +02:00
apogeeoak
9c88ea9126 Improved iterators5.rs explanation. 2021-04-20 18:55:04 -04:00
marisa
2b766ef9f9 Merge pull request #648 from apogeeoak/iterator2
Moved iterators2.rs errors out of tests.
2021-04-20 11:24:10 +02:00
marisa
bd3d9ac9d5 Merge pull request #649 from apogeeoak/iterator3
Enabled iterators3.rs to run without commented out tests.
2021-04-20 11:22:39 +02:00
marisa
aa0db8379c Merge pull request #714 from rust-lang/all-contributors/add-hongshaoyang
docs: add hongshaoyang as a contributor
2021-04-20 11:19:49 +02:00
allcontributors[bot]
eadd41a9ec docs: update .all-contributorsrc [skip ci] 2021-04-20 09:19:39 +00:00
allcontributors[bot]
fab2eb9833 docs: update README.md [skip ci] 2021-04-20 09:19:38 +00:00
Shao Yang Hong
6bd791f2f4 fix(structs): Add 5.3 to structs/README (#652)
Co-authored-by: Shao Yang Hong <shaoyang.hong@ninjavan.co>
2021-04-20 11:19:24 +02:00
marisa
ec5f80dce1 Merge pull request #713 from rust-lang/all-contributors/add-k12ish
docs: add k12ish as a contributor
2021-04-20 11:18:32 +02:00
allcontributors[bot]
65cdc856ae docs: update .all-contributorsrc [skip ci] 2021-04-20 09:18:23 +00:00
allcontributors[bot]
472f61485e docs: update README.md [skip ci] 2021-04-20 09:18:22 +00:00
k12ish
b4de659438 fix(option2): Rename uninformative variables (#675)
Renaming uninformative names like `optional_value`, `value`, `optional_values_vec` and `value` helps users distinguish between the two parts of the task.
2021-04-20 11:18:05 +02:00
marisa
a37a8818c8 Merge pull request #712 from rust-lang/all-contributors/add-arthas168
docs: add arthas168 as a contributor
2021-04-20 11:16:25 +02:00
allcontributors[bot]
bdf01aa174 docs: update .all-contributorsrc [skip ci] 2021-04-20 09:16:16 +00:00
allcontributors[bot]
a941c69f09 docs: update README.md [skip ci] 2021-04-20 09:16:15 +00:00
Pete Pavlovski
72aaa15e6a fix(hashmap2): Update incorrect assertion (#660)
The test description says "at least five types of fruit", but the test itself is checking for exactly five types of fruit, which was a bit misleading for newcomers like me :) 

A simple change from "==" to ">=" should do the trick and successfully check for the "at least" condition.
2021-04-20 11:15:49 +02:00
marisa
3a06de71a8 Merge pull request #708 from Zerotask/list-command-added-to-readme
docs: added hint for rustlings list command
2021-04-20 11:10:38 +02:00
marisa
5e2b39a5c1 Merge pull request #711 from rust-lang/all-contributors/add-Zerotask
docs: add Zerotask as a contributor
2021-04-20 11:09:41 +02:00
allcontributors[bot]
63c942233e docs: update .all-contributorsrc [skip ci] 2021-04-20 09:09:31 +00:00
allcontributors[bot]
2612edc133 docs: update README.md [skip ci] 2021-04-20 09:09:30 +00:00
marisa
e2ce9f42b5 Merge pull request #707 from Zerotask/list-command-progress-info
feat(list): added progress info
2021-04-20 11:09:14 +02:00
Patrick Hintermayer
1c6f7e4b7b feat(list): updated progress percentage 2021-04-19 09:39:05 +02:00
Zerotask
e2c41903ad docs: added hint for rustlings list command
Added hint for `rustlings list` to the "Doing exercises" section.
2021-04-18 16:07:30 +02:00
Zerotask
bd48544e25 style: formatted files with rustfmt 2021-04-18 15:40:47 +02:00
Zerotask
c0e3daacaf feat(list): added progress info
Added a progress info at the bottom of the list for command: rustlings list

closes #705
2021-04-18 15:37:41 +02:00
Abdou Seck
f2ad3a6a0b Merge pull request #697 from WowSuchRicky/main
Rename 'Lichi' to 'Lychee' in the fruit example
2021-04-13 10:40:07 -04:00
Abdou Seck
caf921a01f Merge pull request #674 from Morsicus/fix/collections-exercises-naming
Update collections exercises naming
2021-04-13 10:39:18 -04:00
WowSuchRicky
b790bafc02 Rename lichi to lychee in the fruit example 2021-04-09 14:08:02 -07:00
Abdou Seck
ad3cd54cce Merge pull request #694 from rust-lang/all-contributors/add-tlyu
docs: add tlyu as a contributor
2021-04-05 07:27:42 -04:00
allcontributors[bot]
1a6a725f88 docs: update .all-contributorsrc [skip ci] 2021-04-05 11:27:17 +00:00
allcontributors[bot]
1ad20d94ff docs: update README.md [skip ci] 2021-04-05 11:27:16 +00:00
Abdou Seck
995c6f0fb1 Merge pull request #693 from tlyu/trait-obj-tryfrom
fix: use trait objects for try_from_into and from_str
2021-04-05 07:26:19 -04:00
Taylor Yu
c3e7b83178 fix: use trait objects for from_str
Use `Box<dyn error::Error>` to allow solutions to use `?` to propagate 
errors.
2021-04-04 18:56:10 -05:00
Taylor Yu
2e93a588e0 fix: use trait objects for try_from_into
Use `Box<dyn error::Error>` to allow solutions to use `?` to propagate
errors.  In the tests, explicitly check `is_ok()` instead of trying to
force the error type to `String` (or other `PartialEq` type) using
`assert_eq!()`.
2021-04-04 12:41:32 -05:00
marisa
9aeca3f97e Merge pull request #692 from rust-lang/all-contributors/add-flakolefluk
docs: add flakolefluk as a contributor
2021-04-04 09:44:02 +02:00
allcontributors[bot]
2193fff4bb docs: update .all-contributorsrc [skip ci] 2021-04-04 07:43:51 +00:00
allcontributors[bot]
aec2c65c63 docs: update README.md [skip ci] 2021-04-04 07:43:50 +00:00
Ignacio Le Fluk
a6509cc4d5 fix(functions3): improve function argument type (#687) 2021-04-04 09:43:25 +02:00
marisa
a02b279750 chore: Provide a working Windows installation link 2021-03-23 09:10:40 +01:00
marisa
ece841f5ce Merge pull request #680 from rust-lang/all-contributors/add-blerchy
docs: add blerchy as a contributor
2021-03-22 13:37:10 +01:00
allcontributors[bot]
2a6e4dc8a6 docs: update .all-contributorsrc [skip ci] 2021-03-22 12:37:02 +00:00
allcontributors[bot]
c163011cc0 docs: update README.md [skip ci] 2021-03-22 12:37:01 +00:00
marisa
b350945a16 Merge pull request #676 from blerchy/feat/no-emoji
Replace emojis when NO_EMOJI env variable present
2021-03-22 13:36:26 +01:00
marisa
1ef368a69d Merge pull request #679 from rust-lang/new-install-urls
chore: Update install URLs
2021-03-21 16:35:44 +01:00
marisa
8dc587b01a chore: Update install URLs 2021-03-21 16:34:21 +01:00
allcontributors[bot]
550c4293ed docs: add chapeupreto as a contributor (#678)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2021-03-20 21:13:35 +01:00
Rod Elias
3df094713f chore: capitalize c letter
By capitalizing the `c` letter it makes clear that we're talking about the C programming language.
2021-03-20 21:12:49 +01:00
Matt Lebl
01e7f27aa6 refactor: change from match to if for NO_EMOJI 2021-03-20 11:53:40 -07:00
Matt Lebl
8d62a99637 feat: Replace emojis when NO_EMOJI env variable present 2021-03-19 02:16:07 -07:00
Mickael Fortunato
ab9995e76e doc: Update collections exercises instruction to match the standard naming 2021-03-18 19:11:15 +01:00
Mickael Fortunato
bef39b1259 fix(collections): Naming exercises for vectors and hashmap 2021-03-18 19:11:04 +01:00
Pascal H
0d894e6ff7 fix(quiz3): Force an answer to Q2 (#672)
Add also an example of unimplemented!() macro.
2021-03-16 10:14:25 +01:00
allcontributors[bot]
be9510539e docs: add hpwxf as a contributor (#671)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2021-03-15 09:14:41 +01:00
Pascal H
3bce2ef8d6 chore: clarify collections documentation
C++ `map` is more like BTreeMap.

`unordered_map` in C++(11) is the equivalent of `HashMap` in Rust.
(+ additional like for references).
2021-03-15 09:14:12 +01:00
Ivan Nerazumov
aa9a943ddf fix(installation): first PowerShell command
ExecutionPolicy to RemoteSigned command was fixed because the old command was getting denied access to change the Execution Policy property
2021-03-13 18:45:52 +07:00
Darius Wiles
ebdb66c7bf fix(structs2): correct grammar in hint (#663) 2021-03-13 12:14:44 +01:00
Darius Wiles
9f3e8c2dde fix(structs3): reword heading comment (#664) 2021-03-13 12:14:02 +01:00
apogeeoak
96c56ab08a chore: changed errors3 mode from test to compile 2021-03-12 20:04:29 +01:00
allcontributors[bot]
04dbf03ace docs: add cadolphs as a contributor (#667)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2021-03-12 18:37:58 +01:00
cadolphs
05a753fe63 fix: add check to prevent naive implementation of is_international
* fix(structs3): Add check to prevent naive implementation

* chore(structs3): Add a missed newline after the test I added
2021-03-12 18:36:35 +01:00
allcontributors[bot]
815edb7003 docs: add cjwyett as a contributor (#666)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2021-03-12 15:39:40 +01:00
Cyrus Wyett
5157f56875 chore: fix typo
is however some --> are however some
2021-03-12 15:38:28 +01:00
allcontributors[bot]
3f5abca215 docs: add circumspect as a contributor
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2021-03-12 15:28:03 +01:00
circumspect
833df0b8b3 chore: fix typo
Co-authored-by: Chenkail <40770208+Chenkail@users.noreply.github.com>
2021-03-12 15:26:57 +01:00
marisa
6742860ea5 Merge pull request #658 from rust-lang/all-contributors/add-Crell
docs: add Crell as a contributor
2021-02-25 11:21:11 +01:00
allcontributors[bot]
797e6d45c0 docs: update .all-contributorsrc [skip ci] 2021-02-25 10:20:54 +00:00
allcontributors[bot]
320de0d921 docs: update README.md [skip ci] 2021-02-25 10:20:53 +00:00
marisa
5eed505d74 Merge pull request #656 from Crell/spelling-fix
fix: Spelling error
2021-02-25 11:20:39 +01:00
Larry Garfield
91ee27f22b fix: Spelling error 2021-02-24 15:03:26 -06:00
Jirka Kremser
5f7c89f85d fix(from_str): Correct typos
typos in the comments
2021-02-21 21:50:17 +01:00
apogeeoak
c6712dfccd fix(iterators3): Enabled iterators3.rs to run without commented out tests. 2021-02-12 15:36:53 -05:00
apogeeoak
baf4ba175b fix(iterators2): Moved errors out of tests.
Closes #359
2021-02-11 21:24:32 -05:00
apogeeoak
b29ea17ea9 feat: Added iterators5.rs exercise. 2021-02-10 18:03:29 -05:00
marisa
ab57c26cf9 Merge pull request #644 from apogeeoak/clippy
Updated source to follow clippy suggestions.
2021-02-10 10:37:13 +01:00
marisa
98e5e8835e Merge pull request #645 from rust-lang/all-contributors/add-apogeeoak
docs: add apogeeoak as a contributor
2021-02-10 10:36:57 +01:00
allcontributors[bot]
f5158ece1a docs: update .all-contributorsrc [skip ci] 2021-02-10 09:36:48 +00:00
allcontributors[bot]
d65b4a9a93 docs: update README.md [skip ci] 2021-02-10 09:36:47 +00:00
marisa
8404947bc0 Merge pull request #642 from apogeeoak/contributing
Fixed grammar in contributing.md.
2021-02-10 10:36:04 +01:00
apogeeoak
2e84f34cf3 chore: Updated source to follow clippy suggestions. 2021-02-09 18:21:18 -05:00
apogeeoak
726805f064 docs: Fixed grammar in contributing.md. 2021-02-09 17:43:53 -05:00
marisa
b4a4138559 Merge pull request #641 from rust-lang/all-contributors/add-tal-zvon
docs: add tal-zvon as a contributor
2021-02-07 12:22:49 +01:00
allcontributors[bot]
f1d2b3a39a docs: update .all-contributorsrc [skip ci] 2021-02-07 11:22:33 +00:00
allcontributors[bot]
1f9d006858 docs: update README.md [skip ci] 2021-02-07 11:22:32 +00:00
Tal
cc266d7d80 fix(move_semantics4): Remove redundant "instead" (#640) 2021-02-07 12:22:13 +01:00
marisa
fff72afe2e Merge pull request #636 from rust-lang/all-contributors/add-jbaber
docs: add jbaber as a contributor
2021-01-30 17:12:39 +01:00
allcontributors[bot]
c1abd13b5c docs: update .all-contributorsrc [skip ci] 2021-01-30 16:12:28 +00:00
allcontributors[bot]
75802c14b2 docs: update README.md [skip ci] 2021-01-30 16:12:27 +00:00
John Baber-Lucero
cddc1e86e7 fix(info): Fix typo (#635)
Co-authored-by: John Baber-Lucero <git@frundle.com>
2021-01-30 17:12:06 +01:00
fmoko
24ea42ce61 Merge pull request #627 from rust-lang/all-contributors/add-jfchevrette
docs: add jfchevrette as a contributor
2021-01-22 13:11:43 +01:00
allcontributors[bot]
6102e612fa docs: update .all-contributorsrc [skip ci] 2021-01-22 12:11:34 +00:00
allcontributors[bot]
52bde71166 docs: update README.md [skip ci] 2021-01-22 12:11:33 +00:00
Abdou Seck
15a79cfe9c Merge pull request #626 from jfchevrette/patch-1
Fix instructions(steps) for conversions/from_str exercice
2021-01-21 08:10:25 -05:00
Jean-Francois Chevrette
15e71535f3 fix(from_str): test for error instead of unwrap/should_panic 2021-01-21 07:55:22 -05:00
mokou
9f988bfe29 docs: Remove duplicate uninstallation section 2021-01-17 13:00:50 +01:00
fmoko
e8d1baa4b5 Merge pull request #599 from AbdouSeck/improve-list-command
feat(cli): Improve the list command with options, and then some
2021-01-17 12:37:58 +01:00
Abdou Seck
8bbe4ff138 feat(cli): Improve the list command with options, and then some
1.
`rustlings list` should now display more than just the exercise names.
Information such as file paths and exercises statuses should be displayed.
The `--paths` option limits the displayed fields to only the path names; while the `--names`
option limits the displayed fields to only exercise names.
You can also control which exercises are displayed, by using the `--filter` option, or
the `--solved` or `--unsolved` flags.

Some use cases:
- Fetching pending exercise files with the keyword "conversion" to pass to my editor:
```sh
vim $(rustlings list --filter "conversion" --paths --unsolved)
```

- Fetching exercise names with keyword "conversion" to pass to `rustlings run`:
```sh
for exercise in $(rustlings list --filter "conversion" --names)
do
    rustlings run ${exercise}
done
```

2.
This should also fix #465, and will likely fix #585, as well.
That bug mentioned in those issues has to do with the way the `watch` command handler fetches the pending exercises.
Going forward, the least recently updated exercises along with all the other exercises in a pending state are fetched.
2021-01-08 13:21:00 -05:00
Abdou Seck
0b9220c1fc Add looks_done method to Exercise to expose a resolution state 2021-01-08 13:21:00 -05:00
Abdou Seck
0d65753fdb Merge pull request #622 from lntuition/conversions_more_utc
feat(conversions): Add more unit tests to `from_str` and `from_into` exercises.
2021-01-08 13:18:24 -05:00
Sang-Heon Jeon
4f1374a6e7 feat(from_into) : add test for checking unnecessary trailing value 2021-01-09 00:08:38 +09:00
Sang-Heon Jeon
5a0521e92c feat(from_str) : add test for checking unnecessary trailing value 2021-01-09 00:07:13 +09:00
fmoko
fea86c29d6 chore: Remove Readme GIF 2021-01-08 14:01:04 +01:00
fmoko
9c4614f7e6 Merge pull request #619 from rust-lang/all-contributors/add-chrizel
docs: add chrizel as a contributor
2021-01-06 16:54:47 +01:00
allcontributors[bot]
c24a78ae94 docs: update .all-contributorsrc [skip ci] 2021-01-06 15:54:34 +00:00
allcontributors[bot]
621816fb56 docs: update README.md [skip ci] 2021-01-06 15:54:33 +00:00
fmoko
cfae54d361 Merge pull request #618 from chrizel/patch-1
fix(threads1): line number correction
2021-01-06 16:54:16 +01:00
Christian Zeller
7857b0a689 fix(threads1): line number correction 2021-01-06 13:47:20 +01:00
Marius Ungureanu
10965920fb fix(move_semantics4): Small readbility improvement (#617)
* Small readbility improvement move_semantics4 doc

* Remove `an` as it refers to the argument
2021-01-06 10:12:33 +01:00
fmoko
d2e7ecabd8 Merge pull request #616 from rust-lang/all-contributors/add-wsh
docs: add wsh as a contributor
2021-01-04 14:12:24 +01:00
fmoko
5772589dc3 Merge pull request #615 from wsh/docfixes
docs: mention flatten in the options2 hint
2021-01-04 14:12:11 +01:00
allcontributors[bot]
6df08b411b docs: update .all-contributorsrc [skip ci] 2021-01-04 13:12:11 +00:00
allcontributors[bot]
c355ac6593 docs: update README.md [skip ci] 2021-01-04 13:12:10 +00:00
Will Hayworth
e9b42bbc2a docs: mention flatten in the options2 hint 2021-01-03 03:42:39 -08:00
Abdou Seck
1283aa3bd8 Merge pull request #606 from RoelofWobben/ghost-RoelofWobben-patch-1
fix: Update README.md for Windows users to exclude the rustlings directory
from the list of directories scanned by Anti-Virus programs.
2020-12-31 11:13:03 -05:00
RoelofWobben
ff6cba7205 Update README.md 2020-12-31 10:57:37 -05:00
fmoko
d0107f7921 Merge pull request #609 from xehpuk/patch-1
fix: typo in default out text
2020-12-31 16:12:13 +01:00
xehpuk
644c49f1e0 fix: typo in default out text 2020-12-30 22:56:04 +01:00
mokou
a303d508cf release: 4.3.0 2020-12-29 11:39:26 +01:00
mokou
44d39112ff feat: Rewrite default out text
This has been in place for a long time now, before we had an install
script, so it ended up repeating a bunch of the same things that the
install script does automatically. I rewrote it so that it gives more
helpful information about how you're supposed to do Rustlings.
Hopefully this will reduce the number of "I started Rustlings and it
gave me an error" issues (no offense to anyone who opened one of those,
it was pretty unclear that it _wasn't_ an error).
2020-12-29 11:34:52 +01:00
mokou
28020d0c54 docs: Add note on uninstalling to README 2020-12-29 11:23:08 +01:00
Axel Viala
0ef95947cc fix(functions2): Change signature to trigger precise error message: (#605)
Now trigger this error:
```
error: expected type, found `)`
  --> exercises/functions/functions2.rs:10:16
   |
10 | fn call_me(num:) {
   |                ^ expected type

```
2020-12-27 12:36:38 +01:00
allcontributors[bot]
4ac70a99ae docs: add seancad as a contributor
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-12-15 08:33:47 +01:00
seancad
bcf14cf677 fix: update structs README 2020-12-15 08:32:46 +01:00
fmoko
1dae782cd4 Merge pull request #598 from JuliaCao/update_exec_order
fix: added missing exercises to info.toml
2020-12-13 02:30:57 +01:00
JuliaCao
90cfb6ff28 fix: added missing exercises to info.toml 2020-12-12 10:34:59 -08:00
allcontributors[bot]
26110da7ca docs: add pcn as a contributor
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-12-08 10:12:57 +01:00
Peter N
30644c9a06 fix: gives a bit more context to magic number 2020-12-08 10:08:25 +01:00
JuliaCao
033bf1198f feat: match exercise order to book chapters (#541)
Added exercise to book chapter mapping table to exercise README
2020-12-07 15:37:19 +01:00
fmoko
cdc7d92e57 Merge pull request #592 from tinkhauser/vec1_bugfix
fix(vec1): Have test compare every element in a and v
2020-12-06 15:09:45 +01:00
fmoko
af0e3b8f17 Merge pull request #594 from xakon/fix/try_from_into
feat(try_from_into): remove duplicate annotation
2020-12-03 18:23:48 +01:00
Christos Kontas
04f1d079aa feat(try_from_into): remove duplicate annotation 2020-12-03 17:51:30 +01:00
Jacob Tinkhauser
9b6c629397 fix(vec1): Have test compare every element in a and v
The previous test would stop comparing elements in array a and vec v upon reaching the last element of either. This resulted in the test passing even if v did not contain all the elements in a. This change to the test fixes that bug and should only pass if all the elements in a and v are present and equal.
2020-11-29 01:35:14 +00:00
fmoko
5aa467bef2 Merge pull request #587 from wh5a/bugfix
fix(try_from_into): type error
2020-11-12 16:36:50 +01:00
fmoko
af7ad27f89 chore: Remove buildkite build file 2020-11-12 09:50:55 +01:00
fmoko
d6d57bfbb8 docs: Remove buildkite badge from README 2020-11-12 09:50:39 +01:00
Wei Hu
4f4cfcf3c3 fix(try_from_into): type error 2020-11-11 21:02:00 -08:00
Brock
fa9f522b7f feat: Crab? (#586)
Crab?
2020-11-11 23:06:14 +01:00
Caleb Webber
838f9f3008 feat: add "rustlings list" command 2020-11-10 18:36:19 +01:00
JP
96347df9df fix(try_from_into): Update description (#584)
Description update
2020-11-08 19:30:40 +01:00
Brock
9334783da3 fix(structs1): Adjust wording (#573)
Co-authored-by: fmoko <mokou@posteo.de>
2020-11-08 10:31:45 +01:00
mokou
964b2a331d release: 4.2.0 2020-11-07 14:21:10 +01:00
fiplox
95ccd92616 feat(try_from_into): Add tests (#571)
Co-authored-by: Volodymyr Patuta <6977238-fiplox@users.noreply.gitlab.com>
2020-11-07 14:01:39 +01:00
JP
197d3a3d89 fix(iterators2): Update description (#578)
grammar fix in the description
2020-11-07 13:54:14 +01:00
fmoko
a7ddd747ca Merge pull request #582 from seeplusplus/inotify-watch-error
fix: log error output when inotify limit is exceeded
2020-11-07 13:53:35 +01:00
Caleb Webber
d61b4e5a13 fix: log error output when inotify limit is exceeded
closes #472
2020-11-05 19:30:50 -05:00
allcontributors[bot]
68e646f8aa docs: add seeplusplus as a contributor 2020-11-05 10:03:43 +01:00
Caleb Webber
21bfb2d477 fix(installation): Update the MinRustVersion
closes #577df

Co-authored-by: Caleb Webber <seeplusplus@users.noreply.github.com>
2020-11-05 09:59:25 +01:00
fmoko
a9dae71188 Merge pull request #574 from jrvidal/temp_file
fix: more unique temp_file
2020-10-31 12:57:33 +01:00
fmoko
dd84cc5fd4 Merge pull request #575 from rust-lang/all-contributors/add-sazid 2020-10-30 20:29:47 +01:00
allcontributors[bot]
51631f4c2e docs: update .all-contributorsrc [skip ci] 2020-10-30 19:29:37 +00:00
allcontributors[bot]
535a8c8243 docs: update README.md [skip ci] 2020-10-30 19:29:36 +00:00
fmoko
7abfbd23d0 Merge pull request #572 from sazid/main 2020-10-30 20:28:46 +01:00
sazid
633c00cf80 feat: Add HashMap exercises 2020-10-31 01:11:04 +06:00
sazid
0c12fa31c5 feat: Add Vec exercises 2020-10-31 01:10:49 +06:00
Roberto Vidal
5643ef05bc fix: more unique temp_file 2020-10-30 14:39:28 +01:00
fmoko
f38f42f17d Merge pull request #561 from notmatt/mbs-fixups 2020-10-14 17:22:49 +02:00
Matthew Smillie
472d8592d6 fix(primitive_types6): remove 'unused doc comment' warning 2020-10-13 23:20:17 -07:00
Matthew Smillie
4fb230daf1 fix(primitive_types6): missing comma in test 2020-10-13 23:18:41 -07:00
Rastamo
e6bde22f9c chore: primitive_types6 mode changed to test (#559)
primitive_types6 exercise was changed to test yesterday, but info.toml file wasn't updated.
I think this change should fix it.
2020-10-11 14:00:03 +02:00
allcontributors[bot]
cc5b9b772a docs: add AnnikaCodes as a contributor (#557)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
Co-authored-by: fmoko <mokou@posteo.de>
2020-10-10 17:08:22 +02:00
allcontributors[bot]
ded1474bbb docs: add darnuria as a contributor (#554)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-10-10 16:07:15 +02:00
Axel Viala
2b1fb2b739 feat(primitive_types6): Add a test (#548)
Co-authored-by: Annika <56906084+AnnikaCodes@users.noreply.github.com>
Co-authored-by: fmoko <mokou@posteo.de>
2020-10-10 16:04:19 +02:00
Ryan McQuen
18e0bfef1d fix(quiz3): Second test is for odd numbers, not even. (#553) 2020-10-10 13:11:57 +02:00
fmoko
3be760dc38 Merge pull request #552 from rust-lang/all-contributors/add-ryanpcmcquen 2020-10-09 02:16:07 +02:00
allcontributors[bot]
29dd0b1e41 docs: update .all-contributorsrc [skip ci] 2020-10-09 00:15:54 +00:00
allcontributors[bot]
e1fdfbb062 docs: update README.md [skip ci] 2020-10-09 00:15:53 +00:00
mokou
89c07b5e43 release: 4.1.0 2020-10-05 18:42:26 +02:00
fmoko
9b5350eab1 Merge pull request #546 from jienius/doc-improve-readme
docs: Fix grammatical errors in Readme
2020-10-02 12:52:34 +02:00
jieniu$
5382cd696a docs: Fix grammatical errors in Readme 2020-10-01 20:15:36 -06:00
fmoko
69fc9ce10e Merge pull request #545 from YJDoc2/main 2020-10-01 12:17:05 +02:00
Yashodhan Joshi
13ac6f38dc Merge branch 'master' of https://github.com/YJDoc2/rustlings 2020-10-01 08:34:01 +05:30
Yashodhan Joshi
2ec0bdfd99 fix(variables5) : make shadowing more prominent
closes #375
2020-10-01 08:31:42 +05:30
Alexx Roche
c03e1e6c6c chore: fixed test name 2020-09-27 21:57:51 +02:00
fmoko
2a682abeef Merge pull request #522 from calvinbrown085/adding-test-for-false-case 2020-09-27 17:05:42 +02:00
allcontributors[bot]
9f38b54a2d docs: add greg-el as a contributor
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-09-25 13:43:01 +02:00
Greg Leonard
2933f51949 chore: Change point to comma in from_into.rs
A typo in the fn test_bad_age() hint message had a point rather than comma

Prev:
// Test that "Mark.twenty"

Current:
// Test that "Mark,twenty"
2020-09-25 13:39:52 +02:00
fmoko
a75300b8c7 Merge pull request #536 from rust-lang/all-contributors/add-dev-cyprium 2020-09-22 11:31:53 +02:00
allcontributors[bot]
01f4bb86c3 docs: update .all-contributorsrc [skip ci] 2020-09-22 09:31:42 +00:00
allcontributors[bot]
79c3ada49b docs: update README.md [skip ci] 2020-09-22 09:31:41 +00:00
fmoko
ac276d06fa Merge pull request #535 from rust-lang/all-contributors/add-GaurangTandon 2020-09-22 11:04:45 +02:00
allcontributors[bot]
c7eabe61bb docs: update .all-contributorsrc [skip ci] 2020-09-22 09:04:33 +00:00
allcontributors[bot]
8f28bcf704 docs: update README.md [skip ci] 2020-09-22 09:04:32 +00:00
fmoko
be3b289a10 Merge pull request #534 from rust-lang/all-contributors/add-jmahmood 2020-09-22 10:57:44 +02:00
allcontributors[bot]
19a0c1f3cb docs: update .all-contributorsrc [skip ci] 2020-09-22 08:57:33 +00:00
allcontributors[bot]
dc94fcc6e8 docs: update README.md [skip ci] 2020-09-22 08:57:32 +00:00
fmoko
183237c858 Merge pull request #533 from rust-lang/all-contributors/add-EvanCarroll 2020-09-22 10:56:28 +02:00
allcontributors[bot]
599a44f90f docs: update .all-contributorsrc [skip ci] 2020-09-22 08:56:18 +00:00
allcontributors[bot]
08e9c7aa2f docs: update README.md [skip ci] 2020-09-22 08:56:17 +00:00
fmoko
a893d04e81 Merge pull request #532 from rust-lang/all-contributors/add-siobhanjacobson 2020-09-22 10:55:09 +02:00
allcontributors[bot]
5996bd57ea docs: update .all-contributorsrc [skip ci] 2020-09-22 08:54:54 +00:00
allcontributors[bot]
909b297ae3 docs: update README.md [skip ci] 2020-09-22 08:54:53 +00:00
fmoko
abdc3b2211 Merge pull request #531 from rust-lang/all-contributors/add-wrobstory 2020-09-22 10:52:39 +02:00
allcontributors[bot]
e66d2085b7 docs: update .all-contributorsrc [skip ci] 2020-09-22 08:52:29 +00:00
allcontributors[bot]
4a5e48e88f docs: update README.md [skip ci] 2020-09-22 08:52:28 +00:00
fmoko
3a586a0c19 Merge pull request #530 from rust-lang/all-contributors/add-DiD92 2020-09-22 10:51:01 +02:00
allcontributors[bot]
144dec3fd3 docs: update .all-contributorsrc [skip ci] 2020-09-22 08:50:51 +00:00
allcontributors[bot]
448d116a89 docs: update README.md [skip ci] 2020-09-22 08:50:50 +00:00
fmoko
8493e5d09f Merge pull request #529 from rust-lang/all-contributors/add-apatniv 2020-09-22 10:50:07 +02:00
allcontributors[bot]
83e7365fd8 docs: update .all-contributorsrc [skip ci] 2020-09-22 08:49:57 +00:00
allcontributors[bot]
b6040e6061 docs: update README.md [skip ci] 2020-09-22 08:49:56 +00:00
fmoko
858b9a5119 Merge pull request #528 from rust-lang/all-contributors/add-bertonha 2020-09-22 10:48:48 +02:00
allcontributors[bot]
00fbcd14f7 docs: update .all-contributorsrc [skip ci] 2020-09-22 08:48:39 +00:00
allcontributors[bot]
062f18d353 docs: update README.md [skip ci] 2020-09-22 08:48:38 +00:00
fmoko
58760bce54 Merge pull request #527 from rust-lang/all-contributors/add-jihchi 2020-09-22 10:45:07 +02:00
allcontributors[bot]
ca4f026074 docs: update .all-contributorsrc [skip ci] 2020-09-22 08:44:57 +00:00
allcontributors[bot]
f285ac2281 docs: update README.md [skip ci] 2020-09-22 08:44:56 +00:00
fmoko
0f3db4dbb9 Merge pull request #526 from rust-lang/all-contributors/add-Darrenmeehan 2020-09-22 10:43:33 +02:00
allcontributors[bot]
18b2d451cd docs: update .all-contributorsrc [skip ci] 2020-09-22 08:43:24 +00:00
allcontributors[bot]
b6dd1af7d2 docs: update README.md [skip ci] 2020-09-22 08:43:23 +00:00
fmoko
303c8ee7cd Merge pull request #525 from rust-lang/all-contributors/add-avrong 2020-09-22 10:40:56 +02:00
allcontributors[bot]
98d6b15fc0 docs: update .all-contributorsrc [skip ci] 2020-09-22 08:40:46 +00:00
allcontributors[bot]
77f407dd5f docs: update README.md [skip ci] 2020-09-22 08:40:45 +00:00
fmoko
a12a3ef08b Merge pull request #524 from rust-lang/all-contributors/add-lebedevsergey 2020-09-22 10:39:10 +02:00
allcontributors[bot]
6480fcaf7c docs: update .all-contributorsrc [skip ci] 2020-09-22 08:39:00 +00:00
allcontributors[bot]
f5cb439fe6 docs: update README.md [skip ci] 2020-09-22 08:38:59 +00:00
fmoko
15c9e85690 Merge pull request #523 from rust-lang/all-contributors/add-uce 2020-09-22 10:37:34 +02:00
allcontributors[bot]
8f8a85303b docs: update .all-contributorsrc [skip ci] 2020-09-22 08:36:53 +00:00
allcontributors[bot]
114cc2db21 docs: update README.md [skip ci] 2020-09-22 08:36:52 +00:00
Calvin Brown
bec97b6c76 Fixing test3 to have enough tests to make sure we test all cases 2020-09-21 15:23:19 -05:00
Jannek Squar
114b54cbdb fix(structs3): Small adjustment of variable name
Co-authored-by: Jannek <squar@informatik.uni-hamburg.de>
2020-09-19 21:22:56 +02:00
fmoko
0f16463794 Merge pull request #489 from mukundbhudia/iterators1 2020-09-18 15:23:28 +02:00
Mukund Bhudia
8ff5fde88e Update info.toml for typo fix
Co-authored-by: Andrew Marquez <andy2mgcc@gmail.com>
2020-09-18 10:40:11 +01:00
Ryan McQuen
3286c5ec19 fix(using_as): Add test so that proper type is returned. (#512) 2020-09-07 19:09:27 +02:00
Koalab99
ee7cdc66b3 chore: Removed extra whitespaces
Co-authored-by: Corentin ARNOULD <corentin.arn@gmail.com>
2020-08-27 19:51:19 +02:00
fmoko
9699da4968 Merge pull request #506 from bhgsbatista/patch-1
Make macros4 not compile by default
2020-08-27 11:21:09 +02:00
Samuel Batista
6bb0b48b10 Make macros4 not compile by default
Did you mean this? I'm new to rust and this test passed right away, so unsure what the intention was.
2020-08-26 22:17:03 -04:00
fmoko
70da09eae2 Merge pull request #504 from Ant0wan/quiz2_markers
fix(exercises): adding question mark to quiz2
2020-08-25 21:05:16 +02:00
Antoine Barthelemy
101072ab9f fix(exercises): adding question mark to quiz2
Question marks added for consistency.

closes #496
2020-08-25 16:38:41 +02:00
fmoko
47f7672c03 fix(generics3): clarify grade change 2020-08-25 10:45:12 +02:00
John Heath
dd54ccf677 Make comments on example clearer
I actually struggled because I overlooked the fact that I needed to change the 2.1 to "A+". 

So I wanted to make things clearer for future rustlings.
2020-08-24 22:37:31 +01:00
fmoko
66ec916b3d Merge pull request #498 from seeplusplus/main
fix(arc1): index mod should equal thread count
2020-08-17 12:48:41 +02:00
seeplusplus
b4062ef699 fix(arc1): index mod should equal thread count 2020-08-16 20:55:50 -04:00
fmoko
2d3816341e Merge pull request #492 from etiennebarrie/rustfmt-on-exercises
chore: Run rustfmt on exercises
2020-08-10 17:33:55 +02:00
fmoko
d1054cd596 Merge pull request #493 from etiennebarrie/cargo-fmt
chore: Run cargo fmt
2020-08-10 17:33:22 +02:00
Étienne Barrié
81f8c2f83c chore: Run cargo fmt 2020-08-10 10:42:54 -04:00
Étienne Barrié
3144d3ae63 chore: Run rustfmt on exercises 2020-08-10 10:24:21 -04:00
Mukund Bhudia
9642f5a3f6 feat: Added iterators1.rs exercise 2020-08-04 12:57:01 +01:00
fmoko
c4853ee6bb Merge pull request #487 from dmarcoux/update-rustlings-in-cargo-lock 2020-08-04 01:57:04 +02:00
Dany Marcoux
1cc40bc9ce fix: Update rustlings version in Cargo.lock 2020-08-03 22:17:32 +02:00
Robby
38a615f407 chore: add .vscode to gitignore 2020-07-24 13:23:01 +02:00
Adi Vaknin
4f2468e14f feat(cli): Added 'cls' command to 'watch' mode (#474) 2020-07-23 20:23:27 +02:00
Ryan McQuen
8f7b5bd00e feat: Add ability to run rustlings on repl.it (#471)
Co-authored-by: fmoko <mokou@posteo.de>
2020-07-23 19:21:15 +02:00
Ryan McQuen
4821a8be94 feat: Add gitpod support (#473) 2020-07-23 19:20:21 +02:00
Chad Dougherty
523d18b873 feat(try_from_into): Add insufficient length test (#469) 2020-07-13 11:39:05 +02:00
Eli Blaney
c52be7dfcb docs: Add uninstall info to README.md
* docs: Add uninstall info to README.md
* docs: Format commands as bash block
2020-07-12 08:44:11 +01:00
fmoko
c2bfcf1c54 Merge pull request #468 from benjaminfjones/fix/exercise_whitespace
chore: change exercise whitespace for consistency
2020-07-11 23:12:58 +02:00
Benjamin Jones
bb5f404e35 chore: Alter whitespace for consistency
* Add newline after "I AM DONE" in exercises for consistency
* Remove trailing whitespace from exercises
2020-07-11 11:50:54 -07:00
Philip Pokarowski
106dbbc341 Update README.md (#464) 2020-07-09 09:25:50 +02:00
DEWA Kazuyuki/出羽和之
4b6540c71a fix(enums3): Update Message::ChangeColor to take a tuple. (#457) 2020-07-08 11:56:43 +02:00
Alexx Roche
816b1f5e85 feat: Remind the user of the hint option (#425)
Suggestion from AbdouSeck https://github.com/rust-lang/rustlings/issues/424#issuecomment-639870331
for when the student's code has errors.
2020-07-08 11:52:23 +02:00
Alexx Roche
9f61db5dbe feat: Remind the user of the hint option (#425)
Suggestion from AbdouSeck https://github.com/rust-lang/rustlings/issues/424#issuecomment-639870331
for when the student's code has errors.
2020-07-08 11:51:12 +02:00
mokou
e823bef970 docs: Add missing closing brackets to changelog 2020-07-08 11:43:08 +02:00
mokou
f9ccc6a289 release: 4.0.0 2020-07-08 11:35:27 +02:00
fmoko
b32a666541 Merge pull request #458 from Sowed/main 2020-07-01 10:19:45 +02:00
iamcastelli
b636825de3 Merge pull request #1 from Sowed/then-to-than-docs-patch
fix: Change then to than
2020-06-27 16:49:39 +04:00
iamcastelli
ddd98ad75d fix: Change then to than
`than` makes more grammatical sense than `then` in this context.
2020-06-27 15:58:53 +04:00
mokou
d355927024 Merge remote-tracking branch 'origin/master' into main 2020-06-22 04:47:27 +02:00
fmoko
75c0053bb1 Merge pull request #433 from SebastienCaunes/fix#432
fix : Use of integer for prices, therefore also for weight
2020-06-22 00:09:09 +02:00
mokou
55a9284665 chore: Move from master branch to main branch 2020-06-14 14:48:51 +02:00
Alexx Roche
113cdae2d4 fix(arc1): Passively introduce attributes (#429)
Ensure that std::sync::Arc is actually used, as this exercise can be compiled using things already learnt in previous exercises.
2020-06-14 12:15:35 +02:00
fmoko
c6295ade33 Merge pull request #428 from millefalcon/master
Added example with `String` to show the AsRef working
2020-06-13 22:15:57 +02:00
fmoko
e1e453075f Merge pull request #422 from AbdouSeck/show-tests-prints 2020-06-12 23:04:51 +02:00
Sebastien Caunes
9ca08b8f2b fix : Use of integer for prices, therefore also for weight
rename confusing "from" and "to" to sender_country and recipient_country as suggested
2020-06-11 11:44:47 -05:00
tim bangma
f47d3f422d docs: Update Invoke-WebRequest to Start-BitsTransfer (#373) 2020-06-10 10:51:03 +02:00
Alexx Roche
e6bd8021d9 fix(generics2): Guide students to the answer (#430) 2020-06-09 13:54:18 +02:00
millefalcon
307252e9ae Added example to show the AsRef working 2020-06-08 07:51:34 -04:00
Alexx Roche
bb2ca25110 fix(box1): fix comment typo (#426)
Doesn't effect the code.
2020-06-06 12:07:39 +02:00
Abdou Seck
9e4fb1009f fix(installation): Provide a backup git reference when tag can't be curl
closes #423

If the parsed JSON data curled during a bash installation is not valid, use the repository's tag files
as a backup. If those files don't exist somehow, then checkout the master branch and install it.
2020-06-05 16:33:14 -04:00
Abdou Seck
8ad5f9bf53 feat: Add a --nocapture option to display test harnesses' outputs
This new feature can be accessed by invoking rustlings with --nocapture.

Both unit and integration tests added.

closes #262

BREAKING CHANGES:
The following function take a new boolean argument:
	* `run`
	* `verify`
	* `test`
	* `compile_and_test`
2020-06-04 11:18:26 -04:00
Abdou Seck
02a2fe4871 Collapse nested if statements 2020-06-04 11:18:09 -04:00
Abdou Seck
40741c5b0b Use .to_string rather than format macro 2020-06-03 17:18:48 -04:00
Alexx Roche
0dd1c6ca6b fix: rename quiz1 to tests1 in info (#420)
`rustlings run tests1` wasn't working because of this typo.
2020-06-03 20:07:06 +02:00
Alexx Roche
5563adbb89 fix: fix quiz naming inconsistency (#421)
Inconsistent naming when compared with the other quiz files.
2020-06-03 20:06:35 +02:00
Alexx Roche
524e17df10 fix(variables6): minor typo (#419)
Looks like this was cloned from variables5.rs
2020-06-03 13:34:43 +02:00
fmoko
73e848e96f Merge pull request #416 from danwilhelm/traits-readme
feat: Add traits README
2020-05-30 17:58:31 +02:00
fmoko
5f0806967c Merge pull request #409 from AlexandruGG/feature/box-exercise 2020-05-30 17:58:16 +02:00
Dan Wilhelm
173bb14140 feat: Add traits README 2020-05-28 20:21:33 -07:00
fmoko
918f310674 Merge pull request #410 from tsauvajon/fix-option1
fix(option1): Don't add only zeros to the numbers array
2020-05-29 00:33:00 +02:00
fmoko
a75fdbd8ad Merge pull request #415 from danwilhelm/powershell-correction
chore: Fix PowerShell capitalization
2020-05-29 00:32:45 +02:00
Dan Wilhelm
9d3f189b0e chore: Fix PowerShell capitalization 2020-05-28 14:51:20 -07:00
AlexandruGG
7e79c51222 Add .idea to gitignore 2020-05-28 18:01:32 +01:00
fmoko
a180d831a1 Merge pull request #413 from danwilhelm/generics3-90chars 2020-05-28 10:15:55 +02:00
Dan Wilhelm
e81adc2752 chore: Add Powershell reminder 2020-05-28 09:35:29 +02:00
Allan Soares Duarte
500422d594 chore: Update variables6.rs book link 2020-05-28 09:33:15 +02:00
Dan Wilhelm
0311c03735 chore: Limit generics3 lines to 90 chars 2020-05-27 23:39:11 -07:00
AlexandruGG
df81141d6f Address PR feedback: add tests 2020-05-27 10:03:59 +01:00
Thomas Sauvajon
cce6a44277 fix(option1): Don't add only zeros to the numbers array 2020-05-27 18:55:12 +10:00
AlexandruGG
7479a4737b feat: Add box1.rs exercise 2020-05-26 21:46:24 +01:00
Evan Carroll
06ef4cc654 fix: confine the user further in variable exercises
We want to teach a specific lesson. To ensure that we do, let's try to
provide more clarity on what the user should not do.
2020-05-25 10:09:11 +02:00
Jade McGough
c7c3130507 chore: remove struct2 hint comment 2020-05-20 08:31:28 +02:00
Sanjay K
010a045692 feat: renames test to quiz, fixes #244
BREAKING CHANGE

* changed test to quiz: fixes issues in #244
* fixed info.toml: #244
* fixed naming related issues
2020-05-19 18:47:44 +02:00
fmoko
51666609f1 Merge pull request #365 from sjmann/generics-2-fix 2020-05-19 17:49:55 +02:00
Stefan Kupresak
10967bce57 fix(option2): Add TODO to comments (#400) 2020-05-16 22:48:18 +02:00
IkaR49
763aa6e378 feat: Rewrite try_from_into (#393) 2020-05-15 23:02:57 +02:00
Gaurang Tandon
d6c0a688e6 fix(test2): name of type String and &str (#394) 2020-05-13 12:38:14 +02:00
Jawaad Mahmood
9f75554f2a fix(options1): Add hint about Array Initialization (#389) 2020-05-10 13:21:29 +02:00
Evan Carroll
2b20c8a0f5 fix(errorsn): Try harder to confine the user. (#388) 2020-05-06 21:12:15 +02:00
fmoko
1b4590b42b Merge pull request #385 from siobhanjacobson/fix-enums3-test 2020-05-05 19:50:28 +02:00
Siobhan Jacobson
09e89bbcd3 Update Message::Move in the enums3 test to take a Point. 2020-05-04 18:59:23 -04:00
fmoko
7c4b1f910c Merge pull request #372 from DiD92/exercise_structs3 2020-05-03 19:44:26 +02:00
fmoko
3ceabe91f8 Merge pull request #383 from wrobstory/wrobstory-exercises 2020-05-03 19:44:08 +02:00
fmoko
a39ffb2fb8 Merge pull request #368 from apatniv/update_test_case 2020-05-03 13:31:46 +02:00
apatniv
41f989135d Review Comments: Add other test cases 2020-05-02 20:41:11 -04:00
Rob Story
f6cffc7e48 fix(option1): Add cast to usize, as it is confusing in the context of an exercise about Option 2020-05-02 16:39:37 -07:00
Rob Story
1da84b5f7c feat: Add if2 exercise 2020-05-02 13:02:16 -07:00
fmoko
ebfe76cdb6 Merge pull request #382 from bertonha/deprecated-description 2020-05-02 18:38:32 +02:00
Christofer Bertonha
c301814d68 chore: Remove deprecated description from error_handling/errorsn.rs 2020-05-02 18:30:11 +02:00
fmoko
09478571df Merge pull request #378 from Darrenmeehan/patch-2 2020-04-30 18:33:46 +02:00
Jihchi Lee
a901499ede fix(from_into.rs): typo 2020-04-30 15:53:50 +02:00
fmoko
de65026db0 Merge pull request #377 from danwilhelm/dw-typos 2020-04-30 09:21:42 +02:00
fmoko
071b51d588 Check if python is available while checking for git, rustc and cargo (#376) 2020-04-30 09:21:17 +02:00
Darren Meehan
80390d8a03 docs: Remove outdated MacOS instructions
The quoted file no longer exists
2020-04-30 08:13:41 +01:00
Dan Wilhelm
9590082848 fix: update iterator and macro text for typos and clarity
- /macros/README.md: Typo "modules" => "macros"
- iterators2.py: Reduce line length to <90-char width.
- iterators4.py: Update 'fun' => 'challenge' as per PR#177
- rustlings hint iterators4: improve clarity
2020-04-29 19:11:54 -07:00
Abdou Seck
9cfb617d5b fix(installation): Check if python is available while checking for git,rustc and cargo
closes #374
2020-04-29 15:11:05 -04:00
Dídac Sementé Fernández
b66e2e0962 feat: Added exercise structs3.rs 2020-04-27 20:26:34 +02:00
Aleksei Trifonov
32721bbc83 chore: fix missing space in the hint for errorsn.rs 2020-04-25 10:25:41 +02:00
apatniv
19fb1c240c test: Add missing test case for from_str exercise 2020-04-21 22:51:56 -04:00
Steven Mann
630ff0e00b chore: add explanatory comment to clippy1 2020-04-21 18:50:00 +02:00
sjmann
964c974a02 fix: update generics2 closes #362 2020-04-21 13:34:25 +01:00
lebedevsergey
c9e4f2cfb4 fix: confusing comment in conversions/try_from_into.rs
Co-authored-by: Lebedev <sergey.lebedev@corp.mail.ru>
2020-04-17 15:43:01 +02:00
Said Aspen
a3a554aeed Hints for structs1 and structs2 (#355) 2020-04-16 16:21:36 +02:00
Ufuk Celebi
6c3cc2caf5 chore: delete orphaned error_handling/option1.rs
`error_handling/option1.rs` has been replaced by `option/option1.rs` and
is not referenced in `info.toml` any more.
2020-04-15 23:52:31 +02:00
Said Aspen
5999acd24a feat: Add exercise variables6 covering const (#352) 2020-04-14 10:13:20 +02:00
allcontributors[bot]
59f56b24d9 docs: add saidaspen as a contributor (#353)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-14 10:12:51 +02:00
Saurav
abd0ec379c chore: update variables5.rs book link (#351)
chore: update variables5.rs book link

chore: update variables5.rs book link
2020-04-12 19:35:20 +02:00
fmoko
cfb98a5617 docs: remove now obsolete credits section 2020-04-12 01:03:28 +02:00
allcontributors[bot]
fafcffed25 docs: add crodjer as a contributor (#350)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 01:00:22 +02:00
allcontributors[bot]
3f1209ce19 docs: add sanjaykdragon as a contributor (#349)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:59:07 +02:00
allcontributors[bot]
b217961254 docs: add sl4m as a contributor (#348)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:57:55 +02:00
allcontributors[bot]
cd06b39a42 docs: add Tarnadas as a contributor (#347)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:57:18 +02:00
allcontributors[bot]
84e1f85be2 docs: add sjmann as a contributor (#346)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:56:40 +02:00
allcontributors[bot]
f060f099d4 docs: add pbx as a contributor (#345)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:55:30 +02:00
allcontributors[bot]
e093af4c05 docs: add TorbenJ as a contributor (#344)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:54:59 +02:00
allcontributors[bot]
eface5ef45 docs: add harrisonmetz as a contributor (#343)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:54:28 +02:00
allcontributors[bot]
5b72f478a7 docs: add gnodarse as a contributor (#342)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:53:46 +02:00
allcontributors[bot]
5f5a0465cb docs: add codehearts as a contributor (#341)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
Co-authored-by: fmoko <mokou@posteo.de>
2020-04-12 00:52:51 +02:00
allcontributors[bot]
f509e479a1 docs: add Socratides as a contributor (#339)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:51:02 +02:00
allcontributors[bot]
ad00c2cf51 docs: add AbdouSeck as a contributor (#338)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:49:57 +02:00
allcontributors[bot]
a20f80623e docs: add rahatarmanahmed as a contributor (#337)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:49:05 +02:00
allcontributors[bot]
f26dca6d8e docs: add jensim as a contributor (#336)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:48:12 +02:00
fmoko
9ea089a5d9 docs: bump contributors per line down to 8 2020-04-12 00:47:24 +02:00
allcontributors[bot]
f07d1c9488 docs: add jrvidal as a contributor (#335)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:46:29 +02:00
allcontributors[bot]
0d0c79a5cb docs: add WofWca as a contributor (#334)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:45:01 +02:00
allcontributors[bot]
9bb5aa583f docs: add workingjubilee as a contributor (#333)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:44:27 +02:00
allcontributors[bot]
f26ed591f3 docs: add nyxtom as a contributor (#332)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:43:54 +02:00
allcontributors[bot]
0b4576a028 docs: add gdoenlen as a contributor (#331)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:43:08 +02:00
allcontributors[bot]
d7bb220ba3 docs: add vyaslav as a contributor (#330)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:42:30 +02:00
allcontributors[bot]
f907c710b2 docs: add Dylnuge as a contributor (#329)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:41:21 +02:00
allcontributors[bot]
c6bcb319f8 docs: add ajaxm as a contributor (#328)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:40:26 +02:00
allcontributors[bot]
443600194c docs: add nkanderson as a contributor (#327)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:39:56 +02:00
allcontributors[bot]
7b6f14c25a docs: add petemcfarlane as a contributor (#326)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:39:14 +02:00
allcontributors[bot]
887d919323 docs: add MrFroop as a contributor (#325)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:38:25 +02:00
allcontributors[bot]
74d32f0cca docs: add Jesse-Cameron as a contributor (#324)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:37:45 +02:00
allcontributors[bot]
3f479be7e7 docs: add danwilhelm as a contributor (#323)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:36:55 +02:00
allcontributors[bot]
95d02a23d0 docs: add miller-time as a contributor (#322)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:35:42 +02:00
allcontributors[bot]
8b59b9852f docs: add briankung as a contributor (#321)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:34:41 +02:00
allcontributors[bot]
53bda94f77 docs: add eddyp as a contributor (#320)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:34:06 +02:00
allcontributors[bot]
52580cfd0d docs: add dendi239 as a contributor (#319)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:32:56 +02:00
allcontributors[bot]
cf3d5b44e6 docs: add yvan-sraka as a contributor (#318)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:32:07 +02:00
allcontributors[bot]
491dc2e5ca docs: add cjpearce as a contributor (#317)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:31:21 +02:00
allcontributors[bot]
b89cdef120 docs: add mgeier as a contributor (#316)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:30:31 +02:00
allcontributors[bot]
348fe339b9 docs: add zacanger as a contributor (#315)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:28:52 +02:00
fmoko
e79d7ea981 docs: increase contributors per line 2020-04-12 00:28:06 +02:00
allcontributors[bot]
e7841ba2ed docs: add ColinPitrat as a contributor (#314)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:27:26 +02:00
allcontributors[bot]
37687e9323 docs: add kisom as a contributor (#313)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:24:27 +02:00
allcontributors[bot]
b749314944 docs: add abagshaw as a contributor (#312)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:23:18 +02:00
allcontributors[bot]
3eb0fb5aa6 docs: add shaunbennett as a contributor (#311)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:22:30 +02:00
allcontributors[bot]
44a4cf3b27 docs: add Delet0r as a contributor (#310)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:21:37 +02:00
allcontributors[bot]
9a8762ba6e docs: add evestera as a contributor (#309)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:21:03 +02:00
allcontributors[bot]
2e1bd5ef4e docs: add lukabavdaz as a contributor (#308)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:20:06 +02:00
allcontributors[bot]
a9dc101701 docs: add spacekookie as a contributor (#307)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:18:53 +02:00
allcontributors[bot]
e2835de137 docs: add hynek as a contributor (#306)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:17:40 +02:00
allcontributors[bot]
535e7a6a28 docs: add robertlugg as a contributor (#305)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:16:50 +02:00
allcontributors[bot]
fe96de2e2d docs: add QuietMisdreavus as a contributor (#304)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:14:45 +02:00
allcontributors[bot]
9fd881443f docs: add carols10cents as a contributor (#303)
* docs: update README.md [skip ci]

* docs: create .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2020-04-12 00:09:23 +02:00
99 changed files with 4793 additions and 1512 deletions

1013
.all-contributorsrc Normal file

File diff suppressed because it is too large Load Diff

3
.gitignore vendored
View File

@@ -5,3 +5,6 @@ target/
*.pdb
exercises/clippy/Cargo.toml
exercises/clippy/Cargo.lock
.idea
.vscode
*.iml

7
.gitpod.yml Normal file
View File

@@ -0,0 +1,7 @@
tasks:
- init: /workspace/rustlings/install.sh
command: /workspace/.cargo/bin/rustlings watch
vscode:
extensions:
- rust-lang.rust@0.7.8:CvNqMTgDdt3UXt+6BCDTVg==

2
.replit Normal file
View File

@@ -0,0 +1,2 @@
language = "rust"
run = "[ -x ~/.cargo/bin/rustlings ] && ~/.cargo/bin/rustlings watch || ./install.sh"

View File

@@ -1,3 +1,207 @@
<a name="4.6.0"></a>
## 4.6.0 (2021-09-25)
#### Features
* add advanced_errs2 ([abd6b70c](https://github.com/rust-lang/rustlings/commit/abd6b70c72dc6426752ff41f09160b839e5c449e))
* add advanced_errs1 ([882d535b](https://github.com/rust-lang/rustlings/commit/882d535ba8628d5e0b37e8664b3e2f26260b2671))
* Add a farewell message when quitting `watch` ([1caef0b4](https://github.com/rust-lang/rustlings/commit/1caef0b43494c8b8cdd6c9260147e70d510f1aca))
* add more watch commands ([a7dc080b](https://github.com/rust-lang/rustlings/commit/a7dc080b95e49146fbaafe6922a6de2f8cb1582a), closes [#842](https://github.com/rust-lang/rustlings/issues/842))
* **modules:** update exercises, add modules3 (#822) ([dfd2fab4](https://github.com/rust-lang/rustlings/commit/dfd2fab4f33d1bf59e2e5ee03123c0c9a67a9481))
* **quiz1:** add default function name in comment (#838) ([0a11bad7](https://github.com/rust-lang/rustlings/commit/0a11bad71402b5403143d642f439f57931278c07))
#### Bug Fixes
* Correct small typo in exercises/conversions/from_str.rs ([86cc8529](https://github.com/rust-lang/rustlings/commit/86cc85295ae36948963ae52882e285d7e3e29323))
* **cli:** typo in exercise.rs (#848) ([06d5c097](https://github.com/rust-lang/rustlings/commit/06d5c0973a3dffa3c6c6f70acb775d4c6630323c))
* **from_str, try_from_into:** custom error types ([2dc93cad](https://github.com/rust-lang/rustlings/commit/2dc93caddad43821743e4903d89b355df58d7a49))
* **modules2:** fix typo (#835) ([1c3beb0a](https://github.com/rust-lang/rustlings/commit/1c3beb0a59178c950dc05fe8ee2346b017429ae0))
* **move_semantics5:**
* change &mut *y to &mut x (#814) ([d75759e8](https://github.com/rust-lang/rustlings/commit/d75759e829fdcd64ef071cf4b6eae2a011a7718b))
* Clarify instructions ([df25684c](https://github.com/rust-lang/rustlings/commit/df25684cb79f8413915e00b5efef29369849cef1))
* **quiz1:** Fix inconsistent wording (#826) ([03131a3d](https://github.com/rust-lang/rustlings/commit/03131a3d35d9842598150f9da817f7cc26e2669a))
<a name="4.5.0"></a>
## 4.5.0 (2021-07-07)
#### Features
* Add move_semantics5 exercise. (#746) ([399ab328](https://github.com/rust-lang/rustlings/commit/399ab328d8d407265c09563aa4ef4534b2503ff2))
* **cli:** Add "next" to run the next unsolved exercise. (#785) ([d20e413a](https://github.com/rust-lang/rustlings/commit/d20e413a68772cd493561f2651cf244e822b7ca5))
#### Bug Fixes
* rename result1 to errors4 ([50ab289d](https://github.com/rust-lang/rustlings/commit/50ab289da6b9eb19a7486c341b00048c516b88c0))
* move_semantics5 hints ([1b858285](https://github.com/rust-lang/rustlings/commit/1b85828548f46f58b622b5e0c00f8c989f928807))
* remove trailing whitespaces from iterators1 ([4d4fa774](https://github.com/rust-lang/rustlings/commit/4d4fa77459392acd3581c6068aa8be9a02de12fc))
* add hints to generics1 and generics2 exercises ([31457940](https://github.com/rust-lang/rustlings/commit/31457940846b3844d78d4a4d2b074bc8d6aaf1eb))
* remove trailing whitespace ([d9b69bd1](https://github.com/rust-lang/rustlings/commit/d9b69bd1a0a7a99f2c0d80933ad2eea44c8c71b2))
* **installation:** first PowerShell command ([aa9a943d](https://github.com/rust-lang/rustlings/commit/aa9a943ddf3ae260782e73c26bcc9db60e5894b6))
* **iterators5:** derive Clone, Copy ([91fc9e31](https://github.com/rust-lang/rustlings/commit/91fc9e3118f4af603c9911698cc2a234725cb032))
* **quiz1:** Updated question description (#794) ([d8766496](https://github.com/rust-lang/rustlings/commit/d876649616cc8a8dd5f539f8bc1a5434b960b1e9))
* **try_from_into, from_str:** hints for dyn Error ([11d2cf0d](https://github.com/rust-lang/rustlings/commit/11d2cf0d604dee3f5023c17802d69438e69fa50e))
* **variables5:** confine the answer further ([48ffcbd2](https://github.com/rust-lang/rustlings/commit/48ffcbd2c4cc4d936c2c7480019190f179813cc5))
<a name="4.4.0"></a>
## 4.4.0 (2021-04-24)
#### Bug Fixes
* Fix spelling error in main.rs ([91ee27f2](https://github.com/rust-lang/rustlings/commit/91ee27f22bd3797a9db57e5fd430801c170c5db8))
* typo in default out text ([644c49f1](https://github.com/rust-lang/rustlings/commit/644c49f1e04cbb24e95872b3a52b07d692ae3bc8))
* **collections:** Naming exercises for vectors and hashmap ([bef39b12](https://github.com/rust-lang/rustlings/commit/bef39b125961310b34b34871e480a82e82af4678))
* **from_str:**
* Correct typos ([5f7c89f8](https://github.com/rust-lang/rustlings/commit/5f7c89f85db1f33da01911eaa479c3a2d4721678))
* test for error instead of unwrap/should_panic ([15e71535](https://github.com/rust-lang/rustlings/commit/15e71535f37cfaed36e22eb778728d186e2104ab))
* use trait objects for from_str ([c3e7b831](https://github.com/rust-lang/rustlings/commit/c3e7b831786c9172ed8bd5d150f3c432f242fba9))
* **functions3:** improve function argument type (#687) ([a6509cc4](https://github.com/rust-lang/rustlings/commit/a6509cc4d545d8825f01ddf7ee37823b372154dd))
* **hashmap2:** Update incorrect assertion (#660) ([72aaa15e](https://github.com/rust-lang/rustlings/commit/72aaa15e6ab4b72b3422f1c6356396e20a2a2bb8))
* **info:** Fix typo (#635) ([cddc1e86](https://github.com/rust-lang/rustlings/commit/cddc1e86e7ec744ee644cc774a4887b1a0ded3e8))
* **iterators2:** Moved errors out of tests. ([baf4ba17](https://github.com/rust-lang/rustlings/commit/baf4ba175ba6eb92989e3dd54ecbec4bedc9a863), closes [#359](https://github.com/rust-lang/rustlings/issues/359))
* **iterators3:** Enabled iterators3.rs to run without commented out tests. ([c6712dfc](https://github.com/rust-lang/rustlings/commit/c6712dfccd1a093e590ad22bbc4f49edc417dac0))
* **main:** Let find_exercise work with borrows ([347f30bd](https://github.com/rust-lang/rustlings/commit/347f30bd867343c5ace1097e085a1f7e356553f7))
* **move_semantics4:**
* Remove redundant "instead" (#640) ([cc266d7d](https://github.com/rust-lang/rustlings/commit/cc266d7d80b91e79df3f61984f231b7f1587218e))
* Small readbility improvement (#617) ([10965920](https://github.com/rust-lang/rustlings/commit/10965920fbdf8a1efc85bed869e55a1787006404))
* **option2:** Rename uninformative variables (#675) ([b4de6594](https://github.com/rust-lang/rustlings/commit/b4de6594380636817d13c2677ec6f472a964cf43))
* **quiz3:** Force an answer to Q2 (#672) ([0d894e6f](https://github.com/rust-lang/rustlings/commit/0d894e6ff739943901e1ae8c904582e5c2f843bd))
* **structs:** Add 5.3 to structs/README (#652) ([6bd791f2](https://github.com/rust-lang/rustlings/commit/6bd791f2f44aa7f0ad926df767f6b1fa8f12a9a9))
* **structs2:** correct grammar in hint (#663) ([ebdb66c7](https://github.com/rust-lang/rustlings/commit/ebdb66c7bfb6d687a14cc511a559a222e6fc5de4))
* **structs3:**
* reword heading comment (#664) ([9f3e8c2d](https://github.com/rust-lang/rustlings/commit/9f3e8c2dde645e5264c2d2200e68842b5f47bfa3))
* add check to prevent naive implementation of is_international ([05a753fe](https://github.com/rust-lang/rustlings/commit/05a753fe6333d36dbee5f68c21dec04eacdc75df))
* **threads1:** line number correction ([7857b0a6](https://github.com/rust-lang/rustlings/commit/7857b0a689b0847f48d8c14cbd1865e3b812d5ca))
* **try_from_into:** use trait objects ([2e93a588](https://github.com/rust-lang/rustlings/commit/2e93a588e0abe8badb7eafafb9e7d073c2be5df8))
#### Features
* Replace clap with argh ([7928122f](https://github.com/rust-lang/rustlings/commit/7928122fcef9ca7834d988b1ec8ca0687478beeb))
* Replace emojis when NO_EMOJI env variable present ([8d62a996](https://github.com/rust-lang/rustlings/commit/8d62a9963708dbecd9312e8bcc4b47049c72d155))
* Added iterators5.rs exercise. ([b29ea17e](https://github.com/rust-lang/rustlings/commit/b29ea17ea94d1862114af2cf5ced0e09c197dc35))
* **arc1:** Add more details to description and hint (#710) ([81be4044](https://github.com/rust-lang/rustlings/commit/81be40448777fa338ebced3b0bfc1b32d6370313))
* **cli:** Improve the list command with options, and then some ([8bbe4ff1](https://github.com/rust-lang/rustlings/commit/8bbe4ff1385c5c169c90cd3ff9253f9a91daaf8e))
* **list:**
* updated progress percentage ([1c6f7e4b](https://github.com/rust-lang/rustlings/commit/1c6f7e4b7b9b3bd36f4da2bb2b69c549cc8bd913))
* added progress info ([c0e3daac](https://github.com/rust-lang/rustlings/commit/c0e3daacaf6850811df5bc57fa43e0f249d5cfa4))
<a name="4.3.0"></a>
## 4.3.0 (2020-12-29)
#### Features
* Rewrite default out text ([44d39112](https://github.com/rust-lang/rustlings/commit/44d39112ff122b29c9793fe52e605df1612c6490))
* match exercise order to book chapters (#541) ([033bf119](https://github.com/rust-lang/rustlings/commit/033bf1198fc8bfce1b570e49da7cde010aa552e3))
* Crab? (#586) ([fa9f522b](https://github.com/rust-lang/rustlings/commit/fa9f522b7f043d7ef73a39f003a9272dfe72c4f4))
* add "rustlings list" command ([838f9f30](https://github.com/rust-lang/rustlings/commit/838f9f30083d0b23fd67503dcf0fbeca498e6647))
* **try_from_into:** remove duplicate annotation ([04f1d079](https://github.com/rust-lang/rustlings/commit/04f1d079aa42a2f49af694bc92c67d731d31a53f))
#### Bug Fixes
* update structs README ([bcf14cf6](https://github.com/rust-lang/rustlings/commit/bcf14cf677adb3a38a3ac3ca53f3c69f61153025))
* added missing exercises to info.toml ([90cfb6ff](https://github.com/rust-lang/rustlings/commit/90cfb6ff28377531bfc34acb70547bdb13374f6b))
* gives a bit more context to magic number ([30644c9a](https://github.com/rust-lang/rustlings/commit/30644c9a062b825c0ea89435dc59f0cad86b110e))
* **functions2:** Change signature to trigger precise error message: (#605) ([0ef95947](https://github.com/rust-lang/rustlings/commit/0ef95947cc30482e63a7045be6cc2fb6f6dcb4cc))
* **structs1:** Adjust wording (#573) ([9334783d](https://github.com/rust-lang/rustlings/commit/9334783da31d821cc59174fbe8320df95828926c))
* **try_from_into:**
* type error ([4f4cfcf3](https://github.com/rust-lang/rustlings/commit/4f4cfcf3c36c8718c7c170c9c3a6935e6ef0618c))
* Update description (#584) ([96347df9](https://github.com/rust-lang/rustlings/commit/96347df9df294f01153b29d9ad4ba361f665c755))
* **vec1:** Have test compare every element in a and v ([9b6c6293](https://github.com/rust-lang/rustlings/commit/9b6c629397b24b944f484f5b2bbd8144266b5695))
<a name="4.2.0"></a>
## 4.2.0 (2020-11-07)
#### Features
* Add HashMap exercises ([633c00cf](https://github.com/rust-lang/rustlings/commit/633c00cf8071e1e82959a3010452a32f34f29fc9))
* Add Vec exercises ([0c12fa31](https://github.com/rust-lang/rustlings/commit/0c12fa31c57c03c6287458a0a8aca7afd057baf6))
* **primitive_types6:** Add a test (#548) ([2b1fb2b7](https://github.com/rust-lang/rustlings/commit/2b1fb2b739bf9ad8d6b7b12af25fee173011bfc4))
* **try_from_into:** Add tests (#571) ([95ccd926](https://github.com/rust-lang/rustlings/commit/95ccd92616ae79ba287cce221101e0bbe4f68cdc))
#### Bug Fixes
* log error output when inotify limit is exceeded ([d61b4e5a](https://github.com/rust-lang/rustlings/commit/d61b4e5a13b44d72d004082f523fa1b6b24c1aca))
* more unique temp_file ([5643ef05](https://github.com/rust-lang/rustlings/commit/5643ef05bc81e4a840e9456f4406a769abbe1392))
* **installation:** Update the MinRustVersion ([21bfb2d4](https://github.com/rust-lang/rustlings/commit/21bfb2d4777429c87d8d3b5fbf0ce66006dcd034))
* **iterators2:** Update description (#578) ([197d3a3d](https://github.com/rust-lang/rustlings/commit/197d3a3d8961b2465579218a6749b2b2cefa8ddd))
* **primitive_types6:**
* remove 'unused doc comment' warning ([472d8592](https://github.com/rust-lang/rustlings/commit/472d8592d65c8275332a20dfc269e7ac0d41bc88))
* missing comma in test ([4fb230da](https://github.com/rust-lang/rustlings/commit/4fb230daf1251444fcf29e085cee222a91f8a37e))
* **quiz3:** Second test is for odd numbers, not even. (#553) ([18e0bfef](https://github.com/rust-lang/rustlings/commit/18e0bfef1de53071e353ba1ec5837002ff7290e6))
<a name="4.1.0"></a>
## 4.1.0 (2020-10-05)
#### Bug Fixes
* Update rustlings version in Cargo.lock ([1cc40bc9](https://github.com/rust-lang/rustlings/commit/1cc40bc9ce95c23d56f6d91fa1c4deb646231fef))
* **arc1:** index mod should equal thread count ([b4062ef6](https://github.com/rust-lang/rustlings/commit/b4062ef6993e80dac107c4093ea85166ad3ee0fa))
* **enums3:** Update Message::ChangeColor to take a tuple. (#457) ([4b6540c7](https://github.com/rust-lang/rustlings/commit/4b6540c71adabad647de8a09e57295e7c7c7d794))
* **exercises:** adding question mark to quiz2 ([101072ab](https://github.com/rust-lang/rustlings/commit/101072ab9f8c80b40b8b88cb06cbe38aca2481c5))
* **generics3:** clarify grade change ([47f7672c](https://github.com/rust-lang/rustlings/commit/47f7672c0307732056e7426e81d351f0dd7e22e5))
* **structs3:** Small adjustment of variable name ([114b54cb](https://github.com/rust-lang/rustlings/commit/114b54cbdb977234b39e5f180d937c14c78bb8b2))
* **using_as:** Add test so that proper type is returned. (#512) ([3286c5ec](https://github.com/rust-lang/rustlings/commit/3286c5ec19ea5fb7ded81d047da5f8594108a490))
#### Features
* Added iterators1.rs exercise ([9642f5a3](https://github.com/rust-lang/rustlings/commit/9642f5a3f686270a4f8f6ba969919ddbbc4f7fdd))
* Add ability to run rustlings on repl.it (#471) ([8f7b5bd0](https://github.com/rust-lang/rustlings/commit/8f7b5bd00eb83542b959830ef55192d2d76db90a))
* Add gitpod support (#473) ([4821a8be](https://github.com/rust-lang/rustlings/commit/4821a8be94af4f669042a06ab917934cfacd032f))
* Remind the user of the hint option (#425) ([816b1f5e](https://github.com/rust-lang/rustlings/commit/816b1f5e85d6cc6e72673813a85d0ada2a8f84af))
* Remind the user of the hint option (#425) ([9f61db5d](https://github.com/rust-lang/rustlings/commit/9f61db5dbe38538cf06571fcdd5f806e7901e83a))
* **cli:** Added 'cls' command to 'watch' mode (#474) ([4f2468e1](https://github.com/rust-lang/rustlings/commit/4f2468e14f574a93a2e9b688367b5752ed96ae7b))
* **try_from_into:** Add insufficient length test (#469) ([523d18b8](https://github.com/rust-lang/rustlings/commit/523d18b873a319f7c09262f44bd40e2fab1830e5))
<a name="4.0.0"></a>
## 4.0.0 (2020-07-08)
#### Breaking Changes
* Add a --nocapture option to display test harnesses' outputs ([8ad5f9bf](https://github.com/rust-lang/rustlings/commit/8ad5f9bf531a4848b1104b7b389a20171624c82f))
* Rename test to quiz, fixes #244 ([010a0456](https://github.com/rust-lang/rustlings/commit/010a04569282149cea7f7a76fc4d7f4c9f0f08dd))
#### Features
* Add traits README ([173bb141](https://github.com/rust-lang/rustlings/commit/173bb14140c5530cbdb59e53ace3991a99d804af))
* Add box1.rs exercise ([7479a473](https://github.com/rust-lang/rustlings/commit/7479a4737bdcac347322ad0883ca528c8675e720))
* Rewrite try_from_into (#393) ([763aa6e3](https://github.com/rust-lang/rustlings/commit/763aa6e378a586caae2d8d63755a85eeba227933))
* Add if2 exercise ([1da84b5f](https://github.com/rust-lang/rustlings/commit/1da84b5f7c489f65bd683c244f13c7d1ee812df0))
* Added exercise structs3.rs ([b66e2e09](https://github.com/rust-lang/rustlings/commit/b66e2e09622243e086a0f1258dd27e1a2d61c891))
* Add exercise variables6 covering const (#352) ([5999acd2](https://github.com/rust-lang/rustlings/commit/5999acd24a4f203292be36e0fd18d385887ec481))
#### Bug Fixes
* Change then to than ([ddd98ad7](https://github.com/rust-lang/rustlings/commit/ddd98ad75d3668fbb10eff74374148aa5ed2344d))
* rename quiz1 to tests1 in info (#420) ([0dd1c6ca](https://github.com/rust-lang/rustlings/commit/0dd1c6ca6b389789e0972aa955fe17aa15c95f29))
* fix quiz naming inconsistency (#421) ([5563adbb](https://github.com/rust-lang/rustlings/commit/5563adbb890587fc48fbbc9c4028642687f1e85b))
* confine the user further in variable exercises ([06ef4cc6](https://github.com/rust-lang/rustlings/commit/06ef4cc654e75d22a526812919ee49b8956280bf))
* update iterator and macro text for typos and clarity ([95900828](https://github.com/rust-lang/rustlings/commit/959008284834bece0196a01e17ac69a7e3590116))
* update generics2 closes #362 ([964c974a](https://github.com/rust-lang/rustlings/commit/964c974a0274199d755073b917c2bc5da0c9b4f1))
* confusing comment in conversions/try_from_into.rs ([c9e4f2cf](https://github.com/rust-lang/rustlings/commit/c9e4f2cfb4c48d0b7451263cfb43b9426438122d))
* **arc1:** Passively introduce attributes (#429) ([113cdae2](https://github.com/rust-lang/rustlings/commit/113cdae2d4e4c55905e8056ad326ede7fd7de356))
* **box1:** fix comment typo (#426) ([bb2ca251](https://github.com/rust-lang/rustlings/commit/bb2ca251106b27a7272d9a30872904dd1376654c))
* **errorsn:** Try harder to confine the user. (#388) ([2b20c8a0](https://github.com/rust-lang/rustlings/commit/2b20c8a0f5774d07c58d110d75879f33fc6273b5))
* **from_into.rs:** typo ([a901499e](https://github.com/rust-lang/rustlings/commit/a901499ededd3ce1995164700514fe4e9a0373ea))
* **generics2:** Guide students to the answer (#430) ([e6bd8021](https://github.com/rust-lang/rustlings/commit/e6bd8021d9a7dd06feebc30c9d5f953901d7b419))
* **installation:**
* Provide a backup git reference when tag can't be curl ([9e4fb100](https://github.com/rust-lang/rustlings/commit/9e4fb1009f1c9e3433915c03e22c2af422e5c5fe))
* Check if python is available while checking for git,rustc and cargo ([9cfb617d](https://github.com/rust-lang/rustlings/commit/9cfb617d5b0451b4b51644a1298965390cda9884))
* **option1:**
* Don't add only zeros to the numbers array ([cce6a442](https://github.com/rust-lang/rustlings/commit/cce6a4427718724a9096800754cd3abeca6a1580))
* Add cast to usize, as it is confusing in the context of an exercise about Option ([f6cffc7e](https://github.com/rust-lang/rustlings/commit/f6cffc7e487b42f15a6f958e49704c93a8d4465b))
* **option2:** Add TODO to comments (#400) ([10967bce](https://github.com/rust-lang/rustlings/commit/10967bce57682812dc0891a9f9757da1a9d87404))
* **options1:** Add hint about Array Initialization (#389) ([9f75554f](https://github.com/rust-lang/rustlings/commit/9f75554f2a30295996f03f0160b98c0458305502))
* **test2:** name of type String and &str (#394) ([d6c0a688](https://github.com/rust-lang/rustlings/commit/d6c0a688e6a96f93ad60d540d4b326f342fc0d45))
* **variables6:** minor typo (#419) ([524e17df](https://github.com/rust-lang/rustlings/commit/524e17df10db95f7b90a0f75cc8997182a8a4094))
<a name="3.0.0"></a>
## 3.0.0 (2020-04-11)
@@ -41,14 +245,14 @@
* Update deps to version compatable with aarch64-pc-windows (#263) ([19a93428](https://github.com/rust-lang/rustlings/commit/19a93428b3c73d994292671f829bdc8e5b7b3401))
* **docs:**
* Added a necessary step to Windows installation process (#242) ([3906efcd](https://github.com/rust-lang/rustlings/commit/3906efcd52a004047b460ed548037093de3f523f))
* Fixed mangled sentence from book; edited for clarity (#266) ([ade52ff](https://github.com/rust-lang/rustlings/commit/ade52ffb739987287ddd5705944c8777705faed9))
* Fixed mangled sentence from book; edited for clarity (#266) ([ade52ff](https://github.com/rust-lang/rustlings/commit/ade52ffb739987287ddd5705944c8777705faed9))
* Updated iterators readme to account for iterators4 exercise (#273) ([bec8e3a](https://github.com/rust-lang/rustlings/commit/bec8e3a644cbd88db1c73ea5f1d8a364f4a34016))
* **installation:** make fatal errors more obvious (#272) ([17d0951e](https://github.com/rust-lang/rustlings/commit/17d0951e66fda8e11b204d5c4c41a0d5e22e78f7))
* **iterators2:**
* Remove reference to missing iterators2.rs (#245) ([419f7797](https://github.com/rust-lang/rustlings/commit/419f7797f294e4ce6a2b883199731b5bde77d262))
* **as_ref_mut:** Enable a test and improve per clippy's suggestion (#256) ([dfdf809](https://github.com/rust-lang/rustlings/commit/dfdf8093ebbd4145864995627b812780de52f902))
* **tests1:**
* Change test command ([fe10e06c](https://github.com/rust-lang/rustlings/commit/fe10e06c3733ddb4a21e90d09bf79bfe618e97ce)
* Change test command ([fe10e06c](https://github.com/rust-lang/rustlings/commit/fe10e06c3733ddb4a21e90d09bf79bfe618e97ce)
* Correct test command in tests1.rs comment (#263) ([39fa7ae](https://github.com/rust-lang/rustlings/commit/39fa7ae8b70ad468da49b06f11b2383135a63bcf))
#### Features

View File

@@ -26,12 +26,12 @@ isn't really that complicated since the bulk of the work is done by `rustc`.
<a name="addex"></a>
### Adding an exercise
First step is to add the exercise! Call it `exercises/yourTopic/yourTopicN.rs`, make sure to
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 you want to make sure it runs when using `rustlings`. All exercises are stored in `info.toml`, under the `exercises` array. They're ordered by the order they're ran when using `rustlings verify`.
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`.
You want to make sure where in the file you add your exercise. If you're not sure, add it at the bottom and ask in your pull request. To add an exercise, edit the file like this:
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]]

837
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,11 @@
[package]
name = "rustlings"
version = "3.0.0"
authors = ["Marisa <mokou@posteo.de>", "Carol (Nichols || Goulding) <carol.nichols@gmail.com>"]
version = "4.6.0"
authors = ["anastasie <ana@ana.st>", "Carol (Nichols || Goulding) <carol.nichols@gmail.com>"]
edition = "2018"
[dependencies]
clap = "2.32.0"
argh = "0.1.4"
indicatif = "0.10.3"
console = "0.7.7"
notify = "4.0.15"

229
README.md
View File

@@ -1,12 +1,14 @@
![crab pet](https://i.imgur.com/LbZJgmm.gif)
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-108-orange.svg?style=flat-square)](#contributors-)
<!-- ALL-CONTRIBUTORS-BADGE:END -->
# rustlings 🦀❤️ [![Build status](https://badge.buildkite.com/7af93d81dc522c67a1ec8e33ff5705861b1cb36360b774807f.svg)](https://buildkite.com/mokou/rustlings)
# rustlings 🦀❤️
Greetings and welcome to `rustlings`. This project contains small exercises to get you used to reading and writing Rust code. This includes reading and responding to compiler messages!
_...looking for the old, web-based version of Rustlings? Try [here](https://github.com/rust-lang/rustlings/tree/rustlings-1)_
Alternatively, for a first-time Rust learner, there's several other resources:
Alternatively, for a first-time Rust learner, there are several other resources:
- [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
@@ -15,8 +17,6 @@ Alternatively, for a first-time Rust learner, there's several other resources:
_Note: If you're on MacOS, make sure you've installed Xcode and its developer tools by typing `xcode-select --install`._
_Note: If you have Xcode 10+ installed, you also need to install the package file found at `/Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg`._
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.
## MacOS/Linux
@@ -24,37 +24,45 @@ You will need to have Rust installed. You can get it by visiting https://rustup.
Just run:
```bash
curl -L https://git.io/rustlings | bash
curl -L https://git.io/install-rustlings | bash
# Or if you want it to be installed to a different path:
curl -L https://git.io/rustlings | bash -s mypath/
curl -L https://git.io/install-rustlings | bash -s mypath/
```
This will install Rustlings and give you access to the `rustlings` command. Run it to get started!
## Windows
First, set `ExecutionPolicy` to `RemoteSigned`:
In PowerShell (Run as Administrator), set `ExecutionPolicy` to `RemoteSigned`:
```ps
Set-ExecutionPolicy RemoteSigned
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
```
Then, you can run:
```ps
Invoke-WebRequest https://git.io/rustlings-win | Select-Object -ExpandProperty Content | Out-File $env:TMP/install_rustlings.ps1; Unblock-File $env:TMP/install_rustlings.ps1; Invoke-Expression $env:TMP/install_rustlings.ps1
Start-BitsTransfer -Source https://git.io/JTL5v -Destination $env:TMP/install_rustlings.ps1; Unblock-File $env:TMP/install_rustlings.ps1; Invoke-Expression $env:TMP/install_rustlings.ps1
```
To install Rustlings. Same as on MacOS/Linux, you will have access to the `rustlings` command after it.
When you get a permission denied message then you have to exclude the directory where you placed the rustlings in your virus-scanner
## Browser:
[Run on Repl.it](https://repl.it/github/rust-lang/rustlings)
[Open in Gitpod](https://gitpod.io/#https://github.com/rust-lang/rustlings)
## Manually
Basically: Clone the repository, checkout to the latest tag, run `cargo install`.
Basically: Clone the repository at the latest tag, run `cargo install`.
```bash
git clone https://github.com/rust-lang/rustlings
# find out the latest version at https://github.com/rust-lang/rustlings/releases/latest (on edit 4.6.0)
git clone -b 4.6.0 --depth 1 https://github.com/rust-lang/rustlings
cd rustlings
git checkout tags/3.0.0 # or whatever the latest version is (find out at https://github.com/rust-lang/rustlings/releases/latest)
cargo install --force --path .
```
@@ -69,7 +77,7 @@ Then, same as above, run `rustlings` to get started.
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 task is simple. Most exercises contain an error that keep it 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:
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:
```bash
rustlings watch
@@ -89,6 +97,12 @@ In case you want to go by your own order, or want to only verify a single exerci
rustlings run myExercise1
```
Or simply use the following command to run the next unsolved exercise in the course:
```bash
rustlings run next
```
In case you get stuck, you can run the following command to get a hint for your
exercise:
@@ -96,9 +110,42 @@ exercise:
rustlings hint myExercise1
```
You can also get the hint for the next unsolved exercise with the following command:
``` 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 test that'll test your knowledge on a bunch of sections at once. These tests are found in `exercises/testN.rs`.
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`.
## 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.
## Uninstalling Rustlings
If you want to remove Rustlings from your system, there's 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, since Rustlings got installed via `cargo install`, it's only reasonable to assume that you can also remove it using Cargo, and
exactly that is the case. Run `cargo uninstall` to remove the `rustlings` binary:
``` bash
cargo uninstall rustlings
```
Now you should be done!
## Completion
@@ -122,7 +169,155 @@ If you are interested in improving or adding new ones, please feel free to contr
See [CONTRIBUTING.md](./CONTRIBUTING.md).
## Credits
## Contributors ✨
`rustlings` was originally written by [Carol](https://github.com/carols10cents)!
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tr>
<td align="center"><a href="http://carol-nichols.com"><img src="https://avatars2.githubusercontent.com/u/193874?v=4?s=100" width="100px;" alt=""/><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"><a href="https://twitter.com/QuietMisdreavus"><img src="https://avatars2.githubusercontent.com/u/5217170?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/robertlugg"><img src="https://avatars0.githubusercontent.com/u/6054540?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Robert M Lugg</b></sub></a><br /><a href="#content-robertlugg" title="Content">🖋</a></td>
<td align="center"><a href="https://hynek.me/about/"><img src="https://avatars3.githubusercontent.com/u/41240?v=4?s=100" width="100px;" alt=""/><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"><a href="https://spacekookie.de"><img src="https://avatars0.githubusercontent.com/u/7669898?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/lukabavdaz"><img src="https://avatars0.githubusercontent.com/u/9624558?v=4?s=100" width="100px;" alt=""/><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"><a href="http://vestera.as"><img src="https://avatars2.githubusercontent.com/u/4187449?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/Delet0r"><img src="https://avatars1.githubusercontent.com/u/23195618?v=4?s=100" width="100px;" alt=""/><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"><a href="http://phinary.ca"><img src="https://avatars1.githubusercontent.com/u/10522375?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/abagshaw"><img src="https://avatars2.githubusercontent.com/u/8594541?v=4?s=100" width="100px;" alt=""/><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"><a href="https://ai6ua.net/"><img src="https://avatars2.githubusercontent.com/u/175578?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/ColinPitrat"><img src="https://avatars3.githubusercontent.com/u/1541863?v=4?s=100" width="100px;" alt=""/><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"><a href="https://zacanger.com"><img src="https://avatars3.githubusercontent.com/u/12520493?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/mgeier"><img src="https://avatars1.githubusercontent.com/u/705404?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/cjpearce"><img src="https://avatars1.githubusercontent.com/u/3453268?v=4?s=100" width="100px;" alt=""/><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"><a href="https://yvan-sraka.github.io"><img src="https://avatars2.githubusercontent.com/u/705213?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/dendi239"><img src="https://avatars3.githubusercontent.com/u/16478650?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/eddyp"><img src="https://avatars2.githubusercontent.com/u/123772?v=4?s=100" width="100px;" alt=""/><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"><a href="http://about.me/BrianKung"><img src="https://avatars1.githubusercontent.com/u/2836167?v=4?s=100" width="100px;" alt=""/><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"><a href="https://rcousineau.gitlab.io"><img src="https://avatars3.githubusercontent.com/u/281039?v=4?s=100" width="100px;" alt=""/><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"><a href="http://danwilhelm.com"><img src="https://avatars3.githubusercontent.com/u/6137185?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/Jesse-Cameron"><img src="https://avatars3.githubusercontent.com/u/3723654?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/MrFroop"><img src="https://avatars3.githubusercontent.com/u/196700?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/petemcfarlane"><img src="https://avatars3.githubusercontent.com/u/3472717?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Pete McFarlane</b></sub></a><br /><a href="#content-petemcfarlane" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/nkanderson"><img src="https://avatars0.githubusercontent.com/u/4128825?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/ajaxm"><img src="https://avatars0.githubusercontent.com/u/13360138?v=4?s=100" width="100px;" alt=""/><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"><a href="https://dylnuge.com"><img src="https://avatars2.githubusercontent.com/u/118624?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dylan Nugent</b></sub></a><br /><a href="#content-Dylnuge" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/vyaslav"><img src="https://avatars0.githubusercontent.com/u/1385427?v=4?s=100" width="100px;" alt=""/><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"><a href="https://join.sfxd.org"><img src="https://avatars1.githubusercontent.com/u/17297466?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/nyxtom"><img src="https://avatars2.githubusercontent.com/u/222763?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/workingjubilee"><img src="https://avatars1.githubusercontent.com/u/46493976?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/WofWca"><img src="https://avatars1.githubusercontent.com/u/39462442?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/jrvidal"><img src="https://avatars0.githubusercontent.com/u/1636604?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/jensim"><img src="https://avatars0.githubusercontent.com/u/3663856?v=4?s=100" width="100px;" alt=""/><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"><a href="http://rahatah.me/d"><img src="https://avatars3.githubusercontent.com/u/3174006?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/AbdouSeck"><img src="https://avatars2.githubusercontent.com/u/6490055?v=4?s=100" width="100px;" alt=""/><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"><a href="https://codehearts.com"><img src="https://avatars0.githubusercontent.com/u/2885412?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/Socratides"><img src="https://avatars3.githubusercontent.com/u/27732983?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/gnodarse"><img src="https://avatars3.githubusercontent.com/u/46761795?v=4?s=100" width="100px;" alt=""/><br /><sub><b>gnodarse</b></sub></a><br /><a href="#content-gnodarse" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/harrisonmetz"><img src="https://avatars1.githubusercontent.com/u/7883408?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/TorbenJ"><img src="https://avatars2.githubusercontent.com/u/9077102?v=4?s=100" width="100px;" alt=""/><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"><a href="http://paulbissex.com/"><img src="https://avatars0.githubusercontent.com/u/641?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/sjmann"><img src="https://avatars0.githubusercontent.com/u/6589896?v=4?s=100" width="100px;" alt=""/><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"><a href="https://smmdb.net/"><img src="https://avatars2.githubusercontent.com/u/5855071?v=4?s=100" width="100px;" alt=""/><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"><a href="https://keybase.io/skim"><img src="https://avatars0.githubusercontent.com/u/47347?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/sanjaykdragon"><img src="https://avatars1.githubusercontent.com/u/10261698?v=4?s=100" width="100px;" alt=""/><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"><a href="http://www.rohanjain.in"><img src="https://avatars1.githubusercontent.com/u/343499?v=4?s=100" width="100px;" alt=""/><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"><a href="https://www.saidaspen.se"><img src="https://avatars1.githubusercontent.com/u/7727687?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/uce"><img src="https://avatars3.githubusercontent.com/u/1756620?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/lebedevsergey"><img src="https://avatars2.githubusercontent.com/u/7325764?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/avrong"><img src="https://avatars2.githubusercontent.com/u/6342851?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Aleksei Trifonov</b></sub></a><br /><a href="#content-avrong" title="Content">🖋</a></td>
<td align="center"><a href="https://drn.ie"><img src="https://avatars2.githubusercontent.com/u/411136?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Darren Meehan</b></sub></a><br /><a href="#content-Darrenmeehan" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/jihchi"><img src="https://avatars1.githubusercontent.com/u/87983?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jihchi Lee</b></sub></a><br /><a href="#content-jihchi" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/bertonha"><img src="https://avatars3.githubusercontent.com/u/1225902?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Christofer Bertonha</b></sub></a><br /><a href="#content-bertonha" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/apatniv"><img src="https://avatars2.githubusercontent.com/u/22565917?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/DiD92"><img src="https://avatars3.githubusercontent.com/u/6002416?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/wrobstory"><img src="https://avatars3.githubusercontent.com/u/2601457?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/siobhanjacobson"><img src="https://avatars2.githubusercontent.com/u/28983835?v=4?s=100" width="100px;" alt=""/><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"><a href="https://www.linkedin.com/in/evancarroll/"><img src="https://avatars2.githubusercontent.com/u/19922?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Evan Carroll</b></sub></a><br /><a href="#content-EvanCarroll" title="Content">🖋</a></td>
<td align="center"><a href="http://www.jawaadmahmood.com"><img src="https://avatars3.githubusercontent.com/u/95606?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jawaad Mahmood</b></sub></a><br /><a href="#content-jmahmood" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/GaurangTandon"><img src="https://avatars1.githubusercontent.com/u/6308683?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Gaurang Tandon</b></sub></a><br /><a href="#content-GaurangTandon" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/dev-cyprium"><img src="https://avatars1.githubusercontent.com/u/6002628?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Stefan Kupresak</b></sub></a><br /><a href="#content-dev-cyprium" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/greg-el"><img src="https://avatars3.githubusercontent.com/u/45019882?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Greg Leonard</b></sub></a><br /><a href="#content-greg-el" title="Content">🖋</a></td>
<td align="center"><a href="https://ryanpcmcquen.org"><img src="https://avatars3.githubusercontent.com/u/772937?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/AnnikaCodes"><img src="https://avatars3.githubusercontent.com/u/56906084?v=4?s=100" width="100px;" alt=""/><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"><a href="https://darnuria.eu"><img src="https://avatars1.githubusercontent.com/u/2827553?v=4?s=100" width="100px;" alt=""/><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"><a href="https://sazid.github.io"><img src="https://avatars1.githubusercontent.com/u/2370167?v=4?s=100" width="100px;" alt=""/><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"><a href="https://codingthemsoftly.com"><img src="https://avatars1.githubusercontent.com/u/17479099?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Caleb Webber</b></sub></a><br /><a href="#maintenance-seeplusplus" title="Maintenance">🚧</a></td>
<td align="center"><a href="https://github.com/pcn"><img src="https://avatars2.githubusercontent.com/u/1056756?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Peter N</b></sub></a><br /><a href="#maintenance-pcn" title="Maintenance">🚧</a></td>
<td align="center"><a href="https://github.com/seancad"><img src="https://avatars1.githubusercontent.com/u/47405611?v=4?s=100" width="100px;" alt=""/><br /><sub><b>seancad</b></sub></a><br /><a href="#maintenance-seancad" title="Maintenance">🚧</a></td>
<td align="center"><a href="http://willhayworth.com"><img src="https://avatars3.githubusercontent.com/u/181174?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Will Hayworth</b></sub></a><br /><a href="#content-wsh" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/chrizel"><img src="https://avatars3.githubusercontent.com/u/20802?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Christian Zeller</b></sub></a><br /><a href="#content-chrizel" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/jfchevrette"><img src="https://avatars.githubusercontent.com/u/3001?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/jbaber"><img src="https://avatars.githubusercontent.com/u/1908117?v=4?s=100" width="100px;" alt=""/><br /><sub><b>John Baber-Lucero</b></sub></a><br /><a href="#content-jbaber" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/tal-zvon"><img src="https://avatars.githubusercontent.com/u/3195851?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tal</b></sub></a><br /><a href="#content-tal-zvon" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/apogeeoak"><img src="https://avatars.githubusercontent.com/u/59737221?v=4?s=100" width="100px;" alt=""/><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"><a href="http://www.garfieldtech.com/"><img src="https://avatars.githubusercontent.com/u/254863?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Larry Garfield</b></sub></a><br /><a href="#content-Crell" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/circumspect"><img src="https://avatars.githubusercontent.com/u/40770208?v=4?s=100" width="100px;" alt=""/><br /><sub><b>circumspect</b></sub></a><br /><a href="#content-circumspect" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/cjwyett"><img src="https://avatars.githubusercontent.com/u/34195737?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cyrus Wyett</b></sub></a><br /><a href="#content-cjwyett" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/cadolphs"><img src="https://avatars.githubusercontent.com/u/13894820?v=4?s=100" width="100px;" alt=""/><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"><a href="https://www.haveneer.com"><img src="https://avatars.githubusercontent.com/u/26146722?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Pascal H.</b></sub></a><br /><a href="#content-hpwxf" title="Content">🖋</a></td>
<td align="center"><a href="https://twitter.com/chapeupreto"><img src="https://avatars.githubusercontent.com/u/834048?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rod Elias</b></sub></a><br /><a href="#content-chapeupreto" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/blerchy"><img src="https://avatars.githubusercontent.com/u/2555355?v=4?s=100" width="100px;" alt=""/><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"><a href="http://flakolefluk.dev"><img src="https://avatars.githubusercontent.com/u/11986564?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Ignacio Le Fluk</b></sub></a><br /><a href="#content-flakolefluk" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/tlyu"><img src="https://avatars.githubusercontent.com/u/431873?v=4?s=100" width="100px;" alt=""/><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"><a href="https://zerotask.github.io"><img src="https://avatars.githubusercontent.com/u/20150243?v=4?s=100" width="100px;" alt=""/><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"><a href="https://petkopavlovski.com/"><img src="https://avatars.githubusercontent.com/u/32264020?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Pete Pavlovski</b></sub></a><br /><a href="#content-arthas168" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/k12ish"><img src="https://avatars.githubusercontent.com/u/45272873?v=4?s=100" width="100px;" alt=""/><br /><sub><b>k12ish</b></sub></a><br /><a href="#content-k12ish" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/hongshaoyang"><img src="https://avatars.githubusercontent.com/u/19281800?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Shao Yang Hong</b></sub></a><br /><a href="#content-hongshaoyang" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/bmacer"><img src="https://avatars.githubusercontent.com/u/13931806?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Brandon Macer</b></sub></a><br /><a href="#content-bmacer" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/stoiandan"><img src="https://avatars.githubusercontent.com/u/10388612?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Stoian Dan</b></sub></a><br /><a href="#content-stoiandan" title="Content">🖋</a></td>
<td align="center"><a href="https://about.me/pjdelport"><img src="https://avatars.githubusercontent.com/u/630271?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Pi Delport</b></sub></a><br /><a href="#content-PiDelport" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/sateeshkumarb"><img src="https://avatars.githubusercontent.com/u/429263?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/kayuapi"><img src="https://avatars.githubusercontent.com/u/10304328?v=4?s=100" width="100px;" alt=""/><br /><sub><b>ZC</b></sub></a><br /><a href="#content-kayuapi" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/hyperparabolic"><img src="https://avatars.githubusercontent.com/u/12348474?v=4?s=100" width="100px;" alt=""/><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"><a href="https://www.net4visions.at"><img src="https://avatars.githubusercontent.com/u/5228369?v=4?s=100" width="100px;" alt=""/><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"><a href="https://richthofen.io/"><img src="https://avatars.githubusercontent.com/u/7576730?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/cseltol"><img src="https://avatars.githubusercontent.com/u/64264529?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/lauralindzey"><img src="https://avatars.githubusercontent.com/u/65185744?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/sinharaksh1t"><img src="https://avatars.githubusercontent.com/u/28585848?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rakshit Sinha</b></sub></a><br /><a href="#content-sinharaksh1t" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/dbednar230"><img src="https://avatars.githubusercontent.com/u/54457902?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Damian</b></sub></a><br /><a href="#content-dbednar230" title="Content">🖋</a></td>
<td align="center"><a href="https://benarmstead.co.uk"><img src="https://avatars.githubusercontent.com/u/70973680?v=4?s=100" width="100px;" alt=""/><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"><a href="https://github.com/anuk909"><img src="https://avatars.githubusercontent.com/u/34924662?v=4?s=100" width="100px;" alt=""/><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"><a href="https://granddaifuku.com/"><img src="https://avatars.githubusercontent.com/u/49578068?v=4?s=100" width="100px;" alt=""/><br /><sub><b>granddaifuku</b></sub></a><br /><a href="#content-granddaifuku" title="Content">🖋</a></td>
</tr>
<tr>
<td align="center"><a href="https://weilet.me"><img src="https://avatars.githubusercontent.com/u/32561597?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Weilet</b></sub></a><br /><a href="#content-Weilet" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/Millione"><img src="https://avatars.githubusercontent.com/u/38575932?v=4?s=100" width="100px;" alt=""/><br /><sub><b>LIU JIE</b></sub></a><br /><a href="#content-Millione" title="Content">🖋</a></td>
<td align="center"><a href="https://github.com/abusch"><img src="https://avatars.githubusercontent.com/u/506344?v=4?s=100" width="100px;" alt=""/><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"><a href="https://frogtd.com/"><img src="https://avatars.githubusercontent.com/u/31412003?v=4?s=100" width="100px;" alt=""/><br /><sub><b>frogtd</b></sub></a><br /><a href="#content-frogtd" title="Content">🖋</a></td>
</tr>
</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,5 +0,0 @@
steps:
- label: "Test with stable"
command: rustup run stable cargo test
- label: "Test with beta"
command: rustup run beta cargo test

View File

@@ -1,19 +1,25 @@
Thanks for installing Rustlings!
Is this your first time?
Is this your first time? Don't worry, Rustlings was made for beginners! We are
going to teach you a lot of things about Rust, but before we can get
started, here's a couple of notes about how Rustlings operates:
Let's make sure you're up to speed:
- You have Rust installed, preferably via `rustup`
- You have `~/.cargo/bin` added to your PATH variable
- You have cloned this repository (https://github.com/rust-lang/rustlings)
- You have installed Rust language support for your editor
- You have locally installed the `rustlings` command by running an
installation script or manually executing:
1. The central concept behind Rustlings is that you solve exercises. These
exercises usually have some sort of syntax error in them, which will cause
them to fail compilation or testing. Sometimes there's a logic error instead
of a syntax error. No matter what error, it's your job to find it and fix it!
You'll know when you fixed it because then, the exercise will compile and
Rustlings will be able to move on to the next exercise.
2. If you run Rustlings in watch mode (which we recommend), it'll automatically
start with the first exercise. Don't get confused by an error message popping
up as soon as you run Rustlings! This is part of the exercise that you're
supposed to solve, so open the exercise file in an editor and start your
detective work!
3. If you're stuck on an exercise, there is a helpful hint you can view by typing
'hint' (in watch mode), or running `rustlings hint myexercise`.
4. If an exercise doesn't make sense to you, feel free to open an issue on GitHub!
(https://github.com/rust-lang/rustlings/issues/new). We look at every issue,
and sometimes, other learners do too so you can help each other out!
cargo install --force --path .
If you've done all of this (or even most of it), congrats! You're ready
to start working with Rust.
To get started, run `rustlings watch` in order to get the first exercise.
Make sure to have your editor open!
Got all that? Great! To get started, run `rustlings watch` in order to get the first
exercise. Make sure to have your editor open!

24
exercises/README.md Normal file
View File

@@ -0,0 +1,24 @@
# Exercise to Book Chapter mapping
| Exercise | Book Chapter |
|------------------------|--------------|
| variables | §3.1 |
| functions | §3.3 |
| if | §3.5 |
| move_semantics | §4.1 |
| primitive_types | §4.3 |
| structs | §5.1 |
| enums | §6 |
| modules | §7 |
| collections | §8.1, §8.3 |
| strings | §8.2 |
| error_handling | §9 |
| generics | §10 |
| option | §10.1 |
| traits | §10.2 |
| tests | §11.1 |
| standard_library_types | §13.2 |
| threads | §16.1 |
| macros | §19.6 |
| clippy | n/a |
| conversions | n/a |

View File

@@ -0,0 +1,98 @@
// advanced_errs1.rs
// Remember back in errors6, we had multiple mapping functions so that we
// could translate lower-level errors into our custom error type using
// `map_err()`? What if we could use the `?` operator directly instead?
// Make this code compile! Execute `rustlings hint advanced_errs1` for
// hints :)
// I AM NOT DONE
use std::num::ParseIntError;
use std::str::FromStr;
// This is a custom error type that we will be using in the `FromStr`
// implementation.
#[derive(PartialEq, Debug)]
enum ParsePosNonzeroError {
Creation(CreationError),
ParseInt(ParseIntError),
}
impl From<CreationError> for ParsePosNonzeroError {
fn from(e: CreationError) -> Self {
// TODO: complete this implementation so that the `?` operator will
// work for `CreationError`
}
}
// TODO: implement another instance of the `From` trait here so that the
// `?` operator will work in the other place in the `FromStr`
// implementation below.
// Don't change anything below this line.
impl FromStr for PositiveNonzeroInteger {
type Err = ParsePosNonzeroError;
fn from_str(s: &str) -> Result<PositiveNonzeroInteger, Self::Err> {
let x: i64 = s.parse()?;
Ok(PositiveNonzeroInteger::new(x)?)
}
}
#[derive(PartialEq, Debug)]
struct PositiveNonzeroInteger(u64);
#[derive(PartialEq, Debug)]
enum CreationError {
Negative,
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)),
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_parse_error() {
// We can't construct a ParseIntError, so we have to pattern match.
assert!(matches!(
PositiveNonzeroInteger::from_str("not a number"),
Err(ParsePosNonzeroError::ParseInt(_))
));
}
#[test]
fn test_negative() {
assert_eq!(
PositiveNonzeroInteger::from_str("-555"),
Err(ParsePosNonzeroError::Creation(CreationError::Negative))
);
}
#[test]
fn test_zero() {
assert_eq!(
PositiveNonzeroInteger::from_str("0"),
Err(ParsePosNonzeroError::Creation(CreationError::Zero))
);
}
#[test]
fn test_positive() {
let x = PositiveNonzeroInteger::new(42);
assert!(x.is_ok());
assert_eq!(PositiveNonzeroInteger::from_str("42"), Ok(x.unwrap()));
}
}

View File

@@ -0,0 +1,203 @@
// advanced_errs2.rs
// This exercise demonstrates a few traits that are useful for custom error
// types to implement, especially so that other code can consume the custom
// error type more usefully.
// Make this compile, and make the tests pass!
// Execute `rustlings hint advanced_errs2` for hints.
// Steps:
// 1. Implement a missing trait so that `main()` will compile.
// 2. Complete the partial implementation of `From` for
// `ParseClimateError`.
// 3. Handle the missing error cases in the `FromStr` implementation for
// `Climate`.
// 4. Complete the partial implementation of `Display` for
// `ParseClimateError`.
// I AM NOT DONE
use std::error::Error;
use std::fmt::{self, Display, Formatter};
use std::num::{ParseFloatError, ParseIntError};
use std::str::FromStr;
// This is the custom error type that we will be using for the parser for
// `Climate`.
#[derive(Debug, PartialEq)]
enum ParseClimateError {
Empty,
BadLen,
NoCity,
ParseInt(ParseIntError),
ParseFloat(ParseFloatError),
}
// This `From` implementation allows the `?` operator to work on
// `ParseIntError` values.
impl From<ParseIntError> for ParseClimateError {
fn from(e: ParseIntError) -> Self {
Self::ParseInt(e)
}
}
// This `From` implementation allows the `?` operator to work on
// `ParseFloatError` values.
impl From<ParseFloatError> for ParseClimateError {
fn from(e: ParseFloatError) -> Self {
// TODO: Complete this function
}
}
// TODO: Implement a missing trait so that `main()` below will compile. It
// is not necessary to implement any methods inside the missing trait.
// The `Display` trait allows for other code to obtain the error formatted
// as a user-visible string.
impl Display for ParseClimateError {
// TODO: Complete this function so that it produces the correct strings
// for each error variant.
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
// Imports the variants to make the following code more compact.
use ParseClimateError::*;
match self {
NoCity => write!(f, "no city name"),
ParseFloat(e) => write!(f, "error parsing temperature: {}", e),
_ => write!(f, "unhandled error!"),
}
}
}
#[derive(Debug, PartialEq)]
struct Climate {
city: String,
year: u32,
temp: f32,
}
// Parser for `Climate`.
// 1. Split the input string into 3 fields: city, year, temp.
// 2. Return an error if the string is empty or has the wrong number of
// fields.
// 3. Return an error if the city name is empty.
// 4. Parse the year as a `u32` and return an error if that fails.
// 5. Parse the temp as a `f32` and return an error if that fails.
// 6. Return an `Ok` value containing the completed `Climate` value.
impl FromStr for Climate {
type Err = ParseClimateError;
// TODO: Complete this function by making it handle the missing error
// cases.
fn from_str(s: &str) -> Result<Self, Self::Err> {
let v: Vec<_> = s.split(',').collect();
let (city, year, temp) = match &v[..] {
[city, year, temp] => (city.to_string(), year, temp),
_ => return Err(ParseClimateError::BadLen),
};
let year: u32 = year.parse()?;
let temp: f32 = temp.parse()?;
Ok(Climate { city, year, temp })
}
}
// Don't change anything below this line (other than to enable ignored
// tests).
fn main() -> Result<(), Box<dyn Error>> {
println!("{:?}", "Hong Kong,1999,25.7".parse::<Climate>()?);
println!("{:?}", "".parse::<Climate>()?);
Ok(())
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_empty() {
let res = "".parse::<Climate>();
assert_eq!(res, Err(ParseClimateError::Empty));
assert_eq!(res.unwrap_err().to_string(), "empty input");
}
#[test]
fn test_short() {
let res = "Boston,1991".parse::<Climate>();
assert_eq!(res, Err(ParseClimateError::BadLen));
assert_eq!(res.unwrap_err().to_string(), "incorrect number of fields");
}
#[test]
fn test_long() {
let res = "Paris,1920,17.2,extra".parse::<Climate>();
assert_eq!(res, Err(ParseClimateError::BadLen));
assert_eq!(res.unwrap_err().to_string(), "incorrect number of fields");
}
#[test]
fn test_no_city() {
let res = ",1997,20.5".parse::<Climate>();
assert_eq!(res, Err(ParseClimateError::NoCity));
assert_eq!(res.unwrap_err().to_string(), "no city name");
}
#[test]
fn test_parse_int_neg() {
let res = "Barcelona,-25,22.3".parse::<Climate>();
assert!(matches!(res, Err(ParseClimateError::ParseInt(_))));
let err = res.unwrap_err();
if let ParseClimateError::ParseInt(ref inner) = err {
assert_eq!(
err.to_string(),
format!("error parsing year: {}", inner.to_string())
);
} else {
unreachable!();
};
}
#[test]
fn test_parse_int_bad() {
let res = "Beijing,foo,15.0".parse::<Climate>();
assert!(matches!(res, Err(ParseClimateError::ParseInt(_))));
let err = res.unwrap_err();
if let ParseClimateError::ParseInt(ref inner) = err {
assert_eq!(
err.to_string(),
format!("error parsing year: {}", inner.to_string())
);
} else {
unreachable!();
};
}
#[test]
fn test_parse_float() {
let res = "Manila,2001,bar".parse::<Climate>();
assert!(matches!(res, Err(ParseClimateError::ParseFloat(_))));
let err = res.unwrap_err();
if let ParseClimateError::ParseFloat(ref inner) = err {
assert_eq!(
err.to_string(),
format!("error parsing temperature: {}", inner.to_string())
);
} else {
unreachable!();
};
}
#[test]
fn test_parse_good() {
let res = "Munich,2015,23.1".parse::<Climate>();
assert_eq!(
res,
Ok(Climate {
city: "Munich".to_string(),
year: 2015,
temp: 23.1,
})
);
}
#[test]
#[ignore]
fn test_downcast() {
let res = "São Paulo,-21,28.5".parse::<Climate>();
assert!(matches!(res, Err(ParseClimateError::ParseInt(_))));
let err = res.unwrap_err();
let inner: Option<&(dyn Error + 'static)> = err.source();
assert!(inner.is_some());
assert!(inner.unwrap().is::<ParseIntError>());
}
}

View File

@@ -1,8 +1,10 @@
### Clippy
# Clippy
The Clippy tool is a collection of lints to analyze your code so you can catch common mistakes and improve your Rust code.
If you used the installation script for Rustlings, Clippy should be already installed.
If not you can install it manually via `rustup component add clippy`.
For more information about Clippy lints, please see [their documentation page](https://rust-lang.github.io/rust-clippy/master/).
## Further information
- [GitHub Repository](https://github.com/rust-lang/rust-clippy).

View File

@@ -2,6 +2,8 @@
// The Clippy tool is a collection of lints to analyze your code
// so you can catch common mistakes and improve your Rust code.
//
// For these exercises the code will fail to compile when there are clippy warnings
// check clippy's suggestions from the output to solve the exercise.
// Execute `rustlings hint clippy1` for hints :)
// I AM NOT DONE

View File

@@ -0,0 +1,23 @@
# Collections
Rust’s standard library includes a number of very useful data
structures called collections. Most other data types represent one
specific value, but collections can contain multiple values. Unlike
the built-in array and tuple types, the data these collections point
to is stored on the heap, which means the amount of data does not need
to be known at compile time and can grow or shrink as the program
runs.
This exercise will get you familiar with two fundamental data
structures that are used very often in Rust programs:
* A *vector* allows you to store a variable number of values next to
each other.
* A *hash map* allows you to associate a value with a particular key.
You may also know this by the names [*unordered map* in C++](https://en.cppreference.com/w/cpp/container/unordered_map),
[*dictionary* in Python](https://docs.python.org/3/tutorial/datastructures.html#dictionaries) or an *associative array* in other languages.
## Further information
- [Storing Lists of Values with Vectors](https://doc.rust-lang.org/stable/book/ch08-01-vectors.html)
- [Storing Keys with Associated Values in Hash Maps](https://doc.rust-lang.org/book/ch08-03-hash-maps.html)

View File

@@ -0,0 +1,44 @@
// hashmap1.rs
// A basket of fruits in the form of a hash map needs to be defined.
// The key represents the name of the fruit and the value represents
// how many of that particular fruit is in the basket. You have to put
// at least three different types of fruits (e.g apple, banana, mango)
// in the basket and the total count of all the fruits should be at
// least five.
//
// Make me compile and pass the tests!
//
// Execute the command `rustlings hint hashmap1` if you need
// hints.
// I AM NOT DONE
use std::collections::HashMap;
fn fruit_basket() -> HashMap<String, u32> {
let mut basket = // TODO: declare your hash map here.
// Two bananas are already given for you :)
basket.insert(String::from("banana"), 2);
// TODO: Put more fruits in your basket here.
basket
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn at_least_three_types_of_fruits() {
let basket = fruit_basket();
assert!(basket.len() >= 3);
}
#[test]
fn at_least_five_fruits() {
let basket = fruit_basket();
assert!(basket.values().sum::<u32>() >= 5);
}
}

View File

@@ -0,0 +1,81 @@
// hashmap2.rs
// A basket of fruits in the form of a hash map is given. 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 *MORE
// THAN 11* fruits in the basket. Three types of fruits - Apple (4),
// Mango (2) and Lychee (5) are already given in the basket. You are
// not allowed to insert any more of these fruits!
//
// Make me pass the tests!
//
// Execute the command `rustlings hint hashmap2` if you need
// hints.
// I AM NOT DONE
use std::collections::HashMap;
#[derive(Hash, PartialEq, Eq)]
enum Fruit {
Apple,
Banana,
Mango,
Lychee,
Pineapple,
}
fn fruit_basket(basket: &mut HashMap<Fruit, u32>) {
let fruit_kinds = vec![
Fruit::Apple,
Fruit::Banana,
Fruit::Mango,
Fruit::Lychee,
Fruit::Pineapple,
];
for fruit in fruit_kinds {
// TODO: Put new fruits if not already present. Note that you
// are not allowed to put any type of fruit that's already
// present!
}
}
#[cfg(test)]
mod tests {
use super::*;
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
}
#[test]
fn test_given_fruits_are_not_modified() {
let mut basket = get_fruit_basket();
fruit_basket(&mut basket);
assert_eq!(*basket.get(&Fruit::Apple).unwrap(), 4);
assert_eq!(*basket.get(&Fruit::Mango).unwrap(), 2);
assert_eq!(*basket.get(&Fruit::Lychee).unwrap(), 5);
}
#[test]
fn at_least_five_types_of_fruits() {
let mut basket = get_fruit_basket();
fruit_basket(&mut basket);
let count_fruit_kinds = basket.len();
assert!(count_fruit_kinds >= 5);
}
#[test]
fn greater_than_eleven_fruits() {
let mut basket = get_fruit_basket();
fruit_basket(&mut basket);
let count = basket.values().sum::<u32>();
assert!(count > 11);
}
}

View File

@@ -0,0 +1,25 @@
// vec1.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 the command `rustlings hint vec1` if you need hints.
// 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
(a, v)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_array_and_vec_similarity() {
let (a, v) = array_and_vec();
assert_eq!(a, v[..]);
}
}

View File

@@ -0,0 +1,33 @@
// vec2.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 the command `rustlings hint vec2` if you need
// hints.
// I AM NOT DONE
fn vec_loop(mut v: Vec<i32>) -> Vec<i32> {
for i in v.iter_mut() {
// TODO: Fill this up so that each element in the Vec `v` is
// multiplied by 2.
}
// At this point, `v` should be equal to [4, 8, 12, 16, 20].
v
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_vec_loop() {
let v: Vec<i32> = (1..).filter(|x| x % 2 == 0).take(5).collect();
let ans = vec_loop(v.clone());
assert_eq!(ans, v.iter().map(|x| x * 2).collect::<Vec<i32>>());
}
}

View File

@@ -1,5 +1,4 @@
### Type conversions
# Type conversions
Rust offers a multitude of ways to convert a value of a given type into another type.
@@ -15,6 +14,8 @@ Furthermore, the `std::str` module offers a trait called [`FromStr`](https://doc
These should be the main ways ***within the standard library*** to convert data into your desired types.
#### Book Sections
## Further information
These are not directly covered in the book, but the standard library has great documentation for [conversions here](https://doc.rust-lang.org/std/convert/index.html). The `FromStr` trait is also covered [here](https://doc.rust-lang.org/std/str/trait.FromStr.html).
These are not directly covered in the book, but the standard library has a great documentation for it.
- [conversions](https://doc.rust-lang.org/std/convert/index.html)
- [`FromStr` trait](https://doc.rust-lang.org/std/str/trait.FromStr.html)

View File

@@ -3,6 +3,7 @@
// and https://doc.rust-lang.org/std/convert/trait.AsMut.html, respectively.
// I AM NOT DONE
// Obtain the number of bytes (not characters) in the given argument
// Add the AsRef trait appropriately as a trait bound
fn byte_counter<T>(arg: T) -> usize {
@@ -36,4 +37,16 @@ mod tests {
let s = "Cafe au lait";
assert_eq!(char_counter(s), byte_counter(s));
}
#[test]
fn different_counts_using_string() {
let s = String::from("Café au lait");
assert_ne!(char_counter(s.clone()), byte_counter(s));
}
#[test]
fn same_counts_using_string() {
let s = String::from("Cafe au lait");
assert_eq!(char_counter(s.clone()), byte_counter(s));
}
}

View File

@@ -18,7 +18,6 @@ impl Default for Person {
}
}
// I AM NOT DONE
// Your task is to complete this implementation
// in order for the line `let p = Person::from("Mark,20")` to compile
// Please note that you'll need to parse the age component into a `usize`
@@ -29,9 +28,13 @@ impl Default for Person {
// 1. If the length of the provided string is 0, then return the default of Person
// 2. Split the given string on the commas present in it
// 3. Extract the first element from the split operation and use it as the name
// 4. Extract the other element from the split operation and parse it into a `usize` as the age
// 4. If the name is empty, then return the default of Person
// 5. Extract the other element from the split operation and parse it into a `usize` as the age
// If while parsing the age, something goes wrong, then return the default of Person
// Otherwise, then return an instantiated Person onject with the results
// Otherwise, then return an instantiated Person object with the results
// I AM NOT DONE
impl From<&str> for Person {
fn from(s: &str) -> Person {
}
@@ -72,9 +75,58 @@ mod tests {
}
#[test]
fn test_bad_age() {
// Test that "Mark.twenty" will return the default person due to an error in parsing age
// Test that "Mark,twenty" will return the default person due to an error in parsing age
let p = Person::from("Mark,twenty");
assert_eq!(p.name, "John");
assert_eq!(p.age, 30);
}
#[test]
fn test_missing_comma_and_age() {
let p: Person = Person::from("Mark");
assert_eq!(p.name, "John");
assert_eq!(p.age, 30);
}
#[test]
fn test_missing_age() {
let p: Person = Person::from("Mark,");
assert_eq!(p.name, "John");
assert_eq!(p.age, 30);
}
#[test]
fn test_missing_name() {
let p: Person = Person::from(",1");
assert_eq!(p.name, "John");
assert_eq!(p.age, 30);
}
#[test]
fn test_missing_name_and_age() {
let p: Person = Person::from(",");
assert_eq!(p.name, "John");
assert_eq!(p.age, 30);
}
#[test]
fn test_missing_name_and_invalid_age() {
let p: Person = Person::from(",one");
assert_eq!(p.name, "John");
assert_eq!(p.age, 30);
}
#[test]
fn test_trailing_comma() {
let p: Person = Person::from("Mike,32,");
assert_eq!(p.name, "John");
assert_eq!(p.age, 30);
}
#[test]
fn test_trailing_comma_and_some_string() {
let p: Person = Person::from("Mike,32,man");
assert_eq!(p.name, "John");
assert_eq!(p.age, 30);
}
}

View File

@@ -1,25 +1,45 @@
// This does practically the same thing that TryFrom<&str> does.
// from_str.rs
// This is similar to from_into.rs, but this time we'll implement `FromStr`
// and return errors instead of falling back to a default value.
// Additionally, upon implementing FromStr, you can use the `parse` method
// on strings to generate an object of the implementor type.
// You can read more about it at https://doc.rust-lang.org/std/str/trait.FromStr.html
use std::num::ParseIntError;
use std::str::FromStr;
#[derive(Debug)]
#[derive(Debug, PartialEq)]
struct Person {
name: String,
age: usize,
}
// We will use this error type for the `FromStr` implementation.
#[derive(Debug, PartialEq)]
enum ParsePersonError {
// Empty input string
Empty,
// Incorrect number of fields
BadLen,
// Empty name field
NoName,
// Wrapped error from parse::<usize>()
ParseInt(ParseIntError),
}
// I AM NOT DONE
// Steps:
// 1. If the length of the provided string is 0, then return an error
// 1. If the length of the provided string is 0, an error should be returned
// 2. Split the given string on the commas present in it
// 3. Extract the first element from the split operation and use it as the name
// 4. Extract the other element from the split operation and parse it into a `usize` as the age
// If while parsing the age, something goes wrong, then return an error
// Otherwise, then return a Result of a Person object
// 3. Only 2 elements should be returned from the split, otherwise return an error
// 4. Extract the first element from the split operation and use it as the name
// 5. Extract the other element from the split operation and parse it into a `usize` as the age
// with something like `"4".parse::<usize>()`
// 6. If while extracting the name and the age something goes wrong, an error should be returned
// If everything goes well, then return a Result of a Person object
impl FromStr for Person {
type Err = String;
type Err = ParsePersonError;
fn from_str(s: &str) -> Result<Person, Self::Err> {
}
}
@@ -35,15 +55,68 @@ mod tests {
#[test]
fn empty_input() {
assert!("".parse::<Person>().is_err());
assert_eq!("".parse::<Person>(), Err(ParsePersonError::Empty));
}
#[test]
fn good_input() {
assert!("John,32".parse::<Person>().is_ok());
let p = "John,32".parse::<Person>();
assert!(p.is_ok());
let p = p.unwrap();
assert_eq!(p.name, "John");
assert_eq!(p.age, 32);
}
#[test]
#[should_panic]
fn missing_age() {
"John".parse::<Person>().unwrap();
assert!(matches!(
"John,".parse::<Person>(),
Err(ParsePersonError::ParseInt(_))
));
}
}
#[test]
fn invalid_age() {
assert!(matches!(
"John,twenty".parse::<Person>(),
Err(ParsePersonError::ParseInt(_))
));
}
#[test]
fn missing_comma_and_age() {
assert_eq!("John".parse::<Person>(), Err(ParsePersonError::BadLen));
}
#[test]
fn missing_name() {
assert_eq!(",1".parse::<Person>(), Err(ParsePersonError::NoName));
}
#[test]
fn missing_name_and_age() {
assert!(matches!(
",".parse::<Person>(),
Err(ParsePersonError::NoName | ParsePersonError::ParseInt(_))
));
}
#[test]
fn missing_name_and_invalid_age() {
assert!(matches!(
",one".parse::<Person>(),
Err(ParsePersonError::NoName | ParsePersonError::ParseInt(_))
));
}
#[test]
fn trailing_comma() {
assert_eq!("John,32,".parse::<Person>(), Err(ParsePersonError::BadLen));
}
#[test]
fn trailing_comma_and_some_string() {
assert_eq!(
"John,32,man".parse::<Person>(),
Err(ParsePersonError::BadLen)
);
}
}

View File

@@ -1,71 +1,188 @@
// try_from_into.rs
// TryFrom is a simple and safe type conversion that may fail in a controlled way under some circumstances.
// Basically, this is the same as From. The main difference is that this should return a Result type
// instead of the target type itself.
// You can read more about it at https://doc.rust-lang.org/std/convert/trait.TryFrom.html
use std::convert::{TryInto, TryFrom};
use std::convert::{TryFrom, TryInto};
#[derive(Debug)]
struct Person {
name: String,
age: usize,
#[derive(Debug, PartialEq)]
struct Color {
red: u8,
green: u8,
blue: u8,
}
// We will use this error type for these `TryFrom` conversions.
#[derive(Debug, PartialEq)]
enum IntoColorError {
// Incorrect length of slice
BadLen,
// Integer conversion error
IntConversion,
}
// I AM NOT DONE
// Your task is to complete this implementation
// in order for the line `let p = Person::try_from("Mark,20")` to compile
// and return an Ok result of inner type Person.
// Please note that you'll need to parse the age component into a `usize`
// with something like `"4".parse::<usize>()`. The outcome of this needs to
// be handled appropriately.
// and return an Ok result of inner type Color.
// You need to create an implementation for a tuple of three integers,
// an array of three integers, and a slice of integers.
//
// Steps:
// 1. If the length of the provided string is 0, then return an error
// 2. Split the given string on the commas present in it
// 3. Extract the first element from the split operation and use it as the name
// 4. Extract the other element from the split operation and parse it into a `usize` as the age
// If while parsing the age, something goes wrong, then return an error
// Otherwise, then return a Result of a Person object
impl TryFrom<&str> for Person {
type Error = String;
fn try_from(s: &str) -> Result<Self, Self::Error> {
// Note that the implementation for tuple and array will be checked at compile time,
// but the slice implementation needs to check the slice length!
// Also note that correct RGB color values must be integers in the 0..=255 range.
// Tuple implementation
impl TryFrom<(i16, i16, i16)> for Color {
type Error = IntoColorError;
fn try_from(tuple: (i16, i16, i16)) -> Result<Self, Self::Error> {
}
}
// Array implementation
impl TryFrom<[i16; 3]> for Color {
type Error = IntoColorError;
fn try_from(arr: [i16; 3]) -> Result<Self, Self::Error> {
}
}
// Slice implementation
impl TryFrom<&[i16]> for Color {
type Error = IntoColorError;
fn try_from(slice: &[i16]) -> Result<Self, Self::Error> {
}
}
fn main() {
// Use the `from` function
let p1 = Person::try_from("Mark,20");
// Since From is implemented for Person, we should be able to use Into
let p2: Result<Person, _> = "Gerald,70".try_into();
println!("{:?}", p1);
println!("{:?}", p2);
let c1 = Color::try_from((183, 65, 14));
println!("{:?}", c1);
// Since TryFrom is implemented for Color, we should be able to use TryInto
let c2: Result<Color, _> = [183, 65, 14].try_into();
println!("{:?}", c2);
let v = vec![183, 65, 14];
// With slice we should use `try_from` function
let c3 = Color::try_from(&v[..]);
println!("{:?}", c3);
// or take slice within round brackets and use TryInto
let c4: Result<Color, _> = (&v[..]).try_into();
println!("{:?}", c4);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_bad_convert() {
// Test that John is returned when bad string is provided
let p = Person::try_from("");
assert!(p.is_err());
fn test_tuple_out_of_range_positive() {
assert_eq!(
Color::try_from((256, 1000, 10000)),
Err(IntoColorError::IntConversion)
);
}
#[test]
fn test_good_convert() {
// Test that "Mark,20" works
let p = Person::try_from("Mark,20");
assert!(p.is_ok());
let p = p.unwrap();
assert_eq!(p.name, "Mark");
assert_eq!(p.age, 20);
fn test_tuple_out_of_range_negative() {
assert_eq!(
Color::try_from((-1, -10, -256)),
Err(IntoColorError::IntConversion)
);
}
#[test]
#[should_panic]
fn test_panic_empty_input() {
let p: Person = "".try_into().unwrap();
fn test_tuple_sum() {
assert_eq!(
Color::try_from((-1, 255, 255)),
Err(IntoColorError::IntConversion)
);
}
#[test]
#[should_panic]
fn test_panic_bad_age() {
let p = Person::try_from("Mark,twenty").unwrap();
fn test_tuple_correct() {
let c: Result<Color, _> = (183, 65, 14).try_into();
assert!(c.is_ok());
assert_eq!(
c.unwrap(),
Color {
red: 183,
green: 65,
blue: 14
}
);
}
}
#[test]
fn test_array_out_of_range_positive() {
let c: Result<Color, _> = [1000, 10000, 256].try_into();
assert_eq!(c, Err(IntoColorError::IntConversion));
}
#[test]
fn test_array_out_of_range_negative() {
let c: Result<Color, _> = [-10, -256, -1].try_into();
assert_eq!(c, Err(IntoColorError::IntConversion));
}
#[test]
fn test_array_sum() {
let c: Result<Color, _> = [-1, 255, 255].try_into();
assert_eq!(c, Err(IntoColorError::IntConversion));
}
#[test]
fn test_array_correct() {
let c: Result<Color, _> = [183, 65, 14].try_into();
assert!(c.is_ok());
assert_eq!(
c.unwrap(),
Color {
red: 183,
green: 65,
blue: 14
}
);
}
#[test]
fn test_slice_out_of_range_positive() {
let arr = [10000, 256, 1000];
assert_eq!(
Color::try_from(&arr[..]),
Err(IntoColorError::IntConversion)
);
}
#[test]
fn test_slice_out_of_range_negative() {
let arr = [-256, -1, -10];
assert_eq!(
Color::try_from(&arr[..]),
Err(IntoColorError::IntConversion)
);
}
#[test]
fn test_slice_sum() {
let arr = [-1, 255, 255];
assert_eq!(
Color::try_from(&arr[..]),
Err(IntoColorError::IntConversion)
);
}
#[test]
fn test_slice_correct() {
let v = vec![183, 65, 14];
let c: Result<Color, _> = Color::try_from(&v[..]);
assert!(c.is_ok());
assert_eq!(
c.unwrap(),
Color {
red: 183,
green: 65,
blue: 14
}
);
}
#[test]
fn test_slice_excess_length() {
let v = vec![0, 0, 0, 0];
assert_eq!(Color::try_from(&v[..]), Err(IntoColorError::BadLen));
}
#[test]
fn test_slice_insufficient_length() {
let v = vec![0, 0];
assert_eq!(Color::try_from(&v[..]), Err(IntoColorError::BadLen));
}
}

View File

@@ -1,17 +1,28 @@
// Type casting in Rust is done via the usage of the `as` operator.
// Please note that the `as` operator is not only used when type casting.
// It also helps with renaming imports.
//
// The goal is to make sure that the division does not fail to compile
// and returns the proper type.
// I AM NOT DONE
// The goal is to make sure that the division does not fail to compile
fn average(values: &[f64]) -> f64 {
let total = values
.iter()
.fold(0.0, |a, b| a + b);
let total = values.iter().fold(0.0, |a, b| a + b);
total / values.len()
}
fn main() {
let values = [3.5, 0.3, 13.0, 11.7];
println!("{}", average(&values));
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn returns_proper_type_and_value() {
assert_eq!(average(&[3.5, 0.3, 13.0, 11.7]), 7.125);
}
}

View File

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

View File

@@ -16,10 +16,10 @@ impl Message {
fn main() {
let messages = [
Message::Move{ x: 10, y: 30 },
Message::Move { x: 10, y: 30 },
Message::Echo(String::from("hello world")),
Message::ChangeColor(200, 255, 255),
Message::Quit
Message::Quit,
];
for message in &messages {

View File

@@ -9,13 +9,13 @@ enum Message {
struct Point {
x: u8,
y: u8
y: u8,
}
struct State {
color: (u8, u8, u8),
position: Point,
quit: bool
quit: bool,
}
impl State {
@@ -46,14 +46,14 @@ mod tests {
#[test]
fn test_match_message_call() {
let mut state = State{
let mut state = State {
quit: false,
position: Point{ x: 0, y: 0 },
color: (0, 0, 0)
position: Point { x: 0, y: 0 },
color: (0, 0, 0),
};
state.process(Message::ChangeColor(255, 0, 255));
state.process(Message::ChangeColor((255, 0, 255)));
state.process(Message::Echo(String::from("hello world")));
state.process(Message::Move{ x: 10, y: 15 });
state.process(Message::Move(Point { x: 10, y: 15 }));
state.process(Message::Quit);
assert_eq!(state.color, (255, 0, 255));
@@ -61,5 +61,4 @@ mod tests {
assert_eq!(state.position.y, 15);
assert_eq!(state.quit, true);
}
}

View File

@@ -1,5 +1,11 @@
For this exercise check out the sections:
- [Error Handling](https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html)
- [Generics](https://doc.rust-lang.org/book/ch10-01-syntax.html)
# Error handling
Most errors aren’t serious enough to require the program to stop entirely.
Sometimes, when a function fails, it’s for a reason that you can easily interpret and respond to.
For example, if you try to open a file and that operation fails because the file doesn’t exist, you might want to create the file instead of terminating the process.
of the Rust Book.
## Further information
- [Error Handling](https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html)
- [Generics](https://doc.rust-lang.org/book/ch10-01-syntax.html)
- [Result](https://doc.rust-lang.org/rust-by-example/error/result.html)
- [Boxing errors](https://doc.rust-lang.org/rust-by-example/error/multiple_error_types/boxing_errors.html)

View File

@@ -1,5 +1,5 @@
// result1.rs
// Make this test pass! Execute `rustlings hint result1` for hints :)
// errors4.rs
// Make this test pass! Execute `rustlings hint errors4` for hints :)
// I AM NOT DONE

View File

@@ -0,0 +1,53 @@
// errors5.rs
// This program uses a completed version of the code from errors4.
// It won't compile right now! Why?
// Execute `rustlings hint errors5` for hints!
// I AM NOT DONE
use std::error;
use std::fmt;
use std::num::ParseIntError;
// TODO: update the return type of `main()` to make this compile.
fn main() -> Result<(), ParseIntError> {
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 {
Negative,
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`.
impl fmt::Display for CreationError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let description = match *self {
CreationError::Negative => "number is negative",
CreationError::Zero => "number is zero",
};
f.write_str(description)
}
}
impl error::Error for CreationError {}

View File

@@ -0,0 +1,95 @@
// 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.
// Make these tests pass! Execute `rustlings hint errors6` for hints :)
// I AM NOT DONE
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 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,
}
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))
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[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(_))
));
}
#[test]
fn test_negative() {
assert_eq!(
parse_pos_nonzero("-555"),
Err(ParsePosNonzeroError::Creation(CreationError::Negative))
);
}
#[test]
fn test_zero() {
assert_eq!(
parse_pos_nonzero("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()));
}
}

View File

@@ -1,114 +0,0 @@
// errorsn.rs
// This is a bigger error exercise than the previous ones!
// You can do it! :)
//
// Edit the `read_and_validate` function so that it compiles and
// passes the tests... so many things could go wrong!
//
// - Reading from stdin could produce an io::Error
// - Parsing the input could produce a num::ParseIntError
// - Validating the input could produce a CreationError (defined below)
//
// How can we lump these errors into one general error? That is, what
// type goes where the question marks are, and how do we return
// that type from the body of read_and_validate?
//
// Execute `rustlings hint errorsn` for hints :)
// I AM NOT DONE
use std::error;
use std::fmt;
use std::io;
// PositiveNonzeroInteger is a struct defined below the tests.
fn read_and_validate(b: &mut dyn io::BufRead) -> Result<PositiveNonzeroInteger, ???> {
let mut line = String::new();
b.read_line(&mut line);
let num: i64 = line.trim().parse();
let answer = PositiveNonzeroInteger::new(num);
answer
}
// This is a test helper function that turns a &str into a BufReader.
fn test_with_str(s: &str) -> Result<PositiveNonzeroInteger, Box<dyn error::Error>> {
let mut b = io::BufReader::new(s.as_bytes());
read_and_validate(&mut b)
}
#[test]
fn test_success() {
let x = test_with_str("42\n");
assert_eq!(PositiveNonzeroInteger(42), x.unwrap());
}
#[test]
fn test_not_num() {
let x = test_with_str("eleven billion\n");
assert!(x.is_err());
}
#[test]
fn test_non_positive() {
let x = test_with_str("-40\n");
assert!(x.is_err());
}
#[test]
fn test_ioerror() {
struct Broken;
impl io::Read for Broken {
fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
Err(io::Error::new(io::ErrorKind::BrokenPipe, "uh-oh!"))
}
}
let mut b = io::BufReader::new(Broken);
assert!(read_and_validate(&mut b).is_err());
assert_eq!("uh-oh!", read_and_validate(&mut b).unwrap_err().to_string());
}
#[derive(PartialEq, Debug)]
struct PositiveNonzeroInteger(u64);
impl PositiveNonzeroInteger {
fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> {
if value == 0 {
Err(CreationError::Zero)
} else if value < 0 {
Err(CreationError::Negative)
} else {
Ok(PositiveNonzeroInteger(value as u64))
}
}
}
#[test]
fn test_positive_nonzero_integer_creation() {
assert!(PositiveNonzeroInteger::new(10).is_ok());
assert_eq!(
Err(CreationError::Negative),
PositiveNonzeroInteger::new(-10)
);
assert_eq!(Err(CreationError::Zero), PositiveNonzeroInteger::new(0));
}
#[derive(PartialEq, Debug)]
enum CreationError {
Negative,
Zero,
}
impl fmt::Display for CreationError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str((self as &dyn error::Error).description())
}
}
impl error::Error for CreationError {
fn description(&self) -> &str {
match *self {
CreationError::Negative => "Negative",
CreationError::Zero => "Zero",
}
}
}

View File

@@ -1,31 +0,0 @@
// option1.rs
// This example panics because the second time it calls `pop`, the `vec`
// is empty, so `pop` returns `None`, and `unwrap` panics if it's called
// on `None`. Handle this in a more graceful way than calling `unwrap`!
// Execute `rustlings hint option1` for hints :)
// I AM NOT DONE
pub fn pop_too_much() -> bool {
let mut list = vec![3];
let last = list.pop().unwrap();
println!("The last item in the list is {:?}", last);
let second_to_last = list.pop().unwrap();
println!(
"The second-to-last item in the list is {:?}",
second_to_last
);
true
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn should_not_panic() {
assert!(pop_too_much());
}
}

View File

@@ -1,7 +1,7 @@
### Functions
# Functions
Here, you'll learn how to write functions and how Rust's compiler can trace things way back.
#### Book Sections
## Further information
- [How Functions Work](https://doc.rust-lang.org/book/ch03-03-how-functions-work.html)

View File

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

View File

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

View File

@@ -1,7 +1,11 @@
### Generics
# Generics
In this section you'll learn about saving yourself many lines of code with 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.
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.
### Book Sections
## Further information
- [Generic Data Types](https://doc.rust-lang.org/stable/book/ch10-01-syntax.html)
- [Generic Data Types](https://doc.rust-lang.org/stable/book/ch10-01-syntax.html)
- [Bounds](https://doc.rust-lang.org/rust-by-example/generics/bounds.html)

View File

@@ -1,10 +1,11 @@
// This shopping list program isn't compiling!
// This shopping list program isn't compiling!
// Use your knowledge of generics to fix it.
// Execute `rustlings hint generics1` for hints!
// I AM NOT DONE
fn main() {
let mut shopping_list: Vec<?> = Vec::new();
shopping_list.push("milk");
}

View File

@@ -1,12 +1,15 @@
// 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` for hints!
// I AM NOT DONE
struct Wrapper<u32> {
value: u32
struct Wrapper {
value: u32,
}
impl<u32> Wrapper<u32> {
impl Wrapper {
pub fn new(value: u32) -> Self {
Wrapper { value }
}
@@ -18,13 +21,11 @@ mod tests {
#[test]
fn store_u32_in_wrapper() {
assert_eq!(Wrapper::new(42).value, 42);
assert_eq!(Wrapper::new(42).value, 42);
}
#[test]
fn store_str_in_wrapper() {
// TODO: Delete this assert and uncomment the one below once you have finished the exercise.
assert!(false);
// assert_eq!(Wrapper::new("Foo").value, "Foo");
assert_eq!(Wrapper::new("Foo").value, "Foo");
}
}
}

View File

@@ -1,12 +1,17 @@
// An imaginary magical school has a new report card generation system written in rust!
// Currently the system only supports creating report cards where the student's grade
// is represented numerically (e.g. 1.0 -> 5.5). However, the school also issues alphabetical grades
// (A+ -> F-) and needs to be able to print both types of report card!
// An imaginary magical school has a new report card generation system written in Rust!
// Currently the system only supports creating report cards where the student's grade
// is represented numerically (e.g. 1.0 -> 5.5).
// However, the school also issues alphabetical grades (A+ -> F-) and needs
// to be able to print both types of report card!
// Make the necessary code changes to support alphabetical report cards, thereby making the second
// test pass.
// Make the necessary code changes in the struct ReportCard and the impl block
// to support alphabetical report cards. Change the Grade in the second test to "A+"
// to show that your changes allow alphabetical grades.
// Execute 'rustlings hint generics3' for hints!
// I AM NOT DONE
pub struct ReportCard {
pub grade: f32,
pub student_name: String,
@@ -15,7 +20,8 @@ pub struct ReportCard {
impl ReportCard {
pub fn print(&self) -> String {
format!("{} ({}) - achieved a grade of {}", &self.student_name, &self.student_age, &self.grade)
format!("{} ({}) - achieved a grade of {}",
&self.student_name, &self.student_age, &self.grade)
}
}
@@ -26,21 +32,27 @@ mod tests {
#[test]
fn generate_numeric_report_card() {
let report_card = ReportCard {
grade: 2.1,
student_name: "Tom Wriggle".to_string(),
grade: 2.1,
student_name: "Tom Wriggle".to_string(),
student_age: 12,
};
assert_eq!(report_card.print(), "Tom Wriggle (12) - achieved a grade of 2.1");
assert_eq!(
report_card.print(),
"Tom Wriggle (12) - achieved a grade of 2.1"
);
}
#[test]
fn generate_alphabetic_report_card() {
// TODO: Make sure to change the grade here after you finish the exercise.
let report_card = ReportCard {
grade: 2.1,
student_name: "Gary Plotter".to_string(),
grade: 2.1,
student_name: "Gary Plotter".to_string(),
student_age: 11,
};
assert_eq!(report_card.print(), "Gary Plotter (11) - achieved a grade of A+");
assert_eq!(
report_card.print(),
"Gary Plotter (11) - achieved a grade of A+"
);
}
}
}

View File

@@ -1,7 +1,7 @@
### If
# If
`if`, the most basic type of control flow, is what you'll learn here.
#### Book Sections
## Further information
- [Control Flow - if expressions](https://doc.rust-lang.org/book/ch03-05-control-flow.html#if-expressions)

36
exercises/if/if2.rs Normal file
View File

@@ -0,0 +1,36 @@
// if2.rs
// Step 1: Make me compile!
// Step 2: Get the bar_for_fuzz and default_to_baz tests passing!
// Execute the command `rustlings hint if2` if you want a hint :)
// I AM NOT DONE
pub fn fizz_if_foo(fizzish: &str) -> &str {
if fizzish == "fizz" {
"foo"
} else {
1
}
}
// No test changes needed!
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn foo_for_fizz() {
assert_eq!(fizz_if_foo("fizz"), "foo")
}
#[test]
fn bar_for_fuzz() {
assert_eq!(fizz_if_foo("fuzz"), "bar")
}
#[test]
fn default_to_baz() {
assert_eq!(fizz_if_foo("literally anything"), "baz")
}
}

View File

@@ -1,10 +1,10 @@
### Macros
# Macros
Rust's macro system is very powerful, but also kind of difficult to wrap your
head around. We're not going to teach you how to write your own fully-featured
modules, instead we'll show you how to use and create them.
macros. Instead, we'll show you how to use and create them.
#### Book Sections
## Further information
- [Macros](https://doc.rust-lang.org/book/ch19-06-macros.html)
- [The Little Book of Rust Macros](https://danielkeep.github.io/tlborm/book/index.html)

View File

@@ -1,7 +1,7 @@
### Modules
# Modules
In this section we'll give you an introduction to Rust's module system.
#### Book Sections
## Further information
- [The Module System](https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html)
- [The Module System](https://doc.rust-lang.org/book/ch07-00-managing-growing-projects-with-packages-crates-and-modules.html)

View File

@@ -4,7 +4,13 @@
// I AM NOT DONE
mod sausage_factory {
// Don't let anybody outside of this module see this!
fn get_secret_recipe() -> String {
String::from("Ginger")
}
fn make_sausage() {
get_secret_recipe();
println!("sausage!");
}
}

View File

@@ -1,11 +1,15 @@
// 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.
// Make me compile! Execute `rustlings hint modules2` for hints :)
// I AM NOT DONE
mod delicious_snacks {
use self::fruits::PEAR as fruit;
use self::veggies::CUCUMBER as veggie;
// TODO: Fix these use statements
use self::fruits::PEAR as ???
use self::veggies::CUCUMBER as ???
mod fruits {
pub const PEAR: &'static str = "Pear";

View File

@@ -0,0 +1,18 @@
// 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!
// Make me compile! Execute `rustlings hint modules3` for hints :)
// I AM NOT DONE
// TODO: Complete this use statement
use ???
fn main() {
match SystemTime::now().duration_since(UNIX_EPOCH) {
Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()),
Err(_) => panic!("SystemTime before UNIX EPOCH!"),
}
}

View File

@@ -1,8 +1,8 @@
### Move Semantics
# Move Semantics
These exercises are adapted from [pnkfelix](https://github.com/pnkfelix)'s [Rust Tutorial](https://pnkfelix.github.io/rust-examples-icfp2014/) -- Thank you Felix!!!
#### Book Sections
## Further information
For this section, the book links are especially important.

View File

@@ -1,6 +1,6 @@
// move_semantics4.rs
// Refactor this code so that instead of having `vec0` and creating the vector
// in `fn main`, we instead create it within `fn fill_vec` and transfer the
// in `fn main`, we create it within `fn fill_vec` and transfer the
// freshly created vector from fill_vec to its caller.
// Execute `rustlings hint move_semantics4` for hints!
@@ -18,7 +18,7 @@ fn main() {
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
}
// `fill_vec()` no longer take `vec: Vec<i32>` as argument
// `fill_vec()` no longer takes `vec: Vec<i32>` as argument
fn fill_vec() -> Vec<i32> {
let mut vec = vec;

View File

@@ -0,0 +1,15 @@
// move_semantics5.rs
// Make me compile only be reordering the lines in `main()`, but without
// adding, changing or removing any of them.
// Execute `rustlings hint move_semantics5` for hints :)
// I AM NOT DONE
fn main() {
let mut x = 100;
let y = &mut x;
let z = &mut x;
*y += 100;
*z += 1000;
assert_eq!(x, 1200);
}

View File

@@ -1,8 +1,17 @@
### Option
# Option
#### Book Sections
Type Option represents an optional value: every Option is either Some and contains a value, or None, and does not.
Option types are very common in Rust code, as they have a number of uses:
- Initial values
- Return values for functions that are not defined over their entire input range (partial functions)
- Return value for otherwise reporting simple errors, where None is returned on error
- Optional struct fields
- Struct fields that can be loaned or "taken"
- Optional function arguments
- Nullable pointers
- Swapping things out of difficult situations
To learn about Option<T>, check out these links:
## Further Information
- [Option Enum Format](https://doc.rust-lang.org/stable/book/ch10-01-syntax.html#in-enum-definitions)
- [Option Module Documentation](https://doc.rust-lang.org/std/option/)

View File

@@ -15,9 +15,9 @@ fn main() {
let mut numbers: [Option<u16>; 5];
for iter in 0..5 {
let number_to_add: u16 = {
((iter * 5) + 2) / (4 * 16)
((iter * 1235) + 2) / (4 * 16)
};
numbers[iter] = number_to_add;
numbers[iter as usize] = number_to_add;
}
}

View File

@@ -4,22 +4,22 @@
// I AM NOT DONE
fn main() {
let optional_value = Some(String::from("rustlings"));
// Make this an if let statement whose value is "Some" type
value = optional_value {
println!("the value of optional value is: {}", value);
let optional_word = Some(String::from("rustlings"));
// TODO: Make this an if let statement whose value is "Some" type
word = optional_word {
println!("The word is: {}", word);
} else {
println!("The optional value doesn't contain anything!");
println!("The optional word doesn't contain anything");
}
let mut optional_values_vec: Vec<Option<i8>> = Vec::new();
let mut optional_integers_vec: Vec<Option<i8>> = Vec::new();
for x in 1..10 {
optional_values_vec.push(Some(x));
optional_integers_vec.push(Some(x));
}
// make this a while let statement - remember that vector.pop also adds another layer of Option<T>
// 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
value = optional_values_vec.pop() {
println!("current value: {}", value);
integer = optional_integers_vec.pop() {
println!("current value: {}", integer);
}
}

View File

@@ -0,0 +1,19 @@
// option3.rs
// Make me compile! Execute `rustlings hint option3` for hints
// I AM NOT DONE
struct Point {
x: i32,
y: i32,
}
fn main() {
let y: Option<Point> = Some(Point { x: 100, y: 200 });
match y {
Some(p) => println!("Co-ordinates are {},{} ", p.x, p.y),
_ => println!("no match"),
}
y; // Fix without deleting this line.
}

View File

@@ -1,9 +1,9 @@
### Primitive Types
# Primitive Types
Rust has a couple of basic types that are directly implemented into the
compiler. In this section, we'll go through the most important ones.
#### Book Sections
## Further information
- [Data Types](https://doc.rust-lang.org/stable/book/ch03-02-data-types.html)
- [The Slice Type](https://doc.rust-lang.org/stable/book/ch04-03-slices.html)

View File

@@ -1,5 +1,5 @@
// primitive_types3.rs
// Create an array with at least 100 elements in it where the ??? is.
// Create an array with at least 100 elements in it where the ??? is.
// Execute `rustlings hint primitive_types3` for hints!
// I AM NOT DONE

View File

@@ -1,11 +1,16 @@
// primitive_types6.rs
// Use a tuple index to access the second element of `numbers`.
// You can put this right into the `println!` where the ??? is.
// You can put the expression for the second element where ??? is so that the test passes.
// Execute `rustlings hint primitive_types6` for hints!
// I AM NOT DONE
fn main() {
#[test]
fn indexing_tuple() {
let numbers = (1, 2, 3);
println!("The second number is {}", ???);
// Replace below ??? with the tuple indexing syntax.
let second = ???;
assert_eq!(2, second,
"This is not the 2nd number in the tuple!")
}

View File

@@ -1,23 +1,25 @@
// test1.rs
// This is a test for the following sections:
// quiz1.rs
// This is a quiz for the following sections:
// - Variables
// - Functions
// Mary is buying apples. One apple usually costs 2 Rustbucks, but if you buy
// more than 40 at once, each apple only costs 1! Write a function that calculates
// the price of an order of apples given the order amount. No hints this time!
// the price of an order of apples given the quantity bought. No hints this time!
// I AM NOT DONE
// Put your function here!
// fn ..... {
// fn calculate_apple_price {
// Don't modify this function!
#[test]
fn verify_test() {
let price1 = calculate_apple_price(35);
let price2 = calculate_apple_price(65);
let price2 = calculate_apple_price(40);
let price3 = calculate_apple_price(65);
assert_eq!(70, price1);
assert_eq!(65, price2);
assert_eq!(80, price2);
assert_eq!(65, price3);
}

30
exercises/quiz2.rs Normal file
View File

@@ -0,0 +1,30 @@
// quiz2.rs
// This is a quiz for the following sections:
// - Strings
// 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!
// I AM NOT DONE
fn string_slice(arg: &str) {
println!("{}", arg);
}
fn string(arg: String) {
println!("{}", arg);
}
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());
}

View File

@@ -1,8 +1,8 @@
// test3.rs
// This is a test for the following sections:
// quiz3.rs
// This is a quiz for the following sections:
// - Tests
// This test isn't testing our function -- make it do that in such a way that
// This quiz isn't testing our function -- make it do that in such a way that
// the test passes. Then write a second test that tests that we get the result
// we expect to get when we call `times_two` with a negative number.
// No hints, you can do this :)
@@ -24,6 +24,7 @@ mod tests {
#[test]
fn returns_twice_of_negative_numbers() {
// TODO write an assert for `times_two(-4)`
// TODO replace unimplemented!() with an assert for `times_two(-4)`
unimplemented!()
}
}

View File

@@ -1,9 +1,9 @@
// test4.rs
// This test covers the sections:
// quiz4.rs
// This quiz covers the sections:
// - Modules
// - Macros
// Write a macro that passes the test! No hints this time, you can do it!
// Write a macro that passes the quiz! No hints this time, you can do it!
// I AM NOT DONE

View File

@@ -1,5 +1,10 @@
For the Arc exercise check out the chapter [Shared-State Concurrency](https://doc.rust-lang.org/book/ch16-03-shared-state.html) of the Rust Book.
# Standard library types
For the Iterator exercise check out the chapters [Iterator](https://doc.rust-lang.org/book/ch13-02-iterators.html) of the Rust Book and the [Iterator documentation](https://doc.rust-lang.org/stable/std/iter/).
Do not adjust your monitors-- iterators1.rs is indeed missing. Iterators is a challenging topic, so we're leaving space for a simpler exercise!
This section will teach you about Box, Shared-State Concurrency and Iterators.
## Further information
- [Using Box to Point to Data on the Heap](https://doc.rust-lang.org/book/ch15-01-box.html)
- [Shared-State Concurrency](https://doc.rust-lang.org/book/ch16-03-shared-state.html)
- [Iterator](https://doc.rust-lang.org/book/ch13-02-iterators.html)
- [Iterator documentation](https://doc.rust-lang.org/stable/std/iter/)

View File

@@ -1,11 +1,26 @@
// arc1.rs
// In this exercise, we are given a Vec of u32 called "numbers" with values ranging
// from 0 to 99 -- [ 0, 1, 2, ..., 98, 99 ]
// We would like to use this set of numbers within 8 different threads simultaneously.
// Each thread is going to get the sum of every eighth value, with an offset.
// 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
// TODO comment is and create an initial binding for `child_numbers`
// somewhere. Try not to create any copies of the `numbers` Vec!
// 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` for hints :)
// I AM NOT DONE
#![forbid(unused_imports)] // Do not change this, (or the next) line.
use std::sync::Arc;
use std::thread;
@@ -15,12 +30,13 @@ fn main() {
let mut joinhandles = Vec::new();
for offset in 0..8 {
let child_numbers = // TODO
joinhandles.push(thread::spawn(move || {
let mut i = offset;
let mut sum = 0;
while i < child_numbers.len() {
sum += child_numbers[i];
i += 5;
i += 8;
}
println!("Sum of offset {} is {}", offset, sum);
}));

View File

@@ -0,0 +1,56 @@
// 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 data structure
// frequently found in functional programming languages. Each item in a cons list contains two
// elements: the value of the current item and the next item. The last item is a value called `Nil`.
//
// Step 1: use a `Box` in the enum definition to make the code compile
// Step 2: create both empty and non-empty cons lists by replacing `unimplemented!()`
//
// Note: the tests should not be changed
//
// Execute `rustlings hint box1` for hints :)
// I AM NOT DONE
#[derive(PartialEq, Debug)]
pub enum List {
Cons(i32, List),
Nil,
}
fn main() {
println!("This is an empty cons list: {:?}", create_empty_list());
println!(
"This is a non-empty cons list: {:?}",
create_non_empty_list()
);
}
pub fn create_empty_list() -> List {
unimplemented!()
}
pub fn create_non_empty_list() -> List {
unimplemented!()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_create_empty_list() {
assert_eq!(List::Nil, create_empty_list())
}
#[test]
fn test_create_non_empty_list() {
assert_ne!(create_empty_list(), create_non_empty_list())
}
}

View File

@@ -0,0 +1,24 @@
// iterators1.rs
//
// Make me compile by filling in the `???`s
//
// When performing operations on elements within a collection, iterators are essential.
// This module helps you get familiar with the structure of using an iterator and
// how to go through elements within an iterable collection.
//
// Execute `rustlings hint iterators1` for hints :D
// I AM NOT DONE
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 2.1
assert_eq!(my_iterable_fav_fruits.next(), Some(&"raspberry"));
assert_eq!(my_iterable_fav_fruits.next(), ???); // TODO: Step 3
}

View File

@@ -1,26 +1,41 @@
// iterators2.rs
// In this module, you'll learn some of unique advantages that iterators can offer
// Step 1. Complete the `capitalize_first` function to pass the first two cases
// Step 2. Apply the `capitalize_first` function to a vector of strings, ensuring that it returns a vector of strings as well
// Step 3. Apply the `capitalize_first` function again to a list, but try and ensure it returns a single string
// In this exercise, you'll learn some of the unique advantages that iterators
// can offer. Follow the steps to complete the exercise.
// As always, there are hints if you execute `rustlings hint iterators2`!
// I AM NOT DONE
// Step 1.
// Complete the `capitalize_first` function.
// "hello" -> "Hello"
pub fn capitalize_first(input: &str) -> String {
let mut c = input.chars();
match c.next() {
None => String::new(),
Some(first) => first.collect::<String>() + c.as_str(),
Some(first) => ???,
}
}
// Step 2.
// 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![]
}
// Step 3.
// 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()
}
#[cfg(test)]
mod tests {
use super::*;
// Step 1.
// Tests that verify your `capitalize_first` function implementation
#[test]
fn test_success() {
assert_eq!(capitalize_first("hello"), "Hello");
@@ -31,18 +46,15 @@ mod tests {
assert_eq!(capitalize_first(""), "");
}
// Step 2.
#[test]
fn test_iterate_string_vec() {
let words = vec!["hello", "world"];
let capitalized_words: Vec<String> = // TODO
assert_eq!(capitalized_words, ["Hello", "World"]);
assert_eq!(capitalize_words_vector(&words), ["Hello", "World"]);
}
#[test]
fn test_iterate_into_string() {
let words = vec!["hello", " ", "world"];
let capitalized_words = // TODO
assert_eq!(capitalized_words, "Hello World");
assert_eq!(capitalize_words_string(&words), "Hello World");
}
}

View File

@@ -1,11 +1,10 @@
// 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. Uncomment the last two tests and get them to pass by filling in
// values for `x` using `division_results`.
// 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` to get some hints!
// Have fun :-)
// I AM NOT DONE
@@ -21,16 +20,28 @@ pub struct NotDivisibleError {
divisor: i32,
}
// This function should calculate `a` divided by `b` if `a` is
// evenly divisible by b.
// Otherwise, it should return a suitable error.
// 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> {}
// Complete the function and return a value of the correct type so the test passes.
// Desired output: Ok([1, 11, 1426, 3])
fn result_with_list() -> () {
let numbers = vec![27, 297, 38502, 81];
let division_results = numbers.into_iter().map(|n| divide(n, 27));
}
// Complete the function and return a value of the correct type so the test passes.
// Desired output: [Ok(1), Ok(11), Ok(1426), Ok(3)]
fn list_of_results() -> () {
let numbers = vec![27, 297, 38502, 81];
let division_results = numbers.into_iter().map(|n| divide(n, 27));
}
#[cfg(test)]
mod tests {
use super::*;
// Tests that verify your `divide` function implementation
#[test]
fn test_success() {
assert_eq!(divide(81, 9), Ok(9));
@@ -57,22 +68,16 @@ mod tests {
assert_eq!(divide(0, 81), Ok(0));
}
// Iterator exercises using your `divide` function
/*
#[test]
fn result_with_list() {
let numbers = vec![27, 297, 38502, 81];
let division_results = numbers.into_iter().map(|n| divide(n, 27));
let x //... Fill in here!
assert_eq!(format!("{:?}", x), "Ok([1, 11, 1426, 3])");
fn test_result_with_list() {
assert_eq!(format!("{:?}", result_with_list()), "Ok([1, 11, 1426, 3])");
}
#[test]
fn list_of_results() {
let numbers = vec![27, 297, 38502, 81];
let division_results = numbers.into_iter().map(|n| divide(n, 27));
let x //... Fill in here!
assert_eq!(format!("{:?}", x), "[Ok(1), Ok(11), Ok(1426), Ok(3)]");
fn test_list_of_results() {
assert_eq!(
format!("{:?}", list_of_results()),
"[Ok(1), Ok(11), Ok(1426), Ok(3)]"
);
}
*/
}

View File

@@ -3,13 +3,13 @@
// I AM NOT DONE
pub fn factorial(num: u64) -> u64 {
// Complete this function to return factorial of num
// Complete this function to return the factorial of num
// Do not use:
// - return
// For extra fun don't use:
// Try not to use:
// - imperative style loops (for, while)
// - additional variables
// For the most fun don't use:
// For an extra challenge, don't use:
// - recursion
// Execute `rustlings hint iterators4` for hints.
}

View File

@@ -0,0 +1,122 @@
// iterators5.rs
// Let's define a simple model to track Rustlings exercise progress. Progress
// will be modelled using a hash map. The name of the exercise is the key and
// the progress is the value. Two counting functions were created to count the
// number of exercises with a given progress. These counting functions use
// imperative style for loops. Recreate this counting functionality using
// iterators. Only the two iterator methods (count_iterator and
// count_collection_iterator) need to be modified.
// Execute `rustlings hint iterators5` for hints.
//
// Make the code compile and the tests pass.
// I AM NOT DONE
use std::collections::HashMap;
#[derive(Clone, Copy, PartialEq, Eq)]
enum Progress {
None,
Some,
Complete,
}
fn count_for(map: &HashMap<String, Progress>, value: Progress) -> usize {
let mut count = 0;
for val in map.values() {
if val == &value {
count += 1;
}
}
count
}
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, ... }
}
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 {
count += 1;
}
}
}
count
}
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, ... }, ... ]
}
#[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_equals_for() {
let map = get_map();
assert_eq!(
count_for(&map, Progress::Complete),
count_iterator(&map, Progress::Complete)
);
}
#[test]
fn count_collection_complete() {
let collection = get_vec_map();
assert_eq!(
6,
count_collection_iterator(&collection, Progress::Complete)
);
}
#[test]
fn count_collection_equals_for() {
let collection = get_vec_map();
assert_eq!(
count_collection_for(&collection, Progress::Complete),
count_collection_iterator(&collection, Progress::Complete)
);
}
fn get_map() -> HashMap<String, Progress> {
use Progress::*;
let mut map = HashMap::new();
map.insert(String::from("variables1"), Complete);
map.insert(String::from("functions1"), Complete);
map.insert(String::from("hashmap1"), Complete);
map.insert(String::from("arc1"), Some);
map.insert(String::from("as_ref_mut"), None);
map.insert(String::from("from_str"), None);
map
}
fn get_vec_map() -> Vec<HashMap<String, Progress>> {
use Progress::*;
let map = get_map();
let mut other = HashMap::new();
other.insert(String::from("variables2"), Complete);
other.insert(String::from("functions2"), Complete);
other.insert(String::from("if1"), Complete);
other.insert(String::from("from_into"), None);
other.insert(String::from("try_from_into"), None);
vec![map, other]
}
}

View File

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

View File

@@ -1,7 +1,8 @@
### Structs
# Structs
Rust has three struct types: a classic c struct, a tuple struct, and a unit struct.
Rust has three struct types: a classic C struct, a tuple struct, and a unit struct.
#### Book Sections
## Further information
- [Structures](https://doc.rust-lang.org/rust-by-example/custom_types/structs.html)
- [Structures](https://doc.rust-lang.org/book/ch05-01-defining-structs.html)
- [Method Syntax](https://doc.rust-lang.org/book/ch05-03-method-syntax.html)

View File

@@ -1,6 +1,5 @@
// structs2.rs
// Address all the TODOs to make the tests pass!
// No hints, just do it!
// I AM NOT DONE

View File

@@ -0,0 +1,82 @@
// 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!
// If you have issues execute `rustlings hint structs3`
// I AM NOT DONE
#[derive(Debug)]
struct Package {
sender_country: String,
recipient_country: String,
weight_in_grams: i32,
}
impl Package {
fn new(sender_country: String, recipient_country: String, weight_in_grams: i32) -> Package {
if weight_in_grams <= 0 {
// Something goes here...
} else {
return Package {
sender_country,
recipient_country,
weight_in_grams,
};
}
}
fn is_international(&self) -> ??? {
// Something goes here...
}
fn get_fees(&self, cents_per_gram: i32) -> ??? {
// Something goes here...
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[should_panic]
fn fail_creating_weightless_package() {
let sender_country = String::from("Spain");
let recipient_country = String::from("Austria");
Package::new(sender_country, recipient_country, -2210);
}
#[test]
fn create_international_package() {
let sender_country = String::from("Spain");
let recipient_country = String::from("Russia");
let package = Package::new(sender_country, recipient_country, 1200);
assert!(package.is_international());
}
#[test]
fn create_local_package() {
let sender_country = String::from("Canada");
let recipient_country = sender_country.clone();
let package = Package::new(sender_country, recipient_country, 1200);
assert!(!package.is_international());
}
#[test]
fn calculate_transport_fees() {
let sender_country = String::from("Spain");
let recipient_country = String::from("Spain");
let cents_per_gram = ???;
let package = Package::new(sender_country, recipient_country, 1500);
assert_eq!(package.get_fees(cents_per_gram), 4500);
}
}

View File

@@ -1,30 +0,0 @@
// test2.rs
// This is a test for the following sections:
// - Strings
// Ok, here are a bunch of values-- some are `Strings`, some are `&strs`. 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!
// I AM NOT DONE
fn string_slice(arg: &str) {
println!("{}", arg);
}
fn string(arg: String) {
println!("{}", arg);
}
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());
}

View File

@@ -1,7 +1,7 @@
### Tests
# Tests
Going out of order from the book to cover tests -- many of the following exercises will ask you to make tests pass!
#### Book Sections
## Further information
- [Writing Tests](https://doc.rust-lang.org/book/ch11-01-writing-tests.html)

View File

@@ -18,4 +18,9 @@ mod tests {
fn is_true_when_even() {
assert!();
}
#[test]
fn is_false_when_odd() {
assert!();
}
}

View File

@@ -1 +1,9 @@
For this exercise check out the [Dining Philosophers example](https://doc.rust-lang.org/1.4.0/book/dining-philosophers.html) and the chapter [Concurrency](https://doc.rust-lang.org/book/ch16-01-threads.html) of the Rust Book.
# Threads
In most current operating systems, an executed program’s code is run in a process, and the operating system manages multiple processes at once.
Within your program, you can also have independent parts that run simultaneously. The features that run these independent parts are called threads.
## Further information
- [Dining Philosophers example](https://doc.rust-lang.org/1.4.0/book/dining-philosophers.html)
- [Using Threads to Run Code Simultaneously](https://doc.rust-lang.org/book/ch16-01-threads.html)

View File

@@ -1,7 +1,8 @@
// threads1.rs
// Make this compile! Execute `rustlings hint threads1` for hints :)
// The idea is the thread spawned on line 21 is completing jobs while the main thread is
// monitoring progress until 10 jobs are completed. If you see 6 lines
// The idea is the thread spawned on line 22 is completing jobs while the main thread is
// monitoring progress until 10 jobs are completed. Because of the difference between the
// spawned threads' sleep time, and the waiting threads sleep time, when you see 6 lines
// of "waiting..." and the program ends without timing out when running,
// you've got it :)

View File

@@ -0,0 +1,19 @@
# Traits
A trait is a collection of methods.
Data types can implement traits. To do so, the methods making up the trait are defined for the data type. For example, the `String` data type implements the `From<&str>` trait. This allows a user to write `String::from("hello")`.
In this way, traits are somewhat similar to Java interfaces and C++ abstract classes.
Some additional common Rust traits include:
- `Clone` (the `clone` method)
- `Display` (which allows formatted display via `{}`)
- `Debug` (which allows formatted display via `{:?}`)
Because traits indicate shared behavior between data types, they are useful when writing generics.
## Further information
- [Traits](https://doc.rust-lang.org/book/ch10-02-traits.html)

View File

@@ -1,21 +1,21 @@
// 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.
// I AM NOT DONE
trait AppendBar {
fn append_bar(self) -> Self;
}
impl AppendBar for String {
//Add your code here
}
fn main() {
@@ -40,5 +40,4 @@ mod tests {
String::from("BarBar")
);
}
}
}

View File

@@ -1,12 +1,12 @@
// 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!
@@ -18,9 +18,6 @@ trait AppendBar {
//TODO: Add your code here
#[cfg(test)]
mod tests {
use super::*;
@@ -31,5 +28,4 @@ mod tests {
assert_eq!(foo.pop().unwrap(), String::from("Bar"));
assert_eq!(foo.pop().unwrap(), String::from("Foo"));
}
}

View File

@@ -1,7 +1,9 @@
### Variables
# Variables
Here you'll learn about simple variables.
In Rust, variables are immutable by default.
When a variable is immutable, once a value is bound to a name, you can’t change that value.
You can make them mutable by adding mut in front of the variable name.
#### Book Sections
## Further information
- [Variables and Mutability](https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html)

View File

@@ -6,6 +6,6 @@
fn main() {
let x = 3;
println!("Number {}", x);
x = 5;
x = 5; // don't change this line
println!("Number {}", x);
}

View File

@@ -4,8 +4,8 @@
// I AM NOT DONE
fn main() {
let number = "3";
println!("Number {}", number);
let number = "T-H-R-E-E"; // don't change this line
println!("Spell a Number : {}", number);
number = 3;
println!("Number {}", number);
println!("Number plus two is : {}", number + 2);
}

View File

@@ -0,0 +1,9 @@
// variables6.rs
// Make me compile! Execute the command `rustlings hint variables6` if you want a hint :)
// I AM NOT DONE
const NUMBER = 3;
fn main() {
println!("Number {}", NUMBER);
}

1082
info.toml

File diff suppressed because it is too large Load Diff

View File

@@ -35,7 +35,7 @@ if (Get-Command cargo -ErrorAction SilentlyContinue) {
function vercomp($v1, $v2) {
if ($v1 -eq $v2) {
return 0
}
}
$v1 = $v1.Replace(".", "0")
$v2 = $v2.Replace(".", "0")
@@ -53,7 +53,7 @@ function vercomp($v1, $v2) {
}
$rustVersion = $(rustc --version).Split(" ")[1]
$minRustVersion = "1.31"
$minRustVersion = "1.39"
if ((vercomp $rustVersion $minRustVersion) -eq 2) {
Write-Host "WARNING: Rust version is too old: $rustVersion - needs at least $minRustVersion"
Write-Host "Please update Rust with 'rustup update'"

View File

@@ -30,6 +30,22 @@ else
exit 1
fi
# Look up python installations, starting with 3 with a fallback of 2
if [ -x "$(command -v python3)" ]
then
PY="$(command -v python3)"
elif [ -x "$(command -v python)" ]
then
PY="$(command -v python)"
elif [ -x "$(command -v python2)" ]
then
PY="$(command -v python2)"
else
echo "ERROR: No working python installation was found"
echo "Please install python and add it to the PATH variable"
exit 1
fi
# Function that compares two versions strings v1 and v2 given in arguments (e.g 1.31 and 1.33.0).
# Returns 1 if v1 > v2, 0 if v1 == v2, 2 if v1 < v2.
function vercomp() {
@@ -71,7 +87,7 @@ function vercomp() {
}
RustVersion=$(rustc --version | cut -d " " -f 2)
MinRustVersion=1.31
MinRustVersion=1.39
vercomp $RustVersion $MinRustVersion
if [ $? -eq 2 ]
then
@@ -86,12 +102,30 @@ Path=${1:-rustlings/}
echo "Cloning Rustlings at $Path..."
git clone -q https://github.com/rust-lang/rustlings $Path
Version=$(curl -s https://api.github.com/repos/rust-lang/rustlings/releases/latest | python -c "import json,sys;obj=json.load(sys.stdin);print(obj['tag_name']);")
cd $Path
Version=$(curl -s https://api.github.com/repos/rust-lang/rustlings/releases/latest | ${PY} -c "import json,sys;obj=json.load(sys.stdin);print(obj['tag_name']);")
CargoBin="${CARGO_HOME:-$HOME/.cargo}/bin"
if [[ -z ${Version} ]]
then
echo "The latest tag version could not be fetched remotely."
echo "Using the local git repository..."
Version=$(ls -tr .git/refs/tags/ | tail -1)
if [[ -z ${Version} ]]
then
echo "No valid tag version found"
echo "Rustlings will be installed using the main branch"
Version="main"
else
Version="tags/${Version}"
fi
else
Version="tags/${Version}"
fi
echo "Checking out version $Version..."
cd $Path
git checkout -q tags/$Version
git checkout -q ${Version}
echo "Installing the 'rustlings' executable..."
cargo install --force --path .

View File

@@ -1,5 +1,6 @@
use regex::Regex;
use serde::Deserialize;
use std::env;
use std::fmt::{self, Display, Formatter};
use std::fs::{self, remove_file, File};
use std::io::Read;
@@ -11,15 +12,26 @@ const I_AM_DONE_REGEX: &str = r"(?m)^\s*///?\s*I\s+AM\s+NOT\s+DONE";
const CONTEXT: usize = 2;
const CLIPPY_CARGO_TOML_PATH: &str = "./exercises/clippy/Cargo.toml";
// Get a temporary file name that is hopefully unique
#[inline]
fn temp_file() -> String {
format!("./temp_{}", process::id())
let thread_id: String = format!("{:?}", std::thread::current().id())
.chars()
.filter(|c| c.is_alphanumeric())
.collect();
format!("./temp_{}_{}", process::id(), thread_id)
}
#[derive(Deserialize, Copy, Clone)]
// The mode of the exercise.
#[derive(Deserialize, Copy, Clone, Debug)]
#[serde(rename_all = "lowercase")]
pub enum Mode {
// Indicates that the exercise should be compiled as a binary
Compile,
// Indicates that the exercise should be compiled as a test harness
Test,
// Indicates that the exercise should be linted with clippy
Clippy,
}
@@ -28,41 +40,60 @@ pub struct ExerciseList {
pub exercises: Vec<Exercise>,
}
#[derive(Deserialize)]
// A representation of a rustlings exercise.
// This is deserialized from the accompanying info.toml file
#[derive(Deserialize, Debug)]
pub struct Exercise {
// Name of the exercise
pub name: String,
// The path to the file containing the exercise's source code
pub path: PathBuf,
// The mode of the exercise (Test, Compile, or Clippy)
pub mode: Mode,
// The hint text associated with the exercise
pub hint: String,
}
// An enum to track of the state of an Exercise.
// An Exercise can be either Done or Pending
#[derive(PartialEq, Debug)]
pub enum State {
// The state of the exercise once it's been completed
Done,
// The state of the exercise while it's not completed yet
Pending(Vec<ContextLine>),
}
// The context information of a pending exercise
#[derive(PartialEq, Debug)]
pub struct ContextLine {
// The source code that is still pending completion
pub line: String,
// The line number of the source code still pending completion
pub number: usize,
// Whether or not this is important
pub important: bool,
}
// The result of compiling an exercise
pub struct CompiledExercise<'a> {
exercise: &'a Exercise,
_handle: FileHandle,
}
impl<'a> CompiledExercise<'a> {
// Run the compiled exercise
pub fn run(&self) -> Result<ExerciseOutput, ExerciseOutput> {
self.exercise.run()
}
}
// A representation of an already executed binary
#[derive(Debug)]
pub struct ExerciseOutput {
// The textual contents of the standard output of the binary
pub stdout: String,
// The textual contents of the standard error of the binary
pub stderr: String,
}
@@ -96,9 +127,13 @@ name = "{}"
path = "{}.rs""#,
self.name, self.name, self.name
);
fs::write(CLIPPY_CARGO_TOML_PATH, cargo_toml)
.expect("Failed to write 📎 Clippy 📎 Cargo.toml file.");
// To support the ability to run the clipy exercises, build
let cargo_toml_error_msg = if env::var("NO_EMOJI").is_ok() {
"Failed to write Clippy Cargo.toml file."
} else {
"Failed to write 📎 Clippy 📎 Cargo.toml file."
};
fs::write(CLIPPY_CARGO_TOML_PATH, cargo_toml).expect(cargo_toml_error_msg);
// To support the ability to run the clippy exercises, build
// an executable, in addition to running clippy. With a
// compilation failure, this would silently fail. But we expect
// clippy to reflect the same failure while compiling later.
@@ -109,7 +144,7 @@ path = "{}.rs""#,
.expect("Failed to compile!");
// Due to an issue with Clippy, a cargo clean is required to catch all lints.
// See https://github.com/rust-lang/rust-clippy/issues/2604
// This is already fixed on master branch. See this issue to track merging into Cargo:
// This is already fixed on Clippy's master branch. See this issue to track merging into Cargo:
// https://github.com/rust-lang/rust-clippy/issues/3837
Command::new("cargo")
.args(&["clean", "--manifest-path", CLIPPY_CARGO_TOML_PATH])
@@ -127,7 +162,7 @@ path = "{}.rs""#,
if cmd.status.success() {
Ok(CompiledExercise {
exercise: &self,
exercise: self,
_handle: FileHandle,
})
} else {
@@ -140,7 +175,12 @@ path = "{}.rs""#,
}
fn run(&self) -> Result<ExerciseOutput, ExerciseOutput> {
let arg = match self.mode {
Mode::Test => "--show-output",
_ => "",
};
let cmd = Command::new(&temp_file())
.arg(arg)
.output()
.expect("Failed to run 'run' command");
@@ -197,6 +237,16 @@ path = "{}.rs""#,
State::Pending(context)
}
// Check that the exercise looks to be solved using self.state()
// This is not the best way to check since
// the user can just remove the "I AM NOT DONE" string from the file
// without actually having solved anything.
// The only other way to truly check this would to compile and run
// the exercise; which would be both costly and counterintuitive
pub fn looks_done(&self) -> bool {
self.state() == State::Done
}
}
impl Display for Exercise {
@@ -205,6 +255,7 @@ impl Display for Exercise {
}
}
#[inline]
fn clean() {
let _ignored = remove_file(&temp_file());
}
@@ -280,4 +331,16 @@ mod test {
assert_eq!(exercise.state(), State::Done);
}
#[test]
fn test_exercise_with_output() {
let exercise = Exercise {
name: "exercise_with_output".into(),
path: PathBuf::from("tests/fixture/success/testSuccess.rs"),
mode: Mode::Test,
hint: String::new(),
};
let out = exercise.compile().unwrap().run().unwrap();
assert!(out.stdout.contains("THIS TEST TOO SHALL PASS"));
}
}

View File

@@ -1,16 +1,17 @@
use crate::exercise::{Exercise, ExerciseList};
use crate::run::run;
use crate::verify::verify;
use clap::{crate_version, App, Arg, SubCommand};
use argh::FromArgs;
use console::Emoji;
use notify::DebouncedEvent;
use notify::{RecommendedWatcher, RecursiveMode, Watcher};
use std::ffi::OsStr;
use std::fs;
use std::io;
use std::io::{self, prelude::*};
use std::path::Path;
use std::process::{Command, Stdio};
use std::sync::mpsc::channel;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{channel, RecvTimeoutError};
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
@@ -22,28 +23,91 @@ mod exercise;
mod run;
mod verify;
fn main() {
let matches = App::new("rustlings")
.version(crate_version!())
.author("Olivia Hugger, Carol Nichols")
.about("Rustlings is a collection of small exercises to get you used to writing and reading Rust code")
.subcommand(SubCommand::with_name("verify").alias("v").about("Verifies all exercises according to the recommended order"))
.subcommand(SubCommand::with_name("watch").alias("w").about("Reruns `verify` when files were edited"))
.subcommand(
SubCommand::with_name("run")
.alias("r")
.about("Runs/Tests a single exercise")
.arg(Arg::with_name("name").required(true).index(1)),
)
.subcommand(
SubCommand::with_name("hint")
.alias("h")
.about("Returns a hint for the current exercise")
.arg(Arg::with_name("name").required(true).index(1)),
)
.get_matches();
// In sync with crate version
const VERSION: &str = "4.6.0";
if None == matches.subcommand_name() {
#[derive(FromArgs, PartialEq, Debug)]
/// Rustlings is a collection of small exercises to get you used to writing and reading Rust code
struct Args {
/// show outputs from the test exercises
#[argh(switch)]
nocapture: bool,
/// show the executable version
#[argh(switch, short = 'v')]
version: bool,
#[argh(subcommand)]
nested: Option<Subcommands>,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand)]
enum Subcommands {
Verify(VerifyArgs),
Watch(WatchArgs),
Run(RunArgs),
Hint(HintArgs),
List(ListArgs),
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "verify")]
/// Verifies all exercises according to the recommended order
struct VerifyArgs {}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "watch")]
/// Reruns `verify` when files were edited
struct WatchArgs {}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "run")]
/// Runs/Tests a single exercise
struct RunArgs {
#[argh(positional)]
/// the name of the exercise
name: String,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "hint")]
/// Returns a hint for the given exercise
struct HintArgs {
#[argh(positional)]
/// the name of the exercise
name: String,
}
#[derive(FromArgs, PartialEq, Debug)]
#[argh(subcommand, name = "list")]
/// Lists the exercises available in Rustlings
struct ListArgs {
#[argh(switch, short = 'p')]
/// show only the paths of the exercises
paths: bool,
#[argh(switch, short = 'n')]
/// show only the names of the exercises
names: bool,
#[argh(option, short = 'f')]
/// provide a string to match exercise names
/// comma separated patterns are acceptable
filter: Option<String>,
#[argh(switch, short = 'u')]
/// display only exercises not yet solved
unsolved: bool,
#[argh(switch, short = 's')]
/// display only exercises that have been solved
solved: bool,
}
fn main() {
let args: Args = argh::from_env();
if args.version {
println!("v{}", VERSION);
std::process::exit(0);
}
if args.nested.is_none() {
println!();
println!(r#" welcome to... "#);
println!(r#" _ _ _ "#);
@@ -73,73 +137,169 @@ fn main() {
let toml_str = &fs::read_to_string("info.toml").unwrap();
let exercises = toml::from_str::<ExerciseList>(toml_str).unwrap().exercises;
let verbose = args.nocapture;
if let Some(ref matches) = matches.subcommand_matches("run") {
let name = matches.value_of("name").unwrap();
let matching_exercise = |e: &&Exercise| name == e.name;
let exercise = exercises.iter().find(matching_exercise).unwrap_or_else(|| {
println!("No exercise found for your given name!");
std::process::exit(1)
});
run(&exercise).unwrap_or_else(|_| std::process::exit(1));
}
if let Some(ref matches) = matches.subcommand_matches("hint") {
let name = matches.value_of("name").unwrap();
let exercise = exercises
.iter()
.find(|e| name == e.name)
.unwrap_or_else(|| {
println!("No exercise found for your given name!");
std::process::exit(1)
});
println!("{}", exercise.hint);
}
if matches.subcommand_matches("verify").is_some() {
verify(&exercises).unwrap_or_else(|_| std::process::exit(1));
}
if matches.subcommand_matches("watch").is_some() {
if watch(&exercises).is_ok() {
println!(
"{emoji} All exercises completed! {emoji}",
emoji = Emoji("🎉", "")
);
println!("");
println!("We hope you enjoyed learning about the various aspects of Rust!");
println!(
"If you noticed any issues, please don't hesitate to report them to our repo."
);
println!("You can also contribute your own exercises to help the greater community!");
println!("");
println!("Before reporting an issue or contributing, please read our guidelines:");
println!("https://github.com/rust-lang/rustlings/blob/master/CONTRIBUTING.md");
}
}
if matches.subcommand_name().is_none() {
let command = args.nested.unwrap_or_else(|| {
let text = fs::read_to_string("default_out.txt").unwrap();
println!("{}", text);
std::process::exit(0);
});
match command {
Subcommands::List(subargs) => {
if !subargs.paths && !subargs.names {
println!("{:<17}\t{:<46}\t{:<7}", "Name", "Path", "Status");
}
let mut exercises_done: u16 = 0;
let filters = subargs.filter.clone().unwrap_or_default().to_lowercase();
exercises.iter().for_each(|e| {
let fname = format!("{}", e.path.display());
let filter_cond = filters
.split(',')
.filter(|f| !f.trim().is_empty())
.any(|f| e.name.contains(&f) || fname.contains(&f));
let status = if e.looks_done() {
exercises_done += 1;
"Done"
} else {
"Pending"
};
let solve_cond = {
(e.looks_done() && subargs.solved)
|| (!e.looks_done() && subargs.unsolved)
|| (!subargs.solved && !subargs.unsolved)
};
if solve_cond && (filter_cond || subargs.filter.is_none()) {
let line = if subargs.paths {
format!("{}\n", fname)
} else if subargs.names {
format!("{}\n", e.name)
} else {
format!("{:<17}\t{:<46}\t{:<7}\n", e.name, fname, status)
};
// Somehow using println! leads to the binary panicking
// when its output is piped.
// So, we're handling a Broken Pipe error and exiting with 0 anyway
let stdout = std::io::stdout();
{
let mut handle = stdout.lock();
handle.write_all(line.as_bytes()).unwrap_or_else(|e| {
match e.kind() {
std::io::ErrorKind::BrokenPipe => std::process::exit(0),
_ => std::process::exit(1),
};
});
}
}
});
let percentage_progress = exercises_done as f32 / exercises.len() as f32 * 100.0;
println!(
"Progress: You completed {} / {} exercises ({:.2} %).",
exercises_done,
exercises.len(),
percentage_progress
);
std::process::exit(0);
}
Subcommands::Run(subargs) => {
let exercise = find_exercise(&subargs.name, &exercises);
run(exercise, verbose).unwrap_or_else(|_| std::process::exit(1));
}
Subcommands::Hint(subargs) => {
let exercise = find_exercise(&subargs.name, &exercises);
println!("{}", exercise.hint);
}
Subcommands::Verify(_subargs) => {
verify(&exercises, verbose).unwrap_or_else(|_| std::process::exit(1));
}
Subcommands::Watch(_subargs) => match watch(&exercises, verbose) {
Err(e) => {
println!(
"Error: Could not watch your progress. Error message was {:?}.",
e
);
println!("Most likely you've run out of disk space or your 'inotify limit' has been reached.");
std::process::exit(1);
}
Ok(WatchStatus::Finished) => {
println!(
"{emoji} All exercises completed! {emoji}",
emoji = Emoji("🎉", "")
);
println!();
println!("+----------------------------------------------------+");
println!("| You made it to the Fe-nish line! |");
println!("+-------------------------- ------------------------+");
println!(" \\/ ");
println!(" ▒▒ ▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒ ▒▒ ");
println!(" ▒▒▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒▒▒ ");
println!(" ▒▒▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒▒▒ ");
println!(" ░░▒▒▒▒░░▒▒ ▒▒ ▒▒ ▒▒ ▒▒░░▒▒▒▒ ");
println!(" ▓▓▓▓▓▓▓▓ ▓▓ ▓▓██ ▓▓ ▓▓██ ▓▓ ▓▓▓▓▓▓▓▓ ");
println!(" ▒▒▒▒ ▒▒ ████ ▒▒ ████ ▒▒░░ ▒▒▒▒ ");
println!(" ▒▒ ▒▒▒▒▒▒ ▒▒▒▒▒▒ ▒▒▒▒▒▒ ▒▒ ");
println!(" ▒▒▒▒▒▒▒▒▒▒▓▓▓▓▓▓▒▒▒▒▒▒▒▒▓▓▒▒▓▓▒▒▒▒▒▒▒▒ ");
println!(" ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ");
println!(" ▒▒▒▒▒▒▒▒▒▒██▒▒▒▒▒▒██▒▒▒▒▒▒▒▒▒▒ ");
println!(" ▒▒ ▒▒▒▒▒▒▒▒▒▒██████▒▒▒▒▒▒▒▒▒▒ ▒▒ ");
println!(" ▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒ ");
println!(" ▒▒ ▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒ ▒▒ ");
println!(" ▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ▒▒ ");
println!(" ▒▒ ▒▒ ▒▒ ▒▒ ");
println!();
println!("We hope you enjoyed learning about the various aspects of Rust!");
println!(
"If you noticed any issues, please don't hesitate to report them to our repo."
);
println!(
"You can also contribute your own exercises to help the greater community!"
);
println!();
println!("Before reporting an issue or contributing, please read our guidelines:");
println!("https://github.com/rust-lang/rustlings/blob/main/CONTRIBUTING.md");
}
Ok(WatchStatus::Unfinished) => {
println!("We hope you're enjoying learning about Rust!");
println!("If you want to continue working on the exercises at a later point, you can simply run `rustlings watch` again");
}
},
}
}
fn spawn_watch_shell(failed_exercise_hint: &Arc<Mutex<Option<String>>>) {
fn spawn_watch_shell(
failed_exercise_hint: &Arc<Mutex<Option<String>>>,
should_quit: Arc<AtomicBool>,
) {
let failed_exercise_hint = Arc::clone(failed_exercise_hint);
println!("Type 'hint' to get help");
println!("Welcome to watch mode! You can type 'help' to get an overview of the commands you can use here.");
thread::spawn(move || loop {
let mut input = String::new();
match io::stdin().read_line(&mut input) {
Ok(_) => {
if input.trim().eq("hint") {
let input = input.trim();
if input == "hint" {
if let Some(hint) = &*failed_exercise_hint.lock().unwrap() {
println!("{}", hint);
}
} else if input == "clear" {
println!("\x1B[2J\x1B[1;1H");
} else if input.eq("quit") {
should_quit.store(true, Ordering::SeqCst);
println!("Bye!");
} else if input.eq("help") {
println!("Commands available to you in watch mode:");
println!(" hint - prints the current exercise's hint");
println!(" clear - clears the screen");
println!(" quit - quits watch mode");
println!(" help - displays this help message");
println!();
println!("Watch mode automatically re-evaluates the current exercise");
println!("when you edit a file's contents.")
} else {
println!("unknown command: {}", input);
}
@@ -149,7 +309,33 @@ fn spawn_watch_shell(failed_exercise_hint: &Arc<Mutex<Option<String>>>) {
});
}
fn watch(exercises: &[Exercise]) -> notify::Result<()> {
fn find_exercise<'a>(name: &str, exercises: &'a [Exercise]) -> &'a Exercise {
if name.eq("next") {
exercises
.iter()
.find(|e| !e.looks_done())
.unwrap_or_else(|| {
println!("🎉 Congratulations! You have done all the exercises!");
println!("🔚 There are no more exercises to do next!");
std::process::exit(1)
})
} else {
exercises
.iter()
.find(|e| e.name == name)
.unwrap_or_else(|| {
println!("No exercise found for '{}'!", name);
std::process::exit(1)
})
}
}
enum WatchStatus {
Finished,
Unfinished,
}
fn watch(exercises: &[Exercise], verbose: bool) -> notify::Result<WatchStatus> {
/* Clears the terminal with an ANSI escape code.
Works in UNIX and newer Windows terminals. */
fn clear_screen() {
@@ -157,6 +343,7 @@ fn watch(exercises: &[Exercise]) -> notify::Result<()> {
}
let (tx, rx) = channel();
let should_quit = Arc::new(AtomicBool::new(false));
let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_secs(2))?;
watcher.watch(Path::new("./exercises"), RecursiveMode::Recursive)?;
@@ -164,23 +351,29 @@ fn watch(exercises: &[Exercise]) -> notify::Result<()> {
clear_screen();
let to_owned_hint = |t: &Exercise| t.hint.to_owned();
let failed_exercise_hint = match verify(exercises.iter()) {
Ok(_) => return Ok(()),
let failed_exercise_hint = match verify(exercises.iter(), verbose) {
Ok(_) => return Ok(WatchStatus::Finished),
Err(exercise) => Arc::new(Mutex::new(Some(to_owned_hint(exercise)))),
};
spawn_watch_shell(&failed_exercise_hint);
spawn_watch_shell(&failed_exercise_hint, Arc::clone(&should_quit));
loop {
match rx.recv() {
match rx.recv_timeout(Duration::from_secs(1)) {
Ok(event) => match event {
DebouncedEvent::Create(b) | DebouncedEvent::Chmod(b) | DebouncedEvent::Write(b) => {
if b.extension() == Some(OsStr::new("rs")) && b.exists() {
let filepath = b.as_path().canonicalize().unwrap();
let pending_exercises = exercises
.iter()
.skip_while(|e| !filepath.ends_with(&e.path));
.skip_while(|e| !filepath.ends_with(&e.path))
// .filter(|e| filepath.ends_with(&e.path))
.chain(
exercises
.iter()
.filter(|e| !e.looks_done() && !filepath.ends_with(&e.path)),
);
clear_screen();
match verify(pending_exercises) {
Ok(_) => return Ok(()),
match verify(pending_exercises, verbose) {
Ok(_) => return Ok(WatchStatus::Finished),
Err(exercise) => {
let mut failed_exercise_hint = failed_exercise_hint.lock().unwrap();
*failed_exercise_hint = Some(to_owned_hint(exercise));
@@ -190,8 +383,15 @@ fn watch(exercises: &[Exercise]) -> notify::Result<()> {
}
_ => {}
},
Err(RecvTimeoutError::Timeout) => {
// the timeout expired, just check the `should_quit` variable below then loop again
}
Err(e) => println!("watch error: {:?}", e),
}
// Check if we need to exit
if should_quit.load(Ordering::SeqCst) {
return Ok(WatchStatus::Unfinished);
}
}
}

View File

@@ -2,15 +2,22 @@ use crate::exercise::{Exercise, Mode};
use crate::verify::test;
use indicatif::ProgressBar;
pub fn run(exercise: &Exercise) -> Result<(), ()> {
// Invoke the rust compiler on the path of the given exercise,
// and run the ensuing binary.
// The verbose argument helps determine whether or not to show
// the output from the test harnesses (if the mode of the exercise is test)
pub fn run(exercise: &Exercise, verbose: bool) -> Result<(), ()> {
match exercise.mode {
Mode::Test => test(exercise)?,
Mode::Test => test(exercise, verbose)?,
Mode::Compile => compile_and_run(exercise)?,
Mode::Clippy => compile_and_run(exercise)?,
}
Ok(())
}
// Invoke the rust compiler on the path of the given exercise
// and run the ensuing binary.
// This is strictly for non-test binaries, so output is displayed
fn compile_and_run(exercise: &Exercise) -> Result<(), ()> {
let progress_bar = ProgressBar::new_spinner();
progress_bar.set_message(format!("Compiling {}...", exercise).as_str());

View File

@@ -1,23 +1,33 @@
macro_rules! warn {
($fmt:literal, $ex:expr) => {{
use console::{style, Emoji};
use std::env;
let formatstr = format!($fmt, $ex);
println!(
"{} {}",
style(Emoji("⚠️ ", "!")).red(),
style(formatstr).red()
);
if env::var("NO_EMOJI").is_ok() {
println!("{} {}", style("!").red(), style(formatstr).red());
} else {
println!(
"{} {}",
style(Emoji("⚠️ ", "!")).red(),
style(formatstr).red()
);
}
}};
}
macro_rules! success {
($fmt:literal, $ex:expr) => {{
use console::{style, Emoji};
use std::env;
let formatstr = format!($fmt, $ex);
println!(
"{} {}",
style(Emoji("", "")).green(),
style(formatstr).green()
);
if env::var("NO_EMOJI").is_ok() {
println!("{} {}", style("").green(), style(formatstr).green());
} else {
println!(
"{} {}",
style(Emoji("", "")).green(),
style(formatstr).green()
);
}
}};
}

View File

@@ -1,13 +1,22 @@
use crate::exercise::{CompiledExercise, Exercise, Mode, State};
use console::style;
use indicatif::ProgressBar;
use std::env;
pub fn verify<'a>(start_at: impl IntoIterator<Item = &'a Exercise>) -> Result<(), &'a Exercise> {
// Verify that the provided container of Exercise objects
// can be compiled and run without any failures.
// Any such failures will be reported to the end user.
// If the Exercise being verified is a test, the verbose boolean
// determines whether or not the test harness outputs are displayed.
pub fn verify<'a>(
start_at: impl IntoIterator<Item = &'a Exercise>,
verbose: bool,
) -> Result<(), &'a Exercise> {
for exercise in start_at {
let compile_result = match exercise.mode {
Mode::Test => compile_and_test(&exercise, RunMode::Interactive),
Mode::Compile => compile_and_run_interactively(&exercise),
Mode::Clippy => compile_only(&exercise),
Mode::Test => compile_and_test(exercise, RunMode::Interactive, verbose),
Mode::Compile => compile_and_run_interactively(exercise),
Mode::Clippy => compile_only(exercise),
};
if !compile_result.unwrap_or(false) {
return Err(exercise);
@@ -21,29 +30,32 @@ enum RunMode {
NonInteractive,
}
pub fn test(exercise: &Exercise) -> Result<(), ()> {
compile_and_test(exercise, RunMode::NonInteractive)?;
// Compile and run the resulting test harness of the given Exercise
pub fn test(exercise: &Exercise, verbose: bool) -> Result<(), ()> {
compile_and_test(exercise, RunMode::NonInteractive, verbose)?;
Ok(())
}
// Invoke the rust compiler without running the resulting binary
fn compile_only(exercise: &Exercise) -> Result<bool, ()> {
let progress_bar = ProgressBar::new_spinner();
progress_bar.set_message(format!("Compiling {}...", exercise).as_str());
progress_bar.enable_steady_tick(100);
let _ = compile(&exercise, &progress_bar)?;
let _ = compile(exercise, &progress_bar)?;
progress_bar.finish_and_clear();
success!("Successfully compiled {}!", exercise);
Ok(prompt_for_completion(&exercise, None))
Ok(prompt_for_completion(exercise, None))
}
// Compile the given Exercise and run the resulting binary in an interactive mode
fn compile_and_run_interactively(exercise: &Exercise) -> Result<bool, ()> {
let progress_bar = ProgressBar::new_spinner();
progress_bar.set_message(format!("Compiling {}...", exercise).as_str());
progress_bar.enable_steady_tick(100);
let compilation = compile(&exercise, &progress_bar)?;
let compilation = compile(exercise, &progress_bar)?;
progress_bar.set_message(format!("Running {}...", exercise).as_str());
let result = compilation.run();
@@ -54,16 +66,19 @@ fn compile_and_run_interactively(exercise: &Exercise) -> Result<bool, ()> {
Err(output) => {
warn!("Ran {} with errors", exercise);
println!("{}", output.stdout);
println!("{}", output.stderr);
return Err(());
}
};
success!("Successfully ran {}!", exercise);
Ok(prompt_for_completion(&exercise, Some(output.stdout)))
Ok(prompt_for_completion(exercise, Some(output.stdout)))
}
fn compile_and_test(exercise: &Exercise, run_mode: RunMode) -> Result<bool, ()> {
// Compile the given Exercise as a test harness and display
// the output if verbose is set to true
fn compile_and_test(exercise: &Exercise, run_mode: RunMode, verbose: bool) -> Result<bool, ()> {
let progress_bar = ProgressBar::new_spinner();
progress_bar.set_message(format!("Testing {}...", exercise).as_str());
progress_bar.enable_steady_tick(100);
@@ -73,10 +88,13 @@ fn compile_and_test(exercise: &Exercise, run_mode: RunMode) -> Result<bool, ()>
progress_bar.finish_and_clear();
match result {
Ok(_) => {
Ok(output) => {
if verbose {
println!("{}", output.stdout);
}
success!("Successfully tested {}", &exercise);
if let RunMode::Interactive = run_mode {
Ok(prompt_for_completion(&exercise, None))
Ok(prompt_for_completion(exercise, None))
} else {
Ok(true)
}
@@ -92,6 +110,8 @@ fn compile_and_test(exercise: &Exercise, run_mode: RunMode) -> Result<bool, ()>
}
}
// Compile the given Exercise and return an object with information
// about the state of the compilation
fn compile<'a, 'b>(
exercise: &'a Exercise,
progress_bar: &'b ProgressBar,
@@ -118,22 +138,34 @@ fn prompt_for_completion(exercise: &Exercise, prompt_output: Option<String>) ->
State::Pending(context) => context,
};
let no_emoji = env::var("NO_EMOJI").is_ok();
let clippy_success_msg = if no_emoji {
"The code is compiling, and Clippy is happy!"
} else {
"The code is compiling, and 📎 Clippy 📎 is happy!"
};
let success_msg = match exercise.mode {
Mode::Compile => "The code is compiling!",
Mode::Test => "The code is compiling, and the tests pass!",
Mode::Clippy => "The code is compiling, and 📎 Clippy 📎 is happy!",
Mode::Clippy => clippy_success_msg,
};
println!("");
println!("🎉 🎉 {} 🎉 🎉", success_msg);
println!("");
println!();
if no_emoji {
println!("~*~ {} ~*~", success_msg)
} else {
println!("🎉 🎉 {} 🎉 🎉", success_msg)
}
println!();
if let Some(output) = prompt_output {
println!("Output:");
println!("{}", separator());
println!("{}", output);
println!("{}", separator());
println!("");
println!();
}
println!("You can keep working on this exercise,");
@@ -141,12 +173,12 @@ fn prompt_for_completion(exercise: &Exercise, prompt_output: Option<String>) ->
"or jump into the next one by removing the {} comment:",
style("`I AM NOT DONE`").bold()
);
println!("");
println!();
for context_line in context {
let formatted_line = if context_line.important {
format!("{}", style(context_line.line).bold())
} else {
format!("{}", context_line.line)
context_line.line.to_string()
};
println!(

View File

@@ -9,3 +9,10 @@ name = "pending_test_exercise"
path = "pending_test_exercise.rs"
mode = "test"
hint = """"""
[[exercises]]
name = "finished_exercise"
path = "finished_exercise.rs"
mode = "compile"
hint = """"""

View File

@@ -1,4 +1,5 @@
#[test]
fn passing() {
println!("THIS TEST TOO SHALL PASS");
assert!(true);
}

View File

@@ -24,7 +24,7 @@ fn fails_when_in_wrong_dir() {
fn verify_all_success() {
Command::cargo_bin("rustlings")
.unwrap()
.arg("v")
.arg("verify")
.current_dir("tests/fixture/success")
.assert()
.success();
@@ -34,7 +34,7 @@ fn verify_all_success() {
fn verify_fails_if_some_fails() {
Command::cargo_bin("rustlings")
.unwrap()
.arg("v")
.arg("verify")
.current_dir("tests/fixture/failure")
.assert()
.code(1);
@@ -44,7 +44,7 @@ fn verify_fails_if_some_fails() {
fn run_single_compile_success() {
Command::cargo_bin("rustlings")
.unwrap()
.args(&["r", "compSuccess"])
.args(&["run", "compSuccess"])
.current_dir("tests/fixture/success/")
.assert()
.success();
@@ -54,7 +54,7 @@ fn run_single_compile_success() {
fn run_single_compile_failure() {
Command::cargo_bin("rustlings")
.unwrap()
.args(&["r", "compFailure"])
.args(&["run", "compFailure"])
.current_dir("tests/fixture/failure/")
.assert()
.code(1);
@@ -64,7 +64,7 @@ fn run_single_compile_failure() {
fn run_single_test_success() {
Command::cargo_bin("rustlings")
.unwrap()
.args(&["r", "testSuccess"])
.args(&["run", "testSuccess"])
.current_dir("tests/fixture/success/")
.assert()
.success();
@@ -74,7 +74,7 @@ fn run_single_test_success() {
fn run_single_test_failure() {
Command::cargo_bin("rustlings")
.unwrap()
.args(&["r", "testFailure"])
.args(&["run", "testFailure"])
.current_dir("tests/fixture/failure/")
.assert()
.code(1);
@@ -84,7 +84,7 @@ fn run_single_test_failure() {
fn run_single_test_not_passed() {
Command::cargo_bin("rustlings")
.unwrap()
.args(&["r", "testNotPassed.rs"])
.args(&["run", "testNotPassed.rs"])
.current_dir("tests/fixture/failure/")
.assert()
.code(1);
@@ -94,7 +94,7 @@ fn run_single_test_not_passed() {
fn run_single_test_no_filename() {
Command::cargo_bin("rustlings")
.unwrap()
.arg("r")
.arg("run")
.current_dir("tests/fixture/")
.assert()
.code(1);
@@ -104,7 +104,7 @@ fn run_single_test_no_filename() {
fn run_single_test_no_exercise() {
Command::cargo_bin("rustlings")
.unwrap()
.args(&["r", "compNoExercise.rs"])
.args(&["run", "compNoExercise.rs"])
.current_dir("tests/fixture/failure")
.assert()
.code(1);
@@ -114,7 +114,7 @@ fn run_single_test_no_exercise() {
fn get_hint_for_single_test() {
Command::cargo_bin("rustlings")
.unwrap()
.args(&["h", "testFailure"])
.args(&["hint", "testFailure"])
.current_dir("tests/fixture/failure")
.assert()
.code(0)
@@ -131,10 +131,15 @@ fn all_exercises_require_confirmation() {
file.read_to_string(&mut s).unwrap();
s
};
source.matches("// I AM NOT DONE").next().expect(&format!(
"There should be an `I AM NOT DONE` annotation in {:?}",
path
));
source
.matches("// I AM NOT DONE")
.next()
.unwrap_or_else(|| {
panic!(
"There should be an `I AM NOT DONE` annotation in {:?}",
path
)
});
}
}
@@ -142,7 +147,7 @@ fn all_exercises_require_confirmation() {
fn run_compile_exercise_does_not_prompt() {
Command::cargo_bin("rustlings")
.unwrap()
.args(&["r", "pending_exercise"])
.args(&["run", "pending_exercise"])
.current_dir("tests/fixture/state")
.assert()
.code(0)
@@ -153,9 +158,85 @@ fn run_compile_exercise_does_not_prompt() {
fn run_test_exercise_does_not_prompt() {
Command::cargo_bin("rustlings")
.unwrap()
.args(&["r", "pending_test_exercise"])
.args(&["run", "pending_test_exercise"])
.current_dir("tests/fixture/state")
.assert()
.code(0)
.stdout(predicates::str::contains("I AM NOT DONE").not());
}
#[test]
fn run_single_test_success_with_output() {
Command::cargo_bin("rustlings")
.unwrap()
.args(&["--nocapture", "run", "testSuccess"])
.current_dir("tests/fixture/success/")
.assert()
.code(0)
.stdout(predicates::str::contains("THIS TEST TOO SHALL PAS"));
}
#[test]
fn run_single_test_success_without_output() {
Command::cargo_bin("rustlings")
.unwrap()
.args(&["run", "testSuccess"])
.current_dir("tests/fixture/success/")
.assert()
.code(0)
.stdout(predicates::str::contains("THIS TEST TOO SHALL PAS").not());
}
#[test]
fn run_rustlings_list() {
Command::cargo_bin("rustlings")
.unwrap()
.args(&["list"])
.current_dir("tests/fixture/success")
.assert()
.success();
}
#[test]
fn run_rustlings_list_no_pending() {
Command::cargo_bin("rustlings")
.unwrap()
.args(&["list"])
.current_dir("tests/fixture/success")
.assert()
.success()
.stdout(predicates::str::contains("Pending").not());
}
#[test]
fn run_rustlings_list_both_done_and_pending() {
Command::cargo_bin("rustlings")
.unwrap()
.args(&["list"])
.current_dir("tests/fixture/state")
.assert()
.success()
.stdout(predicates::str::contains("Done").and(predicates::str::contains("Pending")));
}
#[test]
fn run_rustlings_list_without_pending() {
Command::cargo_bin("rustlings")
.unwrap()
.args(&["list", "--solved"])
.current_dir("tests/fixture/state")
.assert()
.success()
.stdout(predicates::str::contains("Pending").not());
}
#[test]
fn run_rustlings_list_without_done() {
Command::cargo_bin("rustlings")
.unwrap()
.args(&["list", "--unsolved"])
.current_dir("tests/fixture/state")
.assert()
.success()
.stdout(predicates::str::contains("Done").not());
}