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.