| 1 | use super::plumbing::*; | 
| 2 | use super::*; | 
| 3 |  | 
| 4 | use std::fmt::{self, Debug}; | 
| 5 |  | 
| 6 | /// `FilterMap` creates an iterator that uses `filter_op` to both filter and map elements. | 
| 7 | /// This struct is created by the [`filter_map()`] method on [`ParallelIterator`]. | 
| 8 | /// | 
| 9 | /// [`filter_map()`]: trait.ParallelIterator.html#method.filter_map | 
| 10 | /// [`ParallelIterator`]: trait.ParallelIterator.html | 
| 11 | #[must_use  = "iterator adaptors are lazy and do nothing unless consumed" ] | 
| 12 | #[derive (Clone)] | 
| 13 | pub struct FilterMap<I: ParallelIterator, P> { | 
| 14 |     base: I, | 
| 15 |     filter_op: P, | 
| 16 | } | 
| 17 |  | 
| 18 | impl<I: ParallelIterator + Debug, P> Debug for FilterMap<I, P> { | 
| 19 |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
| 20 |         f&mut DebugStruct<'_, '_>.debug_struct("FilterMap" ) | 
| 21 |             .field(name:"base" , &self.base) | 
| 22 |             .finish() | 
| 23 |     } | 
| 24 | } | 
| 25 |  | 
| 26 | impl<I: ParallelIterator, P> FilterMap<I, P> { | 
| 27 |     /// Creates a new `FilterMap` iterator. | 
| 28 |     pub(super) fn new(base: I, filter_op: P) -> Self { | 
| 29 |         FilterMap { base, filter_op } | 
| 30 |     } | 
| 31 | } | 
| 32 |  | 
| 33 | impl<I, P, R> ParallelIterator for FilterMap<I, P> | 
| 34 | where | 
| 35 |     I: ParallelIterator, | 
| 36 |     P: Fn(I::Item) -> Option<R> + Sync + Send, | 
| 37 |     R: Send, | 
| 38 | { | 
| 39 |     type Item = R; | 
| 40 |  | 
| 41 |     fn drive_unindexed<C>(self, consumer: C) -> C::Result | 
| 42 |     where | 
| 43 |         C: UnindexedConsumer<Self::Item>, | 
| 44 |     { | 
| 45 |         let consumer: FilterMapConsumer<'_, C, …> = FilterMapConsumer::new(base:consumer, &self.filter_op); | 
| 46 |         self.base.drive_unindexed(consumer) | 
| 47 |     } | 
| 48 | } | 
| 49 |  | 
| 50 | /// //////////////////////////////////////////////////////////////////////// | 
| 51 | /// Consumer implementation | 
| 52 |  | 
| 53 | struct FilterMapConsumer<'p, C, P> { | 
| 54 |     base: C, | 
| 55 |     filter_op: &'p P, | 
| 56 | } | 
| 57 |  | 
| 58 | impl<'p, C, P: 'p> FilterMapConsumer<'p, C, P> { | 
| 59 |     fn new(base: C, filter_op: &'p P) -> Self { | 
| 60 |         FilterMapConsumer { base, filter_op } | 
| 61 |     } | 
| 62 | } | 
| 63 |  | 
| 64 | impl<'p, T, U, C, P> Consumer<T> for FilterMapConsumer<'p, C, P> | 
| 65 | where | 
| 66 |     C: Consumer<U>, | 
| 67 |     P: Fn(T) -> Option<U> + Sync + 'p, | 
| 68 | { | 
| 69 |     type Folder = FilterMapFolder<'p, C::Folder, P>; | 
| 70 |     type Reducer = C::Reducer; | 
| 71 |     type Result = C::Result; | 
| 72 |  | 
| 73 |     fn split_at(self, index: usize) -> (Self, Self, Self::Reducer) { | 
| 74 |         let (left, right, reducer) = self.base.split_at(index); | 
| 75 |         ( | 
| 76 |             FilterMapConsumer::new(left, self.filter_op), | 
| 77 |             FilterMapConsumer::new(right, self.filter_op), | 
| 78 |             reducer, | 
| 79 |         ) | 
| 80 |     } | 
| 81 |  | 
| 82 |     fn into_folder(self) -> Self::Folder { | 
| 83 |         let base = self.base.into_folder(); | 
| 84 |         FilterMapFolder { | 
| 85 |             base, | 
| 86 |             filter_op: self.filter_op, | 
| 87 |         } | 
| 88 |     } | 
| 89 |  | 
| 90 |     fn full(&self) -> bool { | 
| 91 |         self.base.full() | 
| 92 |     } | 
| 93 | } | 
| 94 |  | 
| 95 | impl<'p, T, U, C, P> UnindexedConsumer<T> for FilterMapConsumer<'p, C, P> | 
| 96 | where | 
| 97 |     C: UnindexedConsumer<U>, | 
| 98 |     P: Fn(T) -> Option<U> + Sync + 'p, | 
| 99 | { | 
| 100 |     fn split_off_left(&self) -> Self { | 
| 101 |         FilterMapConsumer::new(self.base.split_off_left(), self.filter_op) | 
| 102 |     } | 
| 103 |  | 
| 104 |     fn to_reducer(&self) -> Self::Reducer { | 
| 105 |         self.base.to_reducer() | 
| 106 |     } | 
| 107 | } | 
| 108 |  | 
| 109 | struct FilterMapFolder<'p, C, P> { | 
| 110 |     base: C, | 
| 111 |     filter_op: &'p P, | 
| 112 | } | 
| 113 |  | 
| 114 | impl<'p, T, U, C, P> Folder<T> for FilterMapFolder<'p, C, P> | 
| 115 | where | 
| 116 |     C: Folder<U>, | 
| 117 |     P: Fn(T) -> Option<U> + Sync + 'p, | 
| 118 | { | 
| 119 |     type Result = C::Result; | 
| 120 |  | 
| 121 |     fn consume(self, item: T) -> Self { | 
| 122 |         let filter_op = self.filter_op; | 
| 123 |         if let Some(mapped_item) = filter_op(item) { | 
| 124 |             let base = self.base.consume(mapped_item); | 
| 125 |             FilterMapFolder { base, filter_op } | 
| 126 |         } else { | 
| 127 |             self | 
| 128 |         } | 
| 129 |     } | 
| 130 |  | 
| 131 |     // This cannot easily specialize `consume_iter` to be better than | 
| 132 |     // the default, because that requires checking `self.base.full()` | 
| 133 |     // during a call to `self.base.consume_iter()`. (#632) | 
| 134 |  | 
| 135 |     fn complete(self) -> C::Result { | 
| 136 |         self.base.complete() | 
| 137 |     } | 
| 138 |  | 
| 139 |     fn full(&self) -> bool { | 
| 140 |         self.base.full() | 
| 141 |     } | 
| 142 | } | 
| 143 |  |