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}