use likely_stable::unlikely;
use crate::ChunkedVec;
pub struct IterMut<'a, T, const N: usize> {
pub(crate) vec: &'a mut ChunkedVec<T, N>,
pub(crate) chunk_idx: usize,
pub(crate) offset: usize,
pub(crate) remaining: usize,
}
impl<T, const N: usize> ChunkedVec<T, N> {
pub fn iter_mut(&mut self) -> IterMut<'_, T, N> {
IterMut {
remaining: self.len(),
vec: self,
chunk_idx: 0,
offset: 0,
}
}
}
impl<'a, T, const N: usize> IterMut<'a, T, N> {
#[inline]
fn advance_position(&mut self) {
self.offset += 1;
if unlikely(self.offset == N) {
self.chunk_idx += 1;
self.offset = 0;
}
self.remaining -= 1;
}
#[inline]
fn current_ptr(&mut self) -> *mut T {
self.vec.data[self.chunk_idx][self.offset].as_mut_ptr()
}
}
impl<'a, T, const N: usize> Iterator for IterMut<'a, T, N> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
if unlikely(self.remaining == 0) {
return None;
}
unsafe {
let ptr = self.current_ptr();
self.advance_position();
Some(&mut *ptr)
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.remaining;
(remaining, Some(remaining))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_iter_mut() {
let mut vec = ChunkedVec::new();
vec.push(1);
vec.push(2);
vec.push(3);
let mut iter = vec.iter_mut();
assert_eq!(iter.next(), Some(&mut 1));
assert_eq!(iter.next(), Some(&mut 2));
let elem = iter.next();
assert_eq!(elem, Some(&mut 3));
*elem.unwrap() = 4;
assert_eq!(iter.next(), None);
assert_eq!(vec[2], 4);
}
}