From 11b09e578c747a09fef640417ad000b14dc4abf2 Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Wed, 12 Jun 2019 15:10:25 +0200 Subject: [PATCH] router: parse an optional visibility The 'pub' in `pub static ROUTER: ...` Signed-off-by: Wolfgang Bumiller --- proxmox-api-macro/src/parsing.rs | 40 +++++++++++++++++++++++++++ proxmox-api-macro/src/router_macro.rs | 16 +++++++---- 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/proxmox-api-macro/src/parsing.rs b/proxmox-api-macro/src/parsing.rs index 4e80228b..8accc824 100644 --- a/proxmox-api-macro/src/parsing.rs +++ b/proxmox-api-macro/src/parsing.rs @@ -3,11 +3,51 @@ use std::collections::HashMap; use proc_macro2::{Delimiter, Group, Ident, Span, TokenStream, TokenTree}; use failure::{bail, Error}; +use quote::quote; use syn::{Expr, Lit}; pub type RawTokenIter = proc_macro2::token_stream::IntoIter; pub type TokenIter = std::iter::Peekable; +pub fn optional_visibility(tokens: &mut TokenIter) -> Result { + // peek: + if let Some(TokenTree::Ident(ident)) = tokens.peek() { + if ident.to_string() != "pub" { + return Ok(syn::Visibility::Inherited); + } + } else { + return Ok(syn::Visibility::Inherited); + } + + // consume: + let ident = match tokens.next().unwrap() { + TokenTree::Ident(ident) => ident, + _ => unreachable!(), + }; + + // peek: + let restriction = match tokens.peek() { + Some(TokenTree::Group(_)) => true, + _ => false, + }; + + let visibility = if restriction { + // consume: + match tokens.next().unwrap() { + TokenTree::Group(g) => { + quote! { #ident #g } + } + _ => unreachable!(), + } + } else { + quote! { #ident } + }; + + use syn::parse::Parser; + let parser = ::parse; + return Ok(parser.parse2(visibility)?); +} + pub fn match_keyword(tokens: &mut TokenIter, keyword: &'static str) -> Result<(), Error> { if let Some(tt) = tokens.next() { if let TokenTree::Ident(ident) = tt { diff --git a/proxmox-api-macro/src/router_macro.rs b/proxmox-api-macro/src/router_macro.rs index e6852fcd..5089aafb 100644 --- a/proxmox-api-macro/src/router_macro.rs +++ b/proxmox-api-macro/src/router_macro.rs @@ -18,6 +18,8 @@ pub fn router_macro(input: TokenStream) -> Result { break; } + let public = optional_visibility(&mut input)?; + match_keyword(&mut input, "static")?; let router_name = need_ident(&mut input)?; @@ -31,7 +33,7 @@ pub fn router_macro(input: TokenStream) -> Result { let content = need_group(&mut input, Delimiter::Brace)?; let router = parse_router(content.stream().into_iter().peekable())?; - let router = router.into_token_stream(&body_type, Some(router_name)); + let router = router.into_token_stream(&body_type, Some((router_name, public))); //eprintln!("{}", router.to_string()); @@ -175,7 +177,11 @@ impl Router { Ok(()) } - fn into_token_stream(self, body_type: &Ident, name: Option) -> TokenStream { + fn into_token_stream( + self, + body_type: &Ident, + name: Option<(Ident, syn::Visibility)>, + ) -> TokenStream { use std::iter::FromIterator; let mut out = quote_spanned! { @@ -225,14 +231,14 @@ impl Router { } } - if let Some(name) = name { + if let Some((name, vis)) = name { let type_name = Ident::new(&format!("{}_TYPE", name.to_string()), name.span()); let var_name = name; let router_expression = TokenStream::from_iter(out); quote! { #[allow(non_camel_case_types)] - struct #type_name( + #vis struct #type_name( std::cell::Cell>>, std::sync::Once, ); @@ -248,7 +254,7 @@ impl Router { } } } - static #var_name : #type_name = #type_name( + #vis static #var_name : #type_name = #type_name( std::cell::Cell::new(None), std::sync::Once::new(), );