extern crate argparse; use std::io; use std::io::{BufRead, BufReader, Error, ErrorKind}; use std::fs::File; use std::process::exit; use argparse::{ArgumentParser, StoreTrue, Store}; mod day1; mod day2; mod day3; fn day_switch(day: i32, reader: T) -> io::Result<()> { match day { 1 => day1::main(reader), 2 => day2::main(reader), 3 => day3::main(reader), _ => Err(Error::new(ErrorKind::Other, "Invalid day")) } } struct Options { use_stdin: bool, } fn run_day(day: i32, opts: &Options) -> io::Result<()> { if opts.use_stdin { let stdin = io::stdin(); day_switch(day, BufReader::new(stdin)) } else { match File::open(format!("../input/{}.txt", day)) { Ok(f) => day_switch(day, BufReader::new(f)), Err(_) => Err(Error::new(ErrorKind::Other, format!("No input file for day {}", day))) } } } fn error_handler(func: F) -> io::Result<()> where F: Fn() -> io::Result<()> { match func() { Ok(()) => Ok(()), Err(err) => { if err.kind() == ErrorKind::Other { println!("Error: {}", err); exit(1) } else { Err(err) } } } } fn main() -> io::Result<()> { let mut day_string = String::new(); let mut options = Options { use_stdin: false }; { let mut parser = ArgumentParser::new(); parser.set_description("AOC 2018 solutions by Tom Smeding"); parser.refer(&mut options.use_stdin) .add_option(&["-s", "--stdin"], StoreTrue, "Read from stdin"); parser.refer(&mut day_string) .add_argument("day", Store, "Day to execute"); parser.parse_args_or_exit(); } error_handler(|| if day_string.len() == 0 { for day in 1..4 { run_day(day, &options)?; } Ok(()) } else { match day_string.parse::() { Ok(day) => run_day(day, &options), Err(_) => { println!("Invalid day argument"); exit(1) } } } ) }