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);
}