1use super::iterators::{ChunkIterator, WindowIterator};
5use super::{QueryBuilder, QueryData};
6use crate::core::state::{Filtered, Sorted};
7use crate::core::state_diagnostics::HashEqBound;
8use num_traits::ToPrimitive;
9use std::cmp::Ordering;
10use std::collections::{HashMap, HashSet, VecDeque};
11use std::hash::Hash;
12use std::iter::Sum;
13use std::marker::PhantomData;
14
15impl<T: 'static> QueryBuilder<T, Sorted> {
16 #[inline]
22 pub fn inspect<F>(self, f: F) -> QueryBuilder<T, Filtered>
23 where
24 F: Fn(&T) + 'static,
25 {
26 match self.data {
27 QueryData::SortedVec { items, .. } => {
28 QueryBuilder {
30 data: QueryData::Iterator(Box::new(items.into_iter().inspect(f))),
31 _state: PhantomData,
32 }
33 }
34 QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
35 }
36 }
37
38 #[inline]
64 pub fn then_by<K, F>(self, key_selector: F) -> QueryBuilder<T, Sorted>
65 where
66 F: Fn(&T) -> K + 'static,
67 K: Ord + 'static,
68 T: 'static,
69 {
70 match self.data {
71 QueryData::SortedVec {
72 mut items,
73 comparator,
74 } => {
75 let primary_comparator = comparator;
76 let new_comparator = Box::new(move |a: &T, b: &T| match primary_comparator(a, b) {
77 Ordering::Equal => key_selector(a).cmp(&key_selector(b)),
78 other => other,
79 });
80
81 items.sort_by(|a, b| new_comparator(a, b));
82
83 QueryBuilder {
84 data: QueryData::SortedVec {
85 items,
86 comparator: new_comparator,
87 },
88 _state: PhantomData,
89 }
90 }
91 QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
92 }
93 }
94
95 #[inline]
127 pub fn then_by_descending<K, F>(self, key_selector: F) -> QueryBuilder<T, Sorted>
128 where
129 F: Fn(&T) -> K + 'static,
130 K: Ord + 'static,
131 T: 'static,
132 {
133 match self.data {
134 QueryData::SortedVec {
135 mut items,
136 comparator,
137 } => {
138 let primary_comparator = comparator;
139 let new_comparator = Box::new(move |a: &T, b: &T| match primary_comparator(a, b) {
140 Ordering::Equal => key_selector(b).cmp(&key_selector(a)),
141 other => other,
142 });
143
144 items.sort_by(|a, b| new_comparator(a, b));
145
146 QueryBuilder {
147 data: QueryData::SortedVec {
148 items,
149 comparator: new_comparator,
150 },
151 _state: PhantomData,
152 }
153 }
154 QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
155 }
156 }
157
158 #[inline]
160 pub fn take(self, n: usize) -> QueryBuilder<T, Filtered> {
161 match self.data {
162 QueryData::SortedVec { items, .. } => QueryBuilder {
163 data: QueryData::Iterator(Box::new(items.into_iter().take(n))),
164 _state: PhantomData,
165 },
166 QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
167 }
168 }
169
170 #[inline]
172 pub fn skip(self, n: usize) -> QueryBuilder<T, Filtered> {
173 match self.data {
174 QueryData::SortedVec { items, .. } => QueryBuilder {
175 data: QueryData::Iterator(Box::new(items.into_iter().skip(n))),
176 _state: PhantomData,
177 },
178 QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
179 }
180 }
181
182 #[inline]
186 pub fn take_while<F>(self, predicate: F) -> QueryBuilder<T, Filtered>
187 where
188 F: Fn(&T) -> bool + 'static,
189 {
190 match self.data {
191 QueryData::SortedVec { items, .. } => QueryBuilder {
192 data: QueryData::Iterator(Box::new(
193 items.into_iter().take_while(move |x| predicate(x)),
194 )),
195 _state: PhantomData,
196 },
197 QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
198 }
199 }
200
201 #[inline]
205 pub fn skip_while<F>(self, predicate: F) -> QueryBuilder<T, Filtered>
206 where
207 F: Fn(&T) -> bool + 'static,
208 {
209 match self.data {
210 QueryData::SortedVec { items, .. } => QueryBuilder {
211 data: QueryData::Iterator(Box::new(
212 items.into_iter().skip_while(move |x| predicate(x)),
213 )),
214 _state: PhantomData,
215 },
216 QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
217 }
218 }
219
220 #[inline]
222 pub fn sum(self) -> T
223 where
224 T: Sum,
225 {
226 match self.data {
227 QueryData::SortedVec { items, .. } => items.into_iter().sum(),
228 QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
229 }
230 }
231
232 #[inline]
234 pub fn average(self) -> Option<f64>
235 where
236 T: ToPrimitive,
237 {
238 match self.data {
239 QueryData::SortedVec { items, .. } => {
240 if items.is_empty() {
241 return None;
242 }
243 let sum: f64 = items.iter().filter_map(|x| x.to_f64()).sum();
244 Some(sum / items.len() as f64)
245 }
246 QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
247 }
248 }
249
250 #[inline]
254 pub fn min(self) -> Option<T>
255 where
256 T: Ord,
257 {
258 match self.data {
259 QueryData::SortedVec { mut items, .. } => {
260 if items.is_empty() {
262 None
263 } else {
264 Some(items.remove(0))
265 }
266 }
267 QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
268 }
269 }
270
271 #[inline]
275 pub fn max(self) -> Option<T>
276 where
277 T: Ord,
278 {
279 match self.data {
280 QueryData::SortedVec { mut items, .. } => {
281 items.pop()
283 }
284 QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
285 }
286 }
287
288 #[inline]
290 pub fn min_by<K, F>(self, key_selector: F) -> Option<T>
291 where
292 F: Fn(&T) -> K,
293 K: Ord,
294 {
295 match self.data {
296 QueryData::SortedVec { items, .. } => items.into_iter().min_by_key(key_selector),
297 QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
298 }
299 }
300
301 #[inline]
303 pub fn max_by<K, F>(self, key_selector: F) -> Option<T>
304 where
305 F: Fn(&T) -> K,
306 K: Ord,
307 {
308 match self.data {
309 QueryData::SortedVec { items, .. } => items.into_iter().max_by_key(key_selector),
310 QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
311 }
312 }
313
314 #[inline]
318 pub fn group_by<K, F>(self, key_selector: F) -> HashMap<K, Vec<T>>
319 where
320 F: Fn(&T) -> K,
321 K: Eq + Hash,
322 {
323 match self.data {
324 QueryData::SortedVec { items, .. } => {
325 let mut groups: HashMap<K, Vec<T>> = HashMap::new();
326 for item in items {
327 let key = key_selector(&item);
328 groups.entry(key).or_default().push(item);
329 }
330 groups
331 }
332 QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
333 }
334 }
335
336 #[inline]
338 pub fn group_by_aggregate<K, R, FK, FA>(self, key_selector: FK, aggregator: FA) -> HashMap<K, R>
339 where
340 FK: Fn(&T) -> K,
341 FA: Fn(&[T]) -> R,
342 K: Eq + Hash,
343 {
344 let groups = self.group_by(key_selector);
345 groups
346 .into_iter()
347 .map(|(k, v)| (k, aggregator(&v)))
348 .collect()
349 }
350
351 #[inline]
355 pub fn distinct(self) -> QueryBuilder<T, Filtered>
356 where
357 T: HashEqBound + Clone,
358 {
359 match self.data {
360 QueryData::SortedVec { items, .. } => {
361 let mut seen = HashSet::new();
362 let filtered = items.into_iter().filter(move |item| {
363 if seen.contains(item) {
364 false
365 } else {
366 seen.insert(item.clone());
367 true
368 }
369 });
370
371 QueryBuilder {
372 data: QueryData::Iterator(Box::new(filtered)),
373 _state: PhantomData,
374 }
375 }
376 QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
377 }
378 }
379
380 #[inline]
382 pub fn distinct_by<K, F>(self, key_selector: F) -> QueryBuilder<T, Filtered>
383 where
384 F: Fn(&T) -> K + 'static,
385 K: Eq + Hash + 'static,
386 {
387 match self.data {
388 QueryData::SortedVec { items, .. } => {
389 let mut seen = HashSet::new();
390 let filtered = items.into_iter().filter(move |item| {
391 let key = key_selector(item);
392 if seen.contains(&key) {
393 false
394 } else {
395 seen.insert(key);
396 true
397 }
398 });
399
400 QueryBuilder {
401 data: QueryData::Iterator(Box::new(filtered)),
402 _state: PhantomData,
403 }
404 }
405 QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
406 }
407 }
408
409 #[inline]
411 pub fn reverse(self) -> QueryBuilder<T, Filtered> {
412 match self.data {
413 QueryData::SortedVec { mut items, .. } => {
414 items.reverse();
415
416 QueryBuilder {
417 data: QueryData::Iterator(Box::new(items.into_iter())),
418 _state: PhantomData,
419 }
420 }
421 QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
422 }
423 }
424
425 #[inline]
431 pub fn chunk(self, size: usize) -> QueryBuilder<Vec<T>, Filtered> {
432 assert!(size > 0, "chunk size must be greater than 0");
433
434 match self.data {
435 QueryData::SortedVec { items, .. } => {
436 let chunk_iter = ChunkIterator {
437 inner: items.into_iter(),
438 chunk_size: size,
439 };
440
441 QueryBuilder {
442 data: QueryData::Iterator(Box::new(chunk_iter)),
443 _state: PhantomData,
444 }
445 }
446 QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
447 }
448 }
449
450 #[inline]
456 pub fn window(self, size: usize) -> QueryBuilder<Vec<T>, Filtered>
457 where
458 T: Clone,
459 {
460 assert!(size > 0, "window size must be greater than 0");
461
462 match self.data {
463 QueryData::SortedVec { items, .. } => {
464 let window_iter = WindowIterator {
465 buffer: VecDeque::new(),
466 inner: Box::new(items.into_iter()),
467 window_size: size,
468 finished: false,
469 };
470
471 QueryBuilder {
472 data: QueryData::Iterator(Box::new(window_iter)),
473 _state: PhantomData,
474 }
475 }
476 QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
477 }
478 }
479
480 #[inline]
482 pub fn zip<U, I>(self, other: I) -> QueryBuilder<(T, U), Filtered>
483 where
484 U: 'static,
485 I: IntoIterator<Item = U> + 'static,
486 I::IntoIter: 'static,
487 {
488 match self.data {
489 QueryData::SortedVec { items, .. } => {
490 let zipped = items.into_iter().zip(other);
491
492 QueryBuilder {
493 data: QueryData::Iterator(Box::new(zipped)),
494 _state: PhantomData,
495 }
496 }
497 QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
498 }
499 }
500
501 #[inline]
503 pub fn enumerate(self) -> QueryBuilder<(usize, T), Filtered> {
504 match self.data {
505 QueryData::SortedVec { items, .. } => {
506 let enumerated = items.into_iter().enumerate();
507
508 QueryBuilder {
509 data: QueryData::Iterator(Box::new(enumerated)),
510 _state: PhantomData,
511 }
512 }
513 QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
514 }
515 }
516
517 #[inline]
519 pub fn partition<F>(self, predicate: F) -> (Vec<T>, Vec<T>)
520 where
521 F: Fn(&T) -> bool,
522 {
523 match self.data {
524 QueryData::SortedVec { items, .. } => {
525 let mut left = Vec::new();
526 let mut right = Vec::new();
527
528 for item in items {
529 if predicate(&item) {
530 left.push(item);
531 } else {
532 right.push(item);
533 }
534 }
535
536 (left, right)
537 }
538 QueryData::Iterator(_) => unreachable!("Sorted state must be SortedVec"),
539 }
540 }
541}