malachite_base/options/
exhaustive.rs

1// Copyright © 2025 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use core::iter::{Chain, Once, once};
10
11/// Generates all [`Option`]s except `None`, with values from a given iterator.
12///
13/// This `struct` is created by [`exhaustive_somes`]; see its documentation for more.
14#[derive(Clone, Debug)]
15pub struct ExhaustiveSomes<I: Iterator> {
16    xs: I,
17}
18
19impl<I: Iterator> Iterator for ExhaustiveSomes<I> {
20    type Item = Option<I::Item>;
21
22    fn next(&mut self) -> Option<Option<I::Item>> {
23        self.xs.next().map(Some)
24    }
25}
26
27/// Generates all [`Option`]s except `None`, with values from a given iterator.
28///
29/// The elements of the given iterator are wrapped in `Some` and generated in the original order.
30///
31/// The output length is `xs.count()`.
32///
33/// # Examples
34/// ```
35/// use itertools::Itertools;
36/// use malachite_base::options::exhaustive::exhaustive_somes;
37///
38/// assert_eq!(
39///     exhaustive_somes([1, 2, 3].iter().cloned()).collect_vec(),
40///     &[Some(1), Some(2), Some(3)]
41/// );
42/// ```
43#[inline]
44pub const fn exhaustive_somes<I: Iterator>(xs: I) -> ExhaustiveSomes<I> {
45    ExhaustiveSomes { xs }
46}
47
48/// Generates all [`Option`]s with values from a given iterator.
49///
50/// `None` comes first, followed by the elements of the given iterator wrapped in `Some`.
51///
52/// The output length is `xs.count()`.
53///
54/// # Examples
55/// ```
56/// use itertools::Itertools;
57/// use malachite_base::options::exhaustive::exhaustive_options;
58///
59/// assert_eq!(
60///     exhaustive_options([1, 2, 3].iter().cloned()).collect_vec(),
61///     &[None, Some(1), Some(2), Some(3)]
62/// );
63/// ```
64#[inline]
65pub fn exhaustive_options<I: Iterator>(xs: I) -> Chain<Once<Option<I::Item>>, ExhaustiveSomes<I>> {
66    once(None).chain(exhaustive_somes(xs))
67}