Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement iterator trait over wrapped vector in Rust?

Tags:

rust

Having code like

#[derive(Debug)]
struct BinaryVec {
    vec: Vec<u8>,
}

impl BinaryVec {
    fn empty() -> BinaryVec {
        BinaryVec { vec: Vec::new() }
    }

    fn push(&mut self, bit: u8) {
        self.vec.push(bit);
    }
}

I'd like to be able to iterate over the structure's vector without making it public. For example, to call it like:

let bin_vec = BinaryVec::empty();
bin_vec.push(1);
bin_vec.push(0);
bin_vec.push(1);
for el in bin_vec.iter() { 
    // do something with 1,0,1 elements 
}

But I see that Iterator trait requires only next method which assumes the saved iter state in the structure.

Is there any way to directly pass vec iter through the higher level struct in Rust without adding new state related fields to the struct?

like image 932
Dmitry Mantis Avatar asked Mar 08 '26 18:03

Dmitry Mantis


1 Answers

Vec<T> itself does not implement Iterator either. However, it implements IntoIterator in three ways:

  • impl<T> IntoIterator for Vec<T>: you can write for item in vec, and each item will take a T by value. This consumes the vector.
  • impl<T> IntoIterator for &'_ [T] (where &Vec<T> derefs to &[T]): you can write for item in &vec, and each item will take a &T.
  • impl<T> IntoIterator for &'_ mut [T] (where &mut Vec<T> derefs to &mut [T]): you can write for item in &mut vec, and each item will take a &mut T.

You probably wanted to implement these for your wrapper as well:

impl IntoIterator for BinaryVec {
  type Item = u8;
  type IntoIter = <Vec<u8> as IntoIterator>::IntoIter; // so that you don't have to write std::vec::IntoIter, which nobody remembers anyway

  fn into_iter(self) -> Self::IntoIter {
    self.vec.into_iter()
  }
}

// We deref to slice so that we can reuse the slice impls
impl Deref for BinaryVec {
  type Output = [u8];

  fn deref(&self) -> &[u8] {
    &self.vec[..]
  }
}
impl DerefMut for BinaryVec {
  type Output = [u8];

  fn deref_mut(&mut self) -> &mut [u8] {
    &mut self.vec[..]
  }
}

Note that implementing IntoIterator for &mut [T] is not trivial (you need to use
methods like split_first_mut if you don't want to write unsafe code), so better reuse the implementation from slices.

like image 82
SOFe Avatar answered Mar 10 '26 12:03

SOFe



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!