try_iterator/try_iterator.rs
1/// Implements the following fallible iterator methods:
2///
3/// * `try_all`;
4/// * `try_any`;
5/// * `try_position`;
6/// * `try_rposition`.
7///
8/// Prefer importing this trait through the crate prelude:
9///
10/// ```
11/// use try_iterator::prelude::*;
12/// ```
13pub trait TryIterator: Iterator {
14 /// Tests if every element of the iterator matches a predicate, stopping at
15 /// the first error and returning that error.
16 ///
17 /// This can also be thought of as the fallible form of
18 /// [`all()`](Iterator::all).
19 ///
20 /// # Examples
21 ///
22 /// Ordinary operation:
23 ///
24 /// ```
25 /// use try_iterator::prelude::*;
26 ///
27 /// let items: &[Result<&str, u32>] = &[
28 /// Ok("foo"),
29 /// Ok("foo"),
30 /// Ok("foo"),
31 /// ];
32 ///
33 /// let res = items.iter()
34 /// .try_all(|item| -> Result<_, u32> {
35 /// let equal = (*item)? == "foo";
36 /// Ok(equal)
37 /// });
38 ///
39 /// assert_eq!(res.is_ok(), true);
40 /// assert_eq!(res.unwrap(), true);
41 /// ```
42 ///
43 /// Fails the whole operation when an [`Err`] is present:
44 ///
45 /// ```
46 /// use try_iterator::prelude::*;
47 ///
48 /// let items: &[Result<&str, u32>] = &[
49 /// Ok("foo"),
50 /// Err(4444),
51 /// Ok("foo"),
52 /// ];
53 ///
54 /// let res = items.iter()
55 /// .try_all(|item| -> Result<_, u32> {
56 /// let equal = (*item)? == "foo";
57 /// Ok(equal)
58 /// });
59 ///
60 /// assert_eq!(res.is_err(), true);
61 /// ```
62 fn try_all<E, F>(&mut self, mut predicate: F) -> Result<bool, E>
63 where Self: Sized,
64 F: FnMut(Self::Item) -> Result<bool, E>,
65 {
66 for item in self {
67 if !predicate(item)? {
68 return Ok(false)
69 }
70 }
71 Ok(true)
72 }
73
74 /// Tests if any element of the iterator matches a predicate, stopping at
75 /// the first error and returning that error.
76 ///
77 /// This can also be thought of as the fallible form of
78 /// [`any()`](Iterator::any).
79 ///
80 /// # Examples
81 ///
82 /// Ordinary operation:
83 ///
84 /// ```
85 /// use try_iterator::prelude::*;
86 ///
87 /// let items: &[Result<&str, u32>] = &[
88 /// Ok("foo"),
89 /// Ok("ayy"),
90 /// Ok("bar"),
91 /// ];
92 ///
93 /// let res = items.iter()
94 /// .try_any(|item| -> Result<_, u32> {
95 /// let equal = (*item)? == "bar";
96 /// Ok(equal)
97 /// });
98 ///
99 /// assert_eq!(res.is_ok(), true);
100 /// assert_eq!(res.unwrap(), true);
101 /// ```
102 ///
103 /// Fails the whole operation when an [`Err`] is present:
104 ///
105 /// ```
106 /// use try_iterator::prelude::*;
107 ///
108 /// let items: &[Result<&str, u32>] = &[
109 /// Ok("foo"),
110 /// Err(7777),
111 /// Ok("bar"),
112 /// ];
113 ///
114 /// let res = items.iter()
115 /// .try_any(|item| -> Result<_, u32> {
116 /// let equal = (*item)? == "bar";
117 /// Ok(equal)
118 /// });
119 ///
120 /// assert_eq!(res.is_err(), true);
121 /// ```
122 fn try_any<E, F>(&mut self, mut predicate: F) -> Result<bool, E>
123 where Self: Sized,
124 F: FnMut(Self::Item) -> Result<bool, E>,
125 {
126 for item in self {
127 if predicate(item)? {
128 return Ok(true)
129 }
130 }
131 Ok(false)
132 }
133
134 /// Searches for an element in an iterator, returning its index, stopping at
135 /// the first error and returning that error.
136 ///
137 /// This can also be thought of as the fallible form of
138 /// [`position()`](Iterator::position).
139 ///
140 /// # Examples
141 ///
142 /// Ordinary operation:
143 ///
144 /// ```
145 /// use try_iterator::prelude::*;
146 ///
147 /// let items: &[Result<&str, u32>] = &[
148 /// Ok("foo"),
149 /// Ok("ayy"),
150 /// Ok("bar"),
151 /// ];
152 ///
153 /// let pos = items.iter()
154 /// .try_position(|item| -> Result<_, u32> {
155 /// let equal = (*item)? == "bar";
156 /// Ok(equal)
157 /// });
158 ///
159 /// assert_eq!(pos.is_ok(), true);
160 /// assert_eq!(pos.unwrap(), Some(2));
161 /// ```
162 ///
163 /// Fails the whole operation when an [`Err`] is present:
164 ///
165 /// ```
166 /// use try_iterator::prelude::*;
167 ///
168 /// let items: &[Result<&str, u32>] = &[
169 /// Ok("foo"),
170 /// Err(8888),
171 /// Ok("bar"),
172 /// ];
173 ///
174 /// let pos = items.iter()
175 /// .try_any(|item| -> Result<_, u32> {
176 /// let equal = (*item)? == "bar";
177 /// Ok(equal)
178 /// });
179 ///
180 /// assert_eq!(pos.is_err(), true);
181 /// ```
182 fn try_position<E, F>(&mut self, mut predicate: F) -> Result<Option<usize>, E>
183 where Self: Sized,
184 F: FnMut(Self::Item) -> Result<bool, E>,
185 {
186 for (idx, item) in self.enumerate() {
187 if predicate(item)? {
188 return Ok(Some(idx));
189 }
190 }
191 Ok(None)
192 }
193
194 /// Searches for an element in an iterator from the right, returning its
195 /// index, stopping at the first error and returning that error.
196 ///
197 /// This can also be thought of as the fallible form of
198 /// [`rposition()`](Iterator::rposition).
199 ///
200 /// # Examples
201 ///
202 /// Ordinary operation:
203 ///
204 /// ```
205 /// use try_iterator::prelude::*;
206 ///
207 /// let items: &[Result<&str, u32>] = &[
208 /// Ok("foo"),
209 /// Ok("ayy"),
210 /// Ok("bar"),
211 /// ];
212 ///
213 /// let pos = items.iter()
214 /// .try_rposition(|item| -> Result<_, u32> {
215 /// let equal = (*item)? == "foo";
216 /// Ok(equal)
217 /// });
218 ///
219 /// assert_eq!(pos.is_ok(), true);
220 /// assert_eq!(pos.unwrap(), Some(0));
221 /// ```
222 ///
223 /// Fails the whole operation when an [`Err`] is present:
224 ///
225 /// ```
226 /// use try_iterator::prelude::*;
227 ///
228 /// let items: &[Result<&str, u32>] = &[
229 /// Ok("foo"),
230 /// Err(9999),
231 /// Ok("bar"),
232 /// ];
233 ///
234 /// let pos = items.iter()
235 /// .try_rposition(|item| -> Result<_, u32> {
236 /// let equal = (*item)? == "foo";
237 /// Ok(equal)
238 /// });
239 ///
240 /// assert_eq!(pos.is_err(), true);
241 /// ```
242 fn try_rposition<E, F>(&mut self, mut predicate: F) -> Result<Option<usize>, E>
243 where Self: Sized + ExactSizeIterator + DoubleEndedIterator,
244 F: FnMut(Self::Item) -> Result<bool, E>,
245 {
246 for (idx, item) in self.enumerate().rev() {
247 if predicate(item)? {
248 return Ok(Some(idx));
249 }
250 }
251 Ok(None)
252 }
253}
254
255impl<'a, T> TryIterator for core::slice::Iter<'a, T> {}
256impl<A, B> TryIterator for std::iter::Chain<A, B> where A: Iterator, B: Iterator<Item = <A as Iterator>::Item> {}
257impl<'a, I, T> TryIterator for std::iter::Cloned<I> where T: 'a + Clone, I: Iterator<Item = &'a T> {}
258impl<'a, I, T> TryIterator for std::iter::Copied<I> where T: 'a + Copy, I: Iterator<Item = &'a T> {}
259impl<I> TryIterator for std::iter::Cycle<I> where I: Clone + Iterator {}
260impl<T> TryIterator for std::iter::Empty<T> {}
261impl<I> TryIterator for std::iter::Enumerate<I> where I: Iterator {}
262impl<I, P> TryIterator for std::iter::Filter<I, P> where I: Iterator, P: FnMut(&<I as Iterator>::Item) -> bool {}
263impl<B, I, F> TryIterator for std::iter::FilterMap<I, F> where I: Iterator, F: FnMut(<I as Iterator>::Item) -> Option<B> {}
264impl<I, U, F> TryIterator for std::iter::FlatMap<I, U, F> where I: Iterator, U: IntoIterator, F: FnMut(<I as Iterator>::Item) -> U {}
265impl<I, U> TryIterator for std::iter::Flatten<I> where I: Iterator, <I as Iterator>::Item: IntoIterator<IntoIter = U, Item = <U as Iterator>::Item>, U: Iterator {}
266impl<T, F> TryIterator for std::iter::FromFn<F> where F: FnMut() -> Option<T> {}
267impl<I> TryIterator for std::iter::Fuse<I> where I: Iterator {}
268impl<I, F> TryIterator for std::iter::Inspect<I, F> where I: Iterator, F: FnMut(&<I as Iterator>::Item) {}
269impl<B, I, F> TryIterator for std::iter::Map<I, F> where I: Iterator, F: FnMut(<I as Iterator>::Item) -> B {}
270impl<B, I, P> TryIterator for std::iter::MapWhile<I, P> where I: Iterator, P: FnMut(<I as Iterator>::Item) -> Option<B> {}
271impl<T> TryIterator for std::iter::Once<T> {}
272impl<A, F> TryIterator for std::iter::OnceWith<F> where F: FnOnce() -> A {}
273impl<I> TryIterator for std::iter::Peekable<I> where I: Iterator {}
274impl<A> TryIterator for std::iter::Repeat<A> where A: Clone {}
275impl<A, F> TryIterator for std::iter::RepeatWith<F> where F: FnMut() -> A {}
276impl<I> TryIterator for std::iter::Rev<I> where I: DoubleEndedIterator {}
277impl<B, I, St, F> TryIterator for std::iter::Scan<I, St, F> where I: Iterator, F: FnMut(&mut St, <I as Iterator>::Item) -> Option<B> {}
278impl<I> TryIterator for std::iter::Skip<I> where I: Iterator {}
279impl<I, P> TryIterator for std::iter::SkipWhile<I, P> where I: Iterator, P: FnMut(&<I as Iterator>::Item) -> bool {}
280impl<I> TryIterator for std::iter::StepBy<I> where I: Iterator {}
281impl<T, F> TryIterator for std::iter::Successors<T, F> where F: FnMut(&T) -> Option<T> {}
282impl<I> TryIterator for std::iter::Take<I> where I: Iterator {}
283impl<I, P> TryIterator for std::iter::TakeWhile<I, P> where I: Iterator, P: FnMut(&<I as Iterator>::Item) -> bool {}
284impl<A, B> TryIterator for std::iter::Zip<A, B> where A: Iterator, B: Iterator {}