I am trying to implement a default iterator for structs implementing a trait. My trait is called DataRow, represents a row of table cells, and looks like this:
pub trait DataRow<'a> {
// Gets a cell by index
fn getCell(&self, i: usize) -> &DataCell<'a>;
// Gets the number of cells in the row
fn getNumCells(&self) -> usize;
}
The default iterator I want to provide should use those two methods to iterate over the row and return cell references. In Java this would boil down to an abstract class DataRow that implements Iterable. In Rust I tried first with IntoIterator:
impl<'a, T> IntoIterator for &'a T
where
T: DataRow<'a>,
{
type Item = &'a DataCell<'a>;
type IntoIter = DataRowIterator<'a, T>;
fn into_iter(self) -> DataRowIterator<'a, T> {
return DataRowIterator::new(self);
}
}
This does not work as anyone could implement their own iterator for their own implementation of the DataRow trait.
My second try was adding an iter method to the trait which creates the iterator and returns it:
fn iter(&self) -> DataRowIterator<'a, Self> {
return DataRowIterator::new(self);
}
This does not work either, because the size of Self is not known at compile time. Since DataRow can contain an arbitrary number of cells, I also cannot mark it as Sized to get around that.
My demo code including notes on the occurring errors
How would someone implement such a "default iterator" for a custom trait?
You can implement IntoIterator for a trait object reference.
impl<'a> IntoIterator for &'a DataRow<'a> {
type Item = &'a DataCell<'a>;
type IntoIter = DataRowIterator<'a>;
fn into_iter(self) -> DataRowIterator<'a> {
DataRowIterator::new(self)
}
}
DataRowIterator should be modified to keep the trait object reference &DataRow instead of &T and use the methods available for the DataRow trait.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With