unzip3/
lib.rs

1
2pub trait Unzip3<A, B, C> {
3    fn unzip3<FromA, FromB, FromC>(self) -> (FromA, FromB, FromC) where
4        FromA: Default + Extend<A>,
5        FromB: Default + Extend<B>,
6        FromC: Default + Extend<C>;
7}
8
9impl<I, A, B, C> Unzip3<A, B, C> for I where
10        I: Sized + Iterator<Item=(A, B, C)>
11{
12    fn unzip3<FromA, FromB, FromC>(self) -> (FromA, FromB, FromC)
13    where
14        FromA: Default + Extend<A>,
15        FromB: Default + Extend<B>,
16        FromC: Default + Extend<C>,
17    {
18        struct SizeHint<A>(usize, Option<usize>, std::marker::PhantomData<A>);
19        impl<A> Iterator for SizeHint<A> {
20            type Item = A;
21
22            fn next(&mut self) -> Option<A> { None }
23            fn size_hint(&self) -> (usize, Option<usize>) {
24                (self.0, self.1)
25            }
26        }
27
28        let (lo, hi) = self.size_hint();
29        let mut ts: FromA = Default::default();
30        let mut us: FromB = Default::default();
31        let mut vs: FromC = Default::default();
32
33        ts.extend(SizeHint(lo, hi, std::marker::PhantomData));
34        us.extend(SizeHint(lo, hi, std::marker::PhantomData));
35        vs.extend(SizeHint(lo, hi, std::marker::PhantomData));
36
37        for (t, u, v) in self {
38            ts.extend(Some(t));
39            us.extend(Some(u));
40            vs.extend(Some(v));
41        }
42
43        (ts, us, vs)
44    }
45}
46
47#[test]
48fn it_works() {
49    let (a, b, c): (Vec<_>, Vec<_>, Vec<_>) = vec![(1,2,3),(4,5,6)].iter().cloned().unzip3();
50
51    assert_eq!(vec![1,4], a);
52    assert_eq!(vec![2,5], b);
53    assert_eq!(vec![3,6], c);
54}