Skip to content

Commit ade352c

Browse files
committed
move input files into exercise directory
1 parent ec5afe7 commit ade352c

9 files changed

Lines changed: 49 additions & 39 deletions

File tree

exercises/24_async/async1.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,18 @@
66
// Let's simulate this using asynchronous programming. Each person is
77
// represented as an asynchronous task, which can be executed concurrently.
88

9+
const SCORES_CLASS_A: &str = "exercises/24_async/scores_class_a.txt";
10+
const SCORES_CLASS_B: &str = "exercises/24_async/scores_class_b.txt";
11+
const SCORES_CLASS_C: &str = "exercises/24_async/scores_class_c.txt";
12+
913
// Async tasks need to be executed by a "runtime", which is not provided by
1014
// Rust's standard library. Here, we use the mainstream runtime `tokio`.
1115
// The macro `tokio::main` wraps the entire main function in a runtime.
1216
#[tokio::main]
1317
async fn main() {
14-
let mean_score_a = tokio::spawn(calculate_mean_score("input_files/scores_class_a.txt"));
15-
let mean_score_b = tokio::spawn(calculate_mean_score("input_files/scores_class_b.txt"));
16-
let mean_score_c = tokio::spawn(calculate_mean_score("input_files/scores_class_c.txt"));
18+
let mean_score_a = tokio::spawn(calculate_mean_score(SCORES_CLASS_A));
19+
let mean_score_b = tokio::spawn(calculate_mean_score(SCORES_CLASS_B));
20+
let mean_score_c = tokio::spawn(calculate_mean_score(SCORES_CLASS_C));
1721

1822
// TODO: Await the spawned tasks to check their results.
1923
assert_eq!(mean_score_a, 84); // alice

rustlings-macros/info.toml

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,19 +1218,15 @@ Add `AsRef<str>` or `AsMut<u32>` as a trait bound to the functions."""
12181218
name = "async1"
12191219
dir = "24_async"
12201220
test = false
1221+
input_files = [
1222+
"scores_class_a.txt",
1223+
"scores_class_b.txt",
1224+
"scores_class_c.txt",
1225+
]
12211226
hint = """
12221227
Asynchronous runtimes like tokio can only spawn tasks that are defined as async
12231228
functions, not regular ones. Add the "async" keyword before the "fn" keyword of
12241229
the functions "tim", "carl" and "nick".
12251230
12261231
An async task can wait for another one to complete by "awaiting" it. Add
12271232
".await" after the three "task_name" variables in the "block_on" call."""
1228-
1229-
[[input_files]]
1230-
name = "scores_class_a.txt"
1231-
1232-
[[input_files]]
1233-
name = "scores_class_b.txt"
1234-
1235-
[[input_files]]
1236-
name = "scores_class_c.txt"

rustlings-macros/src/lib.rs

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,14 @@ use serde::Deserialize;
66
struct ExerciseInfo<'a> {
77
name: &'a str,
88
dir: &'a str,
9-
}
10-
11-
#[derive(Deserialize)]
12-
struct InputFileInfo<'a> {
13-
name: &'a str,
9+
#[serde(default)]
10+
input_files: Vec<&'a str>,
1411
}
1512

1613
#[derive(Deserialize)]
1714
struct InfoFile<'a> {
1815
#[serde(borrow)]
1916
exercises: Vec<ExerciseInfo<'a>>,
20-
input_files: Vec<InputFileInfo<'a>>,
2117
}
2218

2319
#[proc_macro]
@@ -47,22 +43,34 @@ pub fn include_files(_: TokenStream) -> TokenStream {
4743
*dir_ind = dirs.len() - 1;
4844
}
4945

46+
let input_files = exercises.iter().map(|exercise| {
47+
let names = exercise.input_files.iter();
48+
let paths = exercise
49+
.input_files
50+
.iter()
51+
.map(|f| format!("../exercises/{}/{}", exercise.dir, f));
52+
quote! {
53+
&[#(InputFile {
54+
name: #names,
55+
content: include_str!(#paths),
56+
}),*]
57+
}
58+
});
59+
5060
let readmes = dirs
5161
.iter()
5262
.map(|dir| format!("../exercises/{dir}/README.md"));
5363

54-
let input_file_names = info.input_files.iter().map(|f| f.name);
55-
let input_file_paths = info
56-
.input_files
57-
.iter()
58-
.map(|f| format!("../input_files/{}", f.name));
59-
6064
quote! {
6165
EmbeddedFiles {
6266
info_file: #info_file,
63-
exercise_files: &[#(ExerciseFiles { exercise: include_bytes!(#exercise_files), solution: include_bytes!(#solution_files), dir_ind: #dir_inds }),*],
67+
exercise_files: &[#(ExerciseFiles {
68+
exercise: include_bytes!(#exercise_files),
69+
solution: include_bytes!(#solution_files),
70+
dir_ind: #dir_inds,
71+
input_files: #input_files,
72+
}),*],
6473
exercise_dirs: &[#(ExerciseDir { name: #dirs, readme: include_bytes!(#readmes) }),*],
65-
input_files: &[#(InputFile { name: #input_file_names, content: include_str!(#input_file_paths) }),*],
6674
}
6775
}
6876
.into()

solutions/24_async/async1.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,18 @@
66
// Let's simulate this using asynchronous programming. Each person is
77
// represented as an asynchronous task, which can be executed concurrently.
88

9+
const SCORES_CLASS_A: &str = "exercises/24_async/scores_class_a.txt";
10+
const SCORES_CLASS_B: &str = "exercises/24_async/scores_class_b.txt";
11+
const SCORES_CLASS_C: &str = "exercises/24_async/scores_class_c.txt";
12+
913
// Async tasks need to be executed by a "runtime", which is not provided by
1014
// Rust's standard library. Here, we use the mainstream runtime `tokio`.
1115
// The macro `tokio::main` wraps the entire main function in a runtime.
1216
#[tokio::main]
1317
async fn main() {
14-
let mean_score_a = tokio::spawn(calculate_mean_score("input_files/scores_class_a.txt"));
15-
let mean_score_b = tokio::spawn(calculate_mean_score("input_files/scores_class_b.txt"));
16-
let mean_score_c = tokio::spawn(calculate_mean_score("input_files/scores_class_c.txt"));
18+
let mean_score_a = tokio::spawn(calculate_mean_score(SCORES_CLASS_A));
19+
let mean_score_b = tokio::spawn(calculate_mean_score(SCORES_CLASS_B));
20+
let mean_score_c = tokio::spawn(calculate_mean_score(SCORES_CLASS_C));
1721

1822
assert_eq!(mean_score_a.await.unwrap(), 84); // alice
1923
assert_eq!(mean_score_b.await.unwrap(), 89); // bob

src/embedded.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ struct ExerciseFiles {
1717
solution: &'static [u8],
1818
// Index of the related `ExerciseDir` in `EmbeddedFiles::exercise_dirs`.
1919
dir_ind: usize,
20+
// Files that are read by the exercise.
21+
input_files: &'static [InputFile],
2022
}
2123

2224
// Input files that may be read by exercises.
@@ -64,7 +66,6 @@ pub struct EmbeddedFiles {
6466
pub info_file: &'static str,
6567
exercise_files: &'static [ExerciseFiles],
6668
pub exercise_dirs: &'static [ExerciseDir],
67-
pub input_files: &'static [InputFile],
6869
}
6970

7071
impl EmbeddedFiles {
@@ -97,6 +98,12 @@ impl EmbeddedFiles {
9798

9899
fs::write(&exercise_path, exercise_files.exercise)
99100
.with_context(|| format!("Failed to write the exercise file {exercise_path}"))?;
101+
102+
for InputFile { name, content } in exercise_files.input_files {
103+
let path = format!("{prefix}/{dir_name}/{name}", dir_name = dir.name);
104+
fs::write(&path, content)
105+
.with_context(|| format!("Failed to write the input file {path}"))?;
106+
}
100107
}
101108

102109
Ok(())

src/init.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -144,15 +144,6 @@ pub fn init() -> Result<()> {
144144
.with_context(|| format!("Failed to create the file {solution_path}"))?;
145145
}
146146

147-
// init input files
148-
create_dir("input_files").context("Failed to create the directory `input_files`")?;
149-
for input_file in EMBEDDED_FILES.input_files {
150-
fs::write(
151-
format!("input_files/{}", input_file.name),
152-
input_file.content,
153-
)?;
154-
}
155-
156147
let current_cargo_toml = include_str!("../dev-Cargo.toml");
157148
// Skip the first line (comment).
158149
let newline_ind = current_cargo_toml

0 commit comments

Comments
 (0)