use super::Selector;
use crate::{
ast,
ast::MetaNameValue,
error::ExtError as _,
format_err,
};
use proc_macro2::Span;
use std::collections::HashMap;
use syn::spanned::Spanned;
pub fn ensure_pub_visibility(
name: &str,
parent_span: Span,
vis: &syn::Visibility,
) -> Result<(), syn::Error> {
let bad_visibility = match vis {
syn::Visibility::Inherited => Some(parent_span),
syn::Visibility::Restricted(vis_restricted) => Some(vis_restricted.span()),
syn::Visibility::Public(_) => None,
};
if let Some(bad_visibility) = bad_visibility {
return Err(format_err!(
bad_visibility,
"non `pub` ink! {} are not supported",
name
))
}
Ok(())
}
pub fn local_message_id(ident: &syn::Ident) -> u32 {
let input = ident.to_string().into_bytes();
let selector = Selector::compute(&input);
selector.into_be_u32()
}
#[derive(Debug, PartialEq, Eq)]
pub struct WhitelistedAttributes(pub HashMap<String, ()>);
impl Default for WhitelistedAttributes {
fn default() -> Self {
Self(HashMap::from([
("cfg".to_string(), ()),
("cfg_attr".to_string(), ()),
("allow".to_string(), ()),
("warn".to_string(), ()),
("deny".to_string(), ()),
("forbid".to_string(), ()),
("deprecated".to_string(), ()),
("must_use".to_string(), ()),
("doc".to_string(), ()),
("rustfmt".to_string(), ()),
]))
}
}
impl WhitelistedAttributes {
pub fn parse_arg_value(&mut self, arg: &MetaNameValue) -> Result<(), syn::Error> {
return if let ast::MetaValue::Lit(syn::Lit::Str(attributes)) = &arg.value {
attributes.value().split(',').for_each(|attribute| {
self.0.insert(attribute.trim().to_string(), ());
});
Ok(())
} else {
Err(format_err_spanned!(
arg,
"expected a string with attributes separated by `,`",
))
}
}
pub fn filter_attr(&self, attrs: Vec<syn::Attribute>) -> Vec<syn::Attribute> {
attrs
.into_iter()
.filter(|attr| {
if let Some(ident) = attr.path().get_ident() {
self.0.contains_key(&ident.to_string())
} else {
false
}
})
.collect()
}
}
pub fn duplicate_config_err<F, S>(
first: F,
second: S,
name: &str,
ink_attr: &str,
) -> syn::Error
where
F: Spanned,
S: Spanned,
{
format_err!(
second.span(),
"encountered duplicate ink! {} `{}` configuration argument",
ink_attr,
name,
)
.into_combine(format_err!(
first.span(),
"first `{}` configuration argument here",
name
))
}
pub fn find_storage_key_salt(input: &syn::DeriveInput) -> Option<syn::TypeParam> {
input.generics.params.iter().find_map(|param| {
if let syn::GenericParam::Type(type_param) = param {
if let Some(syn::TypeParamBound::Trait(trait_bound)) =
type_param.bounds.first()
{
let segments = &trait_bound.path.segments;
if let Some(last) = segments.last() {
if last.ident == "StorageKey" {
return Some(type_param.clone())
}
}
}
}
None
})
}
pub fn extract_cfg_attributes(
attrs: &[syn::Attribute],
span: Span,
) -> Vec<proc_macro2::TokenStream> {
attrs
.iter()
.filter(|a| a.path().is_ident(super::CFG_IDENT))
.map(|a| quote::quote_spanned!(span=> #a ))
.collect()
}