compressed_intvec/fixed/
iter_mut.rs

1//! # Mutable Iterators
2//!
3//! This module provides iterators for mutable, sequential access to the
4//! elements of a [`FixedVec`].
5//!
6//! # Provided Iterators
7//!
8//! - [`IterMut`]: An iterator that yields a mutable proxy for each element.
9//! - [`ChunksMut`]: An iterator that yields non-overlapping, mutable slices.
10//!
11//! # Examples
12//!
13//! ## Mutating elements in chunks
14//!
15//! The [`ChunksMut`] iterator allows for processing a vector in mutable,
16//! non-overlapping chunks.
17//!
18//! ```rust
19//! use compressed_intvec::fixed::{FixedVec, UFixedVec, BitWidth};
20//!
21//! let data: Vec<u32> = (0..100).collect();
22//! let mut vec: UFixedVec<u32> = FixedVec::builder().bit_width(BitWidth::Explicit(8)).build(&data).unwrap();
23//!
24//! // Process each chunk sequentially.
25//! for mut chunk in vec.chunks_mut(10) {
26//!     // Each chunk is a `FixedVecSlice` that can be mutated.
27//!     for i in 0..chunk.len() {
28//!         if let Some(mut proxy) = chunk.at_mut(i) {
29//!             *proxy *= 2;
30//!         }
31//!     }
32//! }
33//!
34//! assert_eq!(vec.get(10), Some(20));
35//! assert_eq!(vec.get(99), Some(198));
36//! ```
37
38use crate::fixed::{
39    proxy::MutProxy,
40    slice::FixedVecSlice,
41    traits::{Storable, Word},
42    FixedVec,
43};
44use dsi_bitstream::prelude::Endianness;
45use std::{cmp::min, marker::PhantomData};
46
47/// An iterator over non-overlapping, mutable chunks of a [`FixedVec`].
48///
49/// This struct is created by the [`chunks_mut`](super::FixedVec::chunks_mut)
50/// method.
51#[derive(Debug)]
52pub struct ChunksMut<'a, T, W, E, B>
53where
54    T: Storable<W>,
55    W: Word,
56    E: Endianness,
57    B: AsRef<[W]> + AsMut<[W]>,
58{
59    // A raw pointer to the original `FixedVec` is used to allow creating
60    // mutable slices without consuming the iterator.
61    vec_ptr: *mut FixedVec<T, W, E, B>,
62    end: usize,
63    current_pos: usize,
64    chunk_size: usize,
65    // Ensures the iterator's lifetime is tied to the original mutable borrow.
66    _phantom: PhantomData<&'a mut FixedVec<T, W, E, B>>,
67}
68
69impl<'a, T, W, E, B> ChunksMut<'a, T, W, E, B>
70where
71    T: Storable<W>,
72    W: Word,
73    E: Endianness,
74    B: AsRef<[W]> + AsMut<[W]>,
75{
76    /// Creates a new `ChunksMut` iterator.
77    pub(super) fn new(vec: &'a mut FixedVec<T, W, E, B>, chunk_size: usize) -> Self {
78        assert!(chunk_size != 0, "chunk_size cannot be zero");
79        let end = vec.len();
80        Self {
81            vec_ptr: vec as *mut _,
82            chunk_size,
83            current_pos: 0,
84            end,
85            _phantom: PhantomData,
86        }
87    }
88}
89
90impl<'a, T, W, E, B> Iterator for ChunksMut<'a, T, W, E, B>
91where
92    T: Storable<W>,
93    W: Word,
94    E: Endianness,
95    B: AsRef<[W]> + AsMut<[W]>,
96{
97    type Item = FixedVecSlice<&'a mut FixedVec<T, W, E, B>>;
98
99    fn next(&mut self) -> Option<Self::Item> {
100        if self.current_pos >= self.end {
101            return None;
102        }
103
104        let start = self.current_pos;
105        let len = min(self.chunk_size, self.end - start);
106        self.current_pos += len;
107
108        // SAFETY:
109        // 1. `self.vec_ptr` is a valid pointer to a `FixedVec` for the lifetime 'a.
110        // 2. The borrow checker ensures the original `&'a mut FixedVec` is
111        //    exclusively borrowed by this iterator for its entire lifetime.
112        // 3. Each call to `next` produces a slice for a unique, non-overlapping
113        //    range of the original vector, making the mutable borrow safe.
114        let vec_ref = unsafe { &mut *self.vec_ptr };
115        let slice = FixedVecSlice::new(vec_ref, start..start + len);
116
117        Some(slice)
118    }
119}
120
121/// A mutable iterator over the elements of a [`FixedVec`].
122///
123/// This struct is created by the [`iter_mut`](super::FixedVec::iter_mut)
124/// method. It yields a [`MutProxy`] for each element.
125pub struct IterMut<'a, T, W, E, B>
126where
127    T: Storable<W>,
128    W: Word,
129    E: Endianness,
130    B: AsRef<[W]> + AsMut<[W]>,
131{
132    // A raw pointer is used to allow creating proxies without consuming the iterator.
133    vec_ptr: *mut FixedVec<T, W, E, B>,
134    current_index: usize,
135    end_index: usize,
136    _phantom: PhantomData<&'a mut FixedVec<T, W, E, B>>,
137}
138
139impl<'a, T, W, E, B> IterMut<'a, T, W, E, B>
140where
141    T: Storable<W>,
142    W: Word,
143    E: Endianness,
144    B: AsRef<[W]> + AsMut<[W]>,
145{
146    /// Creates a new `IterMut` iterator.
147    pub(super) fn new(vec: &'a mut FixedVec<T, W, E, B>) -> Self {
148        let len = vec.len();
149        Self {
150            vec_ptr: vec as *mut _,
151            current_index: 0,
152            end_index: len,
153            _phantom: PhantomData,
154        }
155    }
156}
157
158impl<'a, T, W, E, B> Iterator for IterMut<'a, T, W, E, B>
159where
160    T: Storable<W>,
161    W: Word,
162    E: Endianness,
163    B: AsRef<[W]> + AsMut<[W]>,
164{
165    type Item = MutProxy<'a, T, W, E, B>;
166
167    fn next(&mut self) -> Option<Self::Item> {
168        if self.current_index >= self.end_index {
169            return None;
170        }
171
172        // SAFETY: The iterator's lifetime `'a` and bounds checking ensure
173        // that the pointer is valid and that we are creating non-overlapping
174        // mutable access proxies one at a time.
175        let proxy = unsafe { MutProxy::new(&mut *self.vec_ptr, self.current_index) };
176        self.current_index += 1;
177
178        Some(proxy)
179    }
180}
181
182/// An unchecked mutable iterator over the elements of a [`FixedVec`].
183///
184/// This struct is created by the [`iter_mut_unchecked`](super::FixedVec::iter_mut_unchecked)
185/// method. It does not perform any bounds checking.
186///
187/// # Safety
188///
189/// The iterator is safe to use only if it is guaranteed that it will not
190/// be advanced beyond the end of the vector.
191pub struct IterMutUnchecked<'a, T, W, E, B>
192where
193    T: Storable<W>,
194    W: Word,
195    E: Endianness,
196    B: AsRef<[W]> + AsMut<[W]>,
197{
198    iter: IterMut<'a, T, W, E, B>,
199}
200
201impl<'a, T, W, E, B> IterMutUnchecked<'a, T, W, E, B>
202where
203    T: Storable<W>,
204    W: Word,
205    E: Endianness,
206    B: AsRef<[W]> + AsMut<[W]>,
207{
208    /// Creates a new `IterMutUnchecked`.
209    pub(super) fn new(vec: &'a mut FixedVec<T, W, E, B>) -> Self {
210        Self {
211            iter: IterMut::new(vec),
212        }
213    }
214
215    /// Returns the next mutable proxy without bounds checking.
216    ///
217    /// # Safety
218    ///
219    /// Calling this method when the iterator is exhausted is undefined behavior.
220    #[inline]
221    pub unsafe fn next_unchecked(&mut self) -> MutProxy<'a, T, W, E, B> {
222        self.iter.next().unwrap_unchecked()
223    }
224}