1use std::mem::{align_of, size_of};
19
20#[cfg(feature = "smallvec")]
21use smallvec::SmallVec;
22
23pub fn repurpose_allocation<T1, T2>(mut v: Vec<T1>) -> Vec<T2> {
26 assert_eq!(size_of::<T1>(), size_of::<T2>(), "same size");
27 assert_eq!(align_of::<T1>(), align_of::<T2>(), "same alignment");
28
29 v.clear();
30 let cap = v.capacity();
31 let p = v.as_mut_ptr().cast();
32 std::mem::forget(v);
33 unsafe { Vec::from_raw_parts(p, 0, cap) }
37}
38
39pub trait Vector<T> {
41 fn push(&mut self, value: T);
43
44 fn extend_from_slice(&mut self, other: &[T])
46 where
47 T: Copy;
48}
49
50impl<T> Vector<T> for Vec<T> {
51 fn push(&mut self, value: T) {
52 Vec::push(self, value)
53 }
54
55 fn extend_from_slice(&mut self, other: &[T])
56 where
57 T: Copy,
58 {
59 Vec::extend_from_slice(self, other)
60 }
61}
62
63#[cfg(feature = "smallvec")]
64impl<A> Vector<A::Item> for SmallVec<A>
65where
66 A: smallvec::Array,
67{
68 fn push(&mut self, value: A::Item) {
69 SmallVec::push(self, value)
70 }
71
72 fn extend_from_slice(&mut self, other: &[A::Item])
73 where
74 A::Item: Copy,
75 {
76 SmallVec::extend_from_slice(self, other)
77 }
78}
79
80#[cfg(feature = "compact_bytes")]
81impl Vector<u8> for compact_bytes::CompactBytes {
82 fn push(&mut self, value: u8) {
83 self.push(value)
84 }
85
86 fn extend_from_slice(&mut self, other: &[u8]) {
87 self.extend_from_slice(other)
88 }
89}
90
91pub trait VecExt<T> {
93 #[must_use = "The vector is modified only if the iterator is consumed"]
145 fn drain_filter_swapping<F>(&mut self, filter: F) -> DrainFilterSwapping<'_, T, F>
146 where
147 F: FnMut(&mut T) -> bool;
148
149 fn is_sorted_by<F>(&self, compare: F) -> bool
151 where
152 F: FnMut(&T, &T) -> bool;
153}
154
155pub trait PartialOrdVecExt<T> {
157 fn is_sorted(&self) -> bool;
160 fn is_strictly_sorted(&self) -> bool;
162}
163
164impl<T> VecExt<T> for Vec<T> {
165 fn drain_filter_swapping<F>(&mut self, filter: F) -> DrainFilterSwapping<'_, T, F>
166 where
167 F: FnMut(&mut T) -> bool,
168 {
169 DrainFilterSwapping {
170 vec: self,
171 idx: 0,
172 pred: filter,
173 }
174 }
175
176 fn is_sorted_by<F>(&self, mut compare: F) -> bool
179 where
180 F: FnMut(&T, &T) -> bool,
181 {
182 self.windows(2).all(|win| compare(&win[0], &win[1]))
183 }
184}
185
186impl<T> PartialOrdVecExt<T> for Vec<T>
187where
188 T: PartialOrd,
189{
190 fn is_sorted(&self) -> bool {
191 self.is_sorted_by(|a, b| a <= b)
192 }
193
194 fn is_strictly_sorted(&self) -> bool {
195 self.is_sorted_by(|a, b| a < b)
196 }
197}
198
199#[derive(Debug)]
215pub struct DrainFilterSwapping<'a, T, F> {
216 vec: &'a mut Vec<T>,
217 idx: usize,
219 pred: F,
221}
222
223impl<'a, T, F> Iterator for DrainFilterSwapping<'a, T, F>
224where
225 F: FnMut(&mut T) -> bool,
226{
227 type Item = T;
228
229 fn next(&mut self) -> Option<Self::Item> {
230 loop {
231 let item = self.vec.get_mut(self.idx)?;
232 if (self.pred)(item) {
233 return Some(self.vec.swap_remove(self.idx));
234 } else {
235 self.idx += 1;
236 }
237 }
238 }
239
240 fn size_hint(&self) -> (usize, Option<usize>) {
241 (0, Some(self.vec.len() - self.idx))
242 }
243}
244
245pub fn swap_remove_multiple<T>(v: &mut Vec<T>, mut indexes: Vec<usize>) -> Vec<T> {
251 indexes.sort();
252 indexes.reverse();
253 let mut result = Vec::new();
254 for r in indexes {
255 result.push(v.swap_remove(r));
256 }
257 result
258}
259
260#[cfg(test)]
261mod test {
262 use super::*;
263
264 #[crate::test]
265 fn miri_test_repurpose() {
266 let v: Vec<usize> = vec![0, 1, 2];
267
268 let mut other: Vec<isize> = repurpose_allocation(v);
269
270 assert!(other.is_empty());
271 other.push(-1);
272 assert_eq!(other[0], -1);
273
274 struct Gus1 {
275 s: String,
276 }
277 impl Drop for Gus1 {
278 fn drop(&mut self) {
279 println!("happy {}", self.s);
280 }
281 }
282
283 struct Gus2 {
284 s: String,
285 }
286 impl Drop for Gus2 {
287 fn drop(&mut self) {
288 println!("happy {}", self.s);
289 }
290 }
291
292 let v: Vec<Gus1> = vec![Gus1 {
294 s: "hmm".to_string(),
295 }];
296
297 let mut other: Vec<Gus2> = repurpose_allocation(v);
298
299 assert!(other.is_empty());
300 other.push(Gus2 {
301 s: "hmm2".to_string(),
302 });
303 assert_eq!(other[0].s, "hmm2");
304 }
305
306 #[crate::test]
307 #[should_panic(expected = "same size")]
308 fn miri_test_wrong_size() {
309 let v: Vec<usize> = vec![0, 1, 2];
310 let _: Vec<()> = repurpose_allocation(v);
311 }
312
313 #[crate::test]
314 #[should_panic(expected = "same alignment")]
315 fn miri_test_wrong_align() {
316 #[repr(align(8))]
317 #[derive(Default)]
318 struct Gus1 {
319 _i: [u8; 16],
320 }
321
322 #[repr(align(16))]
323 #[derive(Default)]
324 struct Gus2 {
325 _i: [u8; 8],
326 }
327
328 use std::mem::size_of;
329 assert_eq!(size_of::<Gus1>(), size_of::<Gus2>(), "same size in test");
330
331 let v: Vec<Gus1> = vec![Default::default()];
334 let _: Vec<Gus2> = repurpose_allocation(v);
335 }
336
337 #[crate::test]
338 fn test_is_sorted_by() {
339 assert!(vec![0, 1, 2].is_sorted_by(|a, b| a < b));
340 assert!(vec![0, 1, 2].is_sorted_by(|a, b| a <= b));
341 assert!(!vec![0, 1, 2].is_sorted_by(|a, b| a > b));
342 assert!(!vec![0, 1, 2].is_sorted_by(|a, b| a >= b));
343 assert!(vec![0, 1, 2].is_sorted_by(|_a, _b| true));
344 assert!(!vec![0, 1, 2].is_sorted_by(|_a, _b| false));
345
346 assert!(!vec![0, 1, 1, 2].is_sorted_by(|a, b| a < b));
347 assert!(vec![0, 1, 1, 2].is_sorted_by(|a, b| a <= b));
348 assert!(!vec![0, 1, 1, 2].is_sorted_by(|a, b| a > b));
349 assert!(!vec![0, 1, 1, 2].is_sorted_by(|a, b| a >= b));
350 assert!(vec![0, 1, 1, 2].is_sorted_by(|_a, _b| true));
351 assert!(!vec![0, 1, 1, 2].is_sorted_by(|_a, _b| false));
352
353 assert!(!vec![2, 1, 0].is_sorted_by(|a, b| a < b));
354 assert!(!vec![2, 1, 0].is_sorted_by(|a, b| a <= b));
355 assert!(vec![2, 1, 0].is_sorted_by(|a, b| a > b));
356 assert!(vec![2, 1, 0].is_sorted_by(|a, b| a >= b));
357 assert!(vec![2, 1, 0].is_sorted_by(|_a, _b| true));
358 assert!(!vec![2, 1, 0].is_sorted_by(|_a, _b| false));
359
360 assert!(!vec![5, 1, 9, 42].is_sorted_by(|a, b| a < b));
361 assert!(!vec![5, 1, 9, 42].is_sorted_by(|a, b| a <= b));
362 assert!(!vec![5, 1, 9, 42].is_sorted_by(|a, b| a > b));
363 assert!(!vec![5, 1, 9, 42].is_sorted_by(|a, b| a >= b));
364 assert!(vec![5, 1, 9, 42].is_sorted_by(|_a, _b| true));
365 assert!(!vec![5, 1, 9, 42].is_sorted_by(|_a, _b| false));
366 }
367}