smile_marco/lib.rs
1//! # smile-marco provides macros such as `Getter`, `Setter`, `Wither`, `Builder`, etc
2//! These macros generate methods such as `get`, `set`, `with`, and `builder` for properties within a struct, providing quick access and manipulation.
3//! Convenient for daily development.
4//! ```toml
5//! [dependencies]
6//! smile-marco = { version = "1.0.0", features = ["full"] }
7//! #or
8//! smile-marco = { version = "1.0.0"}
9//! ```
10//! If needed, use partial macros.
11//! ```toml
12//! [dependencies]
13//! smile-marco = { version = "1.0.0", features = ["getter","setter"] }
14//! ```
15//! # Example
16//! ```rust
17//! use smile_marco::{Builder, Getter, Setter, Wither};
18//!
19//! #[derive(Builder, Getter, Setter, Wither)]
20//! struct Book {
21//! title: String,
22//! #[name(cost)] // rename
23//! price: i32,
24//! #[exclude] // Do not generate set methods for author
25//! author: String,
26//! }
27//!
28//!
29//! let mut book = Book::builder()
30//! .title("Rust Programming".to_string())
31//! .price(100)
32//! .author("rust".to_string())
33//! .build();
34//! assert_eq!(book.title, "Rust Programming".to_string());
35//! book.set_title("Rust Book".into());
36//! assert_eq!(book.title, "Rust Book".to_string());
37//! assert_eq!(book.get_cost(), &100);
38//! let mut book = book.with_cost(|c| c + 100);
39//! assert_eq!(book.price, 200);
40//! ```
41#[cfg(feature = "builder")]
42mod builder;
43#[cfg(feature = "full")]
44mod data;
45#[cfg(feature = "getter")]
46mod getter;
47#[cfg(feature = "setter")]
48mod setter;
49mod util;
50#[cfg(feature = "wither")]
51mod wither;
52
53type TokenStream1 = proc_macro::TokenStream;
54type TokenStream2 = proc_macro2::TokenStream;
55
56/// The Getter macro is used to quickly generate the get method
57///
58/// ```
59/// use smile_marco::Getter;
60/// #[derive(Getter)]
61/// struct Book {
62/// title: String,
63/// #[name(cost)] //rename
64/// price: i32,
65/// #[exclude] // Do not generate get methods for author
66/// author: String,
67/// }
68///
69/// // may be used as such
70/// let book = Book {
71/// title: "Rust Programming".to_string(),
72/// price: 100,
73/// author: "rust".to_string(),
74/// };
75/// assert_eq!(book.get_title(), &"Rust Programming".to_string());
76/// assert_eq!(book.get_cost(), &100);
77///
78///
79/// //Getter Macros automatically generate the following code
80/// impl Book {
81/// #[inline]
82/// pub fn get_title(&self) -> &String {
83/// &self.title
84/// }
85/// #[inline]
86/// pub fn get_cost(&self) -> &i32 {
87/// &self.price
88/// }
89/// }
90/// ```
91///
92#[cfg(feature = "getter")]
93#[proc_macro_derive(Getter, attributes(exclude, name))]
94pub fn getter_derive(input: TokenStream1) -> TokenStream1 {
95 let input = syn::parse_macro_input!(input as syn::DeriveInput);
96 getter::gen_ast(&input)
97}
98
99/// Setter macros are used to quickly generate set methods
100///
101/// ```
102/// use smile_marco::Setter;
103/// #[derive(Setter)]
104/// struct Book {
105/// title: String,
106/// #[name(cost)] // rename
107/// price: i32,
108/// #[exclude] // Do not generate set methods for author
109/// author: String,
110/// }
111/// // And then you can use it like this.
112/// let mut book = Book {
113/// title: "Rust Programming".to_string(),
114/// price: 100,
115/// author: "rust".to_string(),
116/// };
117///
118/// book.set_cost(200);
119/// assert_eq!(book.get_cost(), &200);
120///
121/// //Setter Macros automatically generate the following code
122/// impl Book {
123/// #[inline]
124/// pub fn set_title(&mut self, title: String) {
125/// self.title = title;
126/// }
127/// #[inline]
128/// pub fn set_cost(&mut self, cost: i32) {
129/// self.price = cost;
130/// }
131/// }
132///
133/// ```
134
135#[cfg(feature = "setter")]
136#[proc_macro_derive(Setter, attributes(exclude, name))]
137pub fn setter_derive(input: TokenStream1) -> TokenStream1 {
138 let input = syn::parse_macro_input!(input as syn::DeriveInput);
139 setter::gen_ast(&input)
140}
141
142/// Wither macros are used to quickly generate with methods
143///
144/// ```
145/// use smile_marco::Wither;
146/// #[derive(Wither)]
147/// struct Book {
148/// title: String,
149/// #[name(cost)] //rename
150/// price: i32,
151/// #[exclude] // Do not generate with methods for author
152/// author: String,
153/// }
154/// // may be used as such
155/// let mut book = Book {
156/// title: "Rust Programming".to_string(),
157/// price: 100,
158/// author: "rust".to_string(),
159/// };
160///
161/// let book = book.with_cost(|v| v+100);
162/// assert_eq!(book.price, 200);
163///
164/// //Wither Macros automatically generate the following code
165/// impl Book {
166/// #[inline]
167/// pub fn with_title<F>(mut self, func: F) -> Self
168/// where
169/// F: FnOnce(String) -> String,
170/// {
171/// self.title = func(self.title);
172/// self
173/// }
174/// #[inline]
175/// pub fn with_cost<F>(mut self, func: F) -> Self
176/// where
177/// F: FnOnce(i32) -> i32,
178/// {
179/// self.price = func(self.price);
180/// self
181/// }
182/// }
183///
184
185/// ```
186#[cfg(feature = "wither")]
187#[proc_macro_derive(Wither, attributes(exclude, name))]
188pub fn wither_derive(input: TokenStream1) -> TokenStream1 {
189 let input = syn::parse_macro_input!(input as syn::DeriveInput);
190 wither::gen_ast(&input)
191}
192
193/// Builder macro
194///
195/// ```
196/// use smile_marco::Builder;
197/// #[derive(Builder)]
198/// struct Book {
199/// title: String,
200/// price: i32,
201/// author: String,
202/// }
203///
204/// // may be used as such
205/// let book = Book::builder()
206/// .title("Rust Programming".to_string())
207/// .price(100)
208/// .author("rust".to_string())
209/// .build();
210/// assert_eq!(book.title, "Rust Programming".to_string());
211/// assert_eq!(book.price, 100);
212/// //Builder Macros automatically generate the following code
213/// struct BookBuilder {
214/// title: Option<String>,
215/// price: Option<i32>,
216/// author: Option<String>,
217/// }
218/// impl BookBuilder {
219/// #[inline]
220/// pub fn new() -> Self {
221/// Self {
222/// title: None,
223/// price: None,
224/// author: None,
225/// }
226/// }
227/// #[inline]
228/// pub fn build(self) -> Book {
229/// Book {
230/// title: self.title.expect("title field is not set in Book struct"),
231/// price: self.price.expect("price field is not set in Book struct"),
232/// author: self.author.expect("author field is not set in Book struct"),
233/// }
234/// }
235/// #[inline]
236/// pub fn title(mut self, v: String) -> Self {
237/// self.title = Some(v);
238/// self
239/// }
240/// #[inline]
241/// pub fn price(mut self, v: i32) -> Self {
242/// self.price = Some(v);
243/// self
244/// }
245/// #[inline]
246/// pub fn author(mut self, v: String) -> Self {
247/// self.author = Some(v);
248/// self
249/// }
250/// }
251/// impl Book {
252/// #[inline]
253/// pub fn builder() -> BookBuilder {
254/// BookBuilder::new()
255/// }
256/// }
257///
258
259/// ```
260#[cfg(feature = "builder")]
261#[proc_macro_derive(Builder)]
262pub fn builder_derive(input: TokenStream1) -> TokenStream1 {
263 let input = syn::parse_macro_input!(input as syn::DeriveInput);
264 builder::gen_ast(&input)
265}
266
267/// data macro
268/// ```
269/// use smile_marco::data;
270/// #[data]
271/// struct Book {
272/// title: String,
273/// price: i32,
274/// author: String,
275/// }
276/// // data macro automatically adds to structure `Getter,Setter,Wither,Builder` macros
277/// #[derive(Getter,Setter,Wither,Builder)]
278/// struct Book {
279/// title: String,
280/// price: i32,
281/// author: String,
282/// }
283/// // You can also use the link attribute to specify the source of macros such as Getter、Setter
284/// // and use the exclude attribute to exclude macros
285/// #[data(link="xxx",exclude = ["Getter", "Setter"])]
286/// ```
287#[cfg(feature = "full")]
288#[proc_macro_attribute]
289pub fn data(attr: TokenStream1, item: TokenStream1) -> TokenStream1 {
290 data::ast_gen(attr, item)
291}