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
//! Generates builder methods of every field of a struct. It is meant to be used on structs that
//! implement `Default`. There is no separate builder struct generated and no need to call a
//! `build()` method at the end or `.unwrap()`.
//!
//! This crate is used by the crate `leptos-use` for the option structs that
//! can be passed to the various functions.
//!
//! ## Installation
//!
//! In your project folder run
//!
//! ```sh
//! cargo add default-struct-builder
//! ```
//!
//! ## Usage
//!
//! It is very easy to use:
//!
//! ```
//! use default_struct_builder::DefaultBuilder;
//!
//! #[derive(DefaultBuilder, Default)]
//! pub struct SomeOptions {
//!     throttle: f64,
//!
//!     #[builder(into)]
//!     offset: Option<f64>,
//!
//!     #[builder(skip)]
//!     not_included: u32,
//! }
//! ```
//!
//! you can then use the struct like this:
//!
//! ```
//! # use default_struct_builder::DefaultBuilder;
//! #
//! # #[derive(DefaultBuilder, Default)]
//! # pub struct SomeOptions {
//! #     throttle: f64,
//! #
//! #     #[builder(into)]
//! #     offset: Option<f64>,
//! #
//! #     #[builder(skip)]
//! #     not_included: u32,
//! # }
//! #
//! # fn main() {
//! let options = SomeOptions::default().offset(4.0);
//!
//! assert_eq!(options.offset, Some(4.0));
//! assert_eq!(options.throttle, 0.0);
//! assert_eq!(options.not_included, 0);
//! # }
//! ```
//!
//! ### Generics
//!
//! The macro is ready to be used on generic structs.
//!
//! ```
//! use default_struct_builder::DefaultBuilder;
//!
//! #[derive(DefaultBuilder, Default)]
//! pub struct SomeOptions<T>
//! where
//!     T: Default,
//! {
//!     some_field: T,
//! }
//! ```
//!
//! ### Doc comments
//!
//! All doc comments on fields are directly passed on to their generated setter methods.
//!
//! ## How it works
//!
//! The derive macro generates the following code:
//!
//! ```
//! # #[derive(Default)]
//! # pub struct SomeOptions {
//! #     throttle: f64,
//! #     offset: Option<f64>,
//! #     not_included: u32,
//! # }
//! #
//! impl SomeOptions {
//!     // setter methods are given that consume `self` and return a new `Self` with the field value changed
//!     pub fn throttle(self, value: f64) -> Self {
//!         Self {
//!             throttle: value,
//!             ..self
//!         }
//!     }
//!
//!     // because `into` was specified this method is generic and calls `.into()` when setting the value
//!     pub fn offset<T>(self, value: T) -> Self
//!     where
//!         T: Into<Option<f64>>,
//!     {
//!         Self {
//!             offset: value.into(),
//!             ..self
//!         }
//!     }
//!
//!     // no method for field `not_included` because `skip` was specified
//! }
//! ```
//!
//! ### Generics
//!
//! In the case of a generic field the generated method is a bit more complex because by calling
//! the method the type of the type parameter can be different than before.
//!
//! Let's look at the following example.
//!
//! ```
//! use default_struct_builder::DefaultBuilder;
//!
//! #[derive(DefaultBuilder, Default)]
//! pub struct SomeOptions<T>
//! where
//!     T: Default,
//! {
//!     some_field: T,
//!     other_field: i16,
//! }
//!
//! impl SomeOptions<f32> {
//!     pub fn new() -> Self {
//!         Self {
//!             some_field: 42.0,
//!             other_field: 0,
//!         }   
//!     }
//! }
//! #
//! # fn main() {
//! #    let options = SomeOptions::new().some_field("string");
//! # }
//! ```
//!
//! This generates the setter method below.
//!
//! ```
//! # pub struct SomeOptions<T>
//! # where
//! #     T: Default,
//! # {
//! #     some_field: T,
//! #     other_field: i16,
//! # }
//! #
//! # impl SomeOptions<f32> {
//! #     pub fn new() -> Self {
//! #         Self {
//! #             some_field: 42.0,
//! #             other_field: 0,
//! #         }   
//! #     }
//! # }
//! #
//! impl<T> SomeOptions<T>
//! where
//!     T: Default,
//! {
//!     pub fn some_field<NewT>(self, value: NewT) -> SomeOptions<NewT>
//!     where
//!         NewT: Default,
//!     {
//!         SomeOptions::<NewT> {
//!             some_field: value,
//!             other_field: self.other_field,
//!         }
//!     }
//! }
//!
//! fn main() {
//!    let options = SomeOptions::new()  // at first    SomeOptions<f32>
//!         .some_field("string");       // changed to  SomeOptions<&str>
//! }
//! ```
//!
//! ## Related Work
//!
//! For more general purposes please check out the much more powerful
//! [`derive_builder` crate](https://github.com/colin-kiegel/rust-derive-builder).

mod builder;

use builder::DefaultBuilderDeriveInput;
use darling::FromDeriveInput;
use proc_macro::TokenStream;
use quote::quote;
use syn::parse_macro_input;

#[proc_macro_derive(DefaultBuilder, attributes(builder))]
pub fn derive_builder(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as syn::DeriveInput);
    let data = DefaultBuilderDeriveInput::from_derive_input(&input).expect("Wrong options");
    let stream = quote!(#data);
    stream.into()
}