mnemosyne_arena/scratch/aligned_vec/element_ops.rs
1//! Element-level mutation operations for `AlignedVec`.
2//!
3//! Contains removal, insertion, filtering, partitioning, deduplication,
4//! bulk-transfer, capacity-shrinking, and draining operations. These differ
5//! from the length-and-grow operations in `super::length` in that they
6//! remove or restructure individual elements rather than uniformly growing or
7//! filling the buffer.
8//!
9//! The `drain` method here returns a `super::length::Drain` iterator
10//! defined in the sibling module.
11
12use super::super::element::ScratchElement;
13use super::length::Drain;
14use super::storage::AlignedVec;
15
16impl<T: ScratchElement> AlignedVec<T> {
17 // ── Removal ──────────────────────────────────────────────────────────────
18
19 /// Removes and returns the last element, or `None` if empty. O(1).
20 #[inline]
21 #[must_use]
22 pub fn pop(&mut self) -> Option<T> {
23 if self.len == 0 {
24 return None;
25 }
26 self.len -= 1;
27 // SAFETY: `self.len` was decremented, so the element at the former last
28 // position is still inside the allocation and was initialized; `T: Copy`
29 // makes a bitwise read safe.
30 Some(unsafe { core::ptr::read(self.ptr.add(self.len)) })
31 }
32
33 /// Removes and returns the element at `index` by swapping it with the last.
34 ///
35 /// Does **not** preserve element order. O(1).
36 ///
37 /// # Panics
38 ///
39 /// Panics if `index >= self.len()`.
40 #[inline]
41 #[must_use]
42 pub fn swap_remove(&mut self, index: usize) -> T {
43 assert!(
44 index < self.len,
45 "swap_remove: index {index} >= len {}",
46 self.len
47 );
48 // SAFETY: both `index` and `self.len - 1` are `< self.len`, so both are
49 // inside the initialized region; `T: Copy`.
50 let last = unsafe { core::ptr::read(self.ptr.add(self.len - 1)) };
51 let removed = unsafe { core::ptr::read(self.ptr.add(index)) };
52 if index != self.len - 1 {
53 // SAFETY: writing to `index < self.len` stays inside the allocation.
54 unsafe { core::ptr::write(self.ptr.add(index), last) };
55 }
56 self.len -= 1;
57 removed
58 }
59
60 /// Removes and returns the element at `index`, shifting later elements left.
61 ///
62 /// Preserves order. O(n).
63 ///
64 /// # Panics
65 ///
66 /// Panics if `index >= self.len()`.
67 #[inline]
68 #[must_use]
69 pub fn remove(&mut self, index: usize) -> T {
70 assert!(
71 index < self.len,
72 "remove: index {index} >= len {}",
73 self.len
74 );
75 // SAFETY: `index < len` so the element is initialized; `T: Copy`.
76 let removed = unsafe { core::ptr::read(self.ptr.add(index)) };
77 let tail = self.len - index - 1;
78 if tail > 0 {
79 // SAFETY: source `[index+1, len)` and destination `[index, len-1)` may
80 // overlap, so we use `copy` (memmove semantics), not
81 // `copy_nonoverlapping`.
82 unsafe {
83 core::ptr::copy(self.ptr.add(index + 1), self.ptr.add(index), tail);
84 }
85 }
86 self.len -= 1;
87 removed
88 }
89
90 // ── Insertion ────────────────────────────────────────────────────────────
91
92 /// Inserts `value` at `index`, shifting later elements right. O(n).
93 ///
94 /// # Panics
95 ///
96 /// Panics if `index > self.len()`.
97 #[inline]
98 pub fn insert(&mut self, index: usize, value: T) {
99 assert!(
100 index <= self.len,
101 "insert: index {index} > len {}",
102 self.len
103 );
104 self.reserve(1);
105 if index < self.len {
106 // SAFETY: `index < len < capacity` (reserve ensured it). Source
107 // `[index, len)` and destination `[index+1, len+1)` may overlap, so
108 // we use `copy` (memmove).
109 unsafe {
110 core::ptr::copy(
111 self.ptr.add(index),
112 self.ptr.add(index + 1),
113 self.len - index,
114 );
115 }
116 }
117 // SAFETY: `ptr.add(index)` is inside the now-larger allocation.
118 unsafe { core::ptr::write(self.ptr.add(index), value) };
119 self.len += 1;
120 }
121
122 // ── Filtering ────────────────────────────────────────────────────────────
123
124 /// Retains only elements satisfying `predicate`, removing others in-place.
125 ///
126 /// Preserves relative order. No reallocation.
127 #[inline]
128 pub fn retain<F: FnMut(&T) -> bool>(&mut self, mut predicate: F) {
129 let mut write = 0usize;
130 for read in 0..self.len {
131 // SAFETY: `read < self.len` — inside the initialized region; T: Copy.
132 let elem = unsafe { core::ptr::read(self.ptr.add(read)) };
133 if predicate(&elem) {
134 if write != read {
135 // SAFETY: `write <= read < self.len`; T: Copy.
136 unsafe { core::ptr::write(self.ptr.add(write), elem) };
137 }
138 write += 1;
139 }
140 }
141 self.len = write;
142 }
143
144 // ── Partitioning ─────────────────────────────────────────────────────────
145
146 /// Partitions the buffer in-place around a predicate.
147 ///
148 /// All `true` elements come before all `false` elements. Order within each
149 /// group is not preserved. Returns the count of `true` elements (the pivot
150 /// index). O(n), no allocation.
151 #[inline]
152 pub fn partition_in_place<F: FnMut(&T) -> bool>(&mut self, mut predicate: F) -> usize {
153 let mut lo = 0usize;
154 let mut hi = self.len;
155 loop {
156 while lo < hi {
157 // SAFETY: `lo < hi <= self.len`.
158 let elem = unsafe { core::ptr::read(self.ptr.add(lo)) };
159 if predicate(&elem) {
160 lo += 1;
161 } else {
162 break;
163 }
164 }
165 while lo < hi {
166 hi -= 1;
167 // SAFETY: `hi < self.len`.
168 let elem = unsafe { core::ptr::read(self.ptr.add(hi)) };
169 if predicate(&elem) {
170 break;
171 }
172 }
173 if lo >= hi {
174 break;
175 }
176 // SAFETY: lo and hi are distinct valid indices.
177 unsafe {
178 let a = core::ptr::read(self.ptr.add(lo));
179 let b = core::ptr::read(self.ptr.add(hi));
180 core::ptr::write(self.ptr.add(lo), b);
181 core::ptr::write(self.ptr.add(hi), a);
182 }
183 lo += 1;
184 }
185 lo
186 }
187
188 // ── Deduplication ────────────────────────────────────────────────────────
189
190 /// Removes consecutive duplicate elements.
191 ///
192 /// Sort first to deduplicate globally. In-place, no allocation.
193 #[inline]
194 pub fn dedup(&mut self)
195 where
196 T: PartialEq,
197 {
198 self.dedup_by_key(|x| *x);
199 }
200
201 /// Removes consecutive duplicates according to a key function.
202 ///
203 /// Two adjacent elements `a` and `b` are considered duplicates when
204 /// `key(a) == key(b)`. The first of each run is kept.
205 #[inline]
206 pub fn dedup_by_key<K: PartialEq, F: FnMut(&T) -> K>(&mut self, mut key: F) {
207 if self.len < 2 {
208 return;
209 }
210 let mut write = 1usize;
211 for read in 1..self.len {
212 // SAFETY: `read` and `write - 1` are both `< self.len`; T: Copy.
213 let elem = unsafe { core::ptr::read(self.ptr.add(read)) };
214 let prev = unsafe { core::ptr::read(self.ptr.add(write - 1)) };
215 if key(&elem) != key(&prev) {
216 if write != read {
217 unsafe { core::ptr::write(self.ptr.add(write), elem) };
218 }
219 write += 1;
220 }
221 }
222 self.len = write;
223 }
224
225 // ── Bulk transfer ────────────────────────────────────────────────────────
226
227 /// Moves all elements of `other` into `self`, leaving `other` empty.
228 #[inline]
229 pub fn append(&mut self, other: &mut Self) {
230 if !other.is_empty() {
231 self.extend_from_slice(other.as_slice());
232 other.len = 0;
233 }
234 }
235
236 // ── Splitting ────────────────────────────────────────────────────────────
237
238 /// Splits off `[at, len)` into a new `AlignedVec`; `self` keeps `[0, at)`.
239 ///
240 /// # Panics
241 ///
242 /// Panics if `at > self.len()`.
243 #[must_use]
244 #[inline]
245 pub fn split_off(&mut self, at: usize) -> Self {
246 assert!(at <= self.len, "split_off: at {at} > len {}", self.len);
247 let tail_len = self.len - at;
248 // SAFETY: `[at, at + tail_len)` is within the initialized region; T: Copy.
249 let tail =
250 Self::from_slice(unsafe { core::slice::from_raw_parts(self.ptr.add(at), tail_len) });
251 self.len = at;
252 tail
253 }
254
255 // ── Capacity management ──────────────────────────────────────────────────
256
257 /// Shrinks the capacity to `len()` if possible.
258 ///
259 /// Best-effort: on allocator refusal the buffer remains valid unchanged.
260 #[inline]
261 pub fn shrink_to_fit(&mut self) {
262 self.shrink_to(self.len);
263 }
264
265 // ── Uninitialised access ─────────────────────────────────────────────────
266
267 /// Returns a raw pointer to the uninitialized spare capacity `[len, capacity)`.
268 ///
269 /// The caller must initialize every element in the returned slice before
270 /// calling `set_len_unchecked` to extend the initialized prefix.
271 #[inline]
272 pub fn spare_capacity_mut(&mut self) -> *mut [T] {
273 let spare_len = self.capacity - self.len;
274 // SAFETY: `self.ptr.add(self.len)` is the first byte past the
275 // initialized region, inside the allocation (`capacity >= len`).
276 unsafe { core::ptr::slice_from_raw_parts_mut(self.ptr.add(self.len), spare_len) }
277 }
278
279 // ── Construction helpers ─────────────────────────────────────────────────
280
281 /// Creates a buffer of `len` elements where element `i` is produced by
282 /// `f(i)`. Pre-allocates upfront; no intermediate iterator.
283 #[must_use]
284 #[inline]
285 pub fn from_fn<F: FnMut(usize) -> T>(len: usize, mut f: F) -> Self {
286 let mut buf = Self::with_capacity(len);
287 for i in 0..len {
288 buf.push(f(i));
289 }
290 buf
291 }
292
293 /// Overwrites all `len()` initialized elements with `value`.
294 #[inline]
295 pub fn fill(&mut self, value: T) {
296 // SAFETY: `[0, self.len)` is initialized; T: Copy overwrites safely.
297 unsafe {
298 for i in 0..self.len {
299 core::ptr::write(self.ptr.add(i), value);
300 }
301 }
302 }
303
304 /// Resets all initialized elements to the all-zero bit pattern.
305 ///
306 /// Equivalent to `fill` with the zero value but uses a single
307 /// `write_bytes(0)` call — faster than iterating when the size is large.
308 ///
309 /// Requires the all-zero bit pattern to be a valid value of `T`, which
310 /// is guaranteed by the [`ScratchElement`] invariant.
311 #[inline]
312 pub fn zero_fill(&mut self) {
313 if self.len == 0 {
314 return;
315 }
316 // SAFETY: `[0, self.len)` is within the allocation; all-zero is a
317 // valid bit pattern for every `ScratchElement` type by invariant.
318 unsafe {
319 core::ptr::write_bytes(self.ptr, 0, self.len);
320 }
321 }
322
323 /// Copies a slice of exactly `len()` elements into the buffer.
324 ///
325 /// Panics if `src.len() != self.len()`. Equivalent to
326 /// `self.as_mut_slice().copy_from_slice(src)` but named for discoverability.
327 #[inline]
328 pub fn copy_from_slice(&mut self, src: &[T]) {
329 self.as_mut_slice().copy_from_slice(src);
330 }
331
332 // ── Drain ────────────────────────────────────────────────────────────────
333
334 /// Removes elements in `start..end`, yields them by value, then shifts
335 /// later elements left to fill the gap.
336 ///
337 /// If the iterator is dropped before being fully consumed, remaining
338 /// elements in the range are still removed.
339 ///
340 /// # Panics
341 ///
342 /// Panics if `start > end` or `end > self.len()`.
343 #[inline]
344 #[must_use]
345 pub fn drain(&mut self, start: usize, end: usize) -> Drain<'_, T> {
346 assert!(start <= end, "drain: start > end");
347 assert!(end <= self.len, "drain: end > len");
348 Drain {
349 buf: self,
350 start,
351 end,
352 current: start,
353 }
354 }
355
356 // ── Bulk operations ──────────────────────────────────────────────────────
357
358 /// Concatenates two slices into a new `AlignedVec`, copying both.
359 ///
360 /// Equivalent to `AlignedVec::from_slice(a)` + `extend_from_slice(b)`.
361 #[inline]
362 #[must_use]
363 pub fn concat(a: &[T], b: &[T]) -> Self {
364 let mut v = Self::with_capacity(a.len() + b.len());
365 v.extend_from_slice(a);
366 v.extend_from_slice(b);
367 v
368 }
369}