#![cfg_attr(feature = "nightly", doc = "# #![feature(underscore_const_names)]")]
#![cfg_attr(feature = "nightly", doc = "```")]
#![cfg_attr(not(feature = "nightly"), doc = "```ignore")]
extern crate proc_macro;
use proc_macro::*;
#[cfg(not(feature = "nightly"))]
fn span_id(span: &Span) -> String {
fn bytes_of<T>(val: &T) -> &[u8] {
let ptr = val as *const T as *const u8;
let len = std::mem::size_of::<T>();
unsafe { std::slice::from_raw_parts(ptr, len) }
}
let table: &[u8; 16] = b"0123456789ABCDEF";
let bytes = bytes_of(span);
let mut id = b"_EXCLUSIVE_".to_vec();
id.reserve_exact(bytes.len() * 2);
for &byte in bytes {
let byte = byte as usize;
id.push(table[byte % 16]);
id.push(table[(byte >> 4) % 16]);
}
unsafe { String::from_utf8_unchecked(id) }
}
#[cfg_attr(feature = "nightly", doc = "# #![feature(underscore_const_names)]")]
#[proc_macro]
pub fn exclusive(input: TokenStream) -> TokenStream {
let call_site = Span::call_site();
#[cfg(feature = "nightly")]
let const_name = "_";
#[cfg(not(feature = "nightly"))]
let const_name = span_id(&call_site);
vec![
TokenTree::Ident(Ident::new("const", call_site)),
TokenTree::Ident(Ident::new(&*const_name, call_site)),
TokenTree::Punct(Punct::new(':', Spacing::Alone)),
TokenTree::Ident(Ident::new("fn", call_site)),
TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
TokenTree::Punct(Punct::new('-', Spacing::Joint)),
TokenTree::Punct(Punct::new('>', Spacing::Joint)),
TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
TokenTree::Punct(Punct::new('=', Spacing::Alone)),
TokenTree::Punct(Punct::new('|', Spacing::Joint)),
TokenTree::Punct(Punct::new('|', Spacing::Joint)),
TokenTree::Group(Group::new(Delimiter::Brace, input)),
TokenTree::Punct(Punct::new(';', Spacing::Alone)),
].into_iter().collect()
}