blob: abe2d852c9b3ce0d3a16a795b6449e13a16a8cbe [file] [log] [blame]
use proc_macro2::Ident;
use syn::Path;
use crate::ast::NestedMeta;
use crate::util::PathList;
use crate::{Error, FromField, FromMeta, Result};
use super::ParseAttribute;
/// The `attrs` magic field and attributes that influence its behavior.
#[derive(Debug, Clone)]
pub struct AttrsField {
/// The ident of the field that will receive the forwarded attributes.
pub ident: Ident,
/// Path of the function that will be called to convert the `Vec` of
/// forwarded attributes into the type expected by the field in `ident`.
pub with: Option<Path>,
}
impl FromField for AttrsField {
fn from_field(field: &syn::Field) -> crate::Result<Self> {
let result = Self {
ident: field.ident.clone().ok_or_else(|| {
Error::custom("attributes receiver must be named field").with_span(field)
})?,
with: None,
};
result.parse_attributes(&field.attrs)
}
}
impl ParseAttribute for AttrsField {
fn parse_nested(&mut self, mi: &syn::Meta) -> crate::Result<()> {
if mi.path().is_ident("with") {
if self.with.is_some() {
return Err(Error::duplicate_field_path(mi.path()).with_span(mi));
}
self.with = FromMeta::from_meta(mi)?;
Ok(())
} else {
Err(Error::unknown_field_path_with_alts(mi.path(), &["with"]).with_span(mi))
}
}
}
/// A rule about which attributes to forward to the generated struct.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ForwardAttrsFilter {
All,
Only(PathList),
}
impl ForwardAttrsFilter {
/// Returns `true` if this will not forward any attributes.
pub fn is_empty(&self) -> bool {
match *self {
ForwardAttrsFilter::All => false,
ForwardAttrsFilter::Only(ref list) => list.is_empty(),
}
}
}
impl FromMeta for ForwardAttrsFilter {
fn from_word() -> Result<Self> {
Ok(ForwardAttrsFilter::All)
}
fn from_list(nested: &[NestedMeta]) -> Result<Self> {
Ok(ForwardAttrsFilter::Only(PathList::from_list(nested)?))
}
}