async-hid 0.5.0

A async library for interacting with HID devices
Documentation
#![allow(dead_code)]

use std::iter::Fuse;

pub trait TryIterExt<T, E> {
    fn try_collect_vec(self) -> Result<Vec<T>, E>;

    fn try_flatten(self) -> TryFlattenIter<Self, T>
    where
        T: IntoIterator,
        Self: Sized;
}

impl<T, E, I: Iterator<Item = Result<T, E>>> TryIterExt<T, E> for I {
    fn try_collect_vec(self) -> Result<Vec<T>, E> {
        let mut result = Vec::with_capacity(self.size_hint().0);
        for elem in self {
            result.push(elem?);
        }
        Ok(result)
    }
    fn try_flatten(self) -> TryFlattenIter<Self, T>
    where
        T: IntoIterator
    {
        TryFlattenIter {
            inner: self.fuse(),
            current: None
        }
    }
}

pub struct TryFlattenIter<I, T: IntoIterator> {
    inner: Fuse<I>,
    current: Option<T::IntoIter>
}

impl<I, T, E> Iterator for TryFlattenIter<I, T>
where
    I: Iterator<Item = Result<T, E>>,
    T: IntoIterator
{
    type Item = Result<T::Item, E>;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            if let Some(current) = self.current.as_mut().and_then(Iterator::next) {
                return Some(Ok(current));
            }
            self.current = None;
            match self.inner.next()? {
                Ok(iter) => self.current = Some(iter.into_iter()),
                Err(err) => return Some(Err(err))
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::utils::TryFlattenIter;

    #[test]
    fn test_try_flatten_iter() {
        let iter = TryFlattenIter::<_, Vec<i32>> {
            inner: [Err(0), Ok(vec![1, 2, 3]), Err(4), Ok(vec![5, 6, 7]), Err(8), Err(9)]
                .into_iter()
                .fuse(),
            current: None
        };
        assert_eq!(
            iter.collect::<Vec<_>>(),
            vec![Err(0), Ok(1), Ok(2), Ok(3), Err(4), Ok(5), Ok(6), Ok(7), Err(8), Err(9)]
        );
    }
}