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

View file

@ -8,23 +8,34 @@ exclude = [
] ]
[workspace.package] [workspace.package]
version = "6.0.0-alpha.0" version = "6.0.0-beta.0"
authors = [ authors = [
"Liv <mokou@fastmail.com>", "Liv <mokou@fastmail.com>",
"Mo Bitar <mo8it@proton.me>",
# Alumni
"Carol (Nichols || Goulding) <carol.nichols@gmail.com>", "Carol (Nichols || Goulding) <carol.nichols@gmail.com>",
"Mo <mo8it@proton.me>",
] ]
repository = "https://github.com/rust-lang/rustlings"
license = "MIT" license = "MIT"
edition = "2021" edition = "2021"
[workspace.dependencies]
serde = { version = "1.0.198", features = ["derive"] }
toml_edit = { version = "0.22.12", default-features = false, features = ["parse", "serde"] }
[package] [package]
name = "rustlings" name = "rustlings"
description = "Small exercises to get you used to reading and writing Rust code!" description = "Small exercises to get you used to reading and writing Rust code!"
default-run = "rustlings" default-run = "rustlings"
version.workspace = true version.workspace = true
authors.workspace = true authors.workspace = true
repository.workspace = true
license.workspace = true license.workspace = true
edition.workspace = true edition.workspace = true
keywords = [
"exercise",
"learning",
]
include = [ include = [
"/exercises/", "/exercises/",
"/info.toml", "/info.toml",
@ -40,9 +51,9 @@ crossterm = "0.27.0"
hashbrown = "0.14.3" hashbrown = "0.14.3"
notify-debouncer-mini = "0.4.1" notify-debouncer-mini = "0.4.1"
ratatui = "0.26.2" ratatui = "0.26.2"
rustlings-macros = { path = "rustlings-macros", version = "6.0.0-alpha.0" } rustlings-macros = { path = "rustlings-macros", version = "6.0.0-beta.0" }
serde = { version = "1.0.198", features = ["derive"] } serde.workspace = true
toml_edit = { version = "0.22.12", default-features = false, features = ["parse", "serde"] } toml_edit.workspace = true
which = "6.0.1" which = "6.0.1"
[dev-dependencies] [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 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 ## Continuing On
<!-- TODO: Mention third-party exercises --> <!-- 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) - [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 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 = """ hint = """
The error message points to the function `sale_price` and says it expects a type 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 after the `->`. This is where the function's return type should be -- take a
look at the `is_even` function for an example! 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!"""
[[exercises]] [[exercises]]
name = "functions5" name = "functions5"
@ -236,6 +233,7 @@ Make sure the type is consistent across all arms."""
[[exercises]] [[exercises]]
name = "quiz1" name = "quiz1"
dir = "quizzes"
mode = "test" mode = "test"
hint = "No hints this time ;)" 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]] [[exercises]]
name = "quiz2" name = "quiz2"
dir = "quizzes"
mode = "test" mode = "test"
hint = "No hints this time ;)" 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]] [[exercises]]
name = "quiz3" name = "quiz3"
dir = "quizzes"
mode = "test" mode = "test"
hint = """ hint = """
To find the best solution to this challenge you're going to need to think back To find the best solution to this challenge you're going to need to think back

View file

@ -1,8 +1,9 @@
[package] [package]
name = "rustlings-macros" 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 version.workspace = true
authors.workspace = true authors.workspace = true
repository.workspace = true
license.workspace = true license.workspace = true
edition.workspace = true edition.workspace = true
@ -11,3 +12,5 @@ proc-macro = true
[dependencies] [dependencies]
quote = "1.0.36" quote = "1.0.36"
serde.workspace = true
toml_edit.workspace = true

View file

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