I have a custom iterator which reads data from a reference to a Vec
in a non-contiguous manner. It will never return two references to the same memory, so I believe it is safe to implement a mutable counterpart.
However, the logic for the iterator itself is quite complex, and it would be entirely identical for the mutable version. In an attempt to avoid code duplication, I use my non-mut iterator under the hood, and then cast the result to add mutability. This works as expected, but I am unsure if it's invoking some kind of undefined behavior.
pub mod lib {
pub struct Data {
pub v: Vec<u64>,
}
impl Data {
pub fn iter(&self) -> MyIter {
MyIter {
data: &self.v,
i: 0,
}
}
pub fn iter_mut(&mut self) -> MyIterMut {
MyIterMut { iter: self.iter() }
}
}
pub struct MyIter<'a> {
data: &'a [u64],
i: usize,
}
impl<'a> Iterator for MyIter<'a> {
type Item = &'a u64;
fn next(&mut self) -> Option<Self::Item> {
if self.i == self.data.len() {
return None;
}
let res = &self.data[self.i];
self.i += 1;
Some(res)
}
}
pub struct MyIterMut<'a> {
iter: MyIter<'a>,
}
impl<'a> Iterator for MyIterMut<'a> {
type Item = &'a mut u64;
fn next(&mut self) -> Option<Self::Item> {
unsafe { std::mem::transmute(self.iter.next()) }
}
}
}
fn main() {
let mut d = lib::Data { v: vec![0; 8] };
for elem in d.iter_mut() {
*elem = 123;
}
println!("{:?}", d.v);
}
The mutable iterator is only constructed in the iter_mut
method. This means the initial value will always start as a mutable variable, due to the &mut self
. It wouldn't be possible to construct this mutable iterator from an immutable variable.
In C++, often times you will use a const_cast
to avoid duplicating an implementation that only varies in constness.
Is this something I can do in Rust?