1extern crate proc_macro;
2
3mod parse;
4
5use std::env;
6
7use proc_macro2::Span;
8use proc_macro_hack::proc_macro_hack;
9use quote::quote;
10use syn::{parse_macro_input, Error};
11
12use crate::parse::AuthorsInput;
13
14#[proc_macro_hack]
15pub fn authors(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
16 let input = parse_macro_input!(input as AuthorsInput);
17
18 let authors: Vec<String> = match env::var_os("CARGO_PKG_AUTHORS").map_or_else(
19 || Err(format!("authors environment variable not found")),
20 |s| {
21 s.to_str()
22 .map(|s| s.trim().split(';').map(ToString::to_string).collect())
23 .ok_or_else(|| {
24 format!(
25 "authors environment variable is not valid unicode: {}",
26 s.to_string_lossy()
27 )
28 })
29 },
30 ) {
31 Ok(authors) => authors,
32 Err(err) => return Error::new(Span::call_site(), err).to_compile_error().into(),
33 };
34
35 let output = match input.join {
36 Some(join) => {
37 let s: String = authors.join(&join.value());
38 quote!(#s)
39 }
40 None => quote!(&[#(#authors),*]),
41 };
42
43 output.into()
44}