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}