aoc-next 0.1.0

Helper library for Advent of Code. Inspired by cargo-aoc.
Documentation
// SPDX-FileCopyrightText: 2020 Florian Warzecha <liketechnik@disroot.org>
//
// SPDX-License-Identifier: MPL-2.0

use crate::Aoc;
use std::marker::PhantomData;
use std::time::Instant;

use anyhow::Result;

use crate::input::get_input;
use crate::parser::Parsing;

/// A container that can get input, parse it and execute a solver.
///
/// Implemented by [`Solution`].
pub trait Solvable {
    fn run(&self, aoc: &Aoc) -> Result<()>;
    fn day(&self) -> u8;
}

/// A solution for a specific exercise.
pub struct Solution<P, S, I, O: std::fmt::Display>
where
    P: Parsing<I>,
    S: Fn(I) -> O,
{
    /// The day of the exercise; used to determine the input to use.
    pub day: u8,
    /// The parser for the input.
    pub parser: P,
    /// The solver of the exercise.
    pub solver: Solver<S, I, O>,
}

impl<P, S, I, O: std::fmt::Display> Solvable for Solution<P, S, I, O>
where
    P: Parsing<I>,
    S: Fn(I) -> O,
{
    fn run(&self, aoc: &Aoc) -> Result<()> {
        let input = get_input(aoc, self.day)?;

        print!(
            "Day {} - {} with {}: ",
            self.day,
            self.solver.name,
            self.parser.name()
        );

        let parse_start = Instant::now();
        let parsed_input = self.parser.run(&input);
        let parse_end = Instant::now();

        match parsed_input {
            Ok(parsed_input) => {
                let run_start = Instant::now();
                let result = (self.solver.run)(parsed_input);
                let run_end = Instant::now();

                println!("{}", result);
                println!("\tparser: {:?}", parse_end - parse_start);
                println!("\tsolver: {:?}", run_end - run_start);
            }
            Err(e) => eprintln!("Parser failed: {}", e),
        }

        Ok(())
    }

    fn day(&self) -> u8 {
        self.day
    }
}

/// Container for a solving function.
///
/// The contained function solves a specific
/// exercise.
pub struct Solver<F, I, O: std::fmt::Display>
where
    F: Fn(I) -> O,
{
    pub marker: PhantomData<I>,
    pub name: &'static str,
    pub run: F,
}