2022-09-12 20:10:58 +02:00
|
|
|
use quote::ToTokens;
|
2022-09-12 21:26:10 +02:00
|
|
|
use syn::{
|
|
|
|
parse::{Parse, ParseStream},
|
|
|
|
Token,
|
|
|
|
};
|
2022-09-12 20:10:58 +02:00
|
|
|
|
|
|
|
pub(crate) fn parse_parenthesized_attribute<K, T>(
|
|
|
|
input: ParseStream,
|
|
|
|
out: &mut Option<(K, T)>,
|
|
|
|
) -> syn::Result<()>
|
|
|
|
where
|
|
|
|
K: Parse + ToTokens,
|
|
|
|
T: Parse,
|
|
|
|
{
|
|
|
|
let kw = input.parse()?;
|
|
|
|
|
|
|
|
let content;
|
|
|
|
syn::parenthesized!(content in input);
|
|
|
|
let inner = content.parse()?;
|
|
|
|
|
2022-09-12 21:26:10 +02:00
|
|
|
if out.is_some() {
|
|
|
|
let kw_name = std::any::type_name::<K>().split("::").last().unwrap();
|
2023-01-20 12:04:49 +01:00
|
|
|
let msg = format!("`{kw_name}` specified more than once");
|
2022-09-12 21:26:10 +02:00
|
|
|
return Err(syn::Error::new_spanned(kw, msg));
|
|
|
|
}
|
|
|
|
|
|
|
|
*out = Some((kw, inner));
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn parse_assignment_attribute<K, T>(
|
|
|
|
input: ParseStream,
|
|
|
|
out: &mut Option<(K, T)>,
|
|
|
|
) -> syn::Result<()>
|
|
|
|
where
|
|
|
|
K: Parse + ToTokens,
|
|
|
|
T: Parse,
|
|
|
|
{
|
|
|
|
let kw = input.parse()?;
|
|
|
|
input.parse::<Token![=]>()?;
|
|
|
|
let inner = input.parse()?;
|
|
|
|
|
2022-09-12 20:10:58 +02:00
|
|
|
if out.is_some() {
|
|
|
|
let kw_name = std::any::type_name::<K>().split("::").last().unwrap();
|
2023-01-20 12:04:49 +01:00
|
|
|
let msg = format!("`{kw_name}` specified more than once");
|
2022-09-12 20:10:58 +02:00
|
|
|
return Err(syn::Error::new_spanned(kw, msg));
|
|
|
|
}
|
|
|
|
|
|
|
|
*out = Some((kw, inner));
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) trait Combine: Sized {
|
|
|
|
fn combine(self, other: Self) -> syn::Result<Self>;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn parse_attrs<T>(ident: &str, attrs: &[syn::Attribute]) -> syn::Result<T>
|
|
|
|
where
|
|
|
|
T: Combine + Default + Parse,
|
|
|
|
{
|
|
|
|
attrs
|
|
|
|
.iter()
|
|
|
|
.filter(|attr| attr.path.is_ident(ident))
|
|
|
|
.map(|attr| attr.parse_args::<T>())
|
|
|
|
.try_fold(T::default(), |out, next| out.combine(next?))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn combine_attribute<K, T>(a: &mut Option<(K, T)>, b: Option<(K, T)>) -> syn::Result<()>
|
|
|
|
where
|
|
|
|
K: ToTokens,
|
|
|
|
{
|
|
|
|
if let Some((kw, inner)) = b {
|
|
|
|
if a.is_some() {
|
|
|
|
let kw_name = std::any::type_name::<K>().split("::").last().unwrap();
|
2023-01-20 12:04:49 +01:00
|
|
|
let msg = format!("`{kw_name}` specified more than once");
|
2022-09-12 20:10:58 +02:00
|
|
|
return Err(syn::Error::new_spanned(kw, msg));
|
|
|
|
}
|
|
|
|
*a = Some((kw, inner));
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-11-18 12:05:10 +01:00
|
|
|
pub(crate) fn combine_unary_attribute<K>(a: &mut Option<K>, b: Option<K>) -> syn::Result<()>
|
|
|
|
where
|
|
|
|
K: ToTokens,
|
|
|
|
{
|
|
|
|
if let Some(kw) = b {
|
|
|
|
if a.is_some() {
|
|
|
|
let kw_name = std::any::type_name::<K>().split("::").last().unwrap();
|
2023-01-20 12:04:49 +01:00
|
|
|
let msg = format!("`{kw_name}` specified more than once");
|
2022-11-18 12:05:10 +01:00
|
|
|
return Err(syn::Error::new_spanned(kw, msg));
|
|
|
|
}
|
|
|
|
*a = Some(kw);
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-09-12 20:10:58 +02:00
|
|
|
pub(crate) fn second<T, K>(tuple: (T, K)) -> K {
|
|
|
|
tuple.1
|
|
|
|
}
|