use proc_macro::TokenStream;
use quote::quote;
use syn::{
Ident, Path, Result, Token,
parse::{Parse, ParseStream},
};
struct SetupInput {
components: Option<Path>,
primaries: Option<Path>,
sequences: Option<Path>,
}
impl Parse for SetupInput {
fn parse(input: ParseStream) -> Result<Self> {
let mut components = None;
let mut primaries = None;
let mut sequences = None;
while !input.is_empty() {
let key: Ident = input.parse()?;
input.parse::<Token![=]>()?;
let path: Path = input.parse()?;
if input.peek(Token![,]) {
input.parse::<Token![,]>()?;
}
match key.to_string().as_str() {
"components" => {
if components.is_some() {
return Err(syn::Error::new(key.span(), "duplicate 'components' key"));
}
components = Some(path);
}
"primaries" => {
if primaries.is_some() {
return Err(syn::Error::new(key.span(), "duplicate 'primaries' key"));
}
primaries = Some(path);
}
"sequences" => {
if sequences.is_some() {
return Err(syn::Error::new(key.span(), "duplicate 'sequences' key"));
}
sequences = Some(path);
}
other => {
return Err(syn::Error::new(
key.span(),
format!(
"unknown key '{}'. Expected: components, primaries, or sequences",
other
),
));
}
}
}
Ok(SetupInput {
components,
primaries,
sequences,
})
}
}
pub fn expand(input: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(input as SetupInput);
let components_use = match &input.components {
Some(path) => quote! { pub use #path as components; },
None => quote! { pub use crate::components as components; },
};
let primaries_use = match &input.primaries {
Some(path) => quote! { pub use #path as primaries; },
None => quote! { pub use crate::primaries as primaries; },
};
let sequences_use = match &input.sequences {
Some(path) => quote! { pub use #path as sequences; },
None => quote! { pub use crate::sequences as sequences; },
};
let output = quote! {
#[doc(hidden)]
pub mod __wd_paths {
#components_use
#primaries_use
#sequences_use
}
};
TokenStream::from(output)
}