1//! Parallel iterator types for [results][std::result]
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::result]: https://doc.rust-lang.org/stable/std/result/
7
8use crate::iter::plumbing::*;
9use crate::iter::*;
10use std::sync::Mutex;
11
12use crate::option;
13
14/// Parallel iterator over a result
15#[derive(Debug, Clone)]
16pub struct IntoIter<T: Send> {
17 inner: option::IntoIter<T>,
18}
19
20impl<T: Send, E> IntoParallelIterator for Result<T, E> {
21 type Item = T;
22 type Iter = IntoIter<T>;
23
24 fn into_par_iter(self) -> Self::Iter {
25 IntoIter {
26 inner: self.ok().into_par_iter(),
27 }
28 }
29}
30
31delegate_indexed_iterator! {
32 IntoIter<T> => T,
33 impl<T: Send>
34}
35
36/// Parallel iterator over an immutable reference to a result
37#[derive(Debug)]
38pub struct Iter<'a, T: Sync> {
39 inner: option::IntoIter<&'a T>,
40}
41
42impl<'a, T: Sync> Clone for Iter<'a, T> {
43 fn clone(&self) -> Self {
44 Iter {
45 inner: self.inner.clone(),
46 }
47 }
48}
49
50impl<'a, T: Sync, E> IntoParallelIterator for &'a Result<T, E> {
51 type Item = &'a T;
52 type Iter = Iter<'a, T>;
53
54 fn into_par_iter(self) -> Self::Iter {
55 Iter {
56 inner: self.as_ref().ok().into_par_iter(),
57 }
58 }
59}
60
61delegate_indexed_iterator! {
62 Iter<'a, T> => &'a T,
63 impl<'a, T: Sync + 'a>
64}
65
66/// Parallel iterator over a mutable reference to a result
67#[derive(Debug)]
68pub struct IterMut<'a, T: Send> {
69 inner: option::IntoIter<&'a mut T>,
70}
71
72impl<'a, T: Send, E> IntoParallelIterator for &'a mut Result<T, E> {
73 type Item = &'a mut T;
74 type Iter = IterMut<'a, T>;
75
76 fn into_par_iter(self) -> Self::Iter {
77 IterMut {
78 inner: self.as_mut().ok().into_par_iter(),
79 }
80 }
81}
82
83delegate_indexed_iterator! {
84 IterMut<'a, T> => &'a mut T,
85 impl<'a, T: Send + 'a>
86}
87
88/// Collect an arbitrary `Result`-wrapped collection.
89///
90/// If any item is `Err`, then all previous `Ok` items collected are
91/// discarded, and it returns that error. If there are multiple errors, the
92/// one returned is not deterministic.
93impl<C, T, E> FromParallelIterator<Result<T, E>> for Result<C, E>
94where
95 C: FromParallelIterator<T>,
96 T: Send,
97 E: Send,
98{
99 fn from_par_iter<I>(par_iter: I) -> Self
100 where
101 I: IntoParallelIterator<Item = Result<T, E>>,
102 {
103 fn ok<T, E>(saved: &Mutex<Option<E>>) -> impl Fn(Result<T, E>) -> Option<T> + '_ {
104 move |item| match item {
105 Ok(item) => Some(item),
106 Err(error) => {
107 // We don't need a blocking `lock()`, as anybody
108 // else holding the lock will also be writing
109 // `Some(error)`, and then ours is irrelevant.
110 if let Ok(mut guard) = saved.try_lock() {
111 if guard.is_none() {
112 *guard = Some(error);
113 }
114 }
115 None
116 }
117 }
118 }
119
120 let saved_error = Mutex::new(None);
121 let collection = par_iter
122 .into_par_iter()
123 .map(ok(&saved_error))
124 .while_some()
125 .collect();
126
127 match saved_error.into_inner().unwrap() {
128 Some(error) => Err(error),
129 None => Ok(collection),
130 }
131 }
132}
133