1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
#![recursion_limit = "128"]
extern crate aoc_runner_internal;
extern crate core;
extern crate proc_macro;
extern crate proc_macro2;
extern crate quote;
extern crate syn;
mod generator;
mod map;
mod out;
mod runner;
mod types;
mod utils;
use crate::map::Map;
use crate::utils::is_rls;
use proc_macro as pm;
use proc_macro2 as pm2;
use quote::quote;
thread_local! {
static AOC_RUNNER: Map = Map::new();
}
#[proc_macro_attribute]
/// # Solution meta
///
/// Use this to flag a function as a solution for a given day :
/// `#[aoc(day1, part1)]`
///
/// You can also add a custom name to the function :
/// `#[aoc(day1, part1, Bytes)]`, it's useful to have multiple solutions to a given day & part and compare them !
///
/// The function must take a single parameter : a `&str` or a `&[u8]`, unless you use a [generator]
/// and return any type implementing `Display`.
///
/// ## Results & Options
///
/// Since 0.2.0, you can output `Result` & `Option` from solution function, with the following constraints :
/// - the output type must be named `Result` or `Option`, `type CustomResult<T> = Result<T, CustomError>;` cannot be used in return position.
/// - the first generic parameter must implement `Display`
/// - for `Result`s, the error must implement `Into<std::error::Error>`
///
/// You still can use a path before the `Result`/`Option`, like this : `std::io::Result<i32>`
///
/// [generator]: attr.aoc_generator.html
pub fn aoc(args: pm::TokenStream, input: pm::TokenStream) -> pm::TokenStream {
if is_rls() {
let input: pm2::TokenStream = input.into();
return pm::TokenStream::from(quote! {
#[allow(unused)]
#input
});
}
runner::runner_impl(args, input)
}
#[proc_macro_attribute]
/// # Generator meta
///
/// Use a generator when you need to pre-process your input :
///
/// ## Usage
/// Generator meta have 3 forms :
/// - a generator for the whole day : `#[aoc_generator(day1)]`
/// - a generator for a single part : `#[aoc_generator(day1, part1)]`
/// - a generator for a single (named) solution: `#[aoc_generator(day1, part1, Bytes)]`
///
/// The function must take a single parameter : a `&str` or a `&[u8]`, and output any sized type.
///
/// The corresponding solutions now take any parameter for which `Borrow` is implemented.
///
/// ## Results & Options
///
/// Since 0.2.0, you can output `Result` & `Option` from generator function, with the following constraints :
/// - the output type must be named `Result` or `Option`, `type CustomResult<T> = Result<T, CustomError>;` cannot be used in return position.
/// - for `Result`s, the error must implement `Into<std::error::Error>`
///
/// You still can use a path before the `Result`/`Option`, like this : `std::io::Result<i32>`
///
/// ## Note
/// A generator must be declared before it's solutions.
///
pub fn aoc_generator(args: pm::TokenStream, input: pm::TokenStream) -> pm::TokenStream {
if is_rls() {
let input: pm2::TokenStream = input.into();
return pm::TokenStream::from(quote! {
#[allow(unused)]
#input
});
}
generator::generator_impl(args, input)
}
#[proc_macro]
/// # Library declaration
///
/// This macro must be at the end of lib.rs
///
/// ## Usage
/// `aoc_lib! { year = 2018 }`
pub fn aoc_lib(input: pm::TokenStream) -> pm::TokenStream {
if is_rls() {
return pm::TokenStream::new();
}
out::lib_impl(input)
}
#[proc_macro]
/// # Main declaration
///
/// This macro must be at the end of main.rs
///
/// ## Usage
/// `aoc_main` has 2 forms :
/// - as a standalone binary : `aoc_main! { year = 2018 }`
/// - as a link to a library : `aoc_main! { lib = advent_of_code_2018 }` (you must had `extern crate advent_of_code_2018;` before)
pub fn aoc_main(input: pm::TokenStream) -> pm::TokenStream {
if is_rls() {
return pm::TokenStream::from(quote! { fn main() {} });
}
out::main_impl(input)
}