Compare commits

...

23 commits

Author SHA1 Message Date
mo8it d8c2ab8349 Fix tests 2024-04-24 16:26:48 +02:00
mo8it 0df0be8352 Update Cargo.lock 2024-04-24 16:26:34 +02:00
mo8it 8ebd2f9df2 Update Cargo.toml files 2024-04-24 16:15:14 +02:00
mo8it 4ef345e706 Update dependency 2024-04-24 15:58:34 +02:00
mo8it 0a2d4dae5a Merge branch 'main' 2024-04-24 15:48:29 +02:00
mo8it 71053101c3 Add --locked 2024-04-24 13:28:25 +02:00
Mo 53fdb9044d
Merge pull request #1955 from rust-lang/solutions
Solutions
2024-04-24 02:56:20 +02:00
mo8it 8a085a0a85 Dump solution and show its path 2024-04-24 02:52:30 +02:00
mo8it edf5762612 Preallocate path 2024-04-24 01:17:39 +02:00
mo8it ef02c6c6ab Use the embedded info.toml in debug mode 2024-04-24 00:58:52 +02:00
mo8it e4ee2cd548 Don't write solutions in debug mode 2024-04-24 00:48:58 +02:00
mo8it b77007887c Write the solution file on done 2024-04-24 00:47:46 +02:00
mo8it 2dac8e509b Refactor embedded files to add solutions 2024-04-23 19:18:25 +02:00
mo8it e5a19a4c33 Update deps 2024-04-23 15:32:07 +02:00
mo8it 5349f0e8d4 Add README to the quizzes directory 2024-04-23 15:32:01 +02:00
mo8it ad8e544483 Move quizzes 2024-04-22 01:07:36 +02:00
mo8it ea504e6bf1 Update deps 2024-04-19 12:41:13 +02:00
liv 67a15ef27f fix: remove bad hint in functions4
Technically it's correct, but playing around with this will very quickly
throw you into having to handle `Option`s and futzing around with
`try_into`. Not really something we want to throw upon the user here.

Closes #1948.
2024-04-16 15:23:08 +02:00
liv 258ff6f462
Merge pull request #1946 from rust-lang/all-contributors/add-Selflocking
docs: add Selflocking as a contributor for content
2024-04-08 22:49:11 +02:00
allcontributors[bot] 95a3fe17fa
docs: update .all-contributorsrc [skip ci] 2024-04-08 20:49:03 +00:00
allcontributors[bot] 501861e435
docs: update AUTHORS.md [skip ci] 2024-04-08 20:49:02 +00:00
liv f3890cbae6
Merge pull request #1944 from Selflocking/patch-1
docs: add more info in threads
2024-04-08 22:48:43 +02:00
YunShu f714534393
docs: add more info in threads
info.toml: 

```toml
[[exercises]]
name = "threads3"
path = "exercises/threads/threads3.rs"
mode = "test"
hint = """
An alternate way to handle concurrency between threads is to use
a mpsc (multiple producer, single consumer) channel to communicate.
With both a sending end and a receiving end, it's possible to
send values in one thread and receive them in another.
Multiple producers are possible by using clone() to create a duplicate
of the original sending end.
See https://doc.rust-lang.org/book/ch16-02-message-passing.html for more info.
"""
```

threads3'hint contains this link, so it should be placed in Further Information
2024-04-08 22:07:26 +08:00
116 changed files with 364 additions and 222 deletions

16
Cargo.lock generated
View file

@ -656,9 +656,9 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
[[package]]
name = "rustix"
version = "0.38.33"
version = "0.38.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3cc72858054fcff6d7dea32df2aeaee6a7c24227366d7ea429aada2f26b16ad"
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
dependencies = [
"bitflags 2.5.0",
"errno",
@ -669,7 +669,7 @@ dependencies = [
[[package]]
name = "rustlings"
version = "6.0.0-alpha.0"
version = "6.0.0-beta.0"
dependencies = [
"anyhow",
"assert_cmd",
@ -687,9 +687,11 @@ dependencies = [
[[package]]
name = "rustlings-macros"
version = "6.0.0-alpha.0"
version = "6.0.0-beta.0"
dependencies = [
"quote",
"serde",
"toml_edit",
]
[[package]]
@ -952,11 +954,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.6"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
checksum = "134306a13c5647ad6453e8deaec55d3a44d6021970129e6188735e74bf546697"
dependencies = [
"winapi",
"windows-sys 0.52.0",
]
[[package]]

View file

@ -8,23 +8,34 @@ exclude = [
]
[workspace.package]
version = "6.0.0-alpha.0"
version = "6.0.0-beta.0"
authors = [
"Liv <mokou@fastmail.com>",
"Mo Bitar <mo8it@proton.me>",
# Alumni
"Carol (Nichols || Goulding) <carol.nichols@gmail.com>",
"Mo <mo8it@proton.me>",
]
repository = "https://github.com/rust-lang/rustlings"
license = "MIT"
edition = "2021"
[workspace.dependencies]
serde = { version = "1.0.198", features = ["derive"] }
toml_edit = { version = "0.22.12", default-features = false, features = ["parse", "serde"] }
[package]
name = "rustlings"
description = "Small exercises to get you used to reading and writing Rust code!"
default-run = "rustlings"
version.workspace = true
authors.workspace = true
repository.workspace = true
license.workspace = true
edition.workspace = true
keywords = [
"exercise",
"learning",
]
include = [
"/exercises/",
"/info.toml",
@ -40,9 +51,9 @@ crossterm = "0.27.0"
hashbrown = "0.14.3"
notify-debouncer-mini = "0.4.1"
ratatui = "0.26.2"
rustlings-macros = { path = "rustlings-macros", version = "6.0.0-alpha.0" }
serde = { version = "1.0.198", features = ["derive"] }
toml_edit = { version = "0.22.12", default-features = false, features = ["parse", "serde"] }
rustlings-macros = { path = "rustlings-macros", version = "6.0.0-beta.0" }
serde.workspace = true
toml_edit.workspace = true
which = "6.0.1"
[dev-dependencies]

View file

@ -90,11 +90,6 @@ You can also get the hint for the next pending exercise with the following comma
rustlings hint
```
## Quizzes
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
<!-- TODO: Mention third-party exercises -->

View file

@ -7,3 +7,4 @@ Within your program, you can also have independent parts that run simultaneously
- [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)
- [Using Message Passing to Transfer Data Between Threads](https://doc.rust-lang.org/book/ch16-02-message-passing.html)

View file

@ -0,0 +1,3 @@
# Quizzes
After every couple of sections, there will be a quiz in this directory that'll test your knowledge on a bunch of sections at once.

View file

@ -175,10 +175,7 @@ mode = "run"
hint = """
The error message points to the function `sale_price` and says it expects a type
after the `->`. This is where the function's return type should be -- take a
look at the `is_even` function for an example!
Also: Did you figure out that, technically, `u32` would be the more fitting type
for the inputs of the functions here, since the original prices shouldn't be negative? If so, kudos!"""
look at the `is_even` function for an example!"""
[[exercises]]
name = "functions5"
@ -236,6 +233,7 @@ Make sure the type is consistent across all arms."""
[[exercises]]
name = "quiz1"
dir = "quizzes"
mode = "test"
hint = "No hints this time ;)"
@ -637,6 +635,7 @@ Learn more at https://doc.rust-lang.org/book/ch08-03-hash-maps.html#updating-a-v
[[exercises]]
name = "quiz2"
dir = "quizzes"
mode = "test"
hint = "No hints this time ;)"
@ -870,6 +869,7 @@ See the documentation at: https://doc.rust-lang.org/book/ch10-02-traits.html#spe
[[exercises]]
name = "quiz3"
dir = "quizzes"
mode = "test"
hint = """
To find the best solution to this challenge you're going to need to think back

View file

@ -1,8 +1,9 @@
[package]
name = "rustlings-macros"
description = "A macros crate intended to be only used by rustlings"
description = "A macros crate intended to be used only by Rustlings"
version.workspace = true
authors.workspace = true
repository.workspace = true
license.workspace = true
edition.workspace = true
@ -11,3 +12,5 @@ proc-macro = true
[dependencies]
quote = "1.0.36"
serde.workspace = true
toml_edit.workspace = true

View file

@ -1,86 +1,39 @@
use proc_macro::TokenStream;
use quote::quote;
use std::{fs::read_dir, panic, path::PathBuf};
use serde::Deserialize;
fn path_to_string(path: PathBuf) -> String {
path.into_os_string()
.into_string()
.unwrap_or_else(|original| {
panic!("The path {} is invalid UTF8", original.to_string_lossy());
})
#[derive(Deserialize)]
struct ExerciseInfo {
name: String,
dir: String,
}
#[derive(Deserialize)]
struct InfoFile {
exercises: Vec<ExerciseInfo>,
}
#[proc_macro]
pub fn include_files(_: TokenStream) -> TokenStream {
let mut files = Vec::with_capacity(8);
let mut dirs = Vec::with_capacity(128);
let exercises = toml_edit::de::from_str::<InfoFile>(include_str!("../../info.toml"))
.expect("Failed to parse `info.toml`")
.exercises;
for entry in read_dir("exercises").expect("Failed to open the `exercises` directory") {
let entry = entry.expect("Failed to read the `exercises` directory");
if entry.file_type().unwrap().is_file() {
let path = entry.path();
if path.file_name().unwrap() != "README.md" {
files.push(path_to_string(path));
}
continue;
}
let dir_path = entry.path();
let dir_files = read_dir(&dir_path).unwrap_or_else(|e| {
panic!("Failed to open the directory {}: {e}", dir_path.display());
});
let dir_path = path_to_string(dir_path);
let dir_files = dir_files.filter_map(|entry| {
let entry = entry.unwrap_or_else(|e| {
panic!("Failed to read the directory {dir_path}: {e}");
});
let path = entry.path();
if !entry.file_type().unwrap().is_file() {
panic!("Found {} but expected only files", path.display());
}
if path.file_name().unwrap() == "README.md" {
return None;
}
Some(path_to_string(path))
});
dirs.push(quote! {
EmbeddedFlatDir {
path: #dir_path,
readme: EmbeddedFile {
path: ::std::concat!(#dir_path, "/README.md"),
content: ::std::include_bytes!(::std::concat!("../", #dir_path, "/README.md")),
},
content: &[
#(EmbeddedFile {
path: #dir_files,
content: ::std::include_bytes!(::std::concat!("../", #dir_files)),
}),*
],
}
});
}
let exercise_files = exercises
.iter()
.map(|exercise| format!("../exercises/{}/{}.rs", exercise.dir, exercise.name));
let solution_files = exercises
.iter()
.map(|exercise| format!("../solutions/{}/{}.rs", exercise.dir, exercise.name));
let dirs = exercises.iter().map(|exercise| &exercise.dir);
let readmes = exercises
.iter()
.map(|exercise| format!("../exercises/{}/README.md", exercise.dir));
quote! {
EmbeddedFiles {
exercises_dir: ExercisesDir {
readme: EmbeddedFile {
path: "exercises/README.md",
content: ::std::include_bytes!("../exercises/README.md"),
},
files: &[#(
EmbeddedFile {
path: #files,
content: ::std::include_bytes!(::std::concat!("../", #files)),
}
),*],
dirs: &[#(#dirs),*],
},
exercise_files: &[#(ExerciseFiles { exercise: include_bytes!(#exercise_files), solution: include_bytes!(#solution_files) }),*],
exercise_dirs: &[#(ExerciseDir { name: #dirs, readme: include_bytes!(#readmes) }),*]
}
}
.into()

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

1
solutions/03_if/if1.rs Normal file
View file

@ -0,0 +1 @@
// TODO

1
solutions/03_if/if2.rs Normal file
View file

@ -0,0 +1 @@
// TODO

1
solutions/03_if/if3.rs Normal file
View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

View file

@ -0,0 +1 @@
// TODO

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