#![recursion_limit = "256"]
extern crate proc_macro;
use std::iter::FromIterator;
use proc_macro::*;
#[rustfmt::skip]
mod gen;
#[proc_macro_attribute]
pub fn ctor(_attribute: TokenStream, item: TokenStream) -> TokenStream {
fn identify_item(item: TokenStream) -> String {
let mut next_is_name = false;
for token in item {
if let TokenTree::Ident(ident) = token {
let ident = ident.to_string();
if next_is_name {
return ident;
}
if ident == "fn" || ident == "static" {
next_is_name = true;
}
}
}
panic!("#[ctor] may only be applied to `fn` or `static` items");
}
let name = identify_item(item.clone());
generate(&name, "ctor", item)
}
#[proc_macro_attribute]
pub fn dtor(_attribute: TokenStream, item: TokenStream) -> TokenStream {
fn identify_item(item: TokenStream) -> String {
let mut next_is_name = false;
for token in item {
if let TokenTree::Ident(ident) = token {
let ident = ident.to_string();
if next_is_name {
return ident;
}
if ident == "fn" || ident == "static" {
next_is_name = true;
}
}
}
panic!("#[dtor] may only be applied to `fn` items");
}
let name = identify_item(item.clone());
generate(&name, "dtor", item)
}
fn generate(name: &str, ctor_type: &str, item: TokenStream) -> TokenStream {
use proc_macro::TokenTree as T;
let macros_name = format!("__rust_ctor_macros_{name}");
let mut macro_inner = TokenStream::from_iter([
T::Punct(Punct::new('#', Spacing::Alone)),
T::Group(Group::new(
Delimiter::Bracket,
TokenStream::from_iter([T::Ident(Ident::new(ctor_type, Span::call_site()))]),
)),
#[cfg(feature = "used_linker")]
T::Punct(Punct::new('#', Spacing::Alone)),
#[cfg(feature = "used_linker")]
T::Group(Group::new(
Delimiter::Bracket,
TokenStream::from_iter([
T::Ident(Ident::new("feature", Span::call_site())),
T::Group(Group::new(
Delimiter::Parenthesis,
TokenStream::from_iter([T::Ident(Ident::new(
"used_linker",
Span::call_site(),
))]),
)),
]),
)),
#[cfg(feature = "__warn_on_missing_unsafe")]
T::Punct(Punct::new('#', Spacing::Alone)),
#[cfg(feature = "__warn_on_missing_unsafe")]
T::Group(Group::new(
Delimiter::Bracket,
TokenStream::from_iter([
T::Ident(Ident::new("feature", Span::call_site())),
T::Group(Group::new(
Delimiter::Parenthesis,
TokenStream::from_iter([T::Ident(Ident::new(
"__warn_on_missing_unsafe",
Span::call_site(),
))]),
)),
]),
)),
T::Punct(Punct::new('#', Spacing::Alone)),
T::Group(Group::new(
Delimiter::Bracket,
TokenStream::from_iter([
T::Ident(Ident::new("macro_path", Span::call_site())),
T::Punct(Punct::new('=', Spacing::Alone)),
T::Ident(Ident::new(¯os_name, Span::call_site())),
]),
)),
]);
macro_inner.extend(item);
TokenStream::from_iter([
T::Ident(Ident::new(¯os_name, Span::call_site())),
T::Punct(Punct::new(':', Spacing::Joint)),
T::Punct(Punct::new(':', Spacing::Alone)),
T::Ident(Ident::new("ctor_parse", Span::call_site())),
T::Punct(Punct::new('!', Spacing::Alone)),
T::Group(Group::new(Delimiter::Parenthesis, macro_inner)),
T::Punct(Punct::new(';', Spacing::Alone)),
T::Ident(Ident::new("mod", Span::call_site())),
T::Ident(Ident::new(¯os_name, Span::call_site())),
T::Group(Group::new(Delimiter::Brace, gen::ctor())),
])
}