blob: fc7c723308078f6358ee50a74bf402c68d2b3b4b [file] [log] [blame]
//! Attribute parsing for fields.
use syn::{spanned::Spanned, Attribute, Meta, Result};
use crate::{util::MetaListExt, DeriveWhere, Error, Skip, DERIVE_WHERE};
#[cfg(feature = "zeroize")]
use crate::{Trait, ZeroizeFqs};
/// Attributes on field.
#[derive(Default)]
#[cfg_attr(test, derive(Debug))]
pub struct FieldAttr {
/// [`Trait`](crate::Trait)s to skip this field for.
#[cfg_attr(feature = "zeroize", allow(rustdoc::redundant_explicit_links))]
pub skip: Skip,
/// Use fully-qualified-syntax for the [`Zeroize`](https://docs.rs/zeroize/latest/zeroize/trait.Zeroize.html) implementation on this field.
#[cfg(feature = "zeroize")]
pub zeroize_fqs: ZeroizeFqs,
}
impl FieldAttr {
/// Create [`FieldAttr`] from [`Attribute`]s.
pub fn from_attrs(
derive_wheres: &[DeriveWhere],
skip_inner: &Skip,
attrs: &[Attribute],
) -> Result<Self> {
let mut self_ = FieldAttr::default();
for attr in attrs {
if attr.path().is_ident(DERIVE_WHERE) {
self_.add_meta(derive_wheres, skip_inner, &attr.meta)?
}
}
Ok(self_)
}
/// Add [`Meta`] to [`FieldAttr`].
fn add_meta(
&mut self,
derive_wheres: &[DeriveWhere],
skip_inner: &Skip,
meta: &Meta,
) -> Result<()> {
debug_assert!(meta.path().is_ident(DERIVE_WHERE));
if let Meta::List(list) = meta {
let nested = list.parse_non_empty_nested_metas()?;
for meta in &nested {
if meta.path().is_ident(Skip::SKIP) {
self.skip
.add_attribute(derive_wheres, Some(skip_inner), meta)?;
continue;
}
#[cfg(feature = "zeroize")]
{
if meta.path().is_ident(Trait::Zeroize.as_str()) {
self.zeroize_fqs.add_attribute(meta, derive_wheres)?;
continue;
}
}
return Err(Error::option(meta.path().span()));
}
Ok(())
} else {
Err(Error::option_syntax(meta.span()))
}
}
}