Move solutions from bin into lib.

The files src/bin/01.rs, 02.rs, etc are still created by scaffold, but they now
call the solution in the src/day01.rs, src/day02.rs, thereby allowing benchmarking.

This means that scaffold also updates lib.rs to add the module definitions. Right now
this is done using a simple replace of "// pub mod day01;" with "pub mod day01;".
There is a probably a nicer way to do this, but it works.

Also due to an issue in cargo we need to run "cargo clean -p advent_of_code".
Otherwise "cargo check" will fail.
See https://github.com/rust-lang/cargo/issues/6529
This commit is contained in:
Burkhard Mittelbach 2022-12-04 17:50:45 +01:00
parent 6ae29a25e8
commit e601d48d16
2 changed files with 134 additions and 17 deletions

View file

@ -4,11 +4,11 @@
*/ */
use std::{ use std::{
fs::{File, OpenOptions}, fs::{File, OpenOptions},
io::Write, io::{Error, Read, Seek, Write},
process, process::{self, Command},
}; };
const MODULE_TEMPLATE: &str = r###"pub fn part_one(input: &str) -> Option<u32> { const MODULE_LIB_TEMPLATE: &str = r###"pub fn part_one(input: &str) -> Option<u32> {
None None
} }
@ -16,30 +16,33 @@ pub fn part_two(input: &str) -> Option<u32> {
None None
} }
fn main() {
let input = &advent_of_code::read_file("inputs", DAY);
advent_of_code::solve!(1, part_one, input);
advent_of_code::solve!(2, part_two, input);
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
#[test] #[test]
fn test_part_one() { fn test_part_one() {
let input = advent_of_code::read_file("examples", DAY); let input = crate::read_file("examples", DAY);
assert_eq!(part_one(&input), None); assert_eq!(part_one(&input), None);
} }
#[test] #[test]
fn test_part_two() { fn test_part_two() {
let input = advent_of_code::read_file("examples", DAY); let input = crate::read_file("examples", DAY);
assert_eq!(part_two(&input), None); assert_eq!(part_two(&input), None);
} }
} }
"###; "###;
const MODULE_BIN_TEMPLATE: &str = r###"use advent_of_code::dayDAYPAD::{part_one, part_two};
fn main() {
let input = &advent_of_code::read_file("inputs", DAY);
advent_of_code::solve!(1, part_one, input);
advent_of_code::solve!(2, part_two, input);
}
"###;
fn parse_args() -> Result<u8, pico_args::Error> { fn parse_args() -> Result<u8, pico_args::Error> {
let mut args = pico_args::Arguments::from_env(); let mut args = pico_args::Arguments::from_env();
args.free_from_str() args.free_from_str()
@ -53,6 +56,46 @@ fn create_file(path: &str) -> Result<File, std::io::Error> {
OpenOptions::new().write(true).create(true).open(path) OpenOptions::new().write(true).create(true).open(path)
} }
fn modify_lib(day: u8) -> Result<(), Error> {
let lib_path = "src/lib.rs";
let mut file = OpenOptions::new()
.read(true)
.write(true)
.create(false)
.open(lib_path)?;
let mut old_code = String::new();
file.read_to_string(&mut old_code)?;
file.rewind()?;
file.set_len(0)?;
match file.write_all(
old_code
.replace(
&format!("// pub mod day{:02};", day),
&format!("pub mod day{:02};", day),
)
.as_bytes(),
) {
Ok(_) => {
println!("Updated lib.rs to include 'day{:02}' module", day);
}
Err(e) => {
eprintln!(
"Failed to write updateded lib.rs to include 'day{:02}' module: {}",
day, e
);
process::exit(1);
}
}
file.flush()?;
Ok(())
}
fn main() { fn main() {
let day = match parse_args() { let day = match parse_args() {
Ok(day) => day, Ok(day) => day,
@ -66,22 +109,59 @@ fn main() {
let input_path = format!("src/inputs/{}.txt", day_padded); let input_path = format!("src/inputs/{}.txt", day_padded);
let example_path = format!("src/examples/{}.txt", day_padded); let example_path = format!("src/examples/{}.txt", day_padded);
let module_path = format!("src/bin/{}.rs", day_padded); let module_bin_path = format!("src/bin/{}.rs", day_padded);
let module_lib_path = format!("src/day{}.rs", day_padded);
let mut file = match safe_create_file(&module_path) { match modify_lib(day) {
Ok(_) => {}
Err(e) => {
eprintln!("Failed to update lib.rs file: {}", e);
process::exit(1);
}
}
let mut bin_file = match safe_create_file(&module_bin_path) {
Ok(file) => file, Ok(file) => file,
Err(e) => { Err(e) => {
eprintln!("Failed to create module file: {}", e); eprintln!("Failed to create module bin file: {}", e);
process::exit(1); process::exit(1);
} }
}; };
match file.write_all(MODULE_TEMPLATE.replace("DAY", &day.to_string()).as_bytes()) { match bin_file.write_all(
MODULE_BIN_TEMPLATE
.replace("DAYPAD", &day_padded)
.replace("DAY", &day.to_string())
.as_bytes(),
) {
Ok(_) => { Ok(_) => {
println!("Created module file \"{}\"", &module_path); println!("Created module bin file \"{}\"", &module_bin_path);
} }
Err(e) => { Err(e) => {
eprintln!("Failed to write module contents: {}", e); eprintln!("Failed to write bin module contents: {}", e);
process::exit(1);
}
}
let mut lib_file = match safe_create_file(&module_lib_path) {
Ok(file) => file,
Err(e) => {
eprintln!("Failed to create module lib file: {}", e);
process::exit(1);
}
};
match lib_file.write_all(
MODULE_LIB_TEMPLATE
.replace("DAYPAD", &day_padded)
.replace("DAY", &day.to_string())
.as_bytes(),
) {
Ok(_) => {
println!("Created module lib file \"{}\"", &module_bin_path);
}
Err(e) => {
eprintln!("Failed to write lib module contents: {}", e);
process::exit(1); process::exit(1);
} }
} }
@ -106,6 +186,17 @@ fn main() {
} }
} }
// We need to execute cargo clean -p advent_of_code otherwise there can be cache issues when executing cargo check
// As far as I can tell this relates to https://github.com/rust-lang/cargo/issues/6529
let clean_output = Command::new("cargo")
.args(["clean", "-p", "advent_of_code"])
.output()
.unwrap();
if !clean_output.status.success() {
eprint!("Failed to execute 'cargo clean -p advent_of_code'.");
}
println!("---"); println!("---");
println!( println!(
"🎄 Type `cargo solve {}` to run your solution.", "🎄 Type `cargo solve {}` to run your solution.",

View file

@ -6,6 +6,32 @@
use std::env; use std::env;
use std::fs; use std::fs;
// modules for the different days are automatically uncomented by the scaffold command
pub mod day01;
pub mod day02;
// pub mod day03;
// pub mod day04;
// pub mod day05;
// pub mod day06;
// pub mod day07;
// pub mod day08;
// pub mod day09;
// pub mod day10;
// pub mod day11;
// pub mod day12;
// pub mod day13;
// pub mod day14;
// pub mod day15;
// pub mod day16;
// pub mod day17;
// pub mod day18;
// pub mod day19;
// pub mod day20;
// pub mod day21;
// pub mod day22;
// pub mod day23;
// pub mod day24;
// pub mod day25;
pub mod helpers; pub mod helpers;
pub const ANSI_ITALIC: &str = "\x1b[3m"; pub const ANSI_ITALIC: &str = "\x1b[3m";