| 1 | use super::plumbing::*; | 
| 2 | use super::*; | 
| 3 | use std::iter; | 
| 4 | use std::ops::Range; | 
| 5 | use std::usize; | 
| 6 |  | 
| 7 | /// `Enumerate` is an iterator that returns the current count along with the element. | 
| 8 | /// This struct is created by the [`enumerate()`] method on [`IndexedParallelIterator`] | 
| 9 | /// | 
| 10 | /// [`enumerate()`]: trait.IndexedParallelIterator.html#method.enumerate | 
| 11 | /// [`IndexedParallelIterator`]: trait.IndexedParallelIterator.html | 
| 12 | #[must_use  = "iterator adaptors are lazy and do nothing unless consumed" ] | 
| 13 | #[derive (Debug, Clone)] | 
| 14 | pub struct Enumerate<I: IndexedParallelIterator> { | 
| 15 |     base: I, | 
| 16 | } | 
| 17 |  | 
| 18 | impl<I> Enumerate<I> | 
| 19 | where | 
| 20 |     I: IndexedParallelIterator, | 
| 21 | { | 
| 22 |     /// Creates a new `Enumerate` iterator. | 
| 23 |     pub(super) fn new(base: I) -> Self { | 
| 24 |         Enumerate { base } | 
| 25 |     } | 
| 26 | } | 
| 27 |  | 
| 28 | impl<I> ParallelIterator for Enumerate<I> | 
| 29 | where | 
| 30 |     I: IndexedParallelIterator, | 
| 31 | { | 
| 32 |     type Item = (usize, I::Item); | 
| 33 |  | 
| 34 |     fn drive_unindexed<C>(self, consumer: C) -> C::Result | 
| 35 |     where | 
| 36 |         C: UnindexedConsumer<Self::Item>, | 
| 37 |     { | 
| 38 |         bridge(self, consumer) | 
| 39 |     } | 
| 40 |  | 
| 41 |     fn opt_len(&self) -> Option<usize> { | 
| 42 |         Some(self.len()) | 
| 43 |     } | 
| 44 | } | 
| 45 |  | 
| 46 | impl<I> IndexedParallelIterator for Enumerate<I> | 
| 47 | where | 
| 48 |     I: IndexedParallelIterator, | 
| 49 | { | 
| 50 |     fn drive<C: Consumer<Self::Item>>(self, consumer: C) -> C::Result { | 
| 51 |         bridge(self, consumer) | 
| 52 |     } | 
| 53 |  | 
| 54 |     fn len(&self) -> usize { | 
| 55 |         self.base.len() | 
| 56 |     } | 
| 57 |  | 
| 58 |     fn with_producer<CB>(self, callback: CB) -> CB::Output | 
| 59 |     where | 
| 60 |         CB: ProducerCallback<Self::Item>, | 
| 61 |     { | 
| 62 |         return self.base.with_producer(Callback { callback }); | 
| 63 |  | 
| 64 |         struct Callback<CB> { | 
| 65 |             callback: CB, | 
| 66 |         } | 
| 67 |  | 
| 68 |         impl<I, CB> ProducerCallback<I> for Callback<CB> | 
| 69 |         where | 
| 70 |             CB: ProducerCallback<(usize, I)>, | 
| 71 |         { | 
| 72 |             type Output = CB::Output; | 
| 73 |             fn callback<P>(self, base: P) -> CB::Output | 
| 74 |             where | 
| 75 |                 P: Producer<Item = I>, | 
| 76 |             { | 
| 77 |                 let producer = EnumerateProducer { base, offset: 0 }; | 
| 78 |                 self.callback.callback(producer) | 
| 79 |             } | 
| 80 |         } | 
| 81 |     } | 
| 82 | } | 
| 83 |  | 
| 84 | /// //////////////////////////////////////////////////////////////////////// | 
| 85 | /// Producer implementation | 
| 86 |  | 
| 87 | struct EnumerateProducer<P> { | 
| 88 |     base: P, | 
| 89 |     offset: usize, | 
| 90 | } | 
| 91 |  | 
| 92 | impl<P> Producer for EnumerateProducer<P> | 
| 93 | where | 
| 94 |     P: Producer, | 
| 95 | { | 
| 96 |     type Item = (usize, P::Item); | 
| 97 |     type IntoIter = iter::Zip<Range<usize>, P::IntoIter>; | 
| 98 |  | 
| 99 |     fn into_iter(self) -> Self::IntoIter { | 
| 100 |         // Enumerate only works for IndexedParallelIterators. Since those | 
| 101 |         // have a max length of usize::MAX, their max index is | 
| 102 |         // usize::MAX - 1, so the range 0..usize::MAX includes all | 
| 103 |         // possible indices. | 
| 104 |         // | 
| 105 |         // However, we should to use a precise end to the range, otherwise | 
| 106 |         // reversing the iterator may have to walk back a long ways before | 
| 107 |         // `Zip::next_back` can produce anything. | 
| 108 |         let base = self.base.into_iter(); | 
| 109 |         let end = self.offset + base.len(); | 
| 110 |         (self.offset..end).zip(base) | 
| 111 |     } | 
| 112 |  | 
| 113 |     fn min_len(&self) -> usize { | 
| 114 |         self.base.min_len() | 
| 115 |     } | 
| 116 |     fn max_len(&self) -> usize { | 
| 117 |         self.base.max_len() | 
| 118 |     } | 
| 119 |  | 
| 120 |     fn split_at(self, index: usize) -> (Self, Self) { | 
| 121 |         let (left, right) = self.base.split_at(index); | 
| 122 |         ( | 
| 123 |             EnumerateProducer { | 
| 124 |                 base: left, | 
| 125 |                 offset: self.offset, | 
| 126 |             }, | 
| 127 |             EnumerateProducer { | 
| 128 |                 base: right, | 
| 129 |                 offset: self.offset + index, | 
| 130 |             }, | 
| 131 |         ) | 
| 132 |     } | 
| 133 | } | 
| 134 |  |