Trait attribute_derive::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§
sourcefn parse_partial(input: ParseStream<'_>) -> Result<Self::Partial>
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§
sourcefn from_attributes<A: Borrow<Attribute>>(
attrs: impl IntoIterator<Item = A>,
) -> Result<Self>where
Self: AttributeIdent,
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")
)
sourcefn remove_attributes(attrs: &mut Vec<Attribute>) -> Result<Self>where
Self: AttributeIdent,
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")
)
sourcefn from_attribute(attr: impl Borrow<Attribute>) -> Result<Self>
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);
sourcefn from_input(input: impl Into<TokenStream>) -> Result<Self>
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.
sourcefn parse_input(input: ParseStream<'_>) -> Result<Self>
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
sourcefn from_attribute_partial(attr: impl Borrow<Attribute>) -> Result<Self::Partial>
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.