mirror of
https://github.com/rust-lang/rustlings.git
synced 2026-08-14 14:26:56 +00:00
move input files into exercise directory
This commit is contained in:
parent
1c106e5f1e
commit
f63e11aeb6
@ -6,14 +6,18 @@
|
|||||||
// Let's simulate this using asynchronous programming. Each person is
|
// Let's simulate this using asynchronous programming. Each person is
|
||||||
// represented as an asynchronous task, which can be executed concurrently.
|
// represented as an asynchronous task, which can be executed concurrently.
|
||||||
|
|
||||||
|
const SCORES_CLASS_A: &str = "exercises/24_async/scores_class_a.txt";
|
||||||
|
const SCORES_CLASS_B: &str = "exercises/24_async/scores_class_b.txt";
|
||||||
|
const SCORES_CLASS_C: &str = "exercises/24_async/scores_class_c.txt";
|
||||||
|
|
||||||
// Async tasks need to be executed by a "runtime", which is not provided by
|
// Async tasks need to be executed by a "runtime", which is not provided by
|
||||||
// Rust's standard library. Here, we use the mainstream runtime `tokio`.
|
// Rust's standard library. Here, we use the mainstream runtime `tokio`.
|
||||||
// The macro `tokio::main` wraps the entire main function in a runtime.
|
// The macro `tokio::main` wraps the entire main function in a runtime.
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let mean_score_a = tokio::spawn(calculate_mean_score("input_files/scores_class_a.txt"));
|
let mean_score_a = tokio::spawn(calculate_mean_score(SCORES_CLASS_A));
|
||||||
let mean_score_b = tokio::spawn(calculate_mean_score("input_files/scores_class_b.txt"));
|
let mean_score_b = tokio::spawn(calculate_mean_score(SCORES_CLASS_B));
|
||||||
let mean_score_c = tokio::spawn(calculate_mean_score("input_files/scores_class_c.txt"));
|
let mean_score_c = tokio::spawn(calculate_mean_score(SCORES_CLASS_C));
|
||||||
|
|
||||||
// TODO: Await the spawned tasks to check their results.
|
// TODO: Await the spawned tasks to check their results.
|
||||||
assert_eq!(mean_score_a, 84); // alice
|
assert_eq!(mean_score_a, 84); // alice
|
||||||
|
|||||||
@ -1218,6 +1218,11 @@ Add `AsRef<str>` or `AsMut<u32>` as a trait bound to the functions."""
|
|||||||
name = "async1"
|
name = "async1"
|
||||||
dir = "24_async"
|
dir = "24_async"
|
||||||
test = false
|
test = false
|
||||||
|
input_files = [
|
||||||
|
"scores_class_a.txt",
|
||||||
|
"scores_class_b.txt",
|
||||||
|
"scores_class_c.txt",
|
||||||
|
]
|
||||||
hint = """
|
hint = """
|
||||||
Asynchronous runtimes like tokio can only spawn tasks that are defined as async
|
Asynchronous runtimes like tokio can only spawn tasks that are defined as async
|
||||||
functions, not regular ones. Add the "async" keyword before the "fn" keyword of
|
functions, not regular ones. Add the "async" keyword before the "fn" keyword of
|
||||||
@ -1225,12 +1230,3 @@ the functions "tim", "carl" and "nick".
|
|||||||
|
|
||||||
An async task can wait for another one to complete by "awaiting" it. Add
|
An async task can wait for another one to complete by "awaiting" it. Add
|
||||||
".await" after the three "task_name" variables in the "block_on" call."""
|
".await" after the three "task_name" variables in the "block_on" call."""
|
||||||
|
|
||||||
[[input_files]]
|
|
||||||
name = "scores_class_a.txt"
|
|
||||||
|
|
||||||
[[input_files]]
|
|
||||||
name = "scores_class_b.txt"
|
|
||||||
|
|
||||||
[[input_files]]
|
|
||||||
name = "scores_class_c.txt"
|
|
||||||
|
|||||||
@ -6,18 +6,14 @@ use serde::Deserialize;
|
|||||||
struct ExerciseInfo<'a> {
|
struct ExerciseInfo<'a> {
|
||||||
name: &'a str,
|
name: &'a str,
|
||||||
dir: &'a str,
|
dir: &'a str,
|
||||||
}
|
#[serde(default)]
|
||||||
|
input_files: Vec<&'a str>,
|
||||||
#[derive(Deserialize)]
|
|
||||||
struct InputFileInfo<'a> {
|
|
||||||
name: &'a str,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct InfoFile<'a> {
|
struct InfoFile<'a> {
|
||||||
#[serde(borrow)]
|
#[serde(borrow)]
|
||||||
exercises: Vec<ExerciseInfo<'a>>,
|
exercises: Vec<ExerciseInfo<'a>>,
|
||||||
input_files: Vec<InputFileInfo<'a>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
@ -47,22 +43,34 @@ pub fn include_files(_: TokenStream) -> TokenStream {
|
|||||||
*dir_ind = dirs.len() - 1;
|
*dir_ind = dirs.len() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let input_files = exercises.iter().map(|exercise| {
|
||||||
|
let names = exercise.input_files.iter();
|
||||||
|
let paths = exercise
|
||||||
|
.input_files
|
||||||
|
.iter()
|
||||||
|
.map(|f| format!("../exercises/{}/{}", exercise.dir, f));
|
||||||
|
quote! {
|
||||||
|
&[#(InputFile {
|
||||||
|
name: #names,
|
||||||
|
content: include_str!(#paths),
|
||||||
|
}),*]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let readmes = dirs
|
let readmes = dirs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|dir| format!("../exercises/{dir}/README.md"));
|
.map(|dir| format!("../exercises/{dir}/README.md"));
|
||||||
|
|
||||||
let input_file_names = info.input_files.iter().map(|f| f.name);
|
|
||||||
let input_file_paths = info
|
|
||||||
.input_files
|
|
||||||
.iter()
|
|
||||||
.map(|f| format!("../input_files/{}", f.name));
|
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
EmbeddedFiles {
|
EmbeddedFiles {
|
||||||
info_file: #info_file,
|
info_file: #info_file,
|
||||||
exercise_files: &[#(ExerciseFiles { exercise: include_bytes!(#exercise_files), solution: include_bytes!(#solution_files), dir_ind: #dir_inds }),*],
|
exercise_files: &[#(ExerciseFiles {
|
||||||
|
exercise: include_bytes!(#exercise_files),
|
||||||
|
solution: include_bytes!(#solution_files),
|
||||||
|
dir_ind: #dir_inds,
|
||||||
|
input_files: #input_files,
|
||||||
|
}),*],
|
||||||
exercise_dirs: &[#(ExerciseDir { name: #dirs, readme: include_bytes!(#readmes) }),*],
|
exercise_dirs: &[#(ExerciseDir { name: #dirs, readme: include_bytes!(#readmes) }),*],
|
||||||
input_files: &[#(InputFile { name: #input_file_names, content: include_str!(#input_file_paths) }),*],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
|
|||||||
@ -6,14 +6,18 @@
|
|||||||
// Let's simulate this using asynchronous programming. Each person is
|
// Let's simulate this using asynchronous programming. Each person is
|
||||||
// represented as an asynchronous task, which can be executed concurrently.
|
// represented as an asynchronous task, which can be executed concurrently.
|
||||||
|
|
||||||
|
const SCORES_CLASS_A: &str = "exercises/24_async/scores_class_a.txt";
|
||||||
|
const SCORES_CLASS_B: &str = "exercises/24_async/scores_class_b.txt";
|
||||||
|
const SCORES_CLASS_C: &str = "exercises/24_async/scores_class_c.txt";
|
||||||
|
|
||||||
// Async tasks need to be executed by a "runtime", which is not provided by
|
// Async tasks need to be executed by a "runtime", which is not provided by
|
||||||
// Rust's standard library. Here, we use the mainstream runtime `tokio`.
|
// Rust's standard library. Here, we use the mainstream runtime `tokio`.
|
||||||
// The macro `tokio::main` wraps the entire main function in a runtime.
|
// The macro `tokio::main` wraps the entire main function in a runtime.
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let mean_score_a = tokio::spawn(calculate_mean_score("input_files/scores_class_a.txt"));
|
let mean_score_a = tokio::spawn(calculate_mean_score(SCORES_CLASS_A));
|
||||||
let mean_score_b = tokio::spawn(calculate_mean_score("input_files/scores_class_b.txt"));
|
let mean_score_b = tokio::spawn(calculate_mean_score(SCORES_CLASS_B));
|
||||||
let mean_score_c = tokio::spawn(calculate_mean_score("input_files/scores_class_c.txt"));
|
let mean_score_c = tokio::spawn(calculate_mean_score(SCORES_CLASS_C));
|
||||||
|
|
||||||
assert_eq!(mean_score_a.await.unwrap(), 84); // alice
|
assert_eq!(mean_score_a.await.unwrap(), 84); // alice
|
||||||
assert_eq!(mean_score_b.await.unwrap(), 89); // bob
|
assert_eq!(mean_score_b.await.unwrap(), 89); // bob
|
||||||
|
|||||||
@ -17,6 +17,8 @@ struct ExerciseFiles {
|
|||||||
solution: &'static [u8],
|
solution: &'static [u8],
|
||||||
// Index of the related `ExerciseDir` in `EmbeddedFiles::exercise_dirs`.
|
// Index of the related `ExerciseDir` in `EmbeddedFiles::exercise_dirs`.
|
||||||
dir_ind: usize,
|
dir_ind: usize,
|
||||||
|
// Files that are read by the exercise.
|
||||||
|
input_files: &'static [InputFile],
|
||||||
}
|
}
|
||||||
|
|
||||||
// Input files that may be read by exercises.
|
// Input files that may be read by exercises.
|
||||||
@ -64,7 +66,6 @@ pub struct EmbeddedFiles {
|
|||||||
pub info_file: &'static str,
|
pub info_file: &'static str,
|
||||||
exercise_files: &'static [ExerciseFiles],
|
exercise_files: &'static [ExerciseFiles],
|
||||||
pub exercise_dirs: &'static [ExerciseDir],
|
pub exercise_dirs: &'static [ExerciseDir],
|
||||||
pub input_files: &'static [InputFile],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EmbeddedFiles {
|
impl EmbeddedFiles {
|
||||||
@ -97,6 +98,12 @@ impl EmbeddedFiles {
|
|||||||
|
|
||||||
fs::write(&exercise_path, exercise_files.exercise)
|
fs::write(&exercise_path, exercise_files.exercise)
|
||||||
.with_context(|| format!("Failed to write the exercise file {exercise_path}"))?;
|
.with_context(|| format!("Failed to write the exercise file {exercise_path}"))?;
|
||||||
|
|
||||||
|
for InputFile { name, content } in exercise_files.input_files {
|
||||||
|
let path = format!("{prefix}/{dir_name}/{name}", dir_name = dir.name);
|
||||||
|
fs::write(&path, content)
|
||||||
|
.with_context(|| format!("Failed to write the input file {path}"))?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@ -144,15 +144,6 @@ pub fn init() -> Result<()> {
|
|||||||
.with_context(|| format!("Failed to create the file {solution_path}"))?;
|
.with_context(|| format!("Failed to create the file {solution_path}"))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// init input files
|
|
||||||
create_dir("input_files").context("Failed to create the directory `input_files`")?;
|
|
||||||
for input_file in EMBEDDED_FILES.input_files {
|
|
||||||
fs::write(
|
|
||||||
format!("input_files/{}", input_file.name),
|
|
||||||
input_file.content,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let current_cargo_toml = include_str!("../dev-Cargo.toml");
|
let current_cargo_toml = include_str!("../dev-Cargo.toml");
|
||||||
// Skip the first line (comment).
|
// Skip the first line (comment).
|
||||||
let newline_ind = current_cargo_toml
|
let newline_ind = current_cargo_toml
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user