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