1ea88969fSopenharmony_ciuse crate::{Error, Result}; 2ea88969fSopenharmony_ciuse proc_macro2::{Ident, Span, TokenStream, TokenTree}; 3ea88969fSopenharmony_ci 4ea88969fSopenharmony_cimacro_rules! decl_settings { 5ea88969fSopenharmony_ci ($($val:expr => $variant:ident),+ $(,)*) => { 6ea88969fSopenharmony_ci #[derive(PartialEq)] 7ea88969fSopenharmony_ci pub(crate) enum Setting { 8ea88969fSopenharmony_ci $($variant),* 9ea88969fSopenharmony_ci } 10ea88969fSopenharmony_ci 11ea88969fSopenharmony_ci fn ident_to_setting(ident: Ident) -> Result<Setting> { 12ea88969fSopenharmony_ci match &*ident.to_string() { 13ea88969fSopenharmony_ci $($val => Ok(Setting::$variant),)* 14ea88969fSopenharmony_ci _ => { 15ea88969fSopenharmony_ci let possible_vals = [$($val),*] 16ea88969fSopenharmony_ci .iter() 17ea88969fSopenharmony_ci .map(|v| format!("`{}`", v)) 18ea88969fSopenharmony_ci .collect::<Vec<_>>() 19ea88969fSopenharmony_ci .join(", "); 20ea88969fSopenharmony_ci 21ea88969fSopenharmony_ci Err(Error::new( 22ea88969fSopenharmony_ci ident.span(), 23ea88969fSopenharmony_ci format!("unknown setting `{}`, expected one of {}", ident, possible_vals))) 24ea88969fSopenharmony_ci } 25ea88969fSopenharmony_ci } 26ea88969fSopenharmony_ci } 27ea88969fSopenharmony_ci }; 28ea88969fSopenharmony_ci} 29ea88969fSopenharmony_ci 30ea88969fSopenharmony_cidecl_settings! { 31ea88969fSopenharmony_ci "assert_unwind_safe" => AssertUnwindSafe, 32ea88969fSopenharmony_ci "allow_not_macro" => AllowNotMacro, 33ea88969fSopenharmony_ci "proc_macro_hack" => ProcMacroHack, 34ea88969fSopenharmony_ci} 35ea88969fSopenharmony_ci 36ea88969fSopenharmony_cipub(crate) fn parse_settings(input: TokenStream) -> Result<Settings> { 37ea88969fSopenharmony_ci let mut input = input.into_iter(); 38ea88969fSopenharmony_ci let mut res = Settings(Vec::new()); 39ea88969fSopenharmony_ci loop { 40ea88969fSopenharmony_ci match input.next() { 41ea88969fSopenharmony_ci Some(TokenTree::Ident(ident)) => { 42ea88969fSopenharmony_ci res.0.push(ident_to_setting(ident)?); 43ea88969fSopenharmony_ci } 44ea88969fSopenharmony_ci None => return Ok(res), 45ea88969fSopenharmony_ci other => { 46ea88969fSopenharmony_ci let span = other.map_or(Span::call_site(), |tt| tt.span()); 47ea88969fSopenharmony_ci return Err(Error::new(span, "expected identifier".to_string())); 48ea88969fSopenharmony_ci } 49ea88969fSopenharmony_ci } 50ea88969fSopenharmony_ci 51ea88969fSopenharmony_ci match input.next() { 52ea88969fSopenharmony_ci Some(TokenTree::Punct(ref punct)) if punct.as_char() == ',' => {} 53ea88969fSopenharmony_ci None => return Ok(res), 54ea88969fSopenharmony_ci other => { 55ea88969fSopenharmony_ci let span = other.map_or(Span::call_site(), |tt| tt.span()); 56ea88969fSopenharmony_ci return Err(Error::new(span, "expected `,`".to_string())); 57ea88969fSopenharmony_ci } 58ea88969fSopenharmony_ci } 59ea88969fSopenharmony_ci } 60ea88969fSopenharmony_ci} 61ea88969fSopenharmony_ci 62ea88969fSopenharmony_cipub(crate) struct Settings(Vec<Setting>); 63ea88969fSopenharmony_ci 64ea88969fSopenharmony_ciimpl Settings { 65ea88969fSopenharmony_ci pub(crate) fn is_set(&self, setting: Setting) -> bool { 66ea88969fSopenharmony_ci self.0.iter().any(|s| *s == setting) 67ea88969fSopenharmony_ci } 68ea88969fSopenharmony_ci 69ea88969fSopenharmony_ci pub(crate) fn set(&mut self, setting: Setting) { 70ea88969fSopenharmony_ci self.0.push(setting) 71ea88969fSopenharmony_ci } 72ea88969fSopenharmony_ci} 73