Search code examples
rustiteratortraits

Generic trait for u8 iterators with function that returns a bool iterator


I have this code:

pub trait BytesToBits<T>: Iterator<Item = u8>
where
    T: Iterator<Item = bool>,
{
    fn bits(&mut self) -> T;
}

impl<T> BytesToBits<T> for dyn Iterator<Item = u8>
where
    T: Iterator<Item = bool>,
{
    fn bits(&mut self) -> T {
        self.flat_map(|byte| (0..8).map(move |offset| byte & (1 << offset) != 0))
    }
}

However, compiling it results in:

error[E0308]: mismatched types
  --> src/bitstream.rs:13:9
   |
8  | impl<T> BytesToBits<T> for dyn Iterator<Item = u8>
   |      - this type parameter
...
12 |     fn bits(&mut self) -> T {
   |                           - expected `T` because of return type
13 |         self.flat_map(|byte| (0..8).map(move |offset| byte & (1 << offset) != 0))
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found struct `FlatMap`
   |
   = note: expected type parameter `T`
                      found struct `FlatMap<&mut (dyn Iterator<Item = u8> + 'static), Map<std::ops::Range<{integer}>, [closure@src/bitstream.rs:13:41: 13:54]>, [closure@src/bitstream.rs:13:23: 13:29]>`

I am new to Rust and do not know what I exactly did wrong there and how to resolve the issue.

My goal is to have a trait BytesToBits that extends all Iterator<Item = u8> by providing them with a method bits() that returns an Iterator<Item = bool>.


Solution

  • Thanks for the comments and the answer. I think my issue again boiled down to the fact, that you cannot return traits from functions of traits [1]. I solved it now with a custom iterator:

    pub trait BytesToBits<T>
    where
        T: Iterator<Item = bool>,
    {
        fn bits(self) -> T;
    }
    
    impl<T> BytesToBits<BytesToBitsIterator<T>> for T
    where
        T: Iterator<Item = u8>,
    {
        fn bits(self) -> BytesToBitsIterator<T> {
            BytesToBitsIterator::from(self)
        }
    }
    
    pub struct BytesToBitsIterator<T>
    where
        T: Iterator<Item = u8>,
    {
        bytes: T,
        current: Option<u8>,
        index: u8,
    }
    
    impl<T> From<T> for BytesToBitsIterator<T>
    where
        T: Iterator<Item = u8>,
    {
        fn from(bytes: T) -> Self {
            Self {
                bytes,
                current: None,
                index: 0,
            }
        }
    }
    
    impl<T> Iterator for BytesToBitsIterator<T>
    where
        T: Iterator<Item = u8>,
    {
        type Item = bool;
    
        fn next(&mut self) -> Option<Self::Item> {
            if self.index > 7 {
                self.current = None;
                self.index = 0;
            }
    
            let current = match self.current {
                None => match self.bytes.next() {
                    None => {
                        return None;
                    }
                    Some(byte) => {
                        self.current = Some(byte);
                        byte
                    }
                },
                Some(byte) => byte,
            };
    
            let bit = current & (1 << self.index) != 0;
            self.index += 1;
            Some(bit)
        }
    }
    

    [1] Implement trait that has function which return traits