Skip to main content

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}