1 //! Parallel iterator types for [options][std::option] 2 //! 3 //! You will rarely need to interact with this module directly unless you need 4 //! to name one of the iterator types. 5 //! 6 //! [std::option]: https://doc.rust-lang.org/stable/std/option/ 7 8 use crate::iter::plumbing::*; 9 use crate::iter::*; 10 use std::sync::atomic::{AtomicBool, Ordering}; 11 12 /// A parallel iterator over the value in [`Some`] variant of an [`Option`]. 13 /// 14 /// The iterator yields one value if the [`Option`] is a [`Some`], otherwise none. 15 /// 16 /// This `struct` is created by the [`into_par_iter`] function. 17 /// 18 /// [`Option`]: https://doc.rust-lang.org/std/option/enum.Option.html 19 /// [`Some`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.Some 20 /// [`into_par_iter`]: ../iter/trait.IntoParallelIterator.html#tymethod.into_par_iter 21 #[derive(Debug, Clone)] 22 pub struct IntoIter<T: Send> { 23 opt: Option<T>, 24 } 25 26 impl<T: Send> IntoParallelIterator for Option<T> { 27 type Item = T; 28 type Iter = IntoIter<T>; 29 into_par_iter(self) -> Self::Iter30 fn into_par_iter(self) -> Self::Iter { 31 IntoIter { opt: self } 32 } 33 } 34 35 impl<T: Send> ParallelIterator for IntoIter<T> { 36 type Item = T; 37 drive_unindexed<C>(self, consumer: C) -> C::Result where C: UnindexedConsumer<Self::Item>,38 fn drive_unindexed<C>(self, consumer: C) -> C::Result 39 where 40 C: UnindexedConsumer<Self::Item>, 41 { 42 self.drive(consumer) 43 } 44 opt_len(&self) -> Option<usize>45 fn opt_len(&self) -> Option<usize> { 46 Some(self.len()) 47 } 48 } 49 50 impl<T: Send> IndexedParallelIterator for IntoIter<T> { drive<C>(self, consumer: C) -> C::Result where C: Consumer<Self::Item>,51 fn drive<C>(self, consumer: C) -> C::Result 52 where 53 C: Consumer<Self::Item>, 54 { 55 let mut folder = consumer.into_folder(); 56 if let Some(item) = self.opt { 57 folder = folder.consume(item); 58 } 59 folder.complete() 60 } 61 len(&self) -> usize62 fn len(&self) -> usize { 63 match self.opt { 64 Some(_) => 1, 65 None => 0, 66 } 67 } 68 with_producer<CB>(self, callback: CB) -> CB::Output where CB: ProducerCallback<Self::Item>,69 fn with_producer<CB>(self, callback: CB) -> CB::Output 70 where 71 CB: ProducerCallback<Self::Item>, 72 { 73 callback.callback(OptionProducer { opt: self.opt }) 74 } 75 } 76 77 /// A parallel iterator over a reference to the [`Some`] variant of an [`Option`]. 78 /// 79 /// The iterator yields one value if the [`Option`] is a [`Some`], otherwise none. 80 /// 81 /// This `struct` is created by the [`par_iter`] function. 82 /// 83 /// [`Option`]: https://doc.rust-lang.org/std/option/enum.Option.html 84 /// [`Some`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.Some 85 /// [`par_iter`]: ../iter/trait.IntoParallelRefIterator.html#tymethod.par_iter 86 #[derive(Debug)] 87 pub struct Iter<'a, T: Sync> { 88 inner: IntoIter<&'a T>, 89 } 90 91 impl<'a, T: Sync> Clone for Iter<'a, T> { clone(&self) -> Self92 fn clone(&self) -> Self { 93 Iter { 94 inner: self.inner.clone(), 95 } 96 } 97 } 98 99 impl<'a, T: Sync> IntoParallelIterator for &'a Option<T> { 100 type Item = &'a T; 101 type Iter = Iter<'a, T>; 102 into_par_iter(self) -> Self::Iter103 fn into_par_iter(self) -> Self::Iter { 104 Iter { 105 inner: self.as_ref().into_par_iter(), 106 } 107 } 108 } 109 110 delegate_indexed_iterator! { 111 Iter<'a, T> => &'a T, 112 impl<'a, T: Sync + 'a> 113 } 114 115 /// A parallel iterator over a mutable reference to the [`Some`] variant of an [`Option`]. 116 /// 117 /// The iterator yields one value if the [`Option`] is a [`Some`], otherwise none. 118 /// 119 /// This `struct` is created by the [`par_iter_mut`] function. 120 /// 121 /// [`Option`]: https://doc.rust-lang.org/std/option/enum.Option.html 122 /// [`Some`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.Some 123 /// [`par_iter_mut`]: ../iter/trait.IntoParallelRefMutIterator.html#tymethod.par_iter_mut 124 #[derive(Debug)] 125 pub struct IterMut<'a, T: Send> { 126 inner: IntoIter<&'a mut T>, 127 } 128 129 impl<'a, T: Send> IntoParallelIterator for &'a mut Option<T> { 130 type Item = &'a mut T; 131 type Iter = IterMut<'a, T>; 132 into_par_iter(self) -> Self::Iter133 fn into_par_iter(self) -> Self::Iter { 134 IterMut { 135 inner: self.as_mut().into_par_iter(), 136 } 137 } 138 } 139 140 delegate_indexed_iterator! { 141 IterMut<'a, T> => &'a mut T, 142 impl<'a, T: Send + 'a> 143 } 144 145 /// Private producer for an option 146 struct OptionProducer<T: Send> { 147 opt: Option<T>, 148 } 149 150 impl<T: Send> Producer for OptionProducer<T> { 151 type Item = T; 152 type IntoIter = std::option::IntoIter<T>; 153 into_iter(self) -> Self::IntoIter154 fn into_iter(self) -> Self::IntoIter { 155 self.opt.into_iter() 156 } 157 split_at(self, index: usize) -> (Self, Self)158 fn split_at(self, index: usize) -> (Self, Self) { 159 debug_assert!(index <= 1); 160 let none = OptionProducer { opt: None }; 161 if index == 0 { 162 (none, self) 163 } else { 164 (self, none) 165 } 166 } 167 } 168 169 /// Collect an arbitrary `Option`-wrapped collection. 170 /// 171 /// If any item is `None`, then all previous items collected are discarded, 172 /// and it returns only `None`. 173 impl<C, T> FromParallelIterator<Option<T>> for Option<C> 174 where 175 C: FromParallelIterator<T>, 176 T: Send, 177 { from_par_iter<I>(par_iter: I) -> Self where I: IntoParallelIterator<Item = Option<T>>,178 fn from_par_iter<I>(par_iter: I) -> Self 179 where 180 I: IntoParallelIterator<Item = Option<T>>, 181 { 182 fn check<T>(found_none: &AtomicBool) -> impl Fn(&Option<T>) + '_ { 183 move |item| { 184 if item.is_none() { 185 found_none.store(true, Ordering::Relaxed); 186 } 187 } 188 } 189 190 let found_none = AtomicBool::new(false); 191 let collection = par_iter 192 .into_par_iter() 193 .inspect(check(&found_none)) 194 .while_some() 195 .collect(); 196 197 if found_none.load(Ordering::Relaxed) { 198 None 199 } else { 200 Some(collection) 201 } 202 } 203 } 204