router: parse an optional visibility

The 'pub' in `pub static ROUTER: ...`

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2019-06-12 15:10:25 +02:00
parent 841799d882
commit 11b09e578c
2 changed files with 51 additions and 5 deletions

View File

@ -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<RawTokenIter>;
pub fn optional_visibility(tokens: &mut TokenIter) -> Result<syn::Visibility, Error> {
// 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 = <syn::Visibility as syn::parse::Parse>::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 {

View File

@ -18,6 +18,8 @@ pub fn router_macro(input: TokenStream) -> Result<TokenStream, Error> {
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<TokenStream, Error> {
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<Ident>) -> 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<Option<::proxmox::api::Router<#body_type>>>,
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(),
);