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}