Coverage Report

Created: 2024-05-20 06:38

/rust/registry/src/index.crates.io-6f17d22bba15001f/itertools-0.11.0/src/tuple_impl.rs
Line
Count
Source (jump to first uncovered line)
1
//! Some iterator that produces tuples
2
3
use std::iter::Fuse;
4
use std::iter::FusedIterator;
5
use std::iter::Take;
6
use std::iter::Cycle;
7
use std::marker::PhantomData;
8
9
// `HomogeneousTuple` is a public facade for `TupleCollect`, allowing
10
// tuple-related methods to be used by clients in generic contexts, while
11
// hiding the implementation details of `TupleCollect`.
12
// See https://github.com/rust-itertools/itertools/issues/387
13
14
/// Implemented for homogeneous tuples of size up to 12.
15
pub trait HomogeneousTuple
16
    : TupleCollect
17
{}
18
19
impl<T: TupleCollect> HomogeneousTuple for T {}
20
21
/// An iterator over a incomplete tuple.
22
///
23
/// See [`.tuples()`](crate::Itertools::tuples) and
24
/// [`Tuples::into_buffer()`].
25
0
#[derive(Clone, Debug)]
26
pub struct TupleBuffer<T>
27
    where T: HomogeneousTuple
28
{
29
    cur: usize,
30
    buf: T::Buffer,
31
}
32
33
impl<T> TupleBuffer<T>
34
    where T: HomogeneousTuple
35
{
36
0
    fn new(buf: T::Buffer) -> Self {
37
0
        TupleBuffer {
38
0
            cur: 0,
39
0
            buf,
40
0
        }
41
0
    }
42
}
43
44
impl<T> Iterator for TupleBuffer<T>
45
    where T: HomogeneousTuple
46
{
47
    type Item = T::Item;
48
49
0
    fn next(&mut self) -> Option<Self::Item> {
50
0
        let s = self.buf.as_mut();
51
0
        if let Some(ref mut item) = s.get_mut(self.cur) {
52
0
            self.cur += 1;
53
0
            item.take()
54
        } else {
55
0
            None
56
        }
57
0
    }
58
59
0
    fn size_hint(&self) -> (usize, Option<usize>) {
60
0
        let buffer = &self.buf.as_ref()[self.cur..];
61
0
        let len = if buffer.is_empty() {
62
0
            0
63
        } else {
64
0
            buffer.iter()
65
0
                  .position(|x| x.is_none())
66
0
                  .unwrap_or_else(|| buffer.len())
67
        };
68
0
        (len, Some(len))
69
0
    }
70
}
71
72
impl<T> ExactSizeIterator for TupleBuffer<T>
73
    where T: HomogeneousTuple
74
{
75
}
76
77
/// An iterator that groups the items in tuples of a specific size.
78
///
79
/// See [`.tuples()`](crate::Itertools::tuples) for more information.
80
0
#[derive(Clone, Debug)]
81
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
82
pub struct Tuples<I, T>
83
    where I: Iterator<Item = T::Item>,
84
          T: HomogeneousTuple
85
{
86
    iter: Fuse<I>,
87
    buf: T::Buffer,
88
}
89
90
/// Create a new tuples iterator.
91
0
pub fn tuples<I, T>(iter: I) -> Tuples<I, T>
92
0
    where I: Iterator<Item = T::Item>,
93
0
          T: HomogeneousTuple
94
0
{
95
0
    Tuples {
96
0
        iter: iter.fuse(),
97
0
        buf: Default::default(),
98
0
    }
99
0
}
100
101
impl<I, T> Iterator for Tuples<I, T>
102
    where I: Iterator<Item = T::Item>,
103
          T: HomogeneousTuple
104
{
105
    type Item = T;
106
107
0
    fn next(&mut self) -> Option<Self::Item> {
108
0
        T::collect_from_iter(&mut self.iter, &mut self.buf)
109
0
    }
110
}
111
112
impl<I, T> Tuples<I, T>
113
    where I: Iterator<Item = T::Item>,
114
          T: HomogeneousTuple
115
{
116
    /// Return a buffer with the produced items that was not enough to be grouped in a tuple.
117
    ///
118
    /// ```
119
    /// use itertools::Itertools;
120
    ///
121
    /// let mut iter = (0..5).tuples();
122
    /// assert_eq!(Some((0, 1, 2)), iter.next());
123
    /// assert_eq!(None, iter.next());
124
    /// itertools::assert_equal(vec![3, 4], iter.into_buffer());
125
    /// ```
126
0
    pub fn into_buffer(self) -> TupleBuffer<T> {
127
0
        TupleBuffer::new(self.buf)
128
0
    }
129
}
130
131
132
/// An iterator over all contiguous windows that produces tuples of a specific size.
133
///
134
/// See [`.tuple_windows()`](crate::Itertools::tuple_windows) for more
135
/// information.
136
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
137
0
#[derive(Clone, Debug)]
138
pub struct TupleWindows<I, T>
139
    where I: Iterator<Item = T::Item>,
140
          T: HomogeneousTuple
141
{
142
    iter: I,
143
    last: Option<T>,
144
}
145
146
/// Create a new tuple windows iterator.
147
0
pub fn tuple_windows<I, T>(mut iter: I) -> TupleWindows<I, T>
148
0
    where I: Iterator<Item = T::Item>,
149
0
          T: HomogeneousTuple,
150
0
          T::Item: Clone
151
0
{
152
0
    use std::iter::once;
153
0
154
0
    let mut last = None;
155
0
    if T::num_items() != 1 {
156
        // put in a duplicate item in front of the tuple; this simplifies
157
        // .next() function.
158
0
        if let Some(item) = iter.next() {
159
0
            let iter = once(item.clone()).chain(once(item)).chain(&mut iter);
160
0
            last = T::collect_from_iter_no_buf(iter);
161
0
        }
162
0
    }
163
164
0
    TupleWindows {
165
0
        iter,
166
0
        last,
167
0
    }
168
0
}
169
170
impl<I, T> Iterator for TupleWindows<I, T>
171
    where I: Iterator<Item = T::Item>,
172
          T: HomogeneousTuple + Clone,
173
          T::Item: Clone
174
{
175
    type Item = T;
176
177
0
    fn next(&mut self) -> Option<Self::Item> {
178
0
        if T::num_items() == 1 {
179
0
            return T::collect_from_iter_no_buf(&mut self.iter)
180
0
        }
181
0
        if let Some(ref mut last) = self.last {
182
0
            if let Some(new) = self.iter.next() {
183
0
                last.left_shift_push(new);
184
0
                return Some(last.clone());
185
0
            }
186
0
        }
187
0
        None
188
0
    }
189
}
190
191
impl<I, T> FusedIterator for TupleWindows<I, T>
192
    where I: FusedIterator<Item = T::Item>,
193
          T: HomogeneousTuple + Clone,
194
          T::Item: Clone
195
{}
196
197
/// An iterator over all windows, wrapping back to the first elements when the
198
/// window would otherwise exceed the length of the iterator, producing tuples
199
/// of a specific size.
200
///
201
/// See [`.circular_tuple_windows()`](crate::Itertools::circular_tuple_windows) for more
202
/// information.
203
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
204
0
#[derive(Debug, Clone)]
205
pub struct CircularTupleWindows<I, T: Clone>
206
    where I: Iterator<Item = T::Item> + Clone,
207
          T: TupleCollect + Clone
208
{
209
    iter: Take<TupleWindows<Cycle<I>, T>>,
210
    phantom_data: PhantomData<T>
211
}
212
213
0
pub fn circular_tuple_windows<I, T>(iter: I) -> CircularTupleWindows<I, T>
214
0
    where I: Iterator<Item = T::Item> + Clone + ExactSizeIterator,
215
0
          T: TupleCollect + Clone,
216
0
          T::Item: Clone
217
0
{
218
0
    let len = iter.len();
219
0
    let iter = tuple_windows(iter.cycle()).take(len);
220
0
221
0
    CircularTupleWindows {
222
0
        iter,
223
0
        phantom_data: PhantomData{}
224
0
    }
225
0
}
226
227
impl<I, T> Iterator for CircularTupleWindows<I, T>
228
    where I: Iterator<Item = T::Item> + Clone,
229
          T: TupleCollect + Clone,
230
          T::Item: Clone
231
{
232
    type Item = T;
233
234
0
    fn next(&mut self) -> Option<Self::Item> {
235
0
        self.iter.next()
236
0
    }
237
}
238
239
pub trait TupleCollect: Sized {
240
    type Item;
241
    type Buffer: Default + AsRef<[Option<Self::Item>]> + AsMut<[Option<Self::Item>]>;
242
243
    fn collect_from_iter<I>(iter: I, buf: &mut Self::Buffer) -> Option<Self>
244
        where I: IntoIterator<Item = Self::Item>;
245
246
    fn collect_from_iter_no_buf<I>(iter: I) -> Option<Self>
247
        where I: IntoIterator<Item = Self::Item>;
248
249
    fn num_items() -> usize;
250
251
    fn left_shift_push(&mut self, item: Self::Item);
252
}
253
254
macro_rules! count_ident{
255
    () => {0};
256
    ($i0:ident, $($i:ident,)*) => {1 + count_ident!($($i,)*)};
257
}
258
macro_rules! rev_for_each_ident{
259
    ($m:ident, ) => {};
260
    ($m:ident, $i0:ident, $($i:ident,)*) => {
261
        rev_for_each_ident!($m, $($i,)*);
262
        $m!($i0);
263
    };
264
}
265
266
macro_rules! impl_tuple_collect {
267
    ($dummy:ident,) => {}; // stop
268
    ($dummy:ident, $($Y:ident,)*) => (
269
        impl_tuple_collect!($($Y,)*);
270
        impl<A> TupleCollect for ($(ignore_ident!($Y, A),)*) {
271
            type Item = A;
272
            type Buffer = [Option<A>; count_ident!($($Y,)*) - 1];
273
274
            #[allow(unused_assignments, unused_mut)]
275
0
            fn collect_from_iter<I>(iter: I, buf: &mut Self::Buffer) -> Option<Self>
276
0
                where I: IntoIterator<Item = A>
277
0
            {
278
0
                let mut iter = iter.into_iter();
279
0
                $(
280
0
                    let mut $Y = None;
281
0
                )*
282
0
283
0
                loop {
284
0
                    $(
285
0
                        $Y = iter.next();
286
0
                        if $Y.is_none() {
287
0
                            break
288
0
                        }
289
0
                    )*
290
0
                    return Some(($($Y.unwrap()),*,))
291
                }
292
293
0
                let mut i = 0;
294
0
                let mut s = buf.as_mut();
295
0
                $(
296
0
                    if i < s.len() {
297
0
                        s[i] = $Y;
298
0
                        i += 1;
299
0
                    }
300
                )*
301
0
                return None;
302
0
            }
Unexecuted instantiation: <(_, _, _, _, _) as itertools::tuple_impl::TupleCollect>::collect_from_iter::<_>
Unexecuted instantiation: <(_, _, _, _) as itertools::tuple_impl::TupleCollect>::collect_from_iter::<_>
Unexecuted instantiation: <(_,) as itertools::tuple_impl::TupleCollect>::collect_from_iter::<_>
Unexecuted instantiation: <(_, _, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::collect_from_iter::<_>
Unexecuted instantiation: <(_, _, _) as itertools::tuple_impl::TupleCollect>::collect_from_iter::<_>
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::collect_from_iter::<_>
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::collect_from_iter::<_>
Unexecuted instantiation: <(_, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::collect_from_iter::<_>
Unexecuted instantiation: <(_, _) as itertools::tuple_impl::TupleCollect>::collect_from_iter::<_>
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::collect_from_iter::<_>
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::collect_from_iter::<_>
Unexecuted instantiation: <(_, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::collect_from_iter::<_>
303
304
0
            fn collect_from_iter_no_buf<I>(iter: I) -> Option<Self>
305
0
                where I: IntoIterator<Item = A>
306
0
            {
307
0
                let mut iter = iter.into_iter();
308
309
0
                Some(($(
310
0
                    { let $Y = iter.next()?; $Y },
311
                )*))
312
0
            }
Unexecuted instantiation: <(_, _, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::collect_from_iter_no_buf::<_>
Unexecuted instantiation: <(_,) as itertools::tuple_impl::TupleCollect>::collect_from_iter_no_buf::<_>
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::collect_from_iter_no_buf::<_>
Unexecuted instantiation: <(_, _, _, _, _) as itertools::tuple_impl::TupleCollect>::collect_from_iter_no_buf::<_>
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::collect_from_iter_no_buf::<_>
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::collect_from_iter_no_buf::<_>
Unexecuted instantiation: <(_, _, _, _) as itertools::tuple_impl::TupleCollect>::collect_from_iter_no_buf::<_>
Unexecuted instantiation: <(_, _) as itertools::tuple_impl::TupleCollect>::collect_from_iter_no_buf::<_>
Unexecuted instantiation: <(_, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::collect_from_iter_no_buf::<_>
Unexecuted instantiation: <(_, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::collect_from_iter_no_buf::<_>
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::collect_from_iter_no_buf::<_>
Unexecuted instantiation: <(_, _, _) as itertools::tuple_impl::TupleCollect>::collect_from_iter_no_buf::<_>
313
314
0
            fn num_items() -> usize {
315
0
                count_ident!($($Y,)*)
316
0
            }
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::num_items
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::num_items
Unexecuted instantiation: <(_, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::num_items
Unexecuted instantiation: <(_, _, _, _, _) as itertools::tuple_impl::TupleCollect>::num_items
Unexecuted instantiation: <(_, _, _) as itertools::tuple_impl::TupleCollect>::num_items
Unexecuted instantiation: <(_, _) as itertools::tuple_impl::TupleCollect>::num_items
Unexecuted instantiation: <(_,) as itertools::tuple_impl::TupleCollect>::num_items
Unexecuted instantiation: <(_, _, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::num_items
Unexecuted instantiation: <(_, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::num_items
Unexecuted instantiation: <(_, _, _, _) as itertools::tuple_impl::TupleCollect>::num_items
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::num_items
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::num_items
317
318
0
            fn left_shift_push(&mut self, mut item: A) {
319
0
                use std::mem::replace;
320
0
321
0
                let &mut ($(ref mut $Y),*,) = self;
322
0
                macro_rules! replace_item{($i:ident) => {
323
0
                    item = replace($i, item);
324
0
                }}
325
0
                rev_for_each_ident!(replace_item, $($Y,)*);
326
0
                drop(item);
327
0
            }
Unexecuted instantiation: <(_, _) as itertools::tuple_impl::TupleCollect>::left_shift_push
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::left_shift_push
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::left_shift_push
Unexecuted instantiation: <(_,) as itertools::tuple_impl::TupleCollect>::left_shift_push
Unexecuted instantiation: <(_, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::left_shift_push
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::left_shift_push
Unexecuted instantiation: <(_, _, _, _, _, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::left_shift_push
Unexecuted instantiation: <(_, _, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::left_shift_push
Unexecuted instantiation: <(_, _, _, _, _, _, _) as itertools::tuple_impl::TupleCollect>::left_shift_push
Unexecuted instantiation: <(_, _, _, _, _) as itertools::tuple_impl::TupleCollect>::left_shift_push
Unexecuted instantiation: <(_, _, _, _) as itertools::tuple_impl::TupleCollect>::left_shift_push
Unexecuted instantiation: <(_, _, _) as itertools::tuple_impl::TupleCollect>::left_shift_push
328
        }
329
    )
330
}
331
impl_tuple_collect!(dummy, a, b, c, d, e, f, g, h, i, j, k, l,);