Merge pull request #1955 from rust-lang/solutions

Solutions
This commit is contained in:
Mo 2024-04-24 02:56:20 +02:00 committed by GitHub
commit 53fdb9044d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
115 changed files with 355 additions and 209 deletions

6
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",
@ -690,6 +690,8 @@ name = "rustlings-macros"
version = "6.0.0-alpha.0" version = "6.0.0-alpha.0"
dependencies = [ dependencies = [
"quote", "quote",
"serde",
"toml_edit",
] ]
[[package]] [[package]]

View file

@ -17,6 +17,10 @@ authors = [
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!"
@ -41,8 +45,8 @@ 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-alpha.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

@ -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

@ -236,6 +236,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 +638,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 +872,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

@ -11,3 +11,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

View file

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

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