1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

pub trait Unzip3<A, B, C> {
    fn unzip3<FromA, FromB, FromC>(self) -> (FromA, FromB, FromC) where
        FromA: Default + Extend<A>,
        FromB: Default + Extend<B>,
        FromC: Default + Extend<C>;
}

impl<I, A, B, C> Unzip3<A, B, C> for I where
        I: Sized + Iterator<Item=(A, B, C)>
{
    fn unzip3<FromA, FromB, FromC>(self) -> (FromA, FromB, FromC)
    where
        FromA: Default + Extend<A>,
        FromB: Default + Extend<B>,
        FromC: Default + Extend<C>,
    {
        struct SizeHint<A>(usize, Option<usize>, std::marker::PhantomData<A>);
        impl<A> Iterator for SizeHint<A> {
            type Item = A;

            fn next(&mut self) -> Option<A> { None }
            fn size_hint(&self) -> (usize, Option<usize>) {
                (self.0, self.1)
            }
        }

        let (lo, hi) = self.size_hint();
        let mut ts: FromA = Default::default();
        let mut us: FromB = Default::default();
        let mut vs: FromC = Default::default();

        ts.extend(SizeHint(lo, hi, std::marker::PhantomData));
        us.extend(SizeHint(lo, hi, std::marker::PhantomData));
        vs.extend(SizeHint(lo, hi, std::marker::PhantomData));

        for (t, u, v) in self {
            ts.extend(Some(t));
            us.extend(Some(u));
            vs.extend(Some(v));
        }

        (ts, us, vs)
    }
}

#[test]
fn it_works() {
    let (a, b, c): (Vec<_>, Vec<_>, Vec<_>) = vec![(1,2,3),(4,5,6)].iter().cloned().unzip3();

    assert_eq!(vec![1,4], a);
    assert_eq!(vec![2,5], b);
    assert_eq!(vec![3,6], c);
}