1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
//! # 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.<br/>
//! 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)] ` <br/>
//! #### **Seperated Lists**
//! ` #[some_attr(list(key_a = "value", key_b = 123))] `
//! <br/>
//! *can also be written as*
//! <br/>
//! ` #[some_attr(list(key_a = "value"))] ` <br/>
//! ` #[some_attr(list(key_b = 123))] `
//!
//!
//! ## Multiple Errors
//! Most macros will only return one attribute error at a time. </br>
//! 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. </br>
//! Although Its recommended that you use `CustomArgFromMeta` instead in order to simplify the implementation.
//!
//! See [example](#custom-deserialization-1)
//! <br/>
//!
//! ## 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 [<span style = "color: lightblue">str</span>]** - Renames the field.
//!
//! **default [<span style = "color: lightblue">bool/str</span>]** - Uses a default value if the argument isn't found.
//! <span style = "font-size: 10px"> </span><br/>
//! 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<NestedList>, // 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<u8>
//! }
//! ```
//! It can then be used to parse the following attribute using the from_attrs method:
//!
//! ```rust
//! #[my_attr(name = "some_name", is_selected)]
//! ```
//! <br/>
//!
//! ***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<NestedList>,
//! // booleans are always optional
//! is_selected: bool,
//! }
//! #[derive(List)]
//! pub struct NestedList {
//! num: Option<u8>
//! }
//!
//!
//! #[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<TokenStream2, Vec<syn::Error>> {
//! // Wrapping an attribute in an option makes it optional
//! // A missing error won't be returnwd
//! let maybe_attribute = <Option<MyAttribute>>::from_attrs(ast.ident.span(), &ast.attrs)?;
//!
//! let output: TokenStream2 = {
//! // Your Macro Generation Code
//! };
//!
//! Ok(output)
//! }
//!
//!
//! let generated_tokens =
//! match attempt_derive(ast) {
//! Ok(tokens) => tokens,
//! Err(errors) => {
//! let compile_errors = errors.into_iter().map(|e| e.to_compile_error());
//! quote!(#(#compile_errors)*)
//! }
//! };
//!
//! generated_tokens.into()
//! }
//! ```
//!
//! Another crate using our macro
//!
//! ```rust
//! #[derive(YOUR_MACRO_NAME)]
//! #[my_attr(name = "some_name", is_selected)]
//! struct SomeStruct;
//! ```
//!
//! <br/>
//!
//! ***Now lets add our own argument type***
//!
//! ## Custom Deserialization
//!
//! proc-macro crate:
//! ```rust
//! use derive_attribute::{CustomArg, CustomArgFromMeta};
//!
//! struct ErrorType {
//! Warning,
//! Severe
//! }
//!
//! // Any type that implements 'TryFromMeta' can be deserialized however its a bit verbose
//! // In order to simplify the implementation we can implement 'CustomArgFromMeta' instead and wrap our type in the 'CustomArg' struct
//! impl<V: SynVersion> CustomArgFromMeta<V> for ErrorType {
//! fn try_from_meta(meta: Self::Metadata) -> Result<Self, ErrorMsg> {
//! let maybe_error_kind =
//! match V::deserialize_string(meta) {
//! Some(string) => {
//! match string.to_string().as_str() {
//! "warning" => Some(Self::Warning),
//! "severe" => Some(Self::Severe),
//! _ => None
//! }
//! }
//! None => None
//! };
//!
//! match maybe_error_kind {
//! Some(error_kind) => Ok(error_kind),
//! None => Err(InvalidType { expected: r#" "warning" or "severe" "# })
//! }
//! }
//! }
//!
//! ```
//!
//! Our attribute struct now looks like this:
//! ```rust
//! #[derive(Attribute)]
//! #[attr(name = "my_attr")]
//! struct MyAttribute {
//! // In order to use the simplified trait(CustomArgFromMeta) we need to wrap our struct in 'CustomArg'
//! error_type: CustomArg<ErrorType>,
//!
//! name: String,
//! list: Option<u32>,
//! is_selected: bool,
//! }
//! ```
//! Another crate using our macro:
//! ```rust
//! #[derive(YOUR_MACRO_NAME)]
//! #[error(error_type = "warning", name = "some_name", is_selected)]
//! struct Test;
//! ```
pub use *;
pub use *;