summaryrefslogtreecommitdiff
path: root/rustlings-macros/src
diff options
context:
space:
mode:
authormo8it <mo8it@proton.me>2024-07-05 13:39:50 +0200
committermo8it <mo8it@proton.me>2024-07-05 13:39:50 +0200
commit7123c7ae3a9605fbe962e4ef0a0f1424cd16fef8 (patch)
treec67f7e62bb9a179ae4fdbab492501cb6847e64c7 /rustlings-macros/src
parent77b687d501771c24bd83294d97b8e6f9ffa92d6b (diff)
parent4d9c346a173bb722b929f3ea3c00f84954483e24 (diff)
Merge remote-tracking branch 'upstream/main' into fix-enum-variant-inconsistency
Diffstat (limited to 'rustlings-macros/src')
-rw-r--r--rustlings-macros/src/lib.rs56
1 files changed, 56 insertions, 0 deletions
diff --git a/rustlings-macros/src/lib.rs b/rustlings-macros/src/lib.rs
new file mode 100644
index 0000000..6c6067b
--- /dev/null
+++ b/rustlings-macros/src/lib.rs
@@ -0,0 +1,56 @@
+use proc_macro::TokenStream;
+use quote::quote;
+use serde::Deserialize;
+
+#[derive(Deserialize)]
+struct ExerciseInfo {
+ name: String,
+ dir: String,
+}
+
+#[derive(Deserialize)]
+struct InfoFile {
+ exercises: Vec<ExerciseInfo>,
+}
+
+#[proc_macro]
+pub fn include_files(_: TokenStream) -> TokenStream {
+ let info_file = include_str!("../info.toml");
+ let exercises = toml_edit::de::from_str::<InfoFile>(info_file)
+ .expect("Failed to parse `info.toml`")
+ .exercises;
+
+ 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 mut dirs = Vec::with_capacity(32);
+ let mut dir_inds = vec![0; exercises.len()];
+
+ for (exercise, dir_ind) in exercises.iter().zip(&mut dir_inds) {
+ // The directory is often the last one inserted.
+ if let Some(ind) = dirs.iter().rev().position(|dir| *dir == exercise.dir) {
+ *dir_ind = dirs.len() - 1 - ind;
+ continue;
+ }
+
+ dirs.push(exercise.dir.as_str());
+ *dir_ind = dirs.len() - 1;
+ }
+
+ let readmes = dirs
+ .iter()
+ .map(|dir| format!("../exercises/{dir}/README.md"));
+
+ quote! {
+ EmbeddedFiles {
+ info_file: #info_file,
+ exercise_files: &[#(ExerciseFiles { exercise: include_bytes!(#exercise_files), solution: include_bytes!(#solution_files), dir_ind: #dir_inds }),*],
+ exercise_dirs: &[#(ExerciseDir { name: #dirs, readme: include_bytes!(#readmes) }),*]
+ }
+ }
+ .into()
+}