Coverage Report

Created: 2025-07-01 06:50

/rust/registry/src/index.crates.io-6f17d22bba15001f/itertools-0.12.1/src/intersperse.rs
Line
Count
Source (jump to first uncovered line)
1
use super::size_hint;
2
use std::iter::{Fuse, FusedIterator};
3
4
pub trait IntersperseElement<Item> {
5
    fn generate(&mut self) -> Item;
6
}
7
8
#[derive(Debug, Clone)]
9
pub struct IntersperseElementSimple<Item>(Item);
10
11
impl<Item: Clone> IntersperseElement<Item> for IntersperseElementSimple<Item> {
12
0
    fn generate(&mut self) -> Item {
13
0
        self.0.clone()
14
0
    }
15
}
16
17
/// An iterator adaptor to insert a particular value
18
/// between each element of the adapted iterator.
19
///
20
/// Iterator element type is `I::Item`
21
///
22
/// This iterator is *fused*.
23
///
24
/// See [`.intersperse()`](crate::Itertools::intersperse) for more information.
25
pub type Intersperse<I> = IntersperseWith<I, IntersperseElementSimple<<I as Iterator>::Item>>;
26
27
/// Create a new Intersperse iterator
28
0
pub fn intersperse<I>(iter: I, elt: I::Item) -> Intersperse<I>
29
0
where
30
0
    I: Iterator,
31
0
{
32
0
    intersperse_with(iter, IntersperseElementSimple(elt))
33
0
}
34
35
impl<Item, F: FnMut() -> Item> IntersperseElement<Item> for F {
36
0
    fn generate(&mut self) -> Item {
37
0
        self()
38
0
    }
39
}
40
41
/// An iterator adaptor to insert a particular value created by a function
42
/// between each element of the adapted iterator.
43
///
44
/// Iterator element type is `I::Item`
45
///
46
/// This iterator is *fused*.
47
///
48
/// See [`.intersperse_with()`](crate::Itertools::intersperse_with) for more information.
49
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
50
#[derive(Clone, Debug)]
51
pub struct IntersperseWith<I, ElemF>
52
where
53
    I: Iterator,
54
{
55
    element: ElemF,
56
    iter: Fuse<I>,
57
    /// `peek` is None while no item have been taken out of `iter` (at definition).
58
    /// Then `peek` will alternatively be `Some(None)` and `Some(Some(item))`,
59
    /// where `None` indicates it's time to generate from `element` (unless `iter` is empty).
60
    peek: Option<Option<I::Item>>,
61
}
62
63
/// Create a new `IntersperseWith` iterator
64
0
pub fn intersperse_with<I, ElemF>(iter: I, elt: ElemF) -> IntersperseWith<I, ElemF>
65
0
where
66
0
    I: Iterator,
67
0
{
68
0
    IntersperseWith {
69
0
        peek: None,
70
0
        iter: iter.fuse(),
71
0
        element: elt,
72
0
    }
73
0
}
74
75
impl<I, ElemF> Iterator for IntersperseWith<I, ElemF>
76
where
77
    I: Iterator,
78
    ElemF: IntersperseElement<I::Item>,
79
{
80
    type Item = I::Item;
81
    #[inline]
82
0
    fn next(&mut self) -> Option<Self::Item> {
83
0
        let Self {
84
0
            element,
85
0
            iter,
86
0
            peek,
87
0
        } = self;
88
0
        match peek {
89
0
            Some(item @ Some(_)) => item.take(),
90
0
            Some(None) => match iter.next() {
91
0
                new @ Some(_) => {
92
0
                    *peek = Some(new);
93
0
                    Some(element.generate())
94
                }
95
0
                None => None,
96
            },
97
            None => {
98
0
                *peek = Some(None);
99
0
                iter.next()
100
            }
101
        }
102
0
    }
103
104
0
    fn size_hint(&self) -> (usize, Option<usize>) {
105
0
        let mut sh = self.iter.size_hint();
106
0
        sh = size_hint::add(sh, sh);
107
0
        match self.peek {
108
0
            Some(Some(_)) => size_hint::add_scalar(sh, 1),
109
0
            Some(None) => sh,
110
0
            None => size_hint::sub_scalar(sh, 1),
111
        }
112
0
    }
113
114
0
    fn fold<B, F>(self, init: B, mut f: F) -> B
115
0
    where
116
0
        Self: Sized,
117
0
        F: FnMut(B, Self::Item) -> B,
118
0
    {
119
0
        let Self {
120
0
            mut element,
121
0
            mut iter,
122
0
            peek,
123
0
        } = self;
124
0
        let mut accum = init;
125
126
0
        if let Some(x) = peek.unwrap_or_else(|| iter.next()) {
127
0
            accum = f(accum, x);
128
0
        }
129
130
0
        iter.fold(accum, |accum, x| {
131
0
            let accum = f(accum, element.generate());
132
0
            f(accum, x)
133
0
        })
134
0
    }
135
}
136
137
impl<I, ElemF> FusedIterator for IntersperseWith<I, ElemF>
138
where
139
    I: Iterator,
140
    ElemF: IntersperseElement<I::Item>,
141
{
142
}