1use rust_queries_builder::{Query, LazyQuery, Queryable};
6use key_paths_derive::Keypaths;
7use std::collections::VecDeque;
8
9#[derive(Debug, Clone, Keypaths)]
10struct Product {
11 id: u32,
12 name: String,
13 price: f64,
14 category: String,
15 in_stock: bool,
16}
17
18struct PaginatedCollection<T> {
24 pages: Vec<Vec<T>>,
25 page_size: usize,
26}
27
28impl<T> PaginatedCollection<T> {
29 fn new(page_size: usize) -> Self {
30 Self {
31 pages: Vec::new(),
32 page_size,
33 }
34 }
35
36 fn add(&mut self, item: T) {
37 if self.pages.is_empty() || self.pages.last().unwrap().len() >= self.page_size {
38 self.pages.push(Vec::new());
39 }
40 self.pages.last_mut().unwrap().push(item);
41 }
42
43 fn total_items(&self) -> usize {
44 self.pages.iter().map(|p| p.len()).sum()
45 }
46}
47
48impl<T> Queryable<T> for PaginatedCollection<T> {
50 fn query_iter(&self) -> Box<dyn Iterator<Item = &T> + '_> {
51 Box::new(self.pages.iter().flat_map(|page| page.iter()))
52 }
53}
54
55struct CircularBuffer<T> {
61 buffer: VecDeque<T>,
62 capacity: usize,
63}
64
65impl<T> CircularBuffer<T> {
66 fn new(capacity: usize) -> Self {
67 Self {
68 buffer: VecDeque::with_capacity(capacity),
69 capacity,
70 }
71 }
72
73 fn push(&mut self, item: T) {
74 if self.buffer.len() >= self.capacity {
75 self.buffer.pop_front();
76 }
77 self.buffer.push_back(item);
78 }
79
80 fn len(&self) -> usize {
81 self.buffer.len()
82 }
83}
84
85impl<T> Queryable<T> for CircularBuffer<T> {
87 fn query_iter(&self) -> Box<dyn Iterator<Item = &T> + '_> {
88 Box::new(self.buffer.iter())
89 }
90}
91
92struct FilteredStorage<T, F>
98where
99 F: Fn(&T) -> bool,
100{
101 items: Vec<T>,
102 filter: F,
103}
104
105impl<T, F> FilteredStorage<T, F>
106where
107 F: Fn(&T) -> bool,
108{
109 fn new(filter: F) -> Self {
110 Self {
111 items: Vec::new(),
112 filter,
113 }
114 }
115
116 fn add(&mut self, item: T) -> bool {
117 if (self.filter)(&item) {
118 self.items.push(item);
119 true
120 } else {
121 false
122 }
123 }
124
125 fn len(&self) -> usize {
126 self.items.len()
127 }
128}
129
130impl<T, F> Queryable<T> for FilteredStorage<T, F>
132where
133 F: Fn(&T) -> bool,
134{
135 fn query_iter(&self) -> Box<dyn Iterator<Item = &T> + '_> {
136 Box::new(self.items.iter())
137 }
138}
139
140use std::collections::HashMap;
146
147struct CategoryIndex<T> {
148 by_category: HashMap<String, Vec<T>>,
149}
150
151impl<T> CategoryIndex<T> {
152 fn new() -> Self {
153 Self {
154 by_category: HashMap::new(),
155 }
156 }
157
158 fn add(&mut self, category: String, item: T) {
159 self.by_category
160 .entry(category)
161 .or_insert_with(Vec::new)
162 .push(item);
163 }
164
165 fn total_items(&self) -> usize {
166 self.by_category.values().map(|v| v.len()).sum()
167 }
168
169 fn categories(&self) -> Vec<&String> {
170 self.by_category.keys().collect()
171 }
172}
173
174impl<T> Queryable<T> for CategoryIndex<T> {
176 fn query_iter(&self) -> Box<dyn Iterator<Item = &T> + '_> {
177 Box::new(self.by_category.values().flat_map(|vec| vec.iter()))
178 }
179}
180
181struct LazyLoader<T> {
187 loaded_items: Vec<T>,
188 total_count: usize,
189}
190
191impl<T> LazyLoader<T> {
192 fn new(items: Vec<T>) -> Self {
193 let total = items.len();
194 Self {
195 loaded_items: items,
196 total_count: total,
197 }
198 }
199
200 fn loaded_count(&self) -> usize {
201 self.loaded_items.len()
202 }
203
204 fn total_count(&self) -> usize {
205 self.total_count
206 }
207}
208
209impl<T> Queryable<T> for LazyLoader<T> {
211 fn query_iter(&self) -> Box<dyn Iterator<Item = &T> + '_> {
212 Box::new(self.loaded_items.iter())
213 }
214}
215
216fn create_sample_product(id: u32, name: &str, price: f64, category: &str, in_stock: bool) -> Product {
221 Product {
222 id,
223 name: name.to_string(),
224 price,
225 category: category.to_string(),
226 in_stock,
227 }
228}
229
230fn main() {
231 println!("\n╔════════════════════════════════════════════════════════════════╗");
232 println!("║ Custom Queryable Implementation Demo ║");
233 println!("╚════════════════════════════════════════════════════════════════╝\n");
234
235 println!("═══════════════════════════════════════════════════════════════");
239 println!("Demo 1: PaginatedCollection (custom container)");
240 println!("═══════════════════════════════════════════════════════════════\n");
241
242 let mut paginated = PaginatedCollection::new(3); paginated.add(create_sample_product(1, "Laptop", 999.0, "Electronics", true));
245 paginated.add(create_sample_product(2, "Mouse", 29.0, "Electronics", true));
246 paginated.add(create_sample_product(3, "Keyboard", 129.0, "Electronics", true));
247 paginated.add(create_sample_product(4, "Desk", 299.0, "Furniture", true));
248 paginated.add(create_sample_product(5, "Chair", 199.0, "Furniture", false));
249
250 println!(" Created paginated collection:");
251 println!(" Total items: {}", paginated.total_items());
252 println!(" Pages: {}", paginated.pages.len());
253
254 let items: Vec<Product> = paginated.query_iter().cloned().collect();
257 let query = Query::new(&items)
258 .where_(Product::category_r(), |cat| cat == "Electronics");
259 let electronics = query.all();
260
261 println!("\n Querying paginated collection:");
262 println!(" Electronics found: {}", electronics.len());
263 for product in electronics {
264 println!(" • {}: ${:.2}", product.name, product.price);
265 }
266
267 println!("\n═══════════════════════════════════════════════════════════════");
271 println!("Demo 2: CircularBuffer (fixed capacity)");
272 println!("═══════════════════════════════════════════════════════════════\n");
273
274 let mut circular = CircularBuffer::new(3); circular.push(create_sample_product(1, "Product 1", 100.0, "A", true));
277 circular.push(create_sample_product(2, "Product 2", 200.0, "B", true));
278 circular.push(create_sample_product(3, "Product 3", 300.0, "C", true));
279 circular.push(create_sample_product(4, "Product 4", 400.0, "D", true)); println!(" Circular buffer (capacity 3, added 4 items):");
282 println!(" Current size: {}", circular.len());
283
284 let circ_items: Vec<Product> = circular.query_iter().cloned().collect();
286 let circ_query = Query::new(&circ_items);
287 let avg_price = circ_query.avg(Product::price_r()).unwrap_or(0.0);
288
289 println!("\n Querying circular buffer:");
290 println!(" Average price: ${:.2}", avg_price);
291 println!(" Items:");
292 for (i, product) in circ_items.iter().enumerate() {
293 println!(" {}. {}: ${:.2}", i + 1, product.name, product.price);
294 }
295
296 println!("\n═══════════════════════════════════════════════════════════════");
300 println!("Demo 3: FilteredStorage (auto-filtering container)");
301 println!("═══════════════════════════════════════════════════════════════\n");
302
303 let mut filtered = FilteredStorage::new(|p: &Product| p.price < 200.0);
304
305 println!(" FilteredStorage (only accepts items < $200):");
306 println!(" Adding Laptop ($999): {}", filtered.add(create_sample_product(1, "Laptop", 999.0, "Electronics", true)));
307 println!(" Adding Mouse ($29): {}", filtered.add(create_sample_product(2, "Mouse", 29.0, "Electronics", true)));
308 println!(" Adding Keyboard ($129): {}", filtered.add(create_sample_product(3, "Keyboard", 129.0, "Electronics", true)));
309 println!(" Total stored: {}", filtered.len());
310
311 let filt_items: Vec<Product> = filtered.query_iter().cloned().collect();
313 let filt_query = Query::new(&filt_items)
314 .where_(Product::in_stock_r(), |&v| v);
315 let in_stock = filt_query.all();
316
317 println!("\n Querying filtered storage:");
318 println!(" In stock items: {}", in_stock.len());
319
320 println!("\n═══════════════════════════════════════════════════════════════");
324 println!("Demo 4: CategoryIndex (indexed by category)");
325 println!("═══════════════════════════════════════════════════════════════\n");
326
327 let mut category_index = CategoryIndex::new();
328
329 category_index.add("Electronics".to_string(), create_sample_product(1, "Monitor", 349.0, "Electronics", true));
330 category_index.add("Electronics".to_string(), create_sample_product(2, "Webcam", 79.0, "Electronics", true));
331 category_index.add("Furniture".to_string(), create_sample_product(3, "Desk", 299.0, "Furniture", true));
332 category_index.add("Furniture".to_string(), create_sample_product(4, "Lamp", 39.0, "Furniture", true));
333
334 println!(" CategoryIndex:");
335 println!(" Categories: {:?}", category_index.categories());
336 println!(" Total items: {}", category_index.total_items());
337
338 let idx_items: Vec<Product> = category_index.query_iter().cloned().collect();
340 let idx_query = Query::new(&idx_items);
341 let expensive = idx_query
342 .where_(Product::price_r(), |&p| p > 100.0);
343 let expensive_items = expensive.all();
344
345 println!("\n Querying category index:");
346 println!(" Expensive items (>$100): {}", expensive_items.len());
347 for product in expensive_items {
348 println!(" • {}: ${:.2} ({})", product.name, product.price, product.category);
349 }
350
351 println!("\n═══════════════════════════════════════════════════════════════");
355 println!("Demo 5: LazyLoader (simulated lazy loading)");
356 println!("═══════════════════════════════════════════════════════════════\n");
357
358 let loader = LazyLoader::new(vec![
359 create_sample_product(1, "Item 1", 50.0, "A", true),
360 create_sample_product(2, "Item 2", 150.0, "B", true),
361 create_sample_product(3, "Item 3", 250.0, "C", true),
362 ]);
363
364 println!(" LazyLoader:");
365 println!(" Total available: {}", loader.total_count());
366 println!(" Currently loaded: {}", loader.loaded_count());
367
368 let loader_items: Vec<Product> = loader.query_iter().cloned().collect();
370 let loader_query = Query::new(&loader_items);
371 let total_value = loader_query.sum(Product::price_r());
372
373 println!("\n Querying lazy loader:");
374 println!(" Total value: ${:.2}", total_value);
375
376 println!("\n═══════════════════════════════════════════════════════════════");
380 println!("Demo 6: Using LazyQuery with custom containers");
381 println!("═══════════════════════════════════════════════════════════════\n");
382
383 let mut circular = CircularBuffer::new(5);
384 for i in 1..=10 {
385 circular.push(create_sample_product(
386 i,
387 &format!("Product {}", i),
388 i as f64 * 50.0,
389 if i % 2 == 0 { "Even" } else { "Odd" },
390 true,
391 ));
392 }
393
394 println!(" Circular buffer (capacity 5, added 10 items):");
395 println!(" Current size: {}", circular.len());
396
397 let circ_vec: Vec<Product> = circular.query_iter().cloned().collect();
399 let first_expensive = LazyQuery::new(&circ_vec)
400 .where_(Product::price_r(), |&p| p > 300.0)
401 .first();
402
403 if let Some(product) = first_expensive {
404 println!("\n First expensive item (lazy query):");
405 println!(" {}: ${:.2}", product.name, product.price);
406 }
407
408 println!("\n═══════════════════════════════════════════════════════════════");
412 println!("Demo 7: Queryable for wrapper types");
413 println!("═══════════════════════════════════════════════════════════════\n");
414
415 struct VersionedCollection<T> {
417 items: Vec<T>,
418 version: u32,
419 last_modified: String,
420 }
421
422 impl<T> Queryable<T> for VersionedCollection<T> {
423 fn query_iter(&self) -> Box<dyn Iterator<Item = &T> + '_> {
424 Box::new(self.items.iter())
425 }
426 }
427
428 let versioned = VersionedCollection {
429 items: vec![
430 create_sample_product(1, "V1 Product", 99.0, "Test", true),
431 create_sample_product(2, "V2 Product", 199.0, "Test", true),
432 ],
433 version: 2,
434 last_modified: "2025-10-11".to_string(),
435 };
436
437 println!(" VersionedCollection:");
438 println!(" Version: {}", versioned.version);
439 println!(" Last modified: {}", versioned.last_modified);
440
441 let versioned_items: Vec<Product> = versioned.query_iter().cloned().collect();
442 let query = Query::new(&versioned_items);
443 println!(" Items: {}", query.count());
444
445 println!("\n═══════════════════════════════════════════════════════════════");
449 println!("Demo 8: Cache container (real-world example)");
450 println!("═══════════════════════════════════════════════════════════════\n");
451
452 use std::time::{Duration, SystemTime};
453
454 struct CachedItem<T> {
455 item: T,
456 inserted_at: SystemTime,
457 ttl: Duration,
458 }
459
460 struct Cache<T> {
461 items: Vec<CachedItem<T>>,
462 }
463
464 impl<T> Cache<T> {
465 fn new() -> Self {
466 Self { items: Vec::new() }
467 }
468
469 fn insert(&mut self, item: T, ttl: Duration) {
470 self.items.push(CachedItem {
471 item,
472 inserted_at: SystemTime::now(),
473 ttl,
474 });
475 }
476
477 fn valid_items(&self) -> Vec<&T> {
478 let now = SystemTime::now();
479 self.items
480 .iter()
481 .filter(|cached| {
482 now.duration_since(cached.inserted_at)
483 .map_or(false, |elapsed| elapsed < cached.ttl)
484 })
485 .map(|cached| &cached.item)
486 .collect()
487 }
488 }
489
490 impl<T> Queryable<T> for Cache<T> {
492 fn query_iter(&self) -> Box<dyn Iterator<Item = &T> + '_> {
493 let now = SystemTime::now();
494 Box::new(
495 self.items
496 .iter()
497 .filter(move |cached| {
498 now.duration_since(cached.inserted_at)
499 .map_or(false, |elapsed| elapsed < cached.ttl)
500 })
501 .map(|cached| &cached.item),
502 )
503 }
504 }
505
506 let mut cache = Cache::new();
507 cache.insert(create_sample_product(1, "Cached Item 1", 100.0, "A", true), Duration::from_secs(60));
508 cache.insert(create_sample_product(2, "Cached Item 2", 200.0, "B", true), Duration::from_secs(60));
509
510 let valid = cache.valid_items();
511 println!(" Cache:");
512 println!(" Total items: {}", cache.items.len());
513 println!(" Valid items: {}", valid.len());
514
515 let cache_items: Vec<Product> = cache.query_iter().cloned().collect();
517 let cache_query = Query::new(&cache_items);
518 println!(" Queryable items: {}", cache_query.count());
519
520 println!("\n╔════════════════════════════════════════════════════════════════╗");
524 println!("║ Summary: Implementing Queryable ║");
525 println!("╚════════════════════════════════════════════════════════════════╝\n");
526
527 println!("✅ How to make any container queryable:\n");
528 println!(" 1. Implement the Queryable<T> trait:");
529 println!(" ```rust");
530 println!(" impl<T> Queryable<T> for MyContainer<T> {{");
531 println!(" fn query_iter(&self) -> Box<dyn Iterator<Item = &T> + '_> {{");
532 println!(" Box::new(self.items.iter())");
533 println!(" }}");
534 println!(" }}");
535 println!(" ```\n");
536
537 println!(" 2. Convert to Vec or slice for querying:");
538 println!(" ```rust");
539 println!(" let items: Vec<&Product> = container.query_iter().collect();");
540 println!(" let query = Query::new(&items);");
541 println!(" ```\n");
542
543 println!(" 3. Now use all query operations:");
544 println!(" ```rust");
545 println!(" let results = query.where_(...).all();");
546 println!(" let count = query.count();");
547 println!(" let total = query.sum(field);");
548 println!(" ```\n");
549
550 println!("📝 Custom containers demonstrated:");
551 println!(" • PaginatedCollection - Items stored in pages");
552 println!(" • CircularBuffer - Fixed-capacity FIFO buffer");
553 println!(" • FilteredStorage - Auto-filtering container");
554 println!(" • CategoryIndex - Indexed by category");
555 println!(" • LazyLoader - Simulated lazy loading");
556 println!(" • VersionedCollection - Wrapper with metadata");
557 println!(" • Cache - TTL-based cache\n");
558
559 println!("💡 Use cases:");
560 println!(" • Database result wrappers");
561 println!(" • Custom data structures");
562 println!(" • Specialized collections");
563 println!(" • Caches and buffers");
564 println!(" • Event streams");
565 println!(" • Any container that holds items!\n");
566
567 println!("✓ Custom Queryable demo complete!\n");
568}
569