first_err/lib.rs
1//! # `first-err`
2//!
3//! Find the first `Err` in `Iterator<Item = Result<T, E>>` and allow iterating continuously.
4//!
5//! This crate is specifically designed to replace the following pattern without allocation:
6//!
7//! ```txt
8//! // iter: impl Iterator<Item = Result<T, E>>
9//! iter.collect::<Result<Vec<T>, E>>().map(|vec| vec.into_iter().foo() );
10//! ```
11//!
12//! See [`FirstErr`] trait for more detail.
13//!
14//!
15//!
16//! ## Features
17//!
18//! - Easy-to-use: simple and no way to using wrong.
19//! - Minimized: no `std`, no `alloc`, zero dependency.
20//! - Fast: Roughly on par with a hand-written loop, using lazy evaluation and no allocation.
21//! - Nestable: `T` in `Iterator<Item = Result<T, E>>` can lazily produce more `Result`s.
22//!
23//!
24//!
25//! ## Getting Started
26//!
27//! ```rust
28//! // Use this trait in current scope.
29//! use first_err::FirstErr;
30//!
31//! # fn main() {
32//! // Everything is Ok.
33//! let result = [Ok::<u8, u8>(0), Ok(1), Ok(2)]
34//! .into_iter()
35//! .first_err_or_else(|iter| iter.sum::<u8>());
36//! assert_eq!(result, Ok(3));
37//!
38//! // Contains some `Err` values.
39//! let result = [Ok::<u8, u8>(0), Err(1), Err(2)]
40//! .into_iter()
41//! .first_err_or_else(|iter| iter.sum::<u8>());
42//! assert_eq!(result, Err(1));
43//! # }
44//! ```
45//!
46//!
47//!
48//! ## Why
49//!
50//! In Rust, I frequently encounter a pattern where I need to perform actions on all
51//! items within an iterator, and halt immediately if any error is detected in the layer
52//! I'm working on. But if no error found, the iterator should able to run continuously
53//! and allow me to do further transform.
54//!
55//! The pattern typically looks as follows:
56//!
57//! ```rust
58//! # fn main() {
59//! let array: [Result<u8, u8>; 3] = [Ok(0), Err(1), Err(2)];
60//!
61//! fn fallible_sum(iter: impl IntoIterator<Item = Result<u8, u8>>) -> Result<u8, u8> {
62//! let sum = iter
63//! .into_iter()
64//! .collect::<Result<Vec<_>, _>>()? // early return (and a vec alloc in here)
65//! .into_iter() // continue iterate next layer ...
66//! .sum();
67//!
68//! Ok(sum)
69//! }
70//!
71//! let result = fallible_sum(array);
72//! assert_eq!(result, Err(1));
73//! # }
74//! ```
75//!
76//! In theory, this allocation is not necessary. We can just write that code as an old good
77//! loop:
78//!
79//! ```rust
80//! # fn main() {
81//! let array: [Result<u8, u8>; 3] = [Ok(0), Err(1), Err(2)];
82//!
83//! fn fallible_sum(iter: impl IntoIterator<Item = Result<u8, u8>>) -> Result<u8, u8> {
84//! let mut sum = 0;
85//! for res in iter {
86//! let val = res?; // early return, no alloc
87//! sum += val;
88//! }
89//!
90//! Ok(sum)
91//! }
92//!
93//! let result = fallible_sum(array);
94//! assert_eq!(result, Err(1))
95//! # }
96//! ```
97//!
98//! Using a loop is not bad at all. However, in some situations, maintaining a chainable
99//! iterator is preferable.
100//!
101//! Furthermore, some scenarios may not be as simple as the previous example. Consider this one:
102//!
103//! ```rust
104//! # fn main() {
105//! // The second layer `Result` is usually created by further transform after the first layer
106//! // `Result` be processed. But for the sake of simplicity, we've just use pre-defined values.
107//! let array: [Result<Result<u8, u8>, u8>; 3] = [Ok(Ok(0)), Ok(Err(1)), Err(2)];
108//!
109//! fn fallible_sum(
110//! iter: impl IntoIterator<Item = Result<Result<u8, u8>, u8>>
111//! ) -> Result<u8, u8> {
112//! // take "first `Err`" layer by layer, or the sum value.
113//! let sum = iter
114//! .into_iter()
115//! .collect::<Result<Vec<Result<u8, u8>>, u8>>()?
116//! .into_iter()
117//! .collect::<Result<Vec<u8>, u8>>()?
118//! .into_iter()
119//! .sum();
120//!
121//! Ok(sum)
122//! }
123//!
124//! let result = fallible_sum(array);
125//! assert_eq!(result, Err(2));
126//! # }
127//! ```
128//!
129//! Implementing the above logic in a loop without allocation may be
130//! [error-prone and complicated](https://github.com/visig9/first-err/blob/f666ef16c0b72174e7862468f1dbda382ebe6b68/benches/benchmark.rs#L194-L231).
131//! This crate simplifies that for you:
132//!
133//! ```rust
134//! # use first_err::FirstErr;
135//! #
136//! # fn main() {
137//! let array: [Result<Result<u8, u8>, u8>; 3] = [Ok(Ok(0)), Ok(Err(1)), Err(2)];
138//!
139//! fn fallible_sum(
140//! iter: impl IntoIterator<Item = Result<Result<u8, u8>, u8>>
141//! ) -> Result<u8, u8> {
142//! iter
143//! .into_iter()
144//! .first_err_or_try(|iter1| { // iter1 = impl Iterator<Item = Result<u8, u8>>
145//! iter1.first_err_or_else(|iter2| { // iter2 = impl Iterator<Item = u8>
146//! iter2.sum::<u8>()
147//! })
148//! })
149//! }
150//!
151//! let result = fallible_sum(array);
152//! assert_eq!(result, Err(2));
153//! # }
154//! ```
155//!
156//!
157//!
158//! ## Performance
159//!
160//! The performance of this crate is designed to be roughly on par with hand-written loops.
161//! However, the compiler might apply different optimizations in various situations, and favoring
162//! one approach over the others.
163//!
164//! If you want to to do a benchmark by yourself, use the following command:
165//!
166//! ```sh
167//! cargo bench --bench benchmark -- --output-format bencher
168//! ```
169//!
170//! Also, don't forget to check the actual code that is used for benchmarking, which is in the
171//! `benches` folder.
172
173#![no_std]
174
175pub use option::FirstNoneIter;
176pub use result::FirstErrIter;
177
178/// This trait provides some methods on any `Iterator<Item = Result<T, E>>`, which can take
179/// the first `Err` in iterators, and without allocation.
180///
181/// `Iterator<Item = Option<T>>` version with the same logic are also supported.
182///
183///
184///
185/// ## Guarantees
186///
187/// There are some methods in `FirstErr` trait take a closure that accepts an iterator
188/// as its argument. This crate guarantees all those methods have the following properties.
189///
190///
191///
192/// ### Original Iterator is Evaluated Lazily
193///
194/// The `.next()` of the original iterator only be called as late as possible, For example,
195///
196/// ```rust
197/// # use first_err::FirstErr;
198/// # use std::cell::RefCell;
199/// #
200/// # fn main() {
201/// let mut vec = RefCell::new(vec![]);
202///
203/// let mut result = [Ok::<u8, u8>(0), Ok(1), Err(2), Ok(3)]
204/// .into_iter()
205/// .inspect(|res| { vec.borrow_mut().push(*res) }) // push value from outer
206/// .first_err_or_else(|iter| {
207/// iter
208/// .inspect(|n| { vec.borrow_mut().push(Ok(42)) }) // push value from inner
209/// .sum::<u8>()
210/// });
211///
212/// assert_eq!(result, Err(2));
213/// assert_eq!(
214/// vec.into_inner(),
215/// vec![Ok(0), Ok(42), Ok(1), Ok(42), Err(2)],
216/// );
217/// # }
218/// ```
219///
220///
221///
222/// ### No Need to Manually Consume the Closure's Iterator
223///
224/// User can simple ignore the iterator in closure partially of fully, and still can get
225/// the correct result.
226///
227/// ```rust
228/// # use first_err::FirstErr;
229/// #
230/// # fn main() {
231/// let result = [Ok::<u8, u8>(0), Err(1), Err(2)]
232/// .into_iter()
233/// .first_err_or_else(|_iter| {}); // not need to consume `_iter` iterator,
234/// assert_eq!(result, Err(1)); // and the result still correct.
235/// # }
236/// ```
237///
238///
239///
240/// ### Iterator in Closure Can't be Leaked Out of Closure Scope
241///
242/// Let the iterator in closure escaped from the closure is a compiler error.
243///
244/// ```rust,compile_fail
245/// # use first_err::FirstErr;
246/// #
247/// # fn main() {
248/// let iter = [Ok::<u8, u8>(0), Err(1), Err(2)]
249/// .into_iter()
250/// .first_err_or_else(|iter| iter); // compile error: can't leak `iter` out
251/// # }
252/// ```
253pub trait FirstErr: Iterator {
254 /// Returns the first `Err` item in the current iterator, or an `Ok` value produced by the
255 /// `f` closure.
256 ///
257 /// The argument iterator of the `f` closure will producing the same values in `Ok` sequence,
258 /// but will stop when encounter the first `Err` item.
259 ///
260 ///
261 ///
262 /// # Examples
263 ///
264 /// ```rust
265 /// use first_err::FirstErr;
266 ///
267 /// # fn main() {
268 /// // Everything is Ok.
269 /// let result = [Ok::<u8, u8>(0), Ok(1), Ok(2)]
270 /// .into_iter()
271 /// .first_err_or_else(|iter| iter.sum::<u8>());
272 /// assert_eq!(result, Ok(3));
273 ///
274 /// // Contains some `Err` values.
275 /// let result = [Ok::<u8, u8>(0), Err(1), Err(2)]
276 /// .into_iter()
277 /// .first_err_or_else(|iter| iter.sum::<u8>());
278 /// assert_eq!(result, Err(1));
279 /// # }
280 /// ```
281 #[inline]
282 fn first_err_or_else<T, E, O, F>(self, f: F) -> Result<O, E>
283 where
284 F: FnOnce(&mut FirstErrIter<Self, T, E>) -> O,
285 Self: Iterator<Item = Result<T, E>> + Sized,
286 {
287 FirstErrIter::first_err_or_else(self, f)
288 }
289
290 /// Returns the first `Err` item in the current iterator, or an `Result` value produced
291 /// by the `f` closure.
292 ///
293 /// The argument iterator of the `f` closure will producing the same values in `Ok` sequence,
294 /// but will stop when encounter the first `Err` item.
295 ///
296 ///
297 ///
298 /// # Examples
299 ///
300 /// Basic concept:
301 ///
302 /// ```rust
303 /// use first_err::FirstErr;
304 ///
305 /// # fn main() {
306 /// // Everything is Ok.
307 /// let result = [Ok::<u8, u8>(0), Ok(1), Ok(2)]
308 /// .into_iter()
309 /// .first_err_or_try(|_| Ok("ok"));
310 /// assert_eq!(result, Ok("ok"));
311 ///
312 /// // When closure returns Err.
313 /// let result = [Ok::<u8, u8>(0), Ok(1), Ok(2)]
314 /// .into_iter()
315 /// .first_err_or_try(|_| Err::<u8, u8>(42));
316 /// assert_eq!(result, Err(42));
317 ///
318 /// // When outer iterator contains Err.
319 /// let result = [Ok::<u8, u8>(0), Err(2), Ok(2)]
320 /// .into_iter()
321 /// .first_err_or_try(|_| Ok("ok"));
322 /// assert_eq!(result, Err(2));
323 ///
324 /// // When both contains Err.
325 /// let result = [Ok::<u8, u8>(0), Err(1), Ok(2)]
326 /// .into_iter()
327 /// .first_err_or_try(|_| Err::<u8, u8>(42));
328 /// assert_eq!(result, Err(1));
329 /// # }
330 /// ```
331 ///
332 /// Use the `iter` argument of the `f` closure:
333 ///
334 /// ```rust
335 /// # use first_err::FirstErr;
336 /// #
337 /// # fn main() {
338 /// let admin_id: u32 = 1;
339 /// let user_ids_in_conf = ["32", "5", "8", "19"];
340 ///
341 /// let admin_index = user_ids_in_conf
342 /// .into_iter()
343 /// .map(|s| s.parse::<u32>().map_err(|_| "user id parsing failed"))
344 /// .first_err_or_try(|user_ids_iter| {
345 /// user_ids_iter
346 /// .position(|user_id| user_id == admin_id)
347 /// .ok_or_else(|| "admin not in the user list")
348 /// });
349 ///
350 /// assert_eq!(admin_index, Err("admin not in the user list"));
351 /// # }
352 /// ```
353 #[inline]
354 fn first_err_or_try<T, E, O, F>(self, f: F) -> Result<O, E>
355 where
356 F: FnOnce(&mut FirstErrIter<Self, T, E>) -> Result<O, E>,
357 Self: Iterator<Item = Result<T, E>> + Sized,
358 {
359 self.first_err_or_else(f).and_then(|res| res)
360 }
361
362 /// Returns the first `Err` item in the current iterator, or an `Ok(value)`.
363 ///
364 ///
365 ///
366 /// # Examples
367 ///
368 /// ```rust
369 /// # use first_err::FirstErr;
370 /// #
371 /// # fn main() {
372 /// // Everything is Ok.
373 /// let result = [Ok::<u8, u8>(0), Ok(1), Ok(2)]
374 /// .into_iter()
375 /// .first_err_or("foo");
376 /// assert_eq!(result, Ok("foo"));
377 ///
378 /// // Contains some `Err` values.
379 /// let result = [Ok::<u8, u8>(0), Err(1), Err(2)]
380 /// .into_iter()
381 /// .first_err_or("foo");
382 /// assert_eq!(result, Err(1));
383 /// # }
384 /// ```
385 #[inline]
386 fn first_err_or<T, E, O>(self, value: O) -> Result<O, E>
387 where
388 Self: Iterator<Item = Result<T, E>> + Sized,
389 {
390 self.first_err_or_else(|_| value)
391 }
392
393 /// Returns the first `None` item in the current iterator, or an `Some` value produced
394 /// by the `f` closure.
395 ///
396 /// The argument iterator of the `f` closure will producing the same values in `Some` sequence,
397 /// but will stop when encounter the first `None` item.
398 ///
399 ///
400 ///
401 /// # Examples
402 ///
403 /// ```rust
404 /// use first_err::FirstErr;
405 ///
406 /// # fn main() {
407 /// // Everything is Some.
408 /// let option = [Some::<u8>(0), Some(1), Some(2)]
409 /// .into_iter()
410 /// .first_none_or_else(|iter| iter.sum::<u8>());
411 /// assert_eq!(option, Some(3));
412 ///
413 /// // Contains some `None` values.
414 /// let option = [Some::<u8>(0), None, None]
415 /// .into_iter()
416 /// .first_none_or_else(|iter| iter.sum::<u8>());
417 /// assert_eq!(option, None);
418 /// # }
419 /// ```
420 #[inline]
421 fn first_none_or_else<T, O, F>(self, f: F) -> Option<O>
422 where
423 F: FnOnce(&mut FirstNoneIter<Self, T>) -> O,
424 Self: Iterator<Item = Option<T>> + Sized,
425 {
426 FirstNoneIter::first_none_or_else(self, f)
427 }
428
429 /// Returns the first `None` item in the current iterator, or an `Option` value produced
430 /// by the `f` closure.
431 ///
432 /// The argument iterator of the `f` closure will producing the same values in `Some` sequence,
433 /// but will stop when encounter the first `None` item.
434 ///
435 ///
436 ///
437 /// # Examples
438 ///
439 /// Basic concept:
440 ///
441 /// ```rust
442 /// use first_err::FirstErr;
443 ///
444 /// # fn main() {
445 /// // Everything is Some.
446 /// let option = [Some::<u8>(0), Some(1), Some(2)]
447 /// .into_iter()
448 /// .first_none_or_try(|_| Some("ok"));
449 /// assert_eq!(option, Some("ok"));
450 ///
451 /// // When closure returns None.
452 /// let option: Option<&str> = [Some::<u8>(0), Some(1), Some(2)]
453 /// .into_iter()
454 /// .first_none_or_try(|_| None);
455 /// assert_eq!(option, None);
456 ///
457 /// // When outer iterator contains None.
458 /// let option = [Some::<u8>(0), None, Some(2)]
459 /// .into_iter()
460 /// .first_none_or_try(|_| Some("ok"));
461 /// assert_eq!(option, None);
462 ///
463 /// // When both contains None.
464 /// let option: Option<&str> = [Some::<u8>(0), None, Some(2)]
465 /// .into_iter()
466 /// .first_none_or_try(|_| None);
467 /// assert_eq!(option, None);
468 /// # }
469 /// ```
470 ///
471 /// Use the `iter` argument of the `f` closure:
472 ///
473 /// ```rust
474 /// # use first_err::FirstErr;
475 /// #
476 /// # fn main() {
477 /// let admin_id: u32 = 1;
478 /// let user_ids_in_conf = ["32", "5", "8", "19"];
479 ///
480 /// let admin_index = user_ids_in_conf
481 /// .into_iter()
482 /// .map(|s| s.parse::<u32>().ok())
483 /// .first_none_or_try(|user_ids_iter| {
484 /// user_ids_iter
485 /// .position(|user_id| user_id == admin_id)
486 /// });
487 ///
488 /// assert_eq!(admin_index, None);
489 /// # }
490 /// ```
491 #[inline]
492 fn first_none_or_try<T, O, F>(self, f: F) -> Option<O>
493 where
494 F: FnOnce(&mut FirstNoneIter<Self, T>) -> Option<O>,
495 Self: Iterator<Item = Option<T>> + Sized,
496 {
497 self.first_none_or_else(f).and_then(|opt| opt)
498 }
499
500 /// Returns the first `None` item in the current iterator, or an `Some(value)`.
501 ///
502 ///
503 ///
504 /// # Examples
505 ///
506 /// ```rust
507 /// # use first_err::FirstErr;
508 /// #
509 /// # fn main() {
510 /// // Everything is Some.
511 /// let option = [Some::<u8>(0), Some(1), Some(2)]
512 /// .into_iter()
513 /// .first_none_or("foo");
514 /// assert_eq!(option, Some("foo"));
515 ///
516 /// // Contains some `None` values.
517 /// let option = [Some::<u8>(0), None, None]
518 /// .into_iter()
519 /// .first_none_or("foo");
520 /// assert_eq!(option, None);
521 /// # }
522 /// ```
523 #[inline]
524 fn first_none_or<T, O>(self, value: O) -> Option<O>
525 where
526 Self: Iterator<Item = Option<T>> + Sized,
527 {
528 self.first_none_or_else(|_| value)
529 }
530}
531
532impl<I> FirstErr for I where I: Iterator {}
533
534mod result {
535 use core::iter::FusedIterator;
536
537 /// An `Iterator` can take first `Err` from another iterator.
538 ///
539 /// See [`FirstErr::first_err_or_else()`](crate::FirstErr::first_err_or_else) for more details.
540 #[derive(Debug)]
541 pub struct FirstErrIter<I, T, E>
542 where
543 I: Iterator<Item = Result<T, E>>,
544 {
545 state: State<I, T, E>,
546 }
547
548 impl<I, T, E> FirstErrIter<I, T, E>
549 where
550 I: Iterator<Item = Result<T, E>>,
551 {
552 #[inline]
553 pub(super) fn first_err_or_else<O, F>(inner: I, f: F) -> Result<O, E>
554 where
555 F: FnOnce(&mut Self) -> O,
556 {
557 let mut me = Self {
558 state: State::Active(inner),
559 };
560
561 let output = f(&mut me);
562
563 // Take first err, if not found and not exhausted yet, find it.
564 // If just not found finally, return output.
565 match me.state {
566 State::Active(inner) => {
567 for res in inner {
568 let _ = res?;
569 }
570 Ok(output)
571 }
572 State::Exhausted => Ok(output),
573 State::FoundFirstErr(e) => Err(e),
574 }
575 }
576 }
577
578 impl<I, T, E> Iterator for FirstErrIter<I, T, E>
579 where
580 I: Iterator<Item = Result<T, E>>,
581 {
582 type Item = T;
583
584 #[inline]
585 fn next(&mut self) -> Option<Self::Item> {
586 match &mut self.state {
587 State::Active(inner) => match inner.next() {
588 Some(Ok(t)) => Some(t),
589 Some(Err(e)) => {
590 self.state = State::FoundFirstErr(e);
591 None
592 }
593 None => {
594 self.state = State::Exhausted;
595 None
596 }
597 },
598 State::FoundFirstErr(_) => None,
599 State::Exhausted => None,
600 }
601 }
602
603 #[inline]
604 fn size_hint(&self) -> (usize, Option<usize>) {
605 match &self.state {
606 State::Active(inner) => inner.size_hint(),
607 State::FoundFirstErr(_) => (0, Some(0)),
608 State::Exhausted => (0, Some(0)),
609 }
610 }
611 }
612
613 impl<I, T, E> FusedIterator for FirstErrIter<I, T, E> where I: Iterator<Item = Result<T, E>> {}
614
615 /// Internal state of [`FirstErrIter`].
616 #[derive(Debug)]
617 enum State<I, T, E>
618 where
619 I: Iterator<Item = Result<T, E>>,
620 {
621 Active(I),
622 FoundFirstErr(E),
623 Exhausted,
624 }
625}
626
627mod option {
628 use core::iter::FusedIterator;
629
630 /// An `Iterator` can take first `None` from another iterator.
631 ///
632 /// See [`FirstErr::first_none_or_else()`](crate::FirstErr::first_none_or_else) for more details.
633 #[derive(Debug)]
634 pub struct FirstNoneIter<I, T>
635 where
636 I: Iterator<Item = Option<T>>,
637 {
638 state: State<I, T>,
639 }
640
641 impl<I, T> FirstNoneIter<I, T>
642 where
643 I: Iterator<Item = Option<T>>,
644 {
645 #[inline]
646 pub(super) fn first_none_or_else<O, F>(inner: I, f: F) -> Option<O>
647 where
648 F: FnOnce(&mut Self) -> O,
649 {
650 let mut me = Self {
651 state: State::Active(inner),
652 };
653
654 let output = f(&mut me);
655
656 // Take first None, if not found and not exhausted yet, find it.
657 // If just not found finally, return output.
658 match me.state {
659 State::Active(inner) => {
660 for opt in inner {
661 let _ = opt?;
662 }
663 Some(output)
664 }
665 State::Exhausted => Some(output),
666 State::FoundFirstNone => None,
667 }
668 }
669 }
670
671 impl<I, T> Iterator for FirstNoneIter<I, T>
672 where
673 I: Iterator<Item = Option<T>>,
674 {
675 type Item = T;
676
677 #[inline]
678 fn next(&mut self) -> Option<Self::Item> {
679 match &mut self.state {
680 State::Active(inner) => match inner.next() {
681 Some(Some(t)) => Some(t),
682 Some(None) => {
683 self.state = State::FoundFirstNone;
684 None
685 }
686 None => {
687 self.state = State::Exhausted;
688 None
689 }
690 },
691 State::FoundFirstNone => None,
692 State::Exhausted => None,
693 }
694 }
695
696 #[inline]
697 fn size_hint(&self) -> (usize, Option<usize>) {
698 match &self.state {
699 State::Active(inner) => inner.size_hint(),
700 State::FoundFirstNone => (0, Some(0)),
701 State::Exhausted => (0, Some(0)),
702 }
703 }
704 }
705
706 impl<I, T> FusedIterator for FirstNoneIter<I, T> where I: Iterator<Item = Option<T>> {}
707
708 /// Internal state of [`FirstNoneIter`].
709 #[derive(Debug)]
710 enum State<I, T>
711 where
712 I: Iterator<Item = Option<T>>,
713 {
714 Active(I),
715 FoundFirstNone,
716 Exhausted,
717 }
718}
719
720#[cfg(test)]
721mod tests {
722 mod test_first_err {
723 //! Test first_err_* methods.
724
725 use crate::FirstErr;
726
727 #[test]
728 fn _or_else_with_1_layer_data_and_without_err() {
729 let ans = [Ok::<u8, u8>(0), Ok(1), Ok(2), Ok(3), Ok(4)]
730 .into_iter()
731 .first_err_or_else(|iter1| iter1.sum::<u8>());
732
733 assert_eq!(ans, Ok(10));
734 }
735
736 #[test]
737 fn _or_else_with_1_layer_data_and_with_err() {
738 let ans = [Ok::<u8, u8>(0), Ok(1), Err(2), Ok(3), Ok(4)]
739 .into_iter()
740 .first_err_or_else(|iter1| iter1.sum::<u8>());
741
742 assert_eq!(ans, Err(2));
743 }
744
745 #[test]
746 fn _or_else_with_2_layer_data_and_outmost_err_in_layer_1() {
747 let ans = [
748 Ok::<Result<u8, u8>, u8>(Ok(0)),
749 Ok(Err(1)),
750 Err(2),
751 Ok(Ok(3)),
752 Ok(Ok(4)),
753 ]
754 .into_iter()
755 .first_err_or_else(|iter1| {
756 iter1
757 // could chain other ops
758 .first_err_or_else(|iter2| iter2.sum::<u8>())
759 });
760
761 assert_eq!(ans, Err(2));
762 }
763
764 #[test]
765 fn _or_else_with_2_layer_data_and_outmost_err_in_layer_2() {
766 let ans = [
767 Ok::<Result<u8, u8>, u8>(Ok(0)),
768 Ok(Ok(1)),
769 Ok(Err(2)),
770 Ok(Err(3)),
771 Ok(Ok(4)),
772 ]
773 .into_iter()
774 .first_err_or_else(|iter1| {
775 iter1
776 // could chain other ops
777 .first_err_or_else(|iter2| iter2.sum::<u8>())
778 });
779
780 assert_eq!(ans, Ok(Err(2)));
781 }
782
783 #[test]
784 fn _or_else_with_3_layer_data_and_outmost_err_in_layer_2() {
785 let ans = [
786 Ok::<Result<Result<u8, u8>, u8>, u8>(Ok(Ok(0))),
787 Ok(Ok(Ok(1))),
788 Ok(Ok(Err(2))),
789 Ok(Err(3)),
790 Ok(Ok(Ok(4))),
791 ]
792 .into_iter()
793 .first_err_or_else(|iter1| {
794 iter1
795 // could chain other ops
796 .first_err_or_else(|iter2| {
797 iter2
798 // could chain other ops
799 .first_err_or_else(|iter3| iter3.sum::<u8>())
800 })
801 });
802
803 assert_eq!(ans, Ok(Err(3)));
804 }
805
806 #[test]
807 fn _or_else_not_need_to_consume_iter_manually() {
808 let ans = [Ok::<u8, u8>(0), Err(1), Err(2)]
809 .into_iter()
810 .first_err_or_else(|_iter| {});
811
812 assert_eq!(ans, Err(1));
813 }
814
815 /// In most cases, API users should not be concerned about how many times the original
816 /// iterator's `.next()` method is called, as it gets consumed after
817 /// `first_err_or_else()` is called.
818 ///
819 /// However, if the inner iterator has some side-effect, this behavior is still
820 /// observable, and users may rely on it.
821 ///
822 /// This test is designed to ensure that this behavior remains consistent even when
823 /// the code changes.
824 #[test]
825 fn _or_else_never_call_next_on_orig_iter_after_first_err_found() {
826 let mut orig_iter_next_count = 0;
827
828 [Ok::<u8, u8>(0), Err(1), Err(2)]
829 .into_iter()
830 .inspect(|_| orig_iter_next_count += 1) // side-effect
831 .first_err_or_else(|iter| {
832 // exhaust whole iter.
833 for _ in &mut *iter {}
834
835 // call iter.next() after the iter already exhausted.
836 assert_eq!(iter.next(), None);
837 })
838 .ok();
839
840 assert_eq!(orig_iter_next_count, 2);
841 }
842
843 #[test]
844 fn _or_else_use_lazy_evaluation() {
845 use core::cell::{Cell, RefCell};
846
847 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
848 enum Trace {
849 None,
850 Outer(Result<u8, u8>),
851 Inner(u8),
852 }
853
854 // if index >= N, it will panic.
855 fn record_trace<const N: usize>(
856 traces: &RefCell<[Trace; N]>,
857 idx: &Cell<usize>,
858 v: Trace,
859 ) {
860 let i = idx.get();
861 traces.borrow_mut()[i] = v;
862 idx.set(i + 1);
863 }
864
865 // already known N = 5 within [_; N] in this test case.
866 // We don't use Vec here just bacause want to avoid `alloc` crate.
867 let traces = RefCell::new([Trace::None; 5]);
868
869 let index = Cell::new(0);
870
871 let ans = [Ok::<u8, u8>(0), Ok(1), Err(2), Ok(3)]
872 .iter()
873 .cloned()
874 // record value from outer
875 .inspect(|&res| record_trace(&traces, &index, Trace::Outer(res)))
876 .first_err_or_else(|iter| {
877 iter
878 // record value from inner
879 .inspect(|&n| record_trace(&traces, &index, Trace::Inner(n)))
880 .sum::<u8>()
881 });
882
883 assert_eq!(ans, Err(2));
884 assert_eq!(
885 traces.into_inner(),
886 [
887 Trace::Outer(Ok(0)),
888 Trace::Inner(0),
889 Trace::Outer(Ok(1)),
890 Trace::Inner(1),
891 Trace::Outer(Err(2))
892 ]
893 );
894 }
895
896 #[test]
897 fn _or_else_with_non_fused_iterator() {
898 struct NonFusedIter {
899 curr: u32,
900 }
901
902 impl NonFusedIter {
903 fn new() -> Self {
904 Self { curr: 0 }
905 }
906 }
907
908 impl Iterator for NonFusedIter {
909 type Item = Result<u32, u32>;
910
911 fn next(&mut self) -> Option<Self::Item> {
912 let tmp = self.curr;
913 self.curr += 1;
914
915 match tmp % 3 {
916 0 => Some(Ok(tmp)),
917 1 => None,
918 2 => Some(Err(tmp)),
919 _ => unreachable!(),
920 }
921 }
922 }
923
924 let ans = NonFusedIter::new().first_err_or_else(|iter| iter.sum::<u32>());
925
926 assert_eq!(ans, Ok(0));
927 }
928
929 #[test]
930 fn _or_without_err() {
931 let ans = [Ok::<u8, u8>(0), Ok(1), Ok(2), Ok(3), Ok(4)]
932 .into_iter()
933 .first_err_or("no err");
934
935 assert_eq!(ans, Ok("no err"));
936 }
937
938 #[test]
939 fn _or_with_err() {
940 let ans = [Ok::<u8, u8>(0), Ok(1), Err(2), Ok(3), Ok(4)]
941 .into_iter()
942 .first_err_or("no err");
943
944 assert_eq!(ans, Err(2));
945 }
946
947 #[test]
948 fn _or_try_without_err_and_closure_produce_ok() {
949 let ans = [Ok::<u8, u8>(0), Ok(1), Ok(2), Ok(3), Ok(4)]
950 .into_iter()
951 .first_err_or_try(|iter| iter.nth(1).ok_or(1));
952
953 assert_eq!(ans, Ok(1));
954 }
955
956 #[test]
957 fn _or_try_without_err_and_closure_produce_err() {
958 let ans = [Ok::<u8, u8>(0), Ok(1), Ok(2), Ok(3), Ok(4)]
959 .into_iter()
960 .first_err_or_try(|iter| iter.nth(100).ok_or(100));
961
962 assert_eq!(ans, Err(100));
963 }
964
965 #[test]
966 fn _or_try_with_err_and_closure_produce_ok() {
967 let ans = [Ok::<u8, u8>(0), Ok(1), Err(2), Ok(3), Ok(4)]
968 .into_iter()
969 .first_err_or_try(|iter| iter.nth(1).ok_or(1));
970
971 assert_eq!(ans, Err(2));
972 }
973
974 #[test]
975 fn _or_try_with_err_and_closure_produce_err() {
976 let ans = [Ok::<u8, u8>(0), Ok(1), Err(2), Ok(3), Ok(4)]
977 .into_iter()
978 .first_err_or_try(|iter| iter.nth(100).ok_or(100));
979
980 assert_eq!(ans, Err(2));
981 }
982
983 #[test]
984 fn _methods_can_call_through_trait_object() {
985 let mut array_iter = [Ok::<u8, u8>(0), Err(1), Err(2)].into_iter();
986
987 fn take_dyn(iter: &mut dyn Iterator<Item = Result<u8, u8>>) {
988 iter.first_err_or_else(|iter| iter.sum::<u8>()).ok();
989 iter.first_err_or(0).ok();
990 iter.first_err_or_try(|iter| Ok(iter.sum::<u8>())).ok();
991 }
992
993 take_dyn(&mut array_iter);
994 }
995 }
996
997 mod test_first_none {
998 //! Test first_none_* methods.
999
1000 use crate::FirstErr;
1001
1002 #[test]
1003 fn _or_else_with_1_layer_data_and_without_none() {
1004 let ans = [Some(0u8), Some(1), Some(2), Some(3), Some(4)]
1005 .into_iter()
1006 .first_none_or_else(|iter1| iter1.sum::<u8>());
1007
1008 assert_eq!(ans, Some(10));
1009 }
1010
1011 #[test]
1012 fn _or_else_with_1_layer_data_and_with_none() {
1013 let ans = [Some(0u8), Some(1), None, Some(3), Some(4)]
1014 .into_iter()
1015 .first_none_or_else(|iter1| iter1.sum::<u8>());
1016
1017 assert_eq!(ans, None);
1018 }
1019
1020 #[test]
1021 fn _or_else_with_2_layer_data_and_outmost_none_in_layer_1() {
1022 let ans = [
1023 Some(Some(0u8)),
1024 Some(None),
1025 None,
1026 Some(Some(3)),
1027 Some(Some(4)),
1028 ]
1029 .into_iter()
1030 .first_none_or_else(|iter1| {
1031 iter1
1032 // could chain other ops
1033 .first_none_or_else(|iter2| iter2.sum::<u8>())
1034 });
1035
1036 assert_eq!(ans, None);
1037 }
1038
1039 #[test]
1040 fn _or_else_with_2_layer_data_and_outmost_none_in_layer_2() {
1041 let ans = [
1042 Some(Some(0u8)),
1043 Some(Some(1)),
1044 Some(None),
1045 Some(Some(3)),
1046 Some(Some(4)),
1047 ]
1048 .into_iter()
1049 .first_none_or_else(|iter1| {
1050 iter1
1051 // could chain other ops
1052 .first_none_or_else(|iter2| iter2.sum::<u8>())
1053 });
1054
1055 assert_eq!(ans, Some(None));
1056 }
1057
1058 #[test]
1059 fn _or_else_with_3_layer_data_and_outmost_none_in_layer_2() {
1060 let ans = [
1061 Some(Some(Some(0))),
1062 Some(Some(Some(1))),
1063 Some(Some(None)),
1064 Some(None),
1065 Some(Some(Some(4))),
1066 ]
1067 .into_iter()
1068 .first_none_or_else(|iter1| {
1069 iter1
1070 // could chain other ops
1071 .first_none_or_else(|iter2| {
1072 iter2
1073 // could chain other ops
1074 .first_none_or_else(|iter3| iter3.sum::<u8>())
1075 })
1076 });
1077
1078 assert_eq!(ans, Some(None));
1079 }
1080
1081 #[test]
1082 fn _or_else_not_need_to_consume_iter_manually() {
1083 let ans = [Some(0), None, None]
1084 .into_iter()
1085 .first_none_or_else(|_iter| {});
1086
1087 assert_eq!(ans, None);
1088 }
1089
1090 /// In most cases, API users should not be concerned about how many times the original
1091 /// iterator's `.next()` method is called, as it gets consumed after
1092 /// `first_none_or_else()` is called.
1093 ///
1094 /// However, if the inner iterator has some side-effect, this behavior is still
1095 /// observable, and users may rely on it.
1096 ///
1097 /// This test is designed to ensure that this behavior remains consistent even when
1098 /// the code changes.
1099 #[test]
1100 fn _or_else_never_call_next_on_orig_iter_after_first_none_found() {
1101 let mut orig_iter_next_count = 0;
1102
1103 [Some(0), None, None]
1104 .into_iter()
1105 .inspect(|_| orig_iter_next_count += 1) // side-effect
1106 .first_none_or_else(|iter| {
1107 // exhaust whole iter.
1108 for _ in &mut *iter {}
1109
1110 // call iter.next() after the iter already exhausted.
1111 assert_eq!(iter.next(), None);
1112 });
1113
1114 assert_eq!(orig_iter_next_count, 2);
1115 }
1116
1117 #[test]
1118 fn _or_else_use_lazy_evaluation() {
1119 use core::cell::{Cell, RefCell};
1120
1121 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
1122 enum Trace {
1123 None,
1124 Outer(Option<u8>),
1125 Inner(u8),
1126 }
1127
1128 // if index >= N, it will panic.
1129 fn record_trace<const N: usize>(
1130 traces: &RefCell<[Trace; N]>,
1131 idx: &Cell<usize>,
1132 v: Trace,
1133 ) {
1134 let i = idx.get();
1135 traces.borrow_mut()[i] = v;
1136 idx.set(i + 1);
1137 }
1138
1139 // already known N = 5 within [_; N] in this test case.
1140 // We don't use Vec here just bacause want to avoid `alloc` crate.
1141 let traces = RefCell::new([Trace::None; 5]);
1142
1143 let index = Cell::new(0);
1144
1145 let ans = [Some(0u8), Some(1), None, Some(3)]
1146 .iter()
1147 .cloned()
1148 // record value from outer
1149 .inspect(|&opt| record_trace(&traces, &index, Trace::Outer(opt)))
1150 .first_none_or_else(|iter| {
1151 iter
1152 // record value from inner
1153 .inspect(|&n| record_trace(&traces, &index, Trace::Inner(n)))
1154 .sum::<u8>()
1155 });
1156
1157 assert_eq!(ans, None);
1158 assert_eq!(
1159 traces.into_inner(),
1160 [
1161 Trace::Outer(Some(0)),
1162 Trace::Inner(0),
1163 Trace::Outer(Some(1)),
1164 Trace::Inner(1),
1165 Trace::Outer(None)
1166 ]
1167 );
1168 }
1169
1170 #[test]
1171 fn _or_else_with_non_fused_iterator() {
1172 struct NonFusedIter {
1173 curr: u32,
1174 }
1175
1176 impl NonFusedIter {
1177 fn new() -> Self {
1178 Self { curr: 0 }
1179 }
1180 }
1181
1182 impl Iterator for NonFusedIter {
1183 type Item = Option<u32>;
1184
1185 fn next(&mut self) -> Option<Self::Item> {
1186 let tmp = self.curr;
1187 self.curr += 1;
1188
1189 match tmp % 3 {
1190 0 => Some(Some(tmp)),
1191 1 => None, // after produce a None ...
1192 2 => Some(None), // it still can produce Some(value)
1193 _ => unreachable!(),
1194 }
1195 }
1196 }
1197
1198 let ans = NonFusedIter::new().first_none_or_else(|iter| iter.sum::<u32>());
1199
1200 assert_eq!(ans, Some(0));
1201 }
1202
1203 #[test]
1204 fn _or_without_none() {
1205 let ans = [Some(0u8), Some(1), Some(2), Some(3), Some(4)]
1206 .into_iter()
1207 .first_none_or("no none");
1208
1209 assert_eq!(ans, Some("no none"));
1210 }
1211
1212 #[test]
1213 fn _or_with_none() {
1214 let ans = [Some(0u8), Some(1), None, Some(3), Some(4)]
1215 .into_iter()
1216 .first_none_or("no none");
1217
1218 assert_eq!(ans, None);
1219 }
1220
1221 #[test]
1222 fn _or_try_without_none_and_closure_produce_some() {
1223 let ans = [Some(0u8), Some(1), Some(2), Some(3), Some(4)]
1224 .into_iter()
1225 .first_none_or_try(|iter| iter.nth(1));
1226
1227 assert_eq!(ans, Some(1));
1228 }
1229
1230 #[test]
1231 fn _or_try_without_none_and_closure_produce_none() {
1232 let ans = [Some(0u8), Some(1), Some(2), Some(3), Some(4)]
1233 .into_iter()
1234 .first_none_or_try(|iter| iter.nth(100));
1235
1236 assert_eq!(ans, None);
1237 }
1238
1239 #[test]
1240 fn _or_try_with_none_and_closure_produce_some() {
1241 let ans = [Some(0u8), Some(1), None, Some(3), Some(4)]
1242 .into_iter()
1243 .first_none_or_try(|iter| iter.nth(1));
1244
1245 assert_eq!(ans, None);
1246 }
1247
1248 #[test]
1249 fn _or_try_with_none_and_closure_produce_none() {
1250 let ans = [Some(0u8), Some(1), None, Some(3), Some(4)]
1251 .into_iter()
1252 .first_none_or_try(|iter| iter.nth(100));
1253
1254 assert_eq!(ans, None);
1255 }
1256
1257 #[test]
1258 fn _methods_can_call_through_trait_object() {
1259 let mut array_iter = [Some(0u8), None, None].into_iter();
1260
1261 fn take_dyn(iter: &mut dyn Iterator<Item = Option<u8>>) {
1262 iter.first_none_or_else(|iter| iter.sum::<u8>());
1263 iter.first_none_or(0);
1264 iter.first_none_or_try(|iter| Some(iter.sum::<u8>()));
1265 }
1266
1267 take_dyn(&mut array_iter);
1268 }
1269 }
1270}