0

I an new to lifetimes in rust and I need help. I want to write a custom Iterator to consume the dataset and I am lost with references lifetimes. I already have an iterator implementation but it doesn't consume the dataset (if I understand correctly). The dataset struct is the following

pub struct UtiasDataset {
    pub barcodes: Vec<Barcode>,
    pub groundtruth: Vec<Position>,
    pub landmarks: Vec<Landmark>,
    pub measurements: Vec<RangeBearing>,
    pub odometry: Vec<Odometry>,
}

And I would like to implement an iterator to consume the measurements and odometry vectors. The structs in the vectors are the following

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct RangeBearing {
    time: f64,
    subject_nb: u32,
    range: f64,
    bearing: f64,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Position {
    time: f64,
    x: f64,
    y: f64,
    orientation: f64,
}

I wrote this vector implementation that does not consume (if I understand correctly) the dataset:

pub struct UtiasDatasetIteratorRef<'a> {
    dataset: &'a UtiasDataset,
    index_measurements: usize,
    index_odometry: usize,
}

impl<'a> IntoIterator for &'a UtiasDataset {
    type IntoIter = UtiasDatasetIteratorRef<'a>;
    type Item = (Option<Vec<&'a RangeBearing>>, Option<&'a Odometry>);

    fn into_iter(self) -> Self::IntoIter {
        UtiasDatasetIteratorRef {
            dataset: self,
            index_measurements: 0,
            index_odometry: 0,
        }
    }
}

impl<'a> Iterator for UtiasDatasetIteratorRef<'a> {
    type Item = (Option<Vec<&'a RangeBearing>>, Option<&'a Odometry>);

    fn next(&mut self) -> Option<Self::Item> {
        let mut me = self
            .dataset
            .measurements
            .iter()
            .skip(self.index_measurements);
        let mut od = self.dataset.odometry.iter().skip(self.index_odometry);

        let me_next = me.next()?;
        let od_next = od.next()?;

        if od_next.time < me_next.time {
            self.index_odometry += 1;
            return Some((None, Some(od_next)));
        }
        let mut measurements = vec![me_next];
        self.index_measurements += 1;
        loop {
            let me_next = me.next()?;
            if me_next.time == measurements.last()?.time {
                measurements.push(me_next);
                self.index_measurements += 1;
            } else {
                break;
            }
        }
        if od_next.time == me_next.time {
            return Some((Some(measurements), Some(od_next)));
        }
        Some((Some(measurements), None))
    }
}

What I would like it have a way to return an Item of type (Option<Vec<&RangeBearing>>, Option<&Odometry>) but to consume the dataset so to have something like

pub struct UtiasDatasetIterator {
    dataset: UtiasDataset,
    index_measurements: usize,
    index_odometry: usize,
}

Maybe I am missing something obvious.

Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77
Bob Parker
  • 99
  • 7

0 Answers0