rust_queries_core/
lock_lazy.rs

1//! Lazy query support for locked data structures.
2//!
3//! Provides lazy evaluation with early termination for locked collections.
4
5use crate::locks::LockValue;
6use key_paths_core::KeyPaths;
7use std::marker::PhantomData;
8
9/// Lazy query for locked data with early termination.
10pub struct LockLazyQuery<'a, T: 'static, L, I>
11where
12    L: LockValue<T> + 'a,
13    I: Iterator<Item = &'a L>,
14{
15    iter: I,
16    _phantom: PhantomData<&'a T>,
17}
18
19impl<'a, T: 'static, L, I> LockLazyQuery<'a, T, L, I>
20where
21    L: LockValue<T> + 'a,
22    I: Iterator<Item = &'a L> + 'a,
23{
24    /// Create a new lazy query from an iterator of locks.
25    pub fn new(iter: I) -> Self {
26        Self {
27            iter,
28            _phantom: PhantomData,
29        }
30    }
31
32    /// Filter using a key-path predicate (lazy).
33    pub fn where_<F, P>(self, path: KeyPaths<T, F>, predicate: P) -> LockLazyQuery<'a, T, L, impl Iterator<Item = &'a L> + 'a>
34    where
35        F: 'static,
36        P: Fn(&F) -> bool + 'a,
37    {
38        LockLazyQuery {
39            iter: self.iter.filter(move |lock| {
40                lock.with_value(|item| {
41                    path.get(item).map_or(false, |val| predicate(val))
42                })
43                .unwrap_or(false)
44            }),
45            _phantom: PhantomData,
46        }
47    }
48
49    /// Map to a field value (lazy).
50    pub fn select_lazy<F>(self, path: KeyPaths<T, F>) -> impl Iterator<Item = F> + 'a
51    where
52        F: Clone + 'static,
53    {
54        self.iter.filter_map(move |lock| {
55            lock.with_value(|item| path.get(item).cloned()).flatten()
56        })
57    }
58
59    /// Take first N items (lazy).
60    pub fn take_lazy(self, n: usize) -> impl Iterator<Item = T> + 'a
61    where
62        T: Clone,
63    {
64        self.iter
65            .filter_map(|lock| lock.with_value(|item| item.clone()))
66            .take(n)
67    }
68
69    /// Skip first N items (lazy).
70    pub fn skip_lazy(self, n: usize) -> LockLazyQuery<'a, T, L, impl Iterator<Item = &'a L> + 'a> {
71        LockLazyQuery {
72            iter: self.iter.skip(n),
73            _phantom: PhantomData,
74        }
75    }
76
77    /// Count matching items (terminal).
78    pub fn count(self) -> usize {
79        self.iter.count()
80    }
81
82    /// Get first matching item (terminal).
83    pub fn first(mut self) -> Option<T>
84    where
85        T: Clone,
86    {
87        self.iter
88            .find_map(|lock| lock.with_value(|item| item.clone()))
89    }
90
91    /// Check if any items match (terminal).
92    pub fn any(mut self) -> bool {
93        self.iter.next().is_some()
94    }
95
96    /// Collect into Vec (terminal).
97    pub fn collect(self) -> Vec<T>
98    where
99        T: Clone,
100    {
101        self.iter
102            .filter_map(|lock| lock.with_value(|item| item.clone()))
103            .collect()
104    }
105}
106