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