Files
pezkuwi-subxt/polkadot/node/overseer/overseer-gen/proc-macro/src/parse_attr.rs
T
Shawn Tabrizi ff5d56fb76 cargo +nightly fmt (#3540)
* cargo +nightly fmt

* add cargo-fmt check to ci

* update ci

* fmt

* fmt

* skip macro

* ignore bridges
2021-08-02 10:47:33 +00:00

218 lines
7.3 KiB
Rust

// Copyright 2021 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.
// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
use proc_macro2::Span;
use quote::{quote, ToTokens};
use std::collections::{hash_map::RandomState, HashMap};
use syn::{
parse::{Parse, ParseBuffer},
punctuated::Punctuated,
spanned::Spanned,
Error, Ident, LitInt, Path, Result, Token,
};
mod kw {
syn::custom_keyword!(event);
syn::custom_keyword!(signal);
syn::custom_keyword!(error);
syn::custom_keyword!(network);
syn::custom_keyword!(outgoing);
syn::custom_keyword!(gen);
syn::custom_keyword!(signal_capacity);
syn::custom_keyword!(message_capacity);
}
#[derive(Clone, Debug)]
enum OverseerAttrItem {
ExternEventType { tag: kw::event, eq_token: Token![=], value: Path },
ExternNetworkType { tag: kw::network, eq_token: Token![=], value: Path },
ExternOverseerSignalType { tag: kw::signal, eq_token: Token![=], value: Path },
ExternErrorType { tag: kw::error, eq_token: Token![=], value: Path },
OutgoingType { tag: kw::outgoing, eq_token: Token![=], value: Path },
MessageWrapperName { tag: kw::gen, eq_token: Token![=], value: Ident },
SignalChannelCapacity { tag: kw::signal_capacity, eq_token: Token![=], value: usize },
MessageChannelCapacity { tag: kw::message_capacity, eq_token: Token![=], value: usize },
}
impl ToTokens for OverseerAttrItem {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
let ts = match self {
Self::ExternEventType { tag, eq_token, value } => {
quote! { #tag #eq_token, #value }
},
Self::ExternNetworkType { tag, eq_token, value } => {
quote! { #tag #eq_token, #value }
},
Self::ExternOverseerSignalType { tag, eq_token, value } => {
quote! { #tag #eq_token, #value }
},
Self::ExternErrorType { tag, eq_token, value } => {
quote! { #tag #eq_token, #value }
},
Self::OutgoingType { tag, eq_token, value } => {
quote! { #tag #eq_token, #value }
},
Self::MessageWrapperName { tag, eq_token, value } => {
quote! { #tag #eq_token, #value }
},
Self::SignalChannelCapacity { tag, eq_token, value } => {
quote! { #tag #eq_token, #value }
},
Self::MessageChannelCapacity { tag, eq_token, value } => {
quote! { #tag #eq_token, #value }
},
};
tokens.extend(ts.into_iter());
}
}
impl Parse for OverseerAttrItem {
fn parse(input: &ParseBuffer) -> Result<Self> {
let lookahead = input.lookahead1();
if lookahead.peek(kw::event) {
Ok(OverseerAttrItem::ExternEventType {
tag: input.parse::<kw::event>()?,
eq_token: input.parse()?,
value: input.parse()?,
})
} else if lookahead.peek(kw::signal) {
Ok(OverseerAttrItem::ExternOverseerSignalType {
tag: input.parse::<kw::signal>()?,
eq_token: input.parse()?,
value: input.parse()?,
})
} else if lookahead.peek(kw::error) {
Ok(OverseerAttrItem::ExternErrorType {
tag: input.parse::<kw::error>()?,
eq_token: input.parse()?,
value: input.parse()?,
})
} else if lookahead.peek(kw::network) {
Ok(OverseerAttrItem::ExternNetworkType {
tag: input.parse::<kw::network>()?,
eq_token: input.parse()?,
value: input.parse()?,
})
} else if lookahead.peek(kw::outgoing) {
Ok(OverseerAttrItem::OutgoingType {
tag: input.parse::<kw::outgoing>()?,
eq_token: input.parse()?,
value: input.parse()?,
})
} else if lookahead.peek(kw::gen) {
Ok(OverseerAttrItem::MessageWrapperName {
tag: input.parse::<kw::gen>()?,
eq_token: input.parse()?,
value: input.parse()?,
})
} else if lookahead.peek(kw::signal_capacity) {
Ok(OverseerAttrItem::SignalChannelCapacity {
tag: input.parse::<kw::signal_capacity>()?,
eq_token: input.parse()?,
value: input.parse::<LitInt>()?.base10_parse::<usize>()?,
})
} else if lookahead.peek(kw::message_capacity) {
Ok(OverseerAttrItem::MessageChannelCapacity {
tag: input.parse::<kw::message_capacity>()?,
eq_token: input.parse()?,
value: input.parse::<LitInt>()?.base10_parse::<usize>()?,
})
} else {
Err(lookahead.error())
}
}
}
/// Attribute arguments
#[derive(Clone, Debug)]
pub(crate) struct AttrArgs {
pub(crate) message_wrapper: Ident,
pub(crate) extern_event_ty: Path,
pub(crate) extern_signal_ty: Path,
pub(crate) extern_error_ty: Path,
/// A external subsystem that both consumes and produces messages
/// but is not part of the band of subsystems, it's a mere proxy
/// to another entity that consumes/produces messages.
pub(crate) extern_network_ty: Option<Path>,
pub(crate) outgoing_ty: Option<Path>,
pub(crate) signal_channel_capacity: usize,
pub(crate) message_channel_capacity: usize,
}
macro_rules! extract_variant {
($unique:expr, $variant:ident ; default = $fallback:expr) => {
extract_variant!($unique, $variant).unwrap_or_else(|| $fallback)
};
($unique:expr, $variant:ident ; err = $err:expr) => {
extract_variant!($unique, $variant).ok_or_else(|| Error::new(Span::call_site(), $err))
};
($unique:expr, $variant:ident) => {
$unique.values().find_map(|item| {
if let OverseerAttrItem::$variant { value, .. } = item {
Some(value.clone())
} else {
None
}
})
};
}
impl Parse for AttrArgs {
fn parse(input: &ParseBuffer) -> Result<Self> {
let items: Punctuated<OverseerAttrItem, Token![,]> =
input.parse_terminated(OverseerAttrItem::parse)?;
let mut unique = HashMap::<
std::mem::Discriminant<OverseerAttrItem>,
OverseerAttrItem,
RandomState,
>::default();
for item in items {
if let Some(first) = unique.insert(std::mem::discriminant(&item), item.clone()) {
let mut e = Error::new(
item.span(),
format!("Duplicate definition of overseer generation type found"),
);
e.combine(Error::new(first.span(), "previously defined here."));
return Err(e)
}
}
let signal_channel_capacity =
extract_variant!(unique, SignalChannelCapacity; default = 64_usize);
let message_channel_capacity =
extract_variant!(unique, MessageChannelCapacity; default = 1024_usize);
let error = extract_variant!(unique, ExternErrorType; err = "Must declare the overseer error type via `error=..`.")?;
let event = extract_variant!(unique, ExternEventType; err = "Must declare the overseer event type via `event=..`.")?;
let signal = extract_variant!(unique, ExternOverseerSignalType; err = "Must declare the overseer signal type via `span=..`.")?;
let message_wrapper = extract_variant!(unique, MessageWrapperName; err = "Must declare the overseer generated wrapping message type via `gen=..`.")?;
let network = extract_variant!(unique, ExternNetworkType);
let outgoing = extract_variant!(unique, OutgoingType);
Ok(AttrArgs {
signal_channel_capacity,
message_channel_capacity,
extern_event_ty: event,
extern_signal_ty: signal,
extern_error_ty: error,
extern_network_ty: network,
outgoing_ty: outgoing,
message_wrapper,
})
}
}