attribute_derive

Trait FromAttr

Source
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.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementations on Foreign Types§

Source§

impl FromAttr for bool

Source§

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

Implementors§