macro_helpers/
macro_helpers.rs

1// Demonstrates helper macros that reduce boilerplate code
2// Shows before/after comparisons for common query patterns
3// cargo run --example macro_helpers
4
5use rust_queries_builder::LazyQuery;
6use key_paths_derive::Keypaths;
7
8// Import all the helper macros
9use rust_queries_builder::{
10    lazy_query, query, collect_lazy, filter_collect,
11    count_where, find_first, exists_where, paginate,
12    sum_where, avg_where, select_all, select_where,
13};
14
15#[derive(Debug, Clone, Keypaths)]
16struct Product {
17    id: u32,
18    name: String,
19    price: f64,
20    category: String,
21    stock: u32,
22    rating: f64,
23    active: bool,
24}
25
26fn create_products() -> Vec<Product> {
27    vec![
28        Product { id: 1, name: "Laptop".to_string(), price: 999.99, category: "Electronics".to_string(), stock: 15, rating: 4.8, active: true },
29        Product { id: 2, name: "Mouse".to_string(), price: 29.99, category: "Electronics".to_string(), stock: 50, rating: 4.5, active: true },
30        Product { id: 3, name: "Keyboard".to_string(), price: 129.99, category: "Electronics".to_string(), stock: 30, rating: 4.7, active: true },
31        Product { id: 4, name: "Desk".to_string(), price: 299.99, category: "Furniture".to_string(), stock: 20, rating: 4.6, active: true },
32        Product { id: 5, name: "Chair".to_string(), price: 199.99, category: "Furniture".to_string(), stock: 0, rating: 4.3, active: false },
33    ]
34}
35
36fn main() {
37    println!("\n╔════════════════════════════════════════════════════════════════╗");
38    println!("║  Macro Helpers Demo - Reducing Boilerplate                    ║");
39    println!("╚════════════════════════════════════════════════════════════════╝\n");
40
41    let products = create_products();
42
43    // ============================================================================
44    // EXAMPLE 1: Simple Collection
45    // ============================================================================
46    println!("═══════════════════════════════════════════════════════════════");
47    println!("Example 1: collect_lazy! - Simple collection");
48    println!("═══════════════════════════════════════════════════════════════\n");
49
50    println!("❌ Without macro (verbose):");
51    println!("```rust");
52    println!("let results: Vec<_> = LazyQuery::new(&products).collect();");
53    println!("```\n");
54
55    println!("✅ With macro (concise):");
56    println!("```rust");
57    println!("let results = collect_lazy!(&products);");
58    println!("```\n");
59
60    let results = collect_lazy!(&products);
61    println!("Result: {} products collected\n", results.len());
62
63    // ============================================================================
64    // EXAMPLE 2: Filter and Collect
65    // ============================================================================
66    println!("═══════════════════════════════════════════════════════════════");
67    println!("Example 2: filter_collect! - Filter and collect");
68    println!("═══════════════════════════════════════════════════════════════\n");
69
70    println!("❌ Without macro (verbose):");
71    println!("```rust");
72    println!("let electronics: Vec<_> = LazyQuery::new(&products)");
73    println!("    .where_(Product::category_r(), |cat| cat == \"Electronics\")");
74    println!("    .collect();");
75    println!("```\n");
76
77    println!("✅ With macro (concise):");
78    println!("```rust");
79    println!("let electronics = filter_collect!(");
80    println!("    &products,");
81    println!("    Product::category_r(),");
82    println!("    |cat| cat == \"Electronics\"");
83    println!(");");
84    println!("```\n");
85
86    let electronics = filter_collect!(
87        &products,
88        Product::category_r(),
89        |cat| cat == "Electronics"
90    );
91    println!("Result: {} electronics\n", electronics.len());
92
93    // ============================================================================
94    // EXAMPLE 3: Count with Filter
95    // ============================================================================
96    println!("═══════════════════════════════════════════════════════════════");
97    println!("Example 3: count_where! - Count with filter");
98    println!("═══════════════════════════════════════════════════════════════\n");
99
100    println!("❌ Without macro (verbose):");
101    println!("```rust");
102    println!("let count = LazyQuery::new(&products)");
103    println!("    .where_(Product::stock_r(), |&s| s > 0)");
104    println!("    .count();");
105    println!("```\n");
106
107    println!("✅ With macro (concise):");
108    println!("```rust");
109    println!("let count = count_where!(&products, Product::stock_r(), |&s| s > 0);");
110    println!("```\n");
111
112    let count = count_where!(&products, Product::stock_r(), |&s| s > 0);
113    println!("Result: {} products in stock\n", count);
114
115    // ============================================================================
116    // EXAMPLE 4: Find First
117    // ============================================================================
118    println!("═══════════════════════════════════════════════════════════════");
119    println!("Example 4: find_first! - Find first matching item");
120    println!("═══════════════════════════════════════════════════════════════\n");
121
122    println!("❌ Without macro (verbose):");
123    println!("```rust");
124    println!("let found = LazyQuery::new(&products)");
125    println!("    .where_(Product::price_r(), |&p| p > 500.0)");
126    println!("    .first();");
127    println!("```\n");
128
129    println!("✅ With macro (concise):");
130    println!("```rust");
131    println!("let found = find_first!(&products, Product::price_r(), |&p| p > 500.0);");
132    println!("```\n");
133
134    let found = find_first!(&products, Product::price_r(), |&p| p > 500.0);
135    if let Some(p) = found {
136        println!("Result: Found {} at ${:.2}\n", p.name, p.price);
137    }
138
139    // ============================================================================
140    // EXAMPLE 5: Existence Check
141    // ============================================================================
142    println!("═══════════════════════════════════════════════════════════════");
143    println!("Example 5: exists_where! - Check if any item matches");
144    println!("═══════════════════════════════════════════════════════════════\n");
145
146    println!("❌ Without macro (verbose):");
147    println!("```rust");
148    println!("let has_furniture = LazyQuery::new(&products)");
149    println!("    .where_(Product::category_r(), |cat| cat == \"Furniture\")");
150    println!("    .any();");
151    println!("```\n");
152
153    println!("✅ With macro (concise):");
154    println!("```rust");
155    println!("let has_furniture = exists_where!(");
156    println!("    &products,");
157    println!("    Product::category_r(),");
158    println!("    |cat| cat == \"Furniture\"");
159    println!(");");
160    println!("```\n");
161
162    let has_furniture = exists_where!(
163        &products,
164        Product::category_r(),
165        |cat| cat == "Furniture"
166    );
167    println!("Result: Has furniture = {}\n", has_furniture);
168
169    // ============================================================================
170    // EXAMPLE 6: Pagination
171    // ============================================================================
172    println!("═══════════════════════════════════════════════════════════════");
173    println!("Example 6: paginate! - Quick pagination");
174    println!("═══════════════════════════════════════════════════════════════\n");
175
176    println!("❌ Without macro (verbose):");
177    println!("```rust");
178    println!("let page_2: Vec<_> = LazyQuery::new(&products)");
179    println!("    .skip_lazy(1 * 2)  // page * size");
180    println!("    .take_lazy(2)");
181    println!("    .collect();");
182    println!("```\n");
183
184    println!("✅ With macro (concise):");
185    println!("```rust");
186    println!("let page_2 = paginate!(&products, page: 1, size: 2);");
187    println!("```\n");
188
189    let page_2 = paginate!(&products, page: 1, size: 2);
190    println!("Result: Page 2 has {} items\n", page_2.len());
191
192    // ============================================================================
193    // EXAMPLE 7: Sum with Filter
194    // ============================================================================
195    println!("═══════════════════════════════════════════════════════════════");
196    println!("Example 7: sum_where! - Sum with filter");
197    println!("═══════════════════════════════════════════════════════════════\n");
198
199    println!("❌ Without macro (verbose):");
200    println!("```rust");
201    println!("let total: f64 = LazyQuery::new(&products)");
202    println!("    .where_(Product::active_r(), |&a| a)");
203    println!("    .sum_by(Product::price_r());");
204    println!("```\n");
205
206    println!("✅ With macro (concise):");
207    println!("```rust");
208    println!("let total = sum_where!(&products, Product::price_r(), Product::active_r(), |&a| a);");
209    println!("```\n");
210
211    let total = sum_where!(&products, Product::price_r(), Product::active_r(), |&a| a);
212    println!("Result: Total active products value = ${:.2}\n", total);
213
214    // ============================================================================
215    // EXAMPLE 8: Average with Filter
216    // ============================================================================
217    println!("═══════════════════════════════════════════════════════════════");
218    println!("Example 8: avg_where! - Average with filter");
219    println!("═══════════════════════════════════════════════════════════════\n");
220
221    println!("❌ Without macro (verbose):");
222    println!("```rust");
223    println!("let avg = LazyQuery::new(&products)");
224    println!("    .where_(Product::category_r(), |cat| cat == \"Electronics\")");
225    println!("    .avg_by(Product::price_r())");
226    println!("    .unwrap_or(0.0);");
227    println!("```\n");
228
229    println!("✅ With macro (concise):");
230    println!("```rust");
231    println!("let avg = avg_where!(");
232    println!("    &products,");
233    println!("    Product::price_r(),");
234    println!("    Product::category_r(),");
235    println!("    |cat| cat == \"Electronics\"");
236    println!(").unwrap_or(0.0);");
237    println!("```\n");
238
239    let avg = avg_where!(
240        &products,
241        Product::price_r(),
242        Product::category_r(),
243        |cat| cat == "Electronics"
244    ).unwrap_or(0.0);
245    println!("Result: Average electronics price = ${:.2}\n", avg);
246
247    // ============================================================================
248    // EXAMPLE 9: Select All
249    // ============================================================================
250    println!("═══════════════════════════════════════════════════════════════");
251    println!("Example 9: select_all! - Select field from all items");
252    println!("═══════════════════════════════════════════════════════════════\n");
253
254    println!("❌ Without macro (verbose):");
255    println!("```rust");
256    println!("let names: Vec<String> = LazyQuery::new(&products)");
257    println!("    .select_lazy(Product::name_r())");
258    println!("    .collect();");
259    println!("```\n");
260
261    println!("✅ With macro (concise):");
262    println!("```rust");
263    println!("let names = select_all!(&products, Product::name_r());");
264    println!("```\n");
265
266    let names: Vec<String> = select_all!(&products, Product::name_r());
267    println!("Result: {} product names\n", names.len());
268
269    // ============================================================================
270    // EXAMPLE 10: Select with Filter
271    // ============================================================================
272    println!("═══════════════════════════════════════════════════════════════");
273    println!("Example 10: select_where! - Select field with filter");
274    println!("═══════════════════════════════════════════════════════════════\n");
275
276    println!("❌ Without macro (verbose):");
277    println!("```rust");
278    println!("let furniture_names: Vec<String> = LazyQuery::new(&products)");
279    println!("    .where_(Product::category_r(), |cat| cat == \"Furniture\")");
280    println!("    .select_lazy(Product::name_r())");
281    println!("    .collect();");
282    println!("```\n");
283
284    println!("✅ With macro (concise):");
285    println!("```rust");
286    println!("let furniture_names = select_where!(");
287    println!("    &products,");
288    println!("    Product::name_r(),");
289    println!("    Product::category_r(),");
290    println!("    |cat| cat == \"Furniture\"");
291    println!(");");
292    println!("```\n");
293
294    let furniture_names: Vec<String> = select_where!(
295        &products,
296        Product::name_r(),
297        Product::category_r(),
298        |cat| cat == "Furniture"
299    );
300    println!("Result: {} furniture items\n", furniture_names.len());
301
302    // ============================================================================
303    // COMPARISON: Complex Query
304    // ============================================================================
305    println!("═══════════════════════════════════════════════════════════════");
306    println!("Complex Example: Before & After");
307    println!("═══════════════════════════════════════════════════════════════\n");
308
309    println!("Scenario: Filter electronics, under $500, in stock, get first 5\n");
310
311    println!("❌ WITHOUT MACROS (13 lines):");
312    println!("```rust");
313    println!("let results: Vec<_> = LazyQuery::new(&products)");
314    println!("    .where_(");
315    println!("        Product::category_r(),");
316    println!("        |cat| cat == \"Electronics\"");
317    println!("    )");
318    println!("    .where_(Product::price_r(), |&p| p < 500.0)");
319    println!("    .where_(Product::stock_r(), |&s| s > 0)");
320    println!("    .take_lazy(5)");
321    println!("    .collect();");
322    println!("```\n");
323
324    // Actual verbose version
325    let verbose_results: Vec<_> = LazyQuery::new(&products)
326        .where_(Product::category_r(), |cat| cat == "Electronics")
327        .where_(Product::price_r(), |&p| p < 500.0)
328        .where_(Product::stock_r(), |&s| s > 0)
329        .take_lazy(5)
330        .collect();
331
332    println!("✅ WITH MACROS (Shorter, but still need multiple filters):");
333    println!("```rust");
334    println!("let results = lazy_query!(&products)");
335    println!("    .where_(Product::category_r(), |cat| cat == \"Electronics\")");
336    println!("    .where_(Product::price_r(), |&p| p < 500.0)");
337    println!("    .where_(Product::stock_r(), |&s| s > 0)");
338    println!("    .take_lazy(5)");
339    println!("    .collect();");
340    println!("```\n");
341
342    let macro_results = lazy_query!(&products)
343        .where_(Product::category_r(), |cat| cat == "Electronics")
344        .where_(Product::price_r(), |&p| p < 500.0)
345        .where_(Product::stock_r(), |&s| s > 0)
346        .take_lazy(5)
347        .collect();
348
349    println!("Both approaches found {} items ✅\n", verbose_results.len());
350    assert_eq!(verbose_results.len(), macro_results.len());
351
352    // ============================================================================
353    // CODE REDUCTION METRICS
354    // ============================================================================
355    println!("═══════════════════════════════════════════════════════════════");
356    println!("Code Reduction Metrics");
357    println!("═══════════════════════════════════════════════════════════════\n");
358
359    println!("Pattern Comparisons:\n");
360
361    println!("  1. Simple collect:");
362    println!("     Before: LazyQuery::new(&data).collect()");
363    println!("     After:  collect_lazy!(&data)");
364    println!("     Saved:  ~20 characters\n");
365
366    println!("  2. Filter + collect:");
367    println!("     Before: LazyQuery::new(&data).where_(...).collect()");
368    println!("     After:  filter_collect!(&data, field, pred)");
369    println!("     Saved:  ~35 characters\n");
370
371    println!("  3. Count with filter:");
372    println!("     Before: LazyQuery::new(&data).where_(...).count()");
373    println!("     After:  count_where!(&data, field, pred)");
374    println!("     Saved:  ~30 characters\n");
375
376    println!("  4. Pagination:");
377    println!("     Before: LazyQuery::new(&data).skip_lazy(p*s).take_lazy(s).collect()");
378    println!("     After:  paginate!(&data, page: p, size: s)");
379    println!("     Saved:  ~45 characters\n");
380
381    println!("  5. Sum with filter:");
382    println!("     Before: LazyQuery::new(&data).where_(...).sum_by(...)");
383    println!("     After:  sum_where!(&data, sum_field, filter_field, pred)");
384    println!("     Saved:  ~25 characters\n");
385
386    // ============================================================================
387    // ALL MACRO DEMONSTRATIONS
388    // ============================================================================
389    println!("═══════════════════════════════════════════════════════════════");
390    println!("All Available Macros - Quick Reference");
391    println!("═══════════════════════════════════════════════════════════════\n");
392
393    println!("1. lazy_query!(&data)");
394    let _q1 = lazy_query!(&products);
395    println!("   → LazyQuery::new(&data)\n");
396
397    println!("2. query!(&data)");
398    let _q2 = query!(&products);
399    println!("   → Query::new(&data)\n");
400
401    println!("3. collect_lazy!(&data)");
402    let _r3 = collect_lazy!(&products);
403    println!("   → LazyQuery::new(&data).collect()\n");
404
405    println!("4. filter_collect!(&data, field, pred)");
406    let _r4 = filter_collect!(&products, Product::active_r(), |&a| a);
407    println!("   → LazyQuery::new(&data).where_(field, pred).collect()\n");
408
409    println!("5. count_where!(&data, field, pred)");
410    let _r5 = count_where!(&products, Product::active_r(), |&a| a);
411    println!("   → LazyQuery::new(&data).where_(field, pred).count()\n");
412
413    println!("6. find_first!(&data, field, pred)");
414    let _r6 = find_first!(&products, Product::id_r(), |&id| id == 1);
415    println!("   → LazyQuery::new(&data).where_(field, pred).first()\n");
416
417    println!("7. exists_where!(&data, field, pred)");
418    let _r7 = exists_where!(&products, Product::active_r(), |&a| a);
419    println!("   → LazyQuery::new(&data).where_(field, pred).any()\n");
420
421    println!("8. paginate!(&data, page: p, size: s)");
422    let _r8 = paginate!(&products, page: 0, size: 3);
423    println!("   → LazyQuery::new(&data).skip_lazy(p*s).take_lazy(s).collect()\n");
424
425    println!("9. sum_where!(&data, sum_field, filter_field, pred)");
426    let _r9 = sum_where!(&products, Product::price_r(), Product::active_r(), |&a| a);
427    println!("   → LazyQuery::new(&data).where_(filter_field, pred).sum_by(sum_field)\n");
428
429    println!("10. avg_where!(&data, avg_field, filter_field, pred)");
430    let _r10 = avg_where!(&products, Product::price_r(), Product::active_r(), |&a| a);
431    println!("    → LazyQuery::new(&data).where_(filter_field, pred).avg_by(avg_field)\n");
432
433    println!("11. select_all!(&data, field)");
434    let _r11: Vec<String> = select_all!(&products, Product::name_r());
435    println!("    → LazyQuery::new(&data).select_lazy(field).collect()\n");
436
437    println!("12. select_where!(&data, select_field, filter_field, pred)");
438    let _r12: Vec<String> = select_where!(&products, Product::name_r(), Product::active_r(), |&a| a);
439    println!("    → LazyQuery::new(&data).where_(filter, pred).select_lazy(field).collect()\n");
440
441    // ============================================================================
442    // Summary
443    // ============================================================================
444    println!("╔════════════════════════════════════════════════════════════════╗");
445    println!("║  Summary                                                       ║");
446    println!("╚════════════════════════════════════════════════════════════════╝\n");
447
448    println!("✅ 12 helper macros provided:");
449    println!("   • lazy_query! - Create LazyQuery");
450    println!("   • query! - Create Query");
451    println!("   • collect_lazy! - Quick collect");
452    println!("   • filter_collect! - Filter and collect");
453    println!("   • count_where! - Count with filter");
454    println!("   • find_first! - Find first match");
455    println!("   • exists_where! - Existence check");
456    println!("   • paginate! - Easy pagination");
457    println!("   • sum_where! - Sum with filter");
458    println!("   • avg_where! - Average with filter");
459    println!("   • select_all! - Select all");
460    println!("   • select_where! - Select with filter\n");
461
462    println!("📊 Benefits:");
463    println!("   • Less typing (20-45 characters saved per operation)");
464    println!("   • More readable code");
465    println!("   • Common patterns encapsulated");
466    println!("   • Same performance (zero-cost abstraction)");
467    println!("   • Type-safe (compile-time checked)\n");
468
469    println!("💡 When to use:");
470    println!("   • Use macros for simple, common patterns");
471    println!("   • Use full API for complex queries");
472    println!("   • Mix and match as needed\n");
473
474    println!("✓ Macro helpers demo complete!\n");
475}
476