pub trait FromAttr: Sized + AttributeBase {
    // Required method
    fn parse_partial(input: ParseStream<'_>) -> Result<Self::Partial>;

    // Provided methods
    fn from_attributes<A: Borrow<Attribute>>(
        attrs: impl IntoIterator<Item = A>
    ) -> Result<Self>
       where Self: AttributeIdent { ... }
    fn remove_attributes(attrs: &mut Vec<Attribute>) -> Result<Self>
       where Self: AttributeIdent { ... }
    fn from_attribute(attr: impl Borrow<Attribute>) -> Result<Self> { ... }
    fn from_input(input: impl Into<TokenStream>) -> Result<Self> { ... }
    fn parse_input(input: ParseStream<'_>) -> Result<Self> { ... }
    fn from_attribute_partial(
        attr: impl Borrow<Attribute>
    ) -> Result<Self::Partial> { ... }
}
Expand description

The trait you actually derive on your attribute struct.

Basic gist is a struct like this:

#[derive(FromAttr)]
#[attribute(ident = collection)]
#[attribute(error(missing_field = "`{field}` was not specified"))]
struct CollectionAttribute {
    // Options are optional by default (will be set to None if not specified)
    authority: Option<String>,
    name: String,
    // Any type implementing default can be flagged as optional
    // This will be set to Vec::default() when not specified
    #[attribute(optional)]
    views: Vec<Type>,
    // Booleans can be used without assiging a value. as a flag.
    // If omitted they are set to false
    some_flag: bool,
}

Will be able to parse an attribute like this:

#[collection(authority="Some String", name = r#"Another string"#, views = [Option, ()], some_flag)]

Required Methods§

source

fn parse_partial(input: ParseStream<'_>) -> Result<Self::Partial>

Actual implementation for parsing the attribute. This is the only function required to implement in this trait and derived by the FromAttr derive macro.

Provided Methods§

source

fn from_attributes<A: Borrow<Attribute>>( attrs: impl IntoIterator<Item = A> ) -> Result<Self>
where Self: AttributeIdent,

Parses an IntoIterator of syn::Attributes e.g. Vec<Attribute>. Only available if you specify the attribute ident: #[attribute(ident="<ident>")] when using the derive macro.

It can therefore parse fields set over multiple attributes like:

#[collection(authority = "Authority", name = "Name")]
#[collection(views = [A, B])]

And also catch duplicate/conflicting settings over those.

This is best used for derive macros, where you don’t need to remove your attributes.

§Errors

Fails with a syn::Error so you can conveniently return that as a compiler error in a proc macro in the following cases

  • A required parameter is omitted
  • Invalid input is given for a parameter
  • A non aggregating parameter is specified multiple times
  • An attribute called IDENTS has invalid syntax (e.g. #attr(a: "a"))
source

fn remove_attributes(attrs: &mut Vec<Attribute>) -> Result<Self>
where Self: AttributeIdent,

Parses a &mut Vec<syn::Attributes>. Removing matching attributes. Only available if you specify an ident: #[attribute(ident="<ident>")] when using the derive macro.

It can therefore parse fields set over multiple attributes like:

#[collection(authority = "Authority", name = "Name")]
#[collection(views = [A, B])]

And also catch duplicate/conflicting settings over those.

Use this if you are implementing an attribute macro, and need to remove your helper attributes.

use syn::parse_quote;
use attribute_derive::FromAttr;
let mut attrs = vec![
    parse_quote!(#[ignored]), parse_quote!(#[test]),
    parse_quote!(#[also_ignored]), parse_quote!(#[test])
];
#[derive(FromAttr)]
#[attribute(ident = test)]
struct Test {}
assert!(Test::remove_attributes(&mut attrs).is_ok());

assert_eq!(attrs, vec![parse_quote!(#[ignored]), parse_quote!(#[also_ignored])]);
§Errors

Fails with a syn::Error, so you can conveniently return that as a compiler error in a proc macro in the following cases

  • A necessary parameter is omitted
  • Invalid input is given for a parameter
  • A non aggregating parameter is specified multiple times
  • An attribute called IDENTS has invalid syntax (e.g. #attr(a: "a"))
source

fn from_attribute(attr: impl Borrow<Attribute>) -> Result<Self>

Parses from a single attribute. Ignoring the name.

This is available even without #[attribute(ident = ...)], because it ignores the attribute’s path, allowing to use it to parse e.g. literals:

use attribute_derive::FromAttr;

let attr: syn::Attribute = syn::parse_quote!(#[test = "hello"]);
assert_eq!(String::from_attribute(attr).unwrap(), "hello");

let attr: syn::Attribute = syn::parse_quote!(#[test]);
assert_eq!(bool::from_attribute(attr).unwrap(), true);
source

fn from_input(input: impl Into<TokenStream>) -> Result<Self>

Parses a TokenStream.

Useful for implementing general proc macros to parse the input of your macro.

This is a convenience over parse_input. More details are documented there.

source

fn parse_input(input: ParseStream<'_>) -> Result<Self>

Parses input as the complete attribute.

Due to this only parsing the input for a single attribute it is not able to aggregate input spread over multiple attributes.

§Errors

Fails with a syn::Error, so you can conveniently return that as a compiler error in a proc macro in the following cases

  • A necessary parameter is omitted
  • Invalid input is given for a parameter
  • A non aggregating parameter is specified multiple times
source

fn from_attribute_partial(attr: impl Borrow<Attribute>) -> Result<Self::Partial>

Like parse_partial but instead takes an Attribute.

This allows it to support all three, #[flag], #[function(like)] and #[name = value] attributes.

Object Safety§

This trait is not object safe.

Implementations on Foreign Types§

source§

impl FromAttr for bool

source§

impl<T: FromAttr> FromAttr for Option<T>

Implementors§