From cd9be6fcb2723cc7b9fb8e63b0ac338e612f6667 Mon Sep 17 00:00:00 2001 From: Tristan Guichaoua Date: Thu, 12 Dec 2024 00:18:25 +0100 Subject: [PATCH 1/5] add `day_from_file_name!` --- src/template/day.rs | 52 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/template/day.rs b/src/template/day.rs index 99b8280..ae1b8c6 100644 --- a/src/template/day.rs +++ b/src/template/day.rs @@ -150,6 +150,58 @@ macro_rules! day { }}; } +/// Creates a [`Day`] using the current file name. +/// +/// The file name must be a valid integer in the range 1-25. +#[macro_export] +macro_rules! day_from_file_name { + () => { + const { + let mut path = ::core::panic::Location::caller().file().as_bytes(); + + // Get the last part of the path (e.g. "11.rs") + // path = path.rsplit_once(|c| c == '\\' || c == '/').map(|(_, s)| s).unwrap_or(path) + let mut i = path.len(); + while i > 0 { + let c = path[i - 1]; + if c == b'\\' || c == b'/' { + path = path.split_at(i).1; + break; + } + + i -= 1; + } + + // Remove the extension + // path = path.split_once('.').map(|(s, _)| s).unwrap_or(path) + let mut i = 0; + while i < path.len() { + if path[i] == b'.' { + path = path.split_at(i).0; + break; + } + + i += 1; + } + + // Convert the path back into a &str + // Note: as we only split at ascii chars (/, \ or .) the path should be a valid &str + let path = match ::core::str::from_utf8(path) { + Ok(path) => path, + Err(_) => unreachable!(), + }; + + let day = match u8::from_str_radix(path, 10) { + Ok(day) => day, + Err(_) => panic!("the file name is expected to be a number"), + }; + + $crate::template::Day::new(day) + .expect("the file name should be a number between 1 and 25") + } + }; +} + /* -------------------------------------------------------------------------- */ #[cfg(feature = "test_lib")] From 56615ae5eca234fc6ce756f7776bf7bd6ba9855d Mon Sep 17 00:00:00 2001 From: Tristan Guichaoua Date: Thu, 12 Dec 2024 00:20:11 +0100 Subject: [PATCH 2/5] update `solution!` to use the file name as day --- src/template/mod.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/template/mod.rs b/src/template/mod.rs index dd8e4c0..a83b35f 100644 --- a/src/template/mod.rs +++ b/src/template/mod.rs @@ -42,18 +42,31 @@ pub fn read_file_part(folder: &str, day: Day, part: u8) -> String { #[macro_export] macro_rules! solution { ($day:expr) => { - $crate::solution!(@impl $day, [part_one, 1] [part_two, 2]); + $crate::solution!(@impl $crate::day!($day), [part_one, 1] [part_two, 2]); }; ($day:expr, 1) => { - $crate::solution!(@impl $day, [part_one, 1]); + $crate::solution!(@impl $crate::day!($day), [part_one, 1]); }; ($day:expr, 2) => { - $crate::solution!(@impl $day, [part_two, 2]); + $crate::solution!(@impl $crate::day!($day), [part_two, 2]); + }; + + () => { + $crate::solution!(@impl $crate::day_from_file_name!(), [part_one, 1] [part_two, 2]); + }; + (*) => { + $crate::solution!(); + }; + (*, 1) => { + $crate::solution!(@impl $crate::day_from_file_name!(), [part_one, 1]); + }; + (*, 2) => { + $crate::solution!(@impl $crate::day_from_file_name!(), [part_two, 2]); }; (@impl $day:expr, $( [$func:expr, $part:expr] )*) => { /// The current day. - const DAY: $crate::template::Day = $crate::day!($day); + const DAY: $crate::template::Day = $day; #[cfg(feature = "dhat-heap")] #[global_allocator] From 3a9a27e54dfe6693f28066fcf0c0435d9f531423 Mon Sep 17 00:00:00 2001 From: Tristan Guichaoua Date: Thu, 12 Dec 2024 00:21:33 +0100 Subject: [PATCH 3/5] update the template --- src/template.txt | 2 +- src/template/commands/scaffold.rs | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/template.txt b/src/template.txt index 11344df..c010752 100644 --- a/src/template.txt +++ b/src/template.txt @@ -1,4 +1,4 @@ -advent_of_code::solution!(%DAY_NUMBER%); +advent_of_code::solution!(); pub fn part_one(input: &str) -> Option { None diff --git a/src/template/commands/scaffold.rs b/src/template/commands/scaffold.rs index fc3d950..a314372 100644 --- a/src/template/commands/scaffold.rs +++ b/src/template/commands/scaffold.rs @@ -40,11 +40,7 @@ pub fn handle(day: Day, overwrite: bool) { } }; - match file.write_all( - MODULE_TEMPLATE - .replace("%DAY_NUMBER%", &day.into_inner().to_string()) - .as_bytes(), - ) { + match file.write_all(MODULE_TEMPLATE.as_bytes()) { Ok(()) => { println!("Created module file \"{}\"", &module_path); } From b70d464027cc4fd70372897f69fa7b5f6358cd83 Mon Sep 17 00:00:00 2001 From: Tristan Guichaoua Date: Thu, 12 Dec 2024 00:22:57 +0100 Subject: [PATCH 4/5] make `Day::new` const --- src/template/day.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/template/day.rs b/src/template/day.rs index ae1b8c6..3049928 100644 --- a/src/template/day.rs +++ b/src/template/day.rs @@ -24,7 +24,7 @@ pub struct Day(u8); impl Day { /// Creates a [`Day`] from the provided value if it's in the valid range, /// returns [`None`] otherwise. - pub fn new(day: u8) -> Option { + pub const fn new(day: u8) -> Option { if day == 0 || day > 25 { return None; } From 9910a011eac2ace95ac37d329fc518563832fe84 Mon Sep 17 00:00:00 2001 From: Tristan Guichaoua Date: Thu, 12 Dec 2024 00:33:46 +0100 Subject: [PATCH 5/5] make macros more hygienic --- src/template/day.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/template/day.rs b/src/template/day.rs index 3049928..7124baf 100644 --- a/src/template/day.rs +++ b/src/template/day.rs @@ -191,7 +191,7 @@ macro_rules! day_from_file_name { Err(_) => unreachable!(), }; - let day = match u8::from_str_radix(path, 10) { + let day = match ::core::primitive::u8::from_str_radix(path, 10) { Ok(day) => day, Err(_) => panic!("the file name is expected to be a number"), };