This document describes the high-level architecture of advent_of_code_traits. If you want to familiarize yourself with the code base, you are just in the right place!
This crate uses const generics to impl Solution<Day, Part> where Day is a u32 and Part is a u8.
For readability and convenience, consts Day1..=25 are exported, as well as consts for Part1, Part2.
Days are generated by build.rs so you won't actually see them defined in src/. They are just u32s.
Part1 and Part2 are defined in lib.rs as u8s which helps to avoid mixing them up with Days.
This crate also uses 'autoderef specialization' for ergonomics and performance when running the solution.
Currently this crate is surprisingly simple.
src/lib.rs contains:
- the traits to be implemented by users:
Solution<Day, Part>- One implementation per day, per part.ParseInput<Day, Part>- One implementation per day, per part.
- the trait piecing everything together:
SolutionRunner<Day>
- the consts:
days::*- Day1 to Day25- Part1, Part2
src/specialization.rs contains:
- the autoderef specialized implementations of
SolutionRunnerfor types implementingSolutionandParseInput - the blanket impl of
Solutionfor&TwhereT: Solution, and the same treatment forParseInput - see the docs for the specialization module for more info
This trait is used to parse input into user-defined types before they run their solutions on them.
It defines the associated type and method:
Parsedparse_input
The user may implement ParseInput for Part1 of a day and use the same input type for part2 of the same day, thanks to specialization!
Or the user may decide they need a different type for each part.
In that case they will simply implement ParseInput for both Part1 and Part2.
The Solution trait is the star of the show! Users will implement this trait with their solutions to Advent of Code.
It has two associated types and one required method:
Input- the input type as parsed by ParseInputOutput- the output type, required to impl Debug so it can be printedsolve- the user's solution
Solution is used by SolutionRunner, which orchestrates the user defined traits.
This trait isn't intended to be implemented by end users.
We provide a blanket implementation for types implementing Solution and ParseInput.
More than that, we provide multiple implementations which carefully avoid overlapping. Autoderef specialization is used to prefer the most efficient/complete implementation.
Look at the docs for the specialization module to learn more.