I'm operating f32 array that represents multiple drawable elements (like SVG paths). Each drawable can indicate how many elements in the array it takes up, and then each drawable occurs immediately after the previous.
I want to mutate parts of the array whilst iterating over it. I did this as a while loop, which worked. But I wanted to clean it up and make an iterator for this, which makes the borrow checker complain
fn translate_original(renderables: &mut Vec<f32>, tx: f32, ty: f32) {
// This works
let mut i = 0;
while i < renderables.len() {
translate_renderable(renderables, i, tx, ty);
i = next_renderable(renderables, i);
}
}
fn translate_iterator(renderables: &mut Vec<f32>, tx: f32, ty: f32) {
// This fails
RenderableIterator::new(renderables)
.for_each(|i| translate_renderable(renderables, i, tx, ty));
}
fn main() {
let mut data_1: Vec<f32> = vec![
// renderable 1
2., 10., 10., 20., 20.,
// renderable 2
3., 30., 30., 40., 40., 50., 50.
];
let mut data_2 = data_1.clone();
translate_original(&mut data_1, 5., 5.);
translate_iterator(&mut data_2, 5., 5.);
}
// Set up
fn next_renderable(renderables: &Vec<f32>, i: usize) -> usize {
i + 1 + (renderables[i] as usize)
}
fn translate_renderable(renderables: &mut Vec<f32>, i: usize, tx: f32, ty: f32) {
let from = i + 1;
let to = next_renderable(renderables, i);
for i in (from..to).step_by(2) {
renderables[i] += tx;
renderables[i + 1] += ty;
}
}
pub struct RenderableIterator<'a> {
renderables: &'a Vec<f32>,
i: usize,
}
impl RenderableIterator<'_> {
pub fn new(renderables: &Vec<f32>) -> RenderableIterator {
RenderableIterator { renderables, i: 0 }
}
}
impl Iterator for RenderableIterator<'_> {
type Item = usize;
fn next(&mut self) -> Option<usize> {
if self.i < self.renderables.len() {
let out = Some(self.i);
self.i = next_renderable(&self.renderables, self.i);
out
} else {
None
}
}
}
I sort of understand why it's complaining - but to me it doesn't look any less safe than the while loop version. Is there a way to get the iterator version to work?