1#[macro_export]
70macro_rules! builder_helper {
71 (@ { $self:ty, $($builder:ty),+ }) => {
72 trait Builder {
74 #[inline]
75 fn when_some<T>(self: $self, value: Option<T>, func: impl FnOnce($self, T) -> $self) -> $self
76 where
77 Self: Sized,
78 {
79 match value {
80 Some(v) => func(self, v),
81 None => self,
82 }
83 }
84 }
85
86 $(impl Builder for $builder {})+
87 };
88
89 (Self, $($builder:ty),+ $(,)?) => {
90 $crate::builder_helper!(@ {Self, $($builder),+});
91 };
92
93 (&mut Self, $($builder:ty),+ $(,)?) => {
94 $crate::builder_helper!(@ {&mut Self, $($builder),+});
95 };
96}
97
98#[cfg(test)]
99mod tests {
100 #[test]
103 fn test_builder_helper_self() {
104 struct TestBuilder {
106 value: Option<String>,
107 count: Option<u32>,
108 }
109
110 impl TestBuilder {
111 fn new() -> Self {
112 Self {
113 value: None,
114 count: None,
115 }
116 }
117
118 fn set_value(mut self, value: String) -> Self {
119 self.value = Some(value);
120 self
121 }
122
123 fn set_count(mut self, count: u32) -> Self {
124 self.count = Some(count);
125 self
126 }
127
128 fn build(self) -> (Option<String>, Option<u32>) {
129 (self.value, self.count)
130 }
131 }
132
133 builder_helper!(Self, TestBuilder);
135
136 let builder = TestBuilder::new()
138 .when_some(Some("test".to_string()), |b, v| b.set_value(v))
139 .when_some(None::<u32>, |b, _| b.set_count(0))
140 .when_some(Some(42), |b, c| b.set_count(c));
141
142 let (value, count) = builder.build();
143 assert_eq!(value, Some("test".to_string()));
144 assert_eq!(count, Some(42));
145 }
146
147 #[test]
148 fn test_builder_helper_mut_self() {
149 struct MutTestBuilder {
151 value: Option<String>,
152 count: Option<u32>,
153 }
154
155 impl MutTestBuilder {
156 fn new() -> Self {
157 Self {
158 value: None,
159 count: None,
160 }
161 }
162
163 fn set_value(&mut self, value: String) -> &mut Self {
164 self.value = Some(value);
165 self
166 }
167
168 fn set_count(&mut self, count: u32) -> &mut Self {
169 self.count = Some(count);
170 self
171 }
172
173 fn build(&self) -> (Option<String>, Option<u32>) {
174 (self.value.clone(), self.count)
175 }
176 }
177
178 builder_helper!(&mut Self, MutTestBuilder);
180
181 let mut builder = MutTestBuilder::new();
183 builder
184 .when_some(Some("mut_test".to_string()), |b, v| b.set_value(v))
185 .when_some(None::<u32>, |b, _| b.set_count(0))
186 .when_some(Some(99), |b, c| b.set_count(c));
187
188 let (value, count) = builder.build();
189 assert_eq!(value, Some("mut_test".to_string()));
190 assert_eq!(count, Some(99));
191 }
192
193 #[test]
194 fn test_builder_helper_multiple_types() {
195 struct Builder1 {
197 value: Option<String>,
198 }
199
200 struct Builder2 {
201 value: Option<String>,
202 }
203
204 impl Builder1 {
205 fn new() -> Self {
206 Self { value: None }
207 }
208
209 fn set_value(mut self, value: String) -> Self {
210 self.value = Some(value);
211 self
212 }
213
214 fn build(self) -> Option<String> {
215 self.value
216 }
217 }
218
219 impl Builder2 {
220 fn new() -> Self {
221 Self { value: None }
222 }
223
224 fn set_value(mut self, value: String) -> Self {
225 self.value = Some(value);
226 self
227 }
228
229 fn build(self) -> Option<String> {
230 self.value
231 }
232 }
233
234 builder_helper!(Self, Builder1, Builder2);
236
237 let builder1 =
239 Builder1::new().when_some(Some("builder1".to_string()), |b, v| b.set_value(v));
240 assert_eq!(builder1.build(), Some("builder1".to_string()));
241
242 let builder2 =
244 Builder2::new().when_some(Some("builder2".to_string()), |b, v| b.set_value(v));
245 assert_eq!(builder2.build(), Some("builder2".to_string()));
246 }
247
248 #[test]
249 fn test_when_some_with_none() {
250 struct SimpleBuilder {
251 value: Option<String>,
252 }
253
254 impl SimpleBuilder {
255 fn new() -> Self {
256 Self { value: None }
257 }
258
259 fn set_value(mut self, value: String) -> Self {
260 self.value = Some(value);
261 self
262 }
263
264 fn build(self) -> Option<String> {
265 self.value
266 }
267 }
268
269 builder_helper!(Self, SimpleBuilder);
270
271 let builder = SimpleBuilder::new().when_some(None::<String>, |b, _| {
273 b.set_value("should not be set".to_string())
274 });
275
276 assert_eq!(builder.build(), None);
277 }
278
279 #[test]
280 fn test_when_some_with_some() {
281 struct SimpleBuilder {
282 value: Option<String>,
283 }
284
285 impl SimpleBuilder {
286 fn new() -> Self {
287 Self { value: None }
288 }
289
290 fn set_value(mut self, value: String) -> Self {
291 self.value = Some(value);
292 self
293 }
294
295 fn build(self) -> Option<String> {
296 self.value
297 }
298 }
299
300 builder_helper!(Self, SimpleBuilder);
301
302 let builder =
304 SimpleBuilder::new().when_some(Some("test_value".to_string()), |b, v| b.set_value(v));
305
306 assert_eq!(builder.build(), Some("test_value".to_string()));
307 }
308
309 #[test]
310 fn test_chaining_with_when_some() {
311 struct ChainBuilder {
312 value1: Option<String>,
313 value2: Option<String>,
314 count: Option<u32>,
315 }
316
317 impl ChainBuilder {
318 fn new() -> Self {
319 Self {
320 value1: None,
321 value2: None,
322 count: None,
323 }
324 }
325
326 fn set_value1(mut self, value: String) -> Self {
327 self.value1 = Some(value);
328 self
329 }
330
331 fn set_value2(mut self, value: String) -> Self {
332 self.value2 = Some(value);
333 self
334 }
335
336 fn set_count(mut self, count: u32) -> Self {
337 self.count = Some(count);
338 self
339 }
340
341 fn build(self) -> (Option<String>, Option<String>, Option<u32>) {
342 (self.value1, self.value2, self.count)
343 }
344 }
345
346 builder_helper!(Self, ChainBuilder);
347
348 let builder = ChainBuilder::new()
350 .set_value1("value1".to_string())
351 .when_some(Some("value2".to_string()), |b, v| b.set_value2(v))
352 .when_some(Some(100), |b, c| b.set_count(c))
353 .when_some(None::<String>, |b, _| b.set_value1("ignored".to_string()));
354
355 let (value1, value2, count) = builder.build();
356 assert_eq!(value1, Some("value1".to_string()));
357 assert_eq!(value2, Some("value2".to_string()));
358 assert_eq!(count, Some(100));
359 }
360}