# Derive-Attribute [![Latest Version]][crates.io] [![Documentation]][docs.rs]
[Latest Version]: https://img.shields.io/crates/v/derive-attribute.svg
[crates.io]: https://crates.io/crates/derive-attribute
[Documentation]: https://docs.rs/derive-attribute/badge.svg
[docs.rs]: https://docs.rs/derive-attribute
### **A set of macros to automatically deserialize standard attributes**
- #### Compatible with all major versions of [Syn](https://crates.io/crates/syn)
- #### Supports custom deserialization
- #### Can return multiple errors at once
- #### Allows for flexible attribute syntax
## Syn Compatibility
This crate is meant to be used in conjunction with Syn within a procedural macro crate.
A major version of Syn can be selected as a feature like: `features = ["syn_2"]`.
Note: A Syn version must be selected
## Flexible Attribute Syntax
#### **Implicit Booleans**
` #[some_attr(is_bool)] ` *can also be written as* ` #[some_attr(is_bool = true)] `
#### **Seperated Lists**
` #[some_attr(list(key_a = "value", key_b = 123))] `
*can also be written as*
` #[some_attr(list(key_a = "value"))] `
` #[some_attr(list(key_b = 123))] `
## Multiple Errors
Most macros will only return one attribute error at a time.
This crate's macros can return multiple errors at once resulting in a better developer experience.
## Custom Deserialization
Any type that implements `TryFromMeta` can be used as a valid attribute type.
Although Its recommended that you use `CustomArgFromMeta` instead in order to simplify the implementation.
See [example](#custom-deserialization-1)
## Attr Arguments
The `#[attr()]` attribute can be added to the attribute struct or its fields to add additional options.
**The full list of arguments are:**
**name [str]** - Renames the field.
**default [bool/str]** - Uses a default value if the argument isn't found.
If its a boolean, the type's implementation of Default::default will be used. \
If its a string, it must be a path to a function that returns the type.
# Usage
Our attribute type is declared in a procedural macro crate:
```rust
#[derive(Attribute)]
#[attr(name = "my_attr")] // We set the attribute name to 'my_attr'
struct MyAttribute { // Note: The attribute name will be the struct name in snake_case by default
name: String,
// wrapping a type in an option will make it optional
list: Option, // deserializes a meta list named list i.e. list(num = 1)
// booleans are always optional
is_selected: bool,
}
#[derive(List)]
pub struct NestedList {
num: Option
}
```
It can then be used to parse the following attribute using the from_attrs method:
```rust
#[my_attr(name = "some_name", is_selected)]
```
***lets look at the same attribute used in a derive macro***
## Basic derive
procedural macro crate:
```rust
use derive_attribute::{Attribute, List};
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};
#[derive(Attribute)]
#[attr(name = "my_attr")]
struct MyAttribute {
name: String,
// wrapping a type in an option will make it optional
// deserializes a meta list named list i.e. list(num = 1)
list: Option,
// booleans are always optional
is_selected: bool,
}
#[derive(List)]
pub struct NestedList {
num: Option
}
#[proc_macro_derive(YOUR_MACRO_NAME, attributes(my_attr))]
pub fn derive_my_trait(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast = parse_macro_input!(tokens as DeriveInput);
fn attempt_derive(ast: DeriveInput) -> Result> {
// Wrapping an attribute in an option makes it optional
// A missing error won't be returnwd
let maybe_attribute =