Background
I have a vector of boxed trait objects
trait Structure{
fn frame_proc(&mut self) -> Result<(), ()>;
}
// ...
structures: Vec<Box<dyn Structure>>
and I want to call a mutable method of each of the trait object in the vector.
for structure in &mut structures {
structure.frame_proc()?;
}
However, the problem is that I want to refer to the other trait objects inside frame_proc.
It might mutate the other objects, depending on the implementation of the trait.
Obviously, I can't pass a mutable reference to the vector at the same time as the trait's &mut self. So I came up with a method to split the vector into mutable slices and exclude the one that I will invoke trait method on.
trait Structure{
fn frame_proc(
&mut self,
structures: &mut dyn Iterator<Item = &mut Box<dyn Structure>>,
) -> Result<(), ()>;
}
// ...
for i in 0..structures.len() {
if 0 < i {
let (front, mid) = structures.split_at_mut(i);
let (center, last) = mid
.split_first_mut()
.ok_or(())?;
center.frame_proc(&mut front.into_iter().chain(last.into_iter())),
} else {
let (center, last) = structures
.split_first_mut()
.ok_or(())?;
center.frame_proc(&mut last.iter_mut())?;
}
}
The new frame_proc takes an Iterator trait object, which iterates over the vector except itself, so that the borrow checker is happy.
The problem
This worked well and nice, but there is a small issue. I can't use the iterator more than once in frame_proc. Once the iterator returns the other structures, it remains exhausted. Because it is an iterator, I can't rewind or recreate the iterator from original slice.
I tried to put a Fn trait object as an argument, which returns new iterator every time it is called, but in order to make it work, the Iterator has to be inside a Box (because it is a trait object). But now I can't prove that the boxed iterator won't outlive original slice.
trait Structure{
fn frame_proc(
&mut self,
_iter_structures: &dyn Fn() -> Box<dyn Iterator<Item = &mut Box<dyn Structure>>>,
);
}
let (front, mid) = structures.split_at_mut(i);
let (center, last) = mid
let mut iter = front.into_iter().chain(last.into_iter());
let mut iter_copy = || Box::new(iter);
What I don't want to do is to create a new vector of references to the original structures. It would surely work, but the vector can be hundreds or thousands long. I don't want to copy the whole vector into temporary buffer every time I iterate.
trait Structure{
fn frame_proc(
&mut self,
_structures: &Vec<&mut Box<dyn Structure>>,
) -> Result<(), ()>;
}
let vec = front.into_iter().chain(last.into_iter())
.collect::<Vec<_>>();
center.frame_proc(self, &vec)?;
All I need is just rewind or recreate the iterator behind the mutable reference. Does someone have a good solution?