102 Zeilen
Kein EOL
2,8 KiB
Rust
102 Zeilen
Kein EOL
2,8 KiB
Rust
use proc_macro::TokenStream;
|
|
use quote::quote;
|
|
use syn::{
|
|
buffer::Cursor,
|
|
parse::{Parse, ParseStream, StepCursor},
|
|
Error,
|
|
};
|
|
use syn::{parse, LitInt, Result};
|
|
|
|
struct IncludeData {
|
|
year: String,
|
|
day: String,
|
|
}
|
|
|
|
fn get_string<'a, 'b>(cursor: StepCursor<'a, 'b>) -> Result<(String, Cursor<'a>)> {
|
|
let (lit, c) = match cursor.literal() {
|
|
Some(literal) => literal,
|
|
None => return Err(Error::new(cursor.span(), "Failed to get literal")),
|
|
};
|
|
let span = lit.span();
|
|
let text = match span.source_text() {
|
|
Some(text) => text,
|
|
None => {
|
|
let start = span.start();
|
|
let end = span.end();
|
|
return Err(Error::new(
|
|
span,
|
|
format!(
|
|
"Failed to get sourcetext for {}:{}-{}:{}",
|
|
start.line, start.column, end.line, end.column,
|
|
),
|
|
));
|
|
}
|
|
};
|
|
Ok((text, c))
|
|
}
|
|
|
|
impl Parse for IncludeData {
|
|
fn parse(input: ParseStream) -> Result<Self> {
|
|
let mut data = IncludeData {
|
|
year: "".into(),
|
|
day: "".into(),
|
|
};
|
|
let mut look = input.lookahead1();
|
|
if !look.peek(LitInt) {
|
|
let s = input.span();
|
|
return Err(Error::new(
|
|
s,
|
|
format!("{} is not an valid Year", s.source_text().unwrap()),
|
|
));
|
|
}
|
|
data.year = input.step(get_string).expect("Wanted an string");
|
|
look = input.lookahead1();
|
|
if !look.peek(LitInt) {
|
|
let s = input.span();
|
|
return Err(Error::new(
|
|
s,
|
|
format!("{} is not an valid Day", s.source_text().unwrap()),
|
|
));
|
|
}
|
|
data.day = input.step(get_string).expect("Wanted an string");
|
|
Ok(data)
|
|
}
|
|
}
|
|
|
|
fn get_stream(dir: &str, data: Result<IncludeData>) -> TokenStream {
|
|
match data {
|
|
Ok(id) => {
|
|
let path = format!("../../../{}/{}/{}.txt", dir, id.year, id.day);
|
|
quote! {
|
|
static DATA: &str = include_str!(#path);
|
|
}
|
|
}
|
|
Err(_)=> {
|
|
quote! {
|
|
static DATA: &str = "";
|
|
}
|
|
}
|
|
}.into()
|
|
}
|
|
|
|
/// includes Data from Advent of code
|
|
/// ```ignore (cannot-doctest-external-file-dependency)
|
|
/// include_data!(2015 01)
|
|
///
|
|
/// fn main() {
|
|
/// print!("{DATA}");
|
|
/// }
|
|
/// ```
|
|
/// The Equivalent is
|
|
/// ```ignore (cannot-doctest-external-file-dependency)
|
|
/// static DATA: &str = include_str!("../../../data/2015/01.txt");
|
|
/// ```
|
|
#[proc_macro]
|
|
pub fn include_data(data: TokenStream) -> TokenStream {
|
|
get_stream("data", parse::<IncludeData>(data))
|
|
}
|
|
|
|
#[proc_macro]
|
|
pub fn include_example(data: TokenStream)->TokenStream {
|
|
get_stream("examples", parse::<IncludeData>(data))
|
|
} |