1 use super::plumbing::*; 2 use super::*; 3 use std::cmp; 4 use std::iter; 5 6 /// `Zip` is an iterator that zips up `a` and `b` into a single iterator 7 /// of pairs. This struct is created by the [`zip()`] method on 8 /// [`IndexedParallelIterator`] 9 /// 10 /// [`zip()`]: trait.IndexedParallelIterator.html#method.zip 11 /// [`IndexedParallelIterator`]: trait.IndexedParallelIterator.html 12 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] 13 #[derive(Debug, Clone)] 14 pub struct Zip<A: IndexedParallelIterator, B: IndexedParallelIterator> { 15 a: A, 16 b: B, 17 } 18 19 impl<A, B> Zip<A, B> 20 where 21 A: IndexedParallelIterator, 22 B: IndexedParallelIterator, 23 { 24 /// Creates a new `Zip` iterator. new(a: A, b: B) -> Self25 pub(super) fn new(a: A, b: B) -> Self { 26 Zip { a, b } 27 } 28 } 29 30 impl<A, B> ParallelIterator for Zip<A, B> 31 where 32 A: IndexedParallelIterator, 33 B: IndexedParallelIterator, 34 { 35 type Item = (A::Item, B::Item); 36 drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,37 fn drive_unindexed<C>(self, consumer: C) -> C::Result 38 where 39 C: UnindexedConsumer<Self::Item>, 40 { 41 bridge(self, consumer) 42 } 43 opt_len(&self) -> Option<usize>44 fn opt_len(&self) -> Option<usize> { 45 Some(self.len()) 46 } 47 } 48 49 impl<A, B> IndexedParallelIterator for Zip<A, B> 50 where 51 A: IndexedParallelIterator, 52 B: IndexedParallelIterator, 53 { drive<C>(self, consumer: C) -> C::Result where C: Consumer<Self::Item>,54 fn drive<C>(self, consumer: C) -> C::Result 55 where 56 C: Consumer<Self::Item>, 57 { 58 bridge(self, consumer) 59 } 60 len(&self) -> usize61 fn len(&self) -> usize { 62 cmp::min(self.a.len(), self.b.len()) 63 } 64 with_producer<CB>(self, callback: CB) -> CB::Output where CB: ProducerCallback<Self::Item>,65 fn with_producer<CB>(self, callback: CB) -> CB::Output 66 where 67 CB: ProducerCallback<Self::Item>, 68 { 69 return self.a.with_producer(CallbackA { 70 callback, 71 b: self.b, 72 }); 73 74 struct CallbackA<CB, B> { 75 callback: CB, 76 b: B, 77 } 78 79 impl<CB, ITEM, B> ProducerCallback<ITEM> for CallbackA<CB, B> 80 where 81 B: IndexedParallelIterator, 82 CB: ProducerCallback<(ITEM, B::Item)>, 83 { 84 type Output = CB::Output; 85 86 fn callback<A>(self, a_producer: A) -> Self::Output 87 where 88 A: Producer<Item = ITEM>, 89 { 90 self.b.with_producer(CallbackB { 91 a_producer, 92 callback: self.callback, 93 }) 94 } 95 } 96 97 struct CallbackB<CB, A> { 98 a_producer: A, 99 callback: CB, 100 } 101 102 impl<CB, A, ITEM> ProducerCallback<ITEM> for CallbackB<CB, A> 103 where 104 A: Producer, 105 CB: ProducerCallback<(A::Item, ITEM)>, 106 { 107 type Output = CB::Output; 108 109 fn callback<B>(self, b_producer: B) -> Self::Output 110 where 111 B: Producer<Item = ITEM>, 112 { 113 self.callback.callback(ZipProducer { 114 a: self.a_producer, 115 b: b_producer, 116 }) 117 } 118 } 119 } 120 } 121 122 /// //////////////////////////////////////////////////////////////////////// 123 124 struct ZipProducer<A: Producer, B: Producer> { 125 a: A, 126 b: B, 127 } 128 129 impl<A: Producer, B: Producer> Producer for ZipProducer<A, B> { 130 type Item = (A::Item, B::Item); 131 type IntoIter = iter::Zip<A::IntoIter, B::IntoIter>; 132 into_iter(self) -> Self::IntoIter133 fn into_iter(self) -> Self::IntoIter { 134 self.a.into_iter().zip(self.b.into_iter()) 135 } 136 min_len(&self) -> usize137 fn min_len(&self) -> usize { 138 cmp::max(self.a.min_len(), self.b.min_len()) 139 } 140 max_len(&self) -> usize141 fn max_len(&self) -> usize { 142 cmp::min(self.a.max_len(), self.b.max_len()) 143 } 144 split_at(self, index: usize) -> (Self, Self)145 fn split_at(self, index: usize) -> (Self, Self) { 146 let (a_left, a_right) = self.a.split_at(index); 147 let (b_left, b_right) = self.b.split_at(index); 148 ( 149 ZipProducer { 150 a: a_left, 151 b: b_left, 152 }, 153 ZipProducer { 154 a: a_right, 155 b: b_right, 156 }, 157 ) 158 } 159 } 160