1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
#![cfg_attr(not(feature="std"), no_std)] extern crate proc_macro; extern crate syn; extern crate quote; use proc_macro::TokenStream; use proc_macro2::{Ident, Span}; use syn::buffer::TokenBuffer; use quote::quote; #[cfg(feature="std")] use std::hash::{Hash, Hasher}; #[cfg(not(feature="std"))] extern crate alloc; #[cfg(not(feature="std"))] use alloc::vec::Vec; #[cfg(not(feature="std"))] use alloc::string::ToString; #[cfg(not(feature="std"))] use core::hash::{Hash, Hasher}; #[proc_macro] pub fn setup_names(input: TokenStream) -> TokenStream { let mut names = Vec::new(); let mut name_idents = Vec::new(); let mut hashes = Vec::new(); let buffer = TokenBuffer::new(input); let mut cursor = buffer.begin(); while !cursor.eof() { if let Some((ident, cur)) = cursor.ident() { let s = ident.to_string(); let mut hasher = hashers::fnv::FNV1aHasher64::default(); s.hash(&mut hasher); names.push(s.clone()); name_idents.push(Ident::new(&s, Span::call_site())); hashes.push(hasher.finish()); cursor = cur; if cursor.eof() { break; } if let Some((p, cur)) = cursor.punct() { if p.as_char() != ',' { panic!("Expected comma-separated list of idents. Unexpected token: {}", p.as_char()); } cursor = cur; } else { panic!("Expected comma-separated list of idents. Unexpected token: {}", cursor.token_tree().unwrap().0.to_string()); } } else { panic!("Expected comma-separated list of idents. Unexpected token: {}", cursor.token_tree().unwrap().0.to_string()); } } let retval = quote! { use std::collections::hash_map::DefaultHasher; use std::hash::BuildHasherDefault; use hashbrown::HashMap; #(pub const #name_idents: u64 = #hashes;)* lazy_static!{ pub static ref hashes_to_names: HashMap<u64, String, BuildHasherDefault<DefaultHasher>> = { let mut map = HashMap::default(); #(map.insert(#hashes, #names .to_string());)* map }; } pub fn to_string(hash: u64) -> String { hashes_to_names.get(&hash).unwrap().clone() } }; retval.into() }