Skip to main content

mnemosyne_arena/scratch/aligned_vec/
query.rs

1//! Read-only queries, search, sort, and in-place reordering for [`AlignedVec`].
2//!
3//! None of the methods in this module change the buffer's length or allocate
4//! new storage; they all either return information or delegate to the
5//! equivalent `[T]` slice method. Separating them from the length-changing
6//! operations in [`super::length`] keeps each module focused on a single
7//! responsibility.
8
9use super::AlignedVec;
10use super::ScratchElement;
11
12impl<T: ScratchElement> AlignedVec<T> {
13    // ── Search ────────────────────────────────────────────────────────────────
14
15    /// Binary search for `value` in a sorted slice.
16    ///
17    /// Delegates to `[T]::binary_search`; `AlignedVec::Deref` already gives
18    /// access but this method improves discoverability.
19    #[inline]
20    pub fn binary_search(&self, value: &T) -> Result<usize, usize>
21    where
22        T: Ord,
23    {
24        self.as_slice().binary_search(value)
25    }
26
27    /// Binary search with a comparator. Delegates to `[T]::binary_search_by`.
28    #[inline]
29    pub fn binary_search_by<F: FnMut(&T) -> core::cmp::Ordering>(
30        &self,
31        f: F,
32    ) -> Result<usize, usize> {
33        self.as_slice().binary_search_by(f)
34    }
35
36    /// Binary search by key. Delegates to `[T]::binary_search_by_key`.
37    #[inline]
38    pub fn binary_search_by_key<K: Ord, F: FnMut(&T) -> K>(
39        &self,
40        b: &K,
41        f: F,
42    ) -> Result<usize, usize> {
43        self.as_slice().binary_search_by_key(b, f)
44    }
45
46    /// Returns `true` if the slice contains `value`.
47    ///
48    /// Delegates to `[T]::contains`. For sorted data, prefer `binary_search`.
49    #[inline]
50    #[must_use]
51    pub fn contains(&self, value: &T) -> bool
52    where
53        T: PartialEq,
54    {
55        self.as_slice().contains(value)
56    }
57
58    /// Returns the position of the first occurrence of `value`.
59    #[inline]
60    #[must_use]
61    pub fn position(&self, value: &T) -> Option<usize>
62    where
63        T: PartialEq,
64    {
65        self.as_slice().iter().position(|x| x == value)
66    }
67
68    // ── Sort ──────────────────────────────────────────────────────────────────
69
70    /// Sorts the initialized elements using `T`'s natural ordering.
71    ///
72    /// Delegates to `[T]::sort_unstable`. Provided for discoverability
73    /// alongside the other in-place methods.
74    #[inline]
75    pub fn sort_unstable_inplace(&mut self)
76    where
77        T: Ord,
78    {
79        self.as_mut_slice().sort_unstable();
80    }
81
82    /// Sorts with a custom comparator. Delegates to `[T]::sort_unstable_by`.
83    #[inline]
84    pub fn sort_unstable_by<F: FnMut(&T, &T) -> core::cmp::Ordering>(&mut self, compare: F) {
85        self.as_mut_slice().sort_unstable_by(compare);
86    }
87
88    /// Sorts by a key function. Delegates to `[T]::sort_unstable_by_key`.
89    #[inline]
90    pub fn sort_unstable_by_key<K: Ord, F: FnMut(&T) -> K>(&mut self, f: F) {
91        self.as_mut_slice().sort_unstable_by_key(f);
92    }
93
94    /// Returns `true` if the slice is sorted in ascending order.
95    #[inline]
96    #[must_use]
97    pub fn is_sorted(&self) -> bool
98    where
99        T: PartialOrd,
100    {
101        self.as_slice().windows(2).all(|w| w[0] <= w[1])
102    }
103
104    // ── Slice pattern queries ─────────────────────────────────────────────────
105
106    /// Returns `true` if the buffer starts with `prefix`.
107    #[inline]
108    #[must_use]
109    pub fn starts_with(&self, prefix: &[T]) -> bool
110    where
111        T: PartialEq,
112    {
113        self.as_slice().starts_with(prefix)
114    }
115
116    /// Returns `true` if the buffer ends with `suffix`.
117    #[inline]
118    #[must_use]
119    pub fn ends_with(&self, suffix: &[T]) -> bool
120    where
121        T: PartialEq,
122    {
123        self.as_slice().ends_with(suffix)
124    }
125
126    /// Returns the buffer's content without the leading `prefix`, or `None`
127    /// if it does not start with `prefix`.
128    #[inline]
129    #[must_use]
130    pub fn strip_prefix(&self, prefix: &[T]) -> Option<&[T]>
131    where
132        T: PartialEq,
133    {
134        self.as_slice().strip_prefix(prefix)
135    }
136
137    /// Returns the buffer's content without the trailing `suffix`, or `None`
138    /// if it does not end with `suffix`.
139    #[inline]
140    #[must_use]
141    pub fn strip_suffix(&self, suffix: &[T]) -> Option<&[T]>
142    where
143        T: PartialEq,
144    {
145        self.as_slice().strip_suffix(suffix)
146    }
147
148    // ── In-place reordering ──────────────────────────────────────────────────
149
150    /// Swaps the elements at indices `i` and `j` in-place.
151    ///
152    /// Delegates to `[T]::swap`. O(1).
153    ///
154    /// # Panics
155    ///
156    /// Panics if either index is out of bounds.
157    #[inline]
158    pub fn swap(&mut self, i: usize, j: usize) {
159        self.as_mut_slice().swap(i, j);
160    }
161
162    /// Reverses the order of all initialized elements in-place. O(n).
163    ///
164    /// Delegates to `[T]::reverse`.
165    #[inline]
166    pub fn reverse_inplace(&mut self) {
167        self.as_mut_slice().reverse();
168    }
169
170    /// Rotates all elements `mid` positions to the left.
171    ///
172    /// Element at index `mid` becomes the new first element. Equivalent to
173    /// `[T]::rotate_left`. O(n).
174    ///
175    /// # Panics
176    ///
177    /// Panics if `mid > len()`.
178    #[inline]
179    pub fn rotate_left(&mut self, mid: usize) {
180        self.as_mut_slice().rotate_left(mid);
181    }
182
183    /// Rotates all elements `k` positions to the right.
184    ///
185    /// Equivalent to `[T]::rotate_right`. O(n).
186    ///
187    /// # Panics
188    ///
189    /// Panics if `k > len()`.
190    #[inline]
191    pub fn rotate_right(&mut self, k: usize) {
192        self.as_mut_slice().rotate_right(k);
193    }
194
195    // ── Element access ────────────────────────────────────────────────────────
196
197    /// Returns a reference to the first element, or `None` if empty.
198    #[inline]
199    #[must_use]
200    pub fn first(&self) -> Option<&T> {
201        self.as_slice().first()
202    }
203
204    /// Returns a mutable reference to the first element, or `None` if empty.
205    #[inline]
206    pub fn first_mut(&mut self) -> Option<&mut T> {
207        self.as_mut_slice().first_mut()
208    }
209
210    /// Returns a reference to the last element, or `None` if empty.
211    #[inline]
212    #[must_use]
213    pub fn last(&self) -> Option<&T> {
214        self.as_slice().last()
215    }
216
217    /// Returns a mutable reference to the last element, or `None` if empty.
218    #[inline]
219    pub fn last_mut(&mut self) -> Option<&mut T> {
220        self.as_mut_slice().last_mut()
221    }
222
223    // ── Windowed / chunked iteration ─────────────────────────────────────────
224
225    /// Returns an iterator over overlapping windows of length `size`.
226    ///
227    /// Delegates to `[T]::windows`. Each window is a contiguous `&[T]` of
228    /// exactly `size` elements.
229    ///
230    /// # Panics
231    ///
232    /// Panics if `size == 0`.
233    #[inline]
234    pub fn windows_iter(&self, size: usize) -> core::slice::Windows<'_, T> {
235        self.as_slice().windows(size)
236    }
237
238    /// Returns an iterator over non-overlapping chunks of length `chunk_size`.
239    ///
240    /// Delegates to `[T]::chunks`. The last chunk may be shorter than
241    /// `chunk_size` if the length is not a multiple.
242    ///
243    /// # Panics
244    ///
245    /// Panics if `chunk_size == 0`.
246    #[inline]
247    pub fn chunks_iter(&self, chunk_size: usize) -> core::slice::Chunks<'_, T> {
248        self.as_slice().chunks(chunk_size)
249    }
250
251    /// Returns an iterator over non-overlapping mutable chunks.
252    ///
253    /// Delegates to `[T]::chunks_mut`. The last chunk may be shorter.
254    ///
255    /// # Panics
256    ///
257    /// Panics if `chunk_size == 0`.
258    #[inline]
259    pub fn chunks_mut(&mut self, chunk_size: usize) -> core::slice::ChunksMut<'_, T> {
260        self.as_mut_slice().chunks_mut(chunk_size)
261    }
262
263    /// Returns an iterator over non-overlapping chunks of exactly `chunk_size`.
264    ///
265    /// Delegates to `[T]::chunks_exact`. Elements that don't fit a complete
266    /// chunk are accessible via the iterator's `remainder()`.
267    ///
268    /// # Panics
269    ///
270    /// Panics if `chunk_size == 0`.
271    #[inline]
272    pub fn chunks_exact(&self, chunk_size: usize) -> core::slice::ChunksExact<'_, T> {
273        self.as_slice().chunks_exact(chunk_size)
274    }
275
276    /// Mutable counterpart of [`chunks_exact`][Self::chunks_exact].
277    ///
278    /// # Panics
279    ///
280    /// Panics if `chunk_size == 0`.
281    #[inline]
282    pub fn chunks_exact_mut(&mut self, chunk_size: usize) -> core::slice::ChunksExactMut<'_, T> {
283        self.as_mut_slice().chunks_exact_mut(chunk_size)
284    }
285
286    // ── Splitting ─────────────────────────────────────────────────────────────
287
288    /// Splits the initialized elements into two slices at `mid`.
289    ///
290    /// Returns `(&[0, mid), &[mid, len))`. Delegates to `[T]::split_at`.
291    ///
292    /// # Panics
293    ///
294    /// Panics if `mid > len()`.
295    #[inline]
296    #[must_use]
297    pub fn split_at(&self, mid: usize) -> (&[T], &[T]) {
298        self.as_slice().split_at(mid)
299    }
300
301    /// Mutable counterpart of [`split_at`][Self::split_at].
302    #[inline]
303    pub fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
304        self.as_mut_slice().split_at_mut(mid)
305    }
306}