Macro zvariant_utils::def_attrs
source · macro_rules! def_attrs { (@attr_ty str) => { ... }; (@attr_ty bool) => { ... }; (@attr_ty [str]) => { ... }; (@attr_ty none) => { ... }; (@attr_ty { $(#[$m:meta])* $vis:vis $name:ident($what:literal) { $($attr_name:ident $kind:tt),+ } }) => { ... }; (@match_attr_with $attr_name:ident, $meta:ident, $self:ident, $matched:expr) => { ... }; (@match_attr str $attr_name:ident, $meta:ident, $self:ident) => { ... }; (@match_attr bool $attr_name:ident, $meta:ident, $self:ident) => { ... }; (@match_attr [str] $attr_name:ident, $meta:ident, $self:ident) => { ... }; (@match_attr none $attr_name:ident, $meta:ident, $self:ident) => { ... }; (@match_attr { $(#[$m:meta])* $vis:vis $name:ident($what:literal) $body:tt } $attr_name:ident, $meta:expr, $self:ident) => { ... }; (@def_ty $list_name:ident str) => { ... }; (@def_ty $list_name:ident bool) => { ... }; (@def_ty $list_name:ident [str]) => { ... }; (@def_ty $list_name:ident none) => { ... }; ( @def_ty $list_name:ident { $(#[$m:meta])* $vis:vis $name:ident($what:literal) { $($attr_name:ident $kind:tt),+ } } ) => { ... }; ( @def_struct $list_name:ident $(#[$m:meta])* $vis:vis $name:ident($what:literal) { $($attr_name:ident $kind:tt),+ } ) => { ... }; ( crate $list_name:ident; $( $(#[$m:meta])* $vis:vis $name:ident($what:literal) { $($attr_name:ident $kind:tt),+ } );+; ) => { ... }; }
Expand description
Generates one or more structures used for parsing attributes in proc macros.
Generated structures have one static method called parse that accepts a slice of Attribute
s.
The method finds attributes that contain meta lists (look like #[your_custom_ident(...)]
) and
fills a newly allocated structure with values of the attributes if any.
The expected input looks as follows:
def_attrs! {
crate zvariant;
/// A comment.
pub StructAttributes("struct") { foo str, bar str, baz none };
#[derive(Hash)]
FieldAttributes("field") { field_attr bool };
}
Here we see multiple entries: an entry for an attributes group called StructAttributes
and
another one for FieldAttributes
. The former has three defined attributes: foo
, bar
and
baz
. The generated structures will look like this in that case:
/// A comment.
#[derive(Default, Clone, Debug)]
pub struct StructAttributes {
foo: Option<String>,
bar: Option<String>,
baz: bool,
}
#[derive(Hash)]
#[derive(Default, Clone, Debug)]
struct FieldAttributes {
field_attr: Option<bool>,
}
foo
and bar
attributes got translated to fields with Option<String>
type which contain the
value of the attribute when one is specified. They are marked with str
keyword which stands
for string literals. The baz
attribute, on the other hand, has bool
type because it’s an
attribute without value marked by the none
keyword.
Currently the following literals are supported:
str
- string literals;bool
- boolean literals;[str]
- lists of string literals (#[macro_name(foo("bar", "baz"))]
);none
- no literal at all, the attribute is specified alone.
The strings between braces are embedded into error messages produced when an attribute defined
for one attribute group is used on another group where it is not defined. For example, if the
field_attr
attribute was encountered by the generated StructAttributes::parse
method, the
error message would say that it “is not allowed on structs”.
Nested attribute lists
It is possible to create nested lists for specific attributes. This is done as follows:
def_attrs! {
crate zvariant;
pub OuterAttributes("outer") {
simple_attr bool,
nested_attr {
/// An example of nested attributes.
pub InnerAttributes("inner") {
inner_attr str
}
}
};
}
The syntax for inner attributes is the same as for the outer attributes, but you can specify only one inner attribute per outer attribute.
Calling the macro multiple times
The macro generates an array called ALLOWED_ATTRS
that contains a list of allowed attributes.
Calling the macro twice in the same scope will cause a name alias and thus will fail to compile.
You need to place each macro invocation into a module in that case.
Errors
The generated parse method checks for some error conditions:
- Unknown attributes. When multiple attribute groups are defined in the same macro invocation, one gets a different error message when providing an attribute from a different attribute group.
- Duplicate attributes.
- Missing attribute value or present attribute value when none is expected.
- Invalid literal type for attributes with values.