non_empty_iter/
chain.rs

1//! Linking non-empty and possibly empty iterators together.
2
3use core::iter;
4
5use crate::non_empty::{IntoNonEmptyIterator, NonEmptyIterator};
6
7/// Converts the given arguments to iterators and links them together.
8///
9/// The first argument must be [`IntoNonEmptyIterator`], while the second one can simply
10/// implement [`IntoIterator`] yielding the same item type.
11pub fn chain<I: IntoNonEmptyIterator, J: IntoIterator<Item = I::Item>>(
12    non_empty: I,
13    maybe_empty: J,
14) -> Chain<I::IntoNonEmptyIter, J::IntoIter> {
15    Chain::new(non_empty.into_non_empty_iter(), maybe_empty.into_iter())
16}
17
18/// Represents non-empty iterators that link two iterators together.
19///
20/// The first iterator must be [`NonEmptyIterator`], while the second one can simply
21/// implement [`Iterator`] yielding the same item type.
22#[derive(Debug, Clone)]
23#[must_use = "non-empty iterators are lazy and do nothing unless consumed"]
24pub struct Chain<I: NonEmptyIterator, J: Iterator<Item = I::Item>> {
25    non_empty: I,
26    maybe_empty: J,
27}
28
29impl<I: NonEmptyIterator, J: Iterator<Item = I::Item>> Chain<I, J> {
30    /// Constructs [`Self`].
31    pub const fn new(non_empty: I, maybe_empty: J) -> Self {
32        Self {
33            non_empty,
34            maybe_empty,
35        }
36    }
37}
38
39impl<I: NonEmptyIterator, J: Iterator<Item = I::Item>> IntoIterator for Chain<I, J> {
40    type Item = I::Item;
41
42    type IntoIter = iter::Chain<I::IntoIter, J>;
43
44    fn into_iter(self) -> Self::IntoIter {
45        self.non_empty.into_iter().chain(self.maybe_empty)
46    }
47}
48
49unsafe impl<I: NonEmptyIterator, J: Iterator<Item = I::Item>> NonEmptyIterator for Chain<I, J> {}