git.delta.rocks / unique-network / refs/commits / b2966bbee392

difftreelog

source

pallets/evm-coder-substrate/procedural/src/lib.rs3.4 KiBsourcehistory
1use std::result;23use proc_macro2::{Ident, TokenStream};4use quote::quote;5use syn::{6	parenthesized,7	parse::{Parse, ParseBuffer},8	spanned::Spanned,9	Attribute, Data, DeriveInput, Error, Expr,10};1112type Result<T = TokenStream, E = syn::Error> = result::Result<T, E>;1314fn parse_attr<A: Parse, I>(attrs: &[Attribute], ident: I) -> Result<Option<A>>15where16	Ident: PartialEq<I>,17{18	let attrs = attrs19		.iter()20		.filter(|a| a.path.is_ident(&ident))21		.collect::<Vec<_>>();22	if attrs.len() > 1 {23		return Err(Error::new(24			attrs[1].span(),25			"this attribute may be specified only once",26		));27	} else if attrs.is_empty() {28		return Ok(None);29	}30	let attr = attrs[0];3132	let parsed = syn::parse2(attr.tokens.clone())?;33	Ok(Some(parsed))34}3536struct WeightAttr {37	handler: Expr,38}39impl Parse for WeightAttr {40	fn parse(input: &ParseBuffer) -> Result<Self> {41		let expr;42		parenthesized!(expr in input);43		let handler = Expr::parse(&expr)?;4445		Ok(Self { handler })46	}47}4849#[proc_macro_derive(PreDispatch, attributes(pre_dispatch, weight))]50pub fn derive_predispatch(item: proc_macro::TokenStream) -> proc_macro::TokenStream {51	fn inner(input: DeriveInput) -> Result {52		let (impl_generics, ty_generics, _where_clause) = input.generics.split_for_impl();53		let ident = &input.ident;54		let Data::Enum(data) = &input.data else {55			return Err(Error::new_spanned(input, "PreDispatch input is enum"));56		};5758		let matching = data59			.variants60			.iter()61			.map(|var| {62				let name = &var.ident;63				let handler = match &var.fields {64					syn::Fields::Named(named) => {65						if let Some(weight) = parse_attr::<WeightAttr, _>(&var.attrs, "weight")? {66							let weight = &weight.handler;67							let fields = named.named.iter().flat_map(|n| &n.ident);68							quote! {69								{#(#fields,)*} => {70									::pallet_evm_coder_substrate::execution::DispatchInfo {71										weight: ::pallet_evm_coder_substrate::execution::Weight::from(#weight),72									}73								}74							}75						} else {76							quote! {77								{..} => {78									::pallet_evm_coder_substrate::execution::DispatchInfo {79										weight: ::pallet_evm_coder_substrate::execution::Weight::zero()80									}81								}82							}83						}84					}85					syn::Fields::Unit => {86						if let Some(weight) = parse_attr::<WeightAttr, _>(&var.attrs, "weight")? {87							let weight = &weight.handler;88							quote! {89								=> {90									::pallet_evm_coder_substrate::execution::DispatchInfo {91										weight: ::pallet_evm_coder_substrate::execution::Weight::from(#weight),92									}93								}94							}95						} else {96							quote! {97								=> {98									::pallet_evm_coder_substrate::execution::DispatchInfo {99										weight: ::pallet_evm_coder_substrate::execution::Weight::zero()100									}101								}102							}103						}104					}105					syn::Fields::Unnamed(_) => {106						quote! {107							(call, ..) => {108								call.dispatch_info()109							}110						}111					}112				};113				Ok(quote! {114					Self::#name #handler,115				})116			})117			.collect::<Result>()?;118119		Ok(quote! {120			#[allow(unused_variables)]121			impl #impl_generics ::pallet_evm_coder_substrate::execution::PreDispatch for #ident #ty_generics where T: crate::Config {122				fn dispatch_info(&self) -> ::pallet_evm_coder_substrate::execution::DispatchInfo {123					match self {124						#matching125					}126				}127			}128		})129	}130	let item = syn::parse_macro_input!(item as DeriveInput);131	match inner(item) {132		Ok(o) => o.into(),133		Err(e) => e.into_compile_error().into(),134	}135}