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

Compare commits

...

50 Commits
1.4.0 ... 1.5.1

Author SHA1 Message Date
marisa
a47a62172a 1.5.1 2019-11-11 14:02:27 +01:00
marisa
f72e5a8f05 fix(structs1): Remove misleading comment 2019-11-11 13:57:59 +01:00
marisa
fbe91a67a4 fix(threads): Move Threads behind SLT
Closes #205.
2019-11-11 13:48:09 +01:00
marisa
6dcecb38a4 fix(strings): Move Strings before Structs
Closes #204.
2019-11-11 13:46:42 +01:00
marisa
dcfb427b09 fix(errors3): Update hint
Closes #185.
2019-11-11 13:37:43 +01:00
marisa
ad03d180c9 fix(if1): Remove return reference
This closes #153.
2019-11-11 13:34:21 +01:00
bors
3232a4d60d Auto merge of #228 - WofWca:clear-screen, r=fmoko
improvement(watch): clear screen before each `verify()`

Closes #146
It seems to me that #227 wasn't really fixing the issue.
2019-11-09 15:23:53 +00:00
WofWca
3aff590855 improvement(watch): clear screen before each verify()
Closes #146
2019-11-09 22:24:24 +08:00
marisa
c8babbad27 1.5.0 2019-11-09 10:52:20 +01:00
bors
c6dad28ddc Auto merge of #224 - nyxtom:feat-enums, r=fmoko
feat: Add enums exercises

Creates an exhaustive list of enum exercises. This goes through the basics of different ways to derive enums with mixed data type variants, as well as the use of the all important `match` operator.
2019-11-09 09:41:36 +00:00
bors
fea81419cd Auto merge of #227 - workingjubilee:watch-clears-terminal, r=fmoko
watch: clears terminal before entering loop

Fixes #146

If someone is sliding in and out of "watch" mode, it can make it hard
to tell which error messages are still relevant. This patch resolves
that by clearing the terminal entirely before entering watch's loop.

Note that the escape character is chosen for compatibility reasons, because different shells/terminals can change which commands they accept or have installed, betting on what other commands are in use to collect data seems risky, and just expecting them to implement ANSI escape code sequences is more reliable. This seems especially true since Windows is seeking more UNIX compatibility in its terminals going forward, even though it doesn't implement the POSIX standard per se.
2019-11-09 09:31:50 +00:00
Jubilee Young
83be517e77 watch: clears terminal before entering loop
If someone is sliding in and out of "watch" mode, it can make it hard
to tell which error messages are still relevant. This patch resolves
that by clearing the terminal entirely before entering watch's loop.
2019-11-09 00:57:36 -08:00
marisa
79a569422c fix: Rewrite test1 logic 2019-10-29 20:53:41 +01:00
bors
1e0b12e37e Auto merge of #225 - ssweeny:fix/test1-wording, r=fmoko
chore: Clarify comment in exercises/test1.rs

closes #194

The author of issue #194 suggests that the wording of the comment is at
least ambiguous about the desired results. I believe this change more
clearly describes the expectation of the exercise.
2019-10-29 13:37:30 +00:00
Thomas Holloway
dc15032112 feat: Add enums exercises 2019-10-28 22:49:49 -05:00
Scott Sweeny
2821227acf chore: Clarify comment in exercises/test1.rs
closes #194

The author of issue #194 suggests that the wording of the comment is at
least ambiguous about the desired results. I believe this change more
clearly describes the expectation of the exercise.
2019-10-28 23:08:46 -04:00
bors
2191ef7eee Auto merge of #219 - vyaslav:master, r=fmoko
Added exercise for struct update syntax

Added one exercise for struct update syntax `struct2.rs`
2019-10-28 22:56:54 +00:00
marisa
4c2cf6da75 fix(option1): Fix arguments passed to assert! macro (#222)
fix(option1): Fix arguments passed to assert! macro
2019-10-26 00:27:40 +02:00
marisa
0f3d6d871e chore: Bump version in Cargo.lock (#223)
chore: Bump version in Cargo.lock
2019-10-26 00:27:17 +02:00
Niklas Anderson
bd007d4617 chore: Bump version in Cargo.lock 2019-10-25 14:57:30 -07:00
Niklas Anderson
ead4f7af9e fix(option1): Fix arguments passed to assert! macro 2019-10-25 14:27:24 -07:00
marisa
4808b5b3ba Update README to show latest version, for those who copy/paste (#221)
Update README to show latest version, for those who copy/paste
2019-10-25 01:54:10 +02:00
Mark Provan
f3da6796b9 Update README to show latest version, for those who copy/paste 2019-10-24 13:56:14 +01:00
marisa
cece12e87e docs: Add automatic Windows support to Readme 2019-10-23 13:01:07 +02:00
marisa
68d1727cac chore(ci): Remove GitHub actions for now 2019-10-23 12:56:07 +02:00
bors
8a2e13b20a Auto merge of #220 - gdoenlen:master, r=fmoko
Add windows install script

Adds a powershell install script for windows users that are at least
running powershell 5. It is almost a direct port of install.sh.
This would be used to automatically download the script much like
curl | bash, but with:

`Invoke-WebRequest https://urltoscript.com | 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`
2019-10-23 10:49:36 +00:00
George Doenlen
ee311b8e5c remove execution policy check 2019-10-22 22:26:33 -04:00
George Doenlen
f0de6c4e92 Add basic windows install script.
Adds a powershell install script for windows users that are at least
running powershell 5. It is almost a direct port of install.sh.
This would be used to automatically download the script much like
curl | bash, but with:

`Invoke-WebRequest https://urltoscript.com | 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`
2019-10-22 21:56:50 -04:00
Viacheslav Avramenko
1c4c8764ed feat: Added exercise for struct update syntax 2019-10-21 14:50:59 +02:00
bors
e6161a6f58 Auto merge of #217 - timthelion:timthelion-readme-run, r=fmoko
Tense in README

Don't see why run should be past tense.  At least in my native General American dialect it shouldn't be.
2019-09-25 14:09:52 +00:00
Timothy Hobbs
8c0fe59c90 Tense in README
Don't see why run should be past tense.  At least in my native General American dialect it shouldn't be.
2019-09-07 16:17:45 +00:00
komaeda
17690b3add chore(ci): Add GitHub Actions CI file 2019-08-21 13:23:38 +02:00
bors
f9987c8bed Auto merge of #212 - sosnowski:fix/add-dyn-trait, r=komaeda
fix(errorsn.rs) Update the deprecated syntax by adding dyn to trait o…

fix(errorsn.rs) Update the deprecated syntax by adding dyn to trait objects.

closes #211

Related issue: https://github.com/rust-lang/rustlings/issues/211
2019-08-21 11:01:11 +00:00
Damian S
8109cbad97 fix(errorsn.rs) Update the deprecated syntax by adding dyn to trait objectscloses #211 2019-08-21 11:44:42 +01:00
bors
c5bb32253b Auto merge of #209 - Dylnuge:slice-assert, r=komaeda
fix(primitive_types4): Fail on a slice covering the wrong area

I noticed this issue and it seems like a similar one was raised/fixed in #160 this way. This is my first contribution to this repo (or any Rust project) so let me know if I messed up or need to fix anything!

---
This commit converts primitive_types4 to a test and asserts that the
slice given is equal to the expected slice.

The intent of the primitive_types4 exercise appears to be to ensure the
user understands inclusive and exclusive bounds as well as slice syntax.
`rustlings` commands using `compile` do not verify that a specific
println is reached and, in the case of `watch` and `verify` (but not
`run`), they do not output the `println`s at all.

This fix is semantically similar to #198. It does not take a stance on
the correct way to handle this for all exercises; see #127. There are
likely other exercises whose intent are masked by this issue.
2019-08-18 08:24:44 +00:00
Dylan Nugent
5b1e673cec fix(primitive_types4): Fail on a slice covering the wrong area
This commit converts primitive_types4 to a test and asserts that the
slice given is equal to the expected slice.

The intent of the primitive_types4 exercise appears to be to ensure the
user understands inclusive and exclusive bounds as well as slice syntax.
`rustlings` commands using `compile` do not verify that a specific
println is reached and, in the case of `watch` and `verify` (but not
`run`), they do not output the `println`s at all.

This fix is semantically similar to #198. It does not take a stance on
the correct way to handle this for all exercises; see #127. There are
likely other exercises whose intent are masked by this issue.
2019-08-17 17:16:19 -07:00
bors
2cd06826c0 Auto merge of #206 - ajaxm:ajaxm/rustup-update, r=komaeda
Suggest rustup update in readme

I'm pretty new to Rust. I tried installing rustlings for the first time and got this error:
```
$> cargo install --force --path .
error: `/Users/ajax/projects/rust/rustlings` is not a crate root; specify a crate to install from crates.io, or use --path or --git to specify an alternate source

Caused by:
  failed to parse manifest at `/Users/ajax/projects/rust/rustlings/Cargo.toml`

Caused by:
  editions are unstable

Caused by:
  feature `edition` is required

this Cargo does not support nightly features, but if you
switch to nightly channel you can add
`cargo-features = ["edition"]` to enable this feature
```

I'm not sure if the answer was to run `rustup update` but I noticed that I was running Rust 1.29.0, so updated to 1.36.0 and got it working. If there's a way to specify a minimum required version, pls let me know.

Lastly, the whitespace changes were automatic from my editor. What's the convention here for making such updates? Thanks!
2019-08-13 10:04:36 +00:00
marisa
4f0c5a8d49 1.4.1 2019-08-13 11:59:17 +02:00
bors
3011251da7 Auto merge of #208 - EnricoMiccoli:patch-1, r=komaeda
chore: Correct typo in hint text
2019-08-12 15:24:17 +00:00
Enrico Miccoli
76b4cb5c00 chore: Correct typo 2019-08-12 11:45:40 +02:00
bors
f83af3c25d Auto merge of #207 - nkanderson:fix_iterators2, r=komaeda
Fix iterators2

A couple of small changes to the `iterators2` exercise. @Jesse-Cameron, it looks like you contributed this exercise, so I wanted to check and see if these changes are in line with your intentions. Happy to adjust if they're not :)
2019-08-11 15:44:40 +00:00
Niklas Anderson
e3931718fb chore(iterators2): Add exercise instructions 2019-08-09 07:38:21 -07:00
Niklas Anderson
4cde86643e fix(iterators2): Remove syntax resulting in misleading error message
closes #199
2019-08-09 07:37:27 -07:00
Ajax Manohar
9ee3207280 docs: Suggest rustup update in readme 2019-08-03 10:49:37 -07:00
bors
e696a07190 Auto merge of #201 - zdzc:patch-1, r=komaeda
docs: Fix wrong title

fix #200
2019-07-27 19:07:22 +00:00
Andre Pratama
e0db987441 docs: Fix wrong title
fix #200
2019-07-27 22:14:48 +07:00
bors
1890b0019d Auto merge of #198 - nkanderson:160_options1-add-test, r=komaeda
fix(option1): Add test for prematurely passing exercise

Fixes the bug referenced in #160, but does not address the larger feature work referenced by the issue.
2019-07-27 10:32:47 +00:00
Niklas Anderson
a750e4a1a3 fix(option1): Add test for prematurely passing exercise
Fixes the bug referenced in #160, but does not address the larger feature work referenced by the issue.
2019-07-26 16:58:12 -07:00
bors
1c789dda08 Auto merge of #192 - petemcfarlane:patch-2, r=komaeda
fix(test1): Swap assertion parameter order

`Expected` should come before `actual`, other wise it leads to confusing compiler messages, e.g.
```
note: expected type `()`
         found type `{integer}`
```
There may be other tests that need updating, but this is as far as I am through the Rustlings course right now :)
2019-07-13 16:27:14 +00:00
Pete McFarlane
4086d463a9 fix(test1): Swap assertion parameter order
`Expected` should come before `actual`, other wise it leads to confusing compiler messages, e.g.
```
note: expected type `()`
         found type `{integer}`
```
2019-07-13 13:31:57 +01:00
25 changed files with 519 additions and 119 deletions

View File

@@ -1,3 +1,52 @@
<a name="1.5.1"></a>
### 1.5.1 (2019-11-11)
#### Bug Fixes
* **errors3:** Update hint ([dcfb427b](https://github.com/rust-lang/rustlings/commit/dcfb427b09585f0193f0a294443fdf99f11c64cb), closes [#185](https://github.com/rust-lang/rustlings/issues/185))
* **if1:** Remove `return` reference ([ad03d180](https://github.com/rust-lang/rustlings/commit/ad03d180c9311c0093e56a3531eec1a9a70cdb45))
* **strings:** Move Strings before Structs ([6dcecb38](https://github.com/rust-lang/rustlings/commit/6dcecb38a4435593beb87c8e12d6314143631482), closes [#204](https://github.com/rust-lang/rustlings/issues/204))
* **structs1:** Remove misleading comment ([f72e5a8f](https://github.com/rust-lang/rustlings/commit/f72e5a8f05568dde04eaeac10b9a69872f21cb37))
* **threads:** Move Threads behind SLT ([fbe91a67](https://github.com/rust-lang/rustlings/commit/fbe91a67a482bfe64cbcdd58d06ba830a0f39da3), closes [#205](https://github.com/rust-lang/rustlings/issues/205))
* **watch:** clear screen before each `verify()` ([3aff590](https://github.com/rust-lang/rustlings/commit/3aff59085586c24196a547c2693adbdcf4432648))
<a name="1.5.0"></a>
## 1.5.0 (2019-11-09)
#### Bug Fixes
* **test1:** Rewrite logic ([79a56942](https://github.com/rust-lang/rustlings/commit/79a569422c8309cfc9e4aed25bf4ab3b3859996b))
* **installation:** Fix rustlings installation check ([7a252c47](https://github.com/rust-lang/rustlings/commit/7a252c475551486efb52f949b8af55803b700bc6))
* **iterators:** Rename iterator3.rs ([433d2115](https://github.com/rust-lang/rustlings/commit/433d2115bc1c04b6d34a335a18c9a8f3e2672bc6))
* **iterators2:** Remove syntax resulting in misleading error message ([4cde8664](https://github.com/rust-lang/rustlings/commit/4cde86643e12db162a66e62f23b78962986046ac))
* **option1:**
* Fix arguments passed to assert! macro (#222) ([4c2cf6da](https://github.com/rust-lang/rustlings/commit/4c2cf6da755efe02725e05ecc3a303304c10a6da))
* Fix arguments passed to assert! macro ([ead4f7af](https://github.com/rust-lang/rustlings/commit/ead4f7af9e10e53418efdde5c359159347282afd))
* Add test for prematurely passing exercise ([a750e4a1](https://github.com/rust-lang/rustlings/commit/a750e4a1a3006227292bb17d57d78ce84da6bfc6))
* **primitive_types4:** Fail on a slice covering the wrong area ([5b1e673c](https://github.com/rust-lang/rustlings/commit/5b1e673cec1658afc4ebbbc800213847804facf5))
* **readme:** http to https ([70946b85](https://github.com/rust-lang/rustlings/commit/70946b85e536e80e70ed9505cb650ca0a3a1fbb5))
* **test1:**
* Swap assertion parameter order ([4086d463](https://github.com/rust-lang/rustlings/commit/4086d463a981e81d97781851d17db2ced290f446))
* renamed function name to snake case closes #180 ([89d5186c](https://github.com/rust-lang/rustlings/commit/89d5186c0dae8135ecabf90ee8bb35949bc2d29b))
#### Features
* Add enums exercises ([dc150321](https://github.com/rust-lang/rustlings/commit/dc15032112fc485226a573a18139e5ce928b1755))
* Added exercise for struct update syntax ([1c4c8764](https://github.com/rust-lang/rustlings/commit/1c4c8764ed118740cd4cee73272ddc6cceb9d959))
* **iterators2:** adds iterators2 exercise including config ([9288fccf](https://github.com/rust-lang/rustlings/commit/9288fccf07a2c5043b76d0fd6491e4cf72d76031))
<a name="1.4.1"></a>
### 1.4.1 (2019-08-13)
#### Bug Fixes
* **iterators2:** Remove syntax resulting in misleading error message ([4cde8664](https://github.com/rust-lang/rustlings/commit/4cde86643e12db162a66e62f23b78962986046ac))
* **option1:** Add test for prematurely passing exercise ([a750e4a1](https://github.com/rust-lang/rustlings/commit/a750e4a1a3006227292bb17d57d78ce84da6bfc6))
* **test1:** Swap assertion parameter order ([4086d463](https://github.com/rust-lang/rustlings/commit/4086d463a981e81d97781851d17db2ced290f446))
<a name="1.4.0"></a>
## 1.4.0 (2019-07-13)

2
Cargo.lock generated
View File

@@ -600,7 +600,7 @@ dependencies = [
[[package]]
name = "rustlings"
version = "1.4.0"
version = "1.5.1"
dependencies = [
"assert_cmd 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@@ -1,7 +1,7 @@
[package]
name = "rustlings"
version = "1.4.0"
authors = ["Marisa <marisa@mokou.zone>", "Carol (Nichols || Goulding) <carol.nichols@gmail.com"]
version = "1.5.1"
authors = ["Marisa <mokou@posteo.de>", "Carol (Nichols || Goulding) <carol.nichols@gmail.com"]
edition = "2018"
[dependencies]

View File

@@ -1,4 +1,4 @@
![crab pet](https://i.imgur.com/LbZJgmm.gif)
![crab pet](https://i.imgur.com/LbZJgmm.gif)
# rustlings 🦀❤️
@@ -31,6 +31,16 @@ curl -L https://git.io/rustlings | bash -s mypath/
This will install Rustlings and give you access to the `rustlings` command. Run it to get started!
## Windows
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
```
To install Rustlings. Same as on MacOS/Linux, you will have access to the `rustlings` command after it.
## Manually
Basically: Clone the repository, checkout to the latest tag, run `cargo install`.
@@ -38,17 +48,22 @@ Basically: Clone the repository, checkout to the latest tag, run `cargo install`
```bash
git clone https://github.com/rust-lang/rustlings
cd rustlings
git checkout tags/1.0.0 # or whatever the latest version is (find out at https://github.com/rust-lang/rustlings/releases/latest)
git checkout tags/1.5.1 # or whatever the latest version is (find out at https://github.com/rust-lang/rustlings/releases/latest)
cargo install --force --path .
```
Same as above, run `rustlings` to get started.
If there are installation errors, ensure that your toolchain is up to date. For the latest, run:
```bash
rustup update
```
Then, same as above, run `rustlings` to get started.
## Doing exercises
The exercises are sorted by topic and can be found in the subdirectory `rustlings/exercises/<topic>`. For every topic there is an additional README file with some resources to get you started on the topic. We really recommend that you have a look at them before you start.
The exercises are sorted by topic and can be found in the subdirectory `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 ran 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 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:
```bash
rustlings watch

View File

@@ -0,0 +1,7 @@
### Enums
Rust allows you to define a type called `enums` which allow you to enumerate possible values. In combination with enums, we have the concept of `pattern matching` in Rust, which makes it easy to run different code for different values of an enumeration. Enums, while available in many languages, Rust's enums are most similar to `algebraic data types` in functional languages, such as F#, OCaml, and Haskell.
#### Book Sections
- [Enums](https://doc.rust-lang.org/book/ch06-00-enums.html)

42
exercises/enums/enums1.rs Normal file
View File

@@ -0,0 +1,42 @@
// enums1.rs
// Make me compile! Scroll down for hints!
#[derive(Debug)]
enum Message {
// TODO: define a few types of messages as used below
}
fn main() {
println!("{:?}", Message::Quit);
println!("{:?}", Message::Echo);
println!("{:?}", Message::Move);
println!("{:?}", Message::ChangeColor);
}
// Hint: The declaration of the enumeration type has not been defined yet.

61
exercises/enums/enums2.rs Normal file
View File

@@ -0,0 +1,61 @@
// enums2.rs
// Make me compile! Scroll down for hints
#[derive(Debug)]
enum Message {
// TODO: define the different variants used below
}
impl Message {
fn call(&self) {
println!("{:?}", &self);
}
}
fn main() {
let messages = [
Message::Move{ x: 10, y: 30 },
Message::Echo(String::from("hello world")),
Message::ChangeColor(200, 255, 255),
Message::Quit
];
for message in &messages {
message.call();
}
}
// Hint: you can create enumerations that have different variants with different types
// such as no data, anonymous structs, a single string, tuples, ...etc

63
exercises/enums/enums3.rs Normal file
View File

@@ -0,0 +1,63 @@
// enums3.rs
// Address all the TODOs to make the tests pass!
enum Message {
// TODO: implement the message variant types based on their usage below
}
struct Point {
x: u8,
y: u8
}
struct State {
color: (u8, u8, u8),
position: Point,
quit: bool
}
impl State {
fn change_color(&mut self, color: (u8, u8, u8)) {
self.color = color;
}
fn quit(&mut self) {
self.quit = true;
}
fn echo(&self, s: String) {
println!("{}", s);
}
fn move_position(&mut self, p: Point) {
self.position = p;
}
fn process(&mut self, message: Message) {
// TODO: create a match expression to process the different message variants
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_match_message_call() {
let mut state = State{
quit: false,
position: Point{ x: 0, y: 0 },
color: (0, 0, 0)
};
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::Quit);
assert_eq!(state.color, (255, 0, 255));
assert_eq!(state.position.x, 10);
assert_eq!(state.position.y, 15);
assert_eq!(state.quit, true);
}
}

View File

@@ -1,8 +1,7 @@
// errors3.rs
// This is a program that is trying to use a completed version of the
// `total_cost` function from the previous exercise. It's not working though--
// we can't use the `?` operator in the `main()` function! Why not?
// What should we do instead? Scroll for hints!
// `total_cost` function from the previous exercise. It's not working though!
// Why not? What should we do to fix it? Scroll for hints!
use std::num::ParseIntError;
@@ -45,18 +44,4 @@ pub fn total_cost(item_quantity: &str) -> Result<i32, ParseIntError> {
// Since the `?` operator returns an `Err` early if the thing it's trying to
// do fails, you can only use the `?` operator in functions that have a
// `Result` as their return type.
// Hence the error that you get if you run this code is:
// ```
// error[E0277]: the `?` operator can only be used in a function that returns `Result` (or another type that implements `std::ops::Try`)
// ```
// So we have to use another way of handling a `Result` within `main`.
// Decide what we should do if `pretend_user_input` has a string value that does
// not parse to an integer, and implement that instead of using the `?`
// operator.
// If other functions can return a `Result`, why shouldn't `main`?

View File

@@ -20,7 +20,7 @@ use std::fmt;
use std::io;
// PositiveNonzeroInteger is a struct defined below the tests.
fn read_and_validate(b: &mut io::BufRead) -> Result<PositiveNonzeroInteger, ???> {
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();
@@ -29,7 +29,7 @@ fn read_and_validate(b: &mut io::BufRead) -> Result<PositiveNonzeroInteger, ???>
}
// This is a test helper function that turns a &str into a BufReader.
fn test_with_str(s: &str) -> Result<PositiveNonzeroInteger, Box<error::Error>> {
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)
}
@@ -98,7 +98,7 @@ enum CreationError {
impl fmt::Display for CreationError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str((self as &error::Error).description())
f.write_str((self as &dyn error::Error).description())
}
}
@@ -190,7 +190,7 @@ impl error::Error for CreationError {
// Another hint: under the hood, the `?` operator calls `From::from`
// on the error value to convert it to a boxed trait object, a Box<error::Error>,
// on the error value to convert it to a boxed trait object, a Box<dyn error::Error>,
// which is polymorphic-- that means that lots of different kinds of errors
// can be returned from the same function because all errors act the same
// since they all implement the `error::Error` trait.

View File

@@ -4,7 +4,7 @@
// on `None`. Handle this in a more graceful way than calling `unwrap`!
// Scroll down for hints :)
fn main() {
pub fn pop_too_much() -> bool {
let mut list = vec![3];
let last = list.pop().unwrap();
@@ -15,9 +15,18 @@ fn main() {
"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

@@ -3,7 +3,6 @@
pub fn bigger(a: i32, b: i32) -> i32 {
// Complete this function to return the bigger number!
// Do not use:
// - return
// - another function call
// - additional variables
// Scroll down for hints.

View File

@@ -6,3 +6,4 @@ compiler. In this section, we'll go through the most important ones.
#### Book Sections
- [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

@@ -2,16 +2,13 @@
// Get a slice out of Array a where the ??? is so that the `if` statement
// returns true. Scroll down for hints!!
#[test]
fn main() {
let a = [1, 2, 3, 4, 5];
let nice_slice = ???
if nice_slice == [2, 3, 4] {
println!("Nice slice!");
} else {
println!("Not quite what I was expecting... I see: {:?}", nice_slice);
}
assert_eq!([2, 3, 4], nice_slice)
}
@@ -33,6 +30,28 @@ fn main() {

View File

@@ -1,7 +1,7 @@
// 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
// 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
// As always, there are hints below!
@@ -9,7 +9,7 @@ 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) => first.collect::<String>() + c.as_str(),
}
}
@@ -78,7 +78,7 @@ mod tests {
// Step 1
// You need to call something on `first` before it can be collected
// Currently it's type is `char`. Have a look at the methods that are available on that type:
// Currently its type is `char`. Have a look at the methods that are available on that type:
// https://doc.rust-lang.org/std/primitive.char.html

View File

@@ -1,4 +1,4 @@
### Strings
### Structs
Rust has three struct types: a classic c struct, a tuple struct, and a unit struct.

View File

@@ -26,7 +26,6 @@ mod tests {
#[test]
fn tuple_structs() {
// TODO: Instantiate a tuple struct!
// For more fun, use the field initialization shorthand.
// let green =
assert_eq!(green.0, "green");

View File

@@ -0,0 +1,45 @@
// structs2.rs
// Address all the TODOs to make the tests pass!
// No hints, just do it!
#[derive(Debug)]
struct Order {
name: String,
year: u32,
made_by_phone: bool,
made_by_mobile: bool,
made_by_email: bool,
item_number: u32,
count: u32,
}
fn create_order_template() -> Order {
Order {
name: String::from("Bob"),
year: 2019,
made_by_phone: false,
made_by_mobile: false,
made_by_email: true,
item_number: 123,
count: 0,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn your_order() {
let order_template = create_order_template();
// TODO: Create your own order using the update syntax and template above!
// let your_order =
assert_eq!(your_order.name, "Hacker in Rust");
assert_eq!(your_order.year, order_template.year);
assert_eq!(your_order.made_by_phone, order_template.made_by_phone);
assert_eq!(your_order.made_by_mobile, order_template.made_by_mobile);
assert_eq!(your_order.made_by_email, order_template.made_by_email);
assert_eq!(your_order.item_number, order_template.item_number);
assert_eq!(your_order.count, 1);
}
}

View File

@@ -13,9 +13,9 @@
// Don't modify this function!
#[test]
fn verify_test() {
let price1 = calculate_price(55);
let price2 = calculate_price(40);
let price1 = calculate_apple_price(35);
let price2 = calculate_apple_price(65);
assert_eq!(price1, 55);
assert_eq!(price2, 80);
assert_eq!(70, price1);
assert_eq!(65, price2);
}

View File

@@ -1,27 +1,28 @@
// test2.rs
// This is a test for the following sections:
// - Tests
// - Strings
// This test isn't testing our function -- make it do that in such a way that
// the test passes. Then write a second test that tests that we get the result
// we expect to get when we call `times_two` with a negative number.
// No hints, you can do this :)
// 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!
pub fn times_two(num: i32) -> i32 {
num * 2
fn string_slice(arg: &str) {
println!("{}", arg);
}
fn string(arg: String) {
println!("{}", arg);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn returns_twice_of_positive_numbers() {
assert_eq!(times_two(4), ???);
}
#[test]
fn returns_twice_of_negative_numbers() {
// TODO write an assert for `times_two(-4)`
}
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,28 +1,27 @@
// strings3.rs
// test3.rs
// This is a test for the following sections:
// - Strings
// - Tests
// 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!
// This test isn't testing our function -- make it do that in such a way that
// the test passes. Then write a second test that tests that we get the result
// we expect to get when we call `times_two` with a negative number.
// No hints, you can do this :)
fn string_slice(arg: &str) {
println!("{}", arg);
}
fn string(arg: String) {
println!("{}", arg);
pub fn times_two(num: i32) -> i32 {
num * 2
}
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());
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn returns_twice_of_positive_numbers() {
assert_eq!(times_two(4), ???);
}
#[test]
fn returns_twice_of_negative_numbers() {
// TODO write an assert for `times_two(-4)`
}
}

View File

@@ -66,7 +66,7 @@ mode = "compile"
[[exercises]]
path = "exercises/primitive_types/primitive_types4.rs"
mode = "compile"
mode = "test"
[[exercises]]
path = "exercises/primitive_types/primitive_types5.rs"
@@ -82,6 +82,40 @@ mode = "compile"
path = "exercises/structs/structs1.rs"
mode = "test"
[[exercises]]
path = "exercises/structs/structs2.rs"
mode = "test"
# STRINGS
[[exercises]]
path = "exercises/strings/strings1.rs"
mode = "compile"
[[exercises]]
path = "exercises/strings/strings2.rs"
mode = "compile"
# TEST 2
[[exercises]]
path = "exercises/test2.rs"
mode = "compile"
# ENUMS
[[exercises]]
path = "exercises/enums/enums1.rs"
mode = "compile"
[[exercises]]
path = "exercises/enums/enums2.rs"
mode = "compile"
[[exercises]]
path = "exercises/enums/enums3.rs"
mode = "test"
# TESTS
[[exercises]]
@@ -96,27 +130,11 @@ mode = "test"
path = "exercises/tests/tests3.rs"
mode = "test"
# TEST 2
[[exercises]]
path = "exercises/test2.rs"
mode = "test"
# STRINGS
[[exercises]]
path = "exercises/strings/strings1.rs"
mode = "compile"
[[exercises]]
path = "exercises/strings/strings2.rs"
mode = "compile"
# TEST 3
[[exercises]]
path = "exercises/test3.rs"
mode = "compile"
mode = "test"
# MODULES
@@ -192,18 +210,12 @@ mode = "test"
[[exercises]]
path = "exercises/error_handling/option1.rs"
mode = "compile"
mode = "test"
[[exercises]]
path = "exercises/error_handling/result1.rs"
mode = "test"
# THREADS
[[exercises]]
path = "exercises/threads/threads1.rs"
mode = "compile"
# STANDARD LIBRARY TYPES
[[exercises]]
@@ -221,3 +233,9 @@ mode = "test"
[[exercises]]
path = "exercises/standard_library_types/iterators4.rs"
mode = "test"
# THREADS
[[exercises]]
path = "exercises/threads/threads1.rs"
mode = "compile"

85
install.ps1 Normal file
View File

@@ -0,0 +1,85 @@
#!/usr/bin/env pwsh
#Requires -Version 5
param($path = "$pwd/rustlings")
Write-Host "Let's get you set up with Rustlings!"
Write-Host "Checking requirements..."
if (Get-Command git -ErrorAction SilentlyContinue) {
Write-Host "SUCCESS: Git is installed"
} else {
Write-Host "WARNING: Git does not seem to be installed."
Write-Host "Please download Git using your package manager or over https://git-scm.com/!"
exit 1
}
if (Get-Command rustc -ErrorAction SilentlyContinue) {
Write-Host "SUCCESS: Rust is installed"
} else {
Write-Host "WARNING: Rust does not seem to be installed."
Write-Host "Please download Rust using https://rustup.rs!"
exit 1
}
if (Get-Command cargo -ErrorAction SilentlyContinue) {
Write-Host "SUCCESS: Cargo is installed"
} else {
Write-Host "WARNING: Cargo does not seem to be installed."
Write-Host "Please download Rust and Cargo using https://rustup.rs!"
exit 1
}
# 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($v1, $v2) {
if ($v1 -eq $v2) {
return 0
}
$v1 = $v1.Replace(".", "0")
$v2 = $v2.Replace(".", "0")
if ($v1.Length -gt $v2.Length) {
$v2 = $v2.PadRight($v1.Length, "0")
} else {
$v1 = $v1.PadRight($v2.Length, "0")
}
if ($v1 -gt $v2) {
return 1
} else {
return 2
}
}
$rustVersion = $(rustc --version).Split(" ")[1]
$minRustVersion = "1.31"
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'"
exit 1
} else {
Write-Host "SUCCESS: Rust is up to date"
}
Write-Host "Cloning Rustlings at $path"
git clone -q https://github.com/rust-lang/rustlings $path
if (!($LASTEXITCODE -eq 0)) {
exit 1
}
# UseBasicParsing is deprecated, pwsh 6 or above will automatically use it,
# but anyone running pwsh 5 will have to pass the argument.
$version = Invoke-WebRequest -UseBasicParsing https://api.github.com/repos/rust-lang/rustlings/releases/latest `
| ConvertFrom-Json | Select-Object -ExpandProperty tag_name
Write-Host "Checking out version $version..."
Set-Location $path
git checkout -q tags/$version
Write-Host "Installing the 'rustlings' executable..."
cargo install --force --path .
if (!(Get-Command rustlings -ErrorAction SilentlyContinue)) {
Write-Host "WARNING: Please check that you have '~/.cargo/bin' in your PATH environment variable!"
}
Write-Host "All done! Run 'rustlings' to get started."

View File

@@ -90,11 +90,18 @@ fn main() {
}
fn watch(exercises: &[Exercise]) -> notify::Result<()> {
/* Clears the terminal with an ANSI escape code.
Works in UNIX and newer Windows terminals. */
fn clear_screen() {
println!("\x1Bc");
}
let (tx, rx) = channel();
let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_secs(2))?;
watcher.watch(Path::new("./exercises"), RecursiveMode::Recursive)?;
clear_screen();
let _ignored = verify(exercises.iter());
loop {
@@ -102,11 +109,11 @@ fn watch(exercises: &[Exercise]) -> notify::Result<()> {
Ok(event) => match event {
DebouncedEvent::Create(b) | DebouncedEvent::Chmod(b) | DebouncedEvent::Write(b) => {
if b.extension() == Some(OsStr::new("rs")) && b.exists() {
println!("----------**********----------\n");
let filepath = b.as_path().canonicalize().unwrap();
let exercise = exercises
.iter()
.skip_while(|e| !filepath.ends_with(&e.path));
clear_screen();
let _ignored = verify(exercise);
}
}

View File

@@ -19,11 +19,7 @@ fn compile_only(exercise: &Exercise) -> Result<(), ()> {
let compile_output = exercise.compile();
progress_bar.finish_and_clear();
if compile_output.status.success() {
let formatstr = format!(
"{} Successfully compiled {}!",
Emoji("", ""),
exercise
);
let formatstr = format!("{} Successfully compiled {}!", Emoji("", ""), exercise);
println!("{}", style(formatstr).green());
exercise.clean();
Ok(())