1use crate::iter::plumbing::*;
9use crate::iter::*;
10use std::sync::atomic::{AtomicBool, Ordering};
11
12#[derive(Debug, Clone)]
20pub struct IntoIter<T> {
21 opt: Option<T>,
22}
23
24impl<T: Send> IntoParallelIterator for Option<T> {
25 type Item = T;
26 type Iter = IntoIter<T>;
27
28 fn into_par_iter(self) -> Self::Iter {
29 IntoIter { opt: self }
30 }
31}
32
33impl<T: Send> ParallelIterator for IntoIter<T> {
34 type Item = T;
35
36 fn drive_unindexed<C>(self, consumer: C) -> C::Result
37 where
38 C: UnindexedConsumer<Self::Item>,
39 {
40 self.drive(consumer)
41 }
42
43 fn opt_len(&self) -> Option<usize> {
44 Some(self.len())
45 }
46}
47
48impl<T: Send> IndexedParallelIterator for IntoIter<T> {
49 fn drive<C>(self, consumer: C) -> C::Result
50 where
51 C: Consumer<Self::Item>,
52 {
53 let mut folder = consumer.into_folder();
54 if let Some(item) = self.opt {
55 folder = folder.consume(item);
56 }
57 folder.complete()
58 }
59
60 fn len(&self) -> usize {
61 match self.opt {
62 Some(_) => 1,
63 None => 0,
64 }
65 }
66
67 fn with_producer<CB>(self, callback: CB) -> CB::Output
68 where
69 CB: ProducerCallback<Self::Item>,
70 {
71 callback.callback(OptionProducer { opt: self.opt })
72 }
73}
74
75#[derive(Debug)]
83pub struct Iter<'a, T> {
84 inner: IntoIter<&'a T>,
85}
86
87impl<T> Clone for Iter<'_, T> {
88 fn clone(&self) -> Self {
89 Iter {
90 inner: self.inner.clone(),
91 }
92 }
93}
94
95impl<'a, T: Sync> IntoParallelIterator for &'a Option<T> {
96 type Item = &'a T;
97 type Iter = Iter<'a, T>;
98
99 fn into_par_iter(self) -> Self::Iter {
100 Iter {
101 inner: self.as_ref().into_par_iter(),
102 }
103 }
104}
105
106delegate_indexed_iterator! {
107 Iter<'a, T> => &'a T,
108 impl<'a, T: Sync>
109}
110
111#[derive(Debug)]
119pub struct IterMut<'a, T> {
120 inner: IntoIter<&'a mut T>,
121}
122
123impl<'a, T: Send> IntoParallelIterator for &'a mut Option<T> {
124 type Item = &'a mut T;
125 type Iter = IterMut<'a, T>;
126
127 fn into_par_iter(self) -> Self::Iter {
128 IterMut {
129 inner: self.as_mut().into_par_iter(),
130 }
131 }
132}
133
134delegate_indexed_iterator! {
135 IterMut<'a, T> => &'a mut T,
136 impl<'a, T: Send>
137}
138
139struct OptionProducer<T: Send> {
141 opt: Option<T>,
142}
143
144impl<T: Send> Producer for OptionProducer<T> {
145 type Item = T;
146 type IntoIter = std::option::IntoIter<T>;
147
148 fn into_iter(self) -> Self::IntoIter {
149 self.opt.into_iter()
150 }
151
152 fn split_at(self, index: usize) -> (Self, Self) {
153 debug_assert!(index <= 1);
154 let none = OptionProducer { opt: None };
155 if index == 0 {
156 (none, self)
157 } else {
158 (self, none)
159 }
160 }
161}
162
163impl<C, T> FromParallelIterator<Option<T>> for Option<C>
168where
169 C: FromParallelIterator<T>,
170 T: Send,
171{
172 fn from_par_iter<I>(par_iter: I) -> Self
173 where
174 I: IntoParallelIterator<Item = Option<T>>,
175 {
176 fn check<T>(found_none: &AtomicBool) -> impl Fn(&Option<T>) + '_ {
177 move |item| {
178 if item.is_none() {
179 found_none.store(true, Ordering::Relaxed);
180 }
181 }
182 }
183
184 let found_none = AtomicBool::new(false);
185 let collection = par_iter
186 .into_par_iter()
187 .inspect(check(&found_none))
188 .while_some()
189 .collect();
190
191 if found_none.load(Ordering::Relaxed) {
192 None
193 } else {
194 Some(collection)
195 }
196 }
197}