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 {}