Skip to main content

csskit_arena/
arena_vec.rs

1use crate::Arena;
2use crate::raw_vec::RawVec;
3use allocator_api2::alloc::Allocator;
4use std::fmt;
5use std::hash::{Hash, Hasher};
6use std::ops::{Deref, DerefMut};
7use std::ptr::NonNull;
8
9/// A `bumpalo::vec!`-style constructor for the arena [`Vec`], generic over the allocator backend.
10///
11/// - `vec_in![in alloc]` -> empty
12/// - `vec_in![in alloc; elem; n]` -> `n` clones of `elem`
13/// - `vec_in![in alloc; a, b, c]` -> the listed elements, in order
14#[macro_export]
15macro_rules! vec_in {
16	(in $alloc:expr $(,)?) => { $crate::Vec::new_in($alloc) };
17	(in $alloc:expr; $elem:expr; $n:expr) => {{
18		let n = $n;
19		let mut v = $crate::Vec::with_capacity_in(n, $alloc);
20		for _ in 0..n {
21			v.push(::core::clone::Clone::clone(&$elem));
22		}
23		v
24	}};
25	(in $alloc:expr; $($x:expr),+ $(,)?) => {{
26		let mut v = $crate::Vec::new_in($alloc);
27		$( v.push($x); )+
28		v
29	}};
30}
31
32/// A growable, arena-allocated contiguous array, generic over any [`Allocator`].
33///
34/// Unlike `std`'s `Vec`, this never runs element destructors: values live in the arena and are released wholesale when
35/// the arena is dropped. `T` should therefore not own resources outside the arena that require `Drop` to run.
36#[repr(C)]
37pub struct Vec<'a, T, A: Allocator = &'a Arena> {
38	raw: RawVec<T>,
39	alloc: A,
40	marker: std::marker::PhantomData<&'a ()>,
41}
42
43impl<'a, T, A: Allocator> Vec<'a, T, A> {
44	/// Create a new, empty `Vec` backed by `alloc`. Allocates nothing until the first push.
45	#[inline]
46	pub fn new_in(alloc: A) -> Self {
47		Self { raw: RawVec::new(), alloc, marker: std::marker::PhantomData }
48	}
49
50	/// Create a new, empty `Vec` with room for at least `cap` elements.
51	#[inline]
52	pub fn with_capacity_in(cap: usize, alloc: A) -> Self {
53		let mut raw = RawVec::new();
54		if cap > 0 {
55			raw.grow(cap as u32, &alloc);
56		}
57		Self { raw, alloc, marker: std::marker::PhantomData }
58	}
59
60	#[inline]
61	pub fn len(&self) -> usize {
62		self.raw.len as usize
63	}
64
65	#[inline]
66	pub fn is_empty(&self) -> bool {
67		self.raw.len == 0
68	}
69
70	#[inline]
71	pub fn capacity(&self) -> usize {
72		self.raw.cap as usize
73	}
74
75	/// View the contents as a slice.
76	#[inline]
77	pub fn as_slice(&self) -> &[T] {
78		self
79	}
80
81	/// View the contents as a mutable slice.
82	#[inline]
83	pub fn as_mut_slice(&mut self) -> &mut [T] {
84		self
85	}
86
87	#[inline]
88	fn reserve_one(&mut self) {
89		if self.raw.len == self.raw.cap {
90			self.raw.grow(self.raw.len + 1, &self.alloc);
91		}
92	}
93
94	/// Append an element, growing the backing allocation if necessary.
95	#[inline]
96	pub fn push(&mut self, value: T) {
97		self.reserve_one();
98		debug_assert!(self.raw.len < self.raw.cap, "reserve_one must guarantee spare capacity");
99		unsafe {
100			self.raw.ptr.as_ptr().add(self.raw.len as usize).write(value);
101		}
102		self.raw.len += 1;
103	}
104
105	/// Remove and return the last element, or `None` if empty.
106	#[inline]
107	pub fn pop(&mut self) -> Option<T> {
108		if self.raw.len == 0 {
109			return None;
110		}
111		self.raw.len -= 1;
112		Some(unsafe { self.raw.ptr.as_ptr().add(self.raw.len as usize).read() })
113	}
114
115	/// Insert `value` at `index`, shifting later elements right.
116	///
117	/// # Panics
118	/// Panics if `index > len`.
119	pub fn insert(&mut self, index: usize, value: T) {
120		assert!(index as u32 <= self.raw.len, "insertion index out of bounds");
121		self.reserve_one();
122		debug_assert!(self.raw.len < self.raw.cap, "reserve_one must guarantee spare capacity");
123		unsafe {
124			let base = self.raw.ptr.as_ptr();
125			let at = base.add(index);
126			std::ptr::copy(at, at.add(1), (self.raw.len as usize) - index);
127			at.write(value);
128		}
129		self.raw.len += 1;
130	}
131
132	/// Remove and return the element at `index`, shifting later elements left.
133	///
134	/// # Panics
135	/// Panics if `index >= len`.
136	pub fn remove(&mut self, index: usize) -> T {
137		assert!((index as u32) < self.raw.len, "removal index out of bounds");
138		unsafe {
139			let base = self.raw.ptr.as_ptr();
140			let at = base.add(index);
141			let value = at.read();
142			std::ptr::copy(at.add(1), at, (self.raw.len as usize) - index - 1);
143			self.raw.len -= 1;
144			value
145		}
146	}
147
148	/// Shorten the vector to `len` elements. Excess elements are forgotten (no destructors run).
149	#[inline]
150	pub fn truncate(&mut self, len: usize) {
151		if (len as u32) < self.raw.len {
152			self.raw.len = len as u32;
153		}
154	}
155
156	/// Empty the vector. Elements are forgotten (no destructors run).
157	#[inline]
158	pub fn clear(&mut self) {
159		self.raw.len = 0;
160	}
161
162	/// Retain only elements for which `f` returns `true`, preserving order.
163	///
164	/// Panic-safe: if `f` panics, elements already processed are left in a consistent state (kept ones compacted to the
165	/// front, dropped ones removed) and the not-yet-processed tail is shifted back so no element is duplicated or lost,
166	/// mirroring [`std::vec::Vec::retain`].
167	pub fn retain<F: FnMut(&T) -> bool>(&mut self, mut f: F) {
168		let original_len = self.raw.len;
169		let base = self.raw.ptr.as_ptr();
170		self.raw.len = 0;
171
172		struct Guard<'v, 'a, T, A: Allocator> {
173			v: &'v mut Vec<'a, T, A>,
174			base: *mut T,
175			processed: u32,
176			deleted: u32,
177			original_len: u32,
178		}
179		impl<'v, 'a, T, A: Allocator> Drop for Guard<'v, 'a, T, A> {
180			fn drop(&mut self) {
181				let tail = self.original_len - self.processed;
182				if self.deleted > 0 && tail > 0 {
183					unsafe {
184						std::ptr::copy(
185							self.base.add(self.processed as usize),
186							self.base.add((self.processed - self.deleted) as usize),
187							tail as usize,
188						);
189					}
190				}
191				self.v.raw.len = self.original_len - self.deleted;
192			}
193		}
194
195		let mut g = Guard { v: self, base, processed: 0, deleted: 0, original_len };
196		for read in 0..original_len {
197			let keep = unsafe { f(&*g.base.add(read as usize)) };
198			g.processed = read + 1;
199			if keep {
200				if g.deleted > 0 {
201					unsafe {
202						let src = g.base.add(read as usize);
203						g.base.add((read - g.deleted) as usize).write(src.read());
204					}
205				}
206			} else {
207				unsafe { g.base.add(read as usize).drop_in_place() };
208				g.deleted += 1;
209			}
210		}
211		drop(g);
212	}
213
214	/// Remove consecutive elements that compare equal, keeping the first of each run.
215	pub fn dedup(&mut self)
216	where
217		T: PartialEq,
218	{
219		if self.raw.len < 2 {
220			return;
221		}
222		let base = self.raw.ptr.as_ptr();
223		let mut write = 1usize;
224		for read in 1..self.raw.len as usize {
225			// SAFETY: `read` is below the length, and every index below `write` holds a live element that
226			// was either never moved or written by an earlier step of this loop.
227			let duplicate = unsafe { *base.add(read) == *base.add(write - 1) };
228			if duplicate {
229				// SAFETY: as above; the element is live and is not read again.
230				unsafe { base.add(read).drop_in_place() };
231				continue;
232			}
233			if write != read {
234				// SAFETY: as above; `write` is behind `read`, so the read and the write do not alias.
235				unsafe { base.add(write).write(base.add(read).read()) };
236			}
237			write += 1;
238		}
239		self.raw.len = write as u32;
240	}
241
242	/// Remove the elements in `range`, yielding them by value. Elements after the range are shifted
243	/// down to fill the gap when the returned [`Drain`] is dropped.
244	///
245	/// # Panics
246	/// Panics if the range is out of bounds or its start is after its end.
247	pub fn drain<R: std::ops::RangeBounds<u32>>(&mut self, range: R) -> Drain<'_, T> {
248		let len = self.raw.len;
249		let start = match range.start_bound() {
250			std::ops::Bound::Included(&n) => n,
251			std::ops::Bound::Excluded(&n) => n + 1,
252			std::ops::Bound::Unbounded => 0,
253		};
254		let end = match range.end_bound() {
255			std::ops::Bound::Included(&n) => n + 1,
256			std::ops::Bound::Excluded(&n) => n,
257			std::ops::Bound::Unbounded => len,
258		};
259		assert!(start <= end, "drain start must not exceed end");
260		assert!(end <= len, "drain range out of bounds");
261		self.raw.len = start;
262		Drain {
263			ptr: self.raw.ptr.as_ptr(),
264			index: start,
265			end,
266			tail: len,
267			vec_len: NonNull::from(&mut self.raw.len),
268			marker: std::marker::PhantomData,
269		}
270	}
271
272	/// Consume the `Vec`, returning its contents as a slice borrowed from the arena for `'a`.
273	///
274	/// Use this to hand arena-allocated data to an API wanting `&'a [T]`: the elements outlive this handle because they
275	/// belong to the arena, not to the `Vec`.
276	#[inline]
277	pub fn into_slice(self) -> &'a [T] {
278		// SAFETY: `ptr` is aligned and points at `len` initialised `T`s living in the arena for `'a` (or is dangling when
279		// `len` is 0, which `from_raw_parts` permits). `Vec` has no `Drop`, so nothing destroys the elements behind the
280		// returned reference.
281		unsafe { std::slice::from_raw_parts(self.raw.ptr.as_ptr(), self.raw.len as usize) }
282	}
283}
284
285impl<'a, T: Clone, A: Allocator> Vec<'a, T, A> {
286	/// Append all elements of `slice` by cloning.
287	pub fn extend_from_slice(&mut self, slice: &[T]) {
288		self.reserve(slice.len());
289		for value in slice {
290			self.push(value.clone());
291		}
292	}
293
294	#[inline]
295	fn reserve(&mut self, additional: usize) {
296		let required = self.raw.len + (additional as u32);
297		if required > self.raw.cap {
298			self.raw.grow(required, &self.alloc);
299		}
300	}
301}
302
303impl<'a, T, A: Allocator> Extend<T> for Vec<'a, T, A> {
304	fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
305		let iter = iter.into_iter();
306		let (lower, _) = iter.size_hint();
307		if lower > 0 {
308			let required = self.raw.len + (lower as u32);
309			if required > self.raw.cap {
310				self.raw.grow(required, &self.alloc);
311			}
312		}
313		for value in iter {
314			self.push(value);
315		}
316	}
317}
318
319impl<'a, T, A: Allocator> Deref for Vec<'a, T, A> {
320	type Target = [T];
321
322	#[inline]
323	fn deref(&self) -> &[T] {
324		debug_assert!(self.raw.len <= self.raw.cap, "len must never exceed capacity");
325		unsafe { std::slice::from_raw_parts(self.raw.ptr.as_ptr(), self.raw.len as usize) }
326	}
327}
328
329impl<'a, T, A: Allocator> DerefMut for Vec<'a, T, A> {
330	#[inline]
331	fn deref_mut(&mut self) -> &mut [T] {
332		debug_assert!(self.raw.len <= self.raw.cap, "len must never exceed capacity");
333		unsafe { std::slice::from_raw_parts_mut(self.raw.ptr.as_ptr(), self.raw.len as usize) }
334	}
335}
336
337impl<'a, T: Clone, A: Allocator + Clone> Clone for Vec<'a, T, A> {
338	fn clone(&self) -> Self {
339		let mut out = Vec::with_capacity_in(self.raw.len as usize, self.alloc.clone());
340		for value in self.iter() {
341			out.push(value.clone());
342		}
343		out
344	}
345}
346
347impl<'a, T: fmt::Debug, A: Allocator> fmt::Debug for Vec<'a, T, A> {
348	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
349		fmt::Debug::fmt(&**self, f)
350	}
351}
352
353impl<'a, T: PartialEq, A: Allocator> PartialEq for Vec<'a, T, A> {
354	fn eq(&self, other: &Self) -> bool {
355		**self == **other
356	}
357}
358
359impl<'a, T: Eq, A: Allocator> Eq for Vec<'a, T, A> {}
360
361impl<'a, T: PartialOrd, A: Allocator> PartialOrd for Vec<'a, T, A> {
362	fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
363		(**self).partial_cmp(&**other)
364	}
365}
366
367impl<'a, T: Ord, A: Allocator> Ord for Vec<'a, T, A> {
368	fn cmp(&self, other: &Self) -> std::cmp::Ordering {
369		(**self).cmp(&**other)
370	}
371}
372
373impl<'a, T, A: Allocator, I: std::slice::SliceIndex<[T]>> std::ops::Index<I> for Vec<'a, T, A> {
374	type Output = I::Output;
375	#[inline]
376	fn index(&self, index: I) -> &Self::Output {
377		std::ops::Index::index(&**self, index)
378	}
379}
380
381impl<'a, T, A: Allocator, I: std::slice::SliceIndex<[T]>> std::ops::IndexMut<I> for Vec<'a, T, A> {
382	#[inline]
383	fn index_mut(&mut self, index: I) -> &mut Self::Output {
384		std::ops::IndexMut::index_mut(&mut **self, index)
385	}
386}
387
388impl<'a, T: Hash, A: Allocator> Hash for Vec<'a, T, A> {
389	fn hash<H: Hasher>(&self, state: &mut H) {
390		(**self).hash(state);
391	}
392}
393
394impl<'a, T, A: Allocator> AsRef<[T]> for Vec<'a, T, A> {
395	#[inline]
396	fn as_ref(&self) -> &[T] {
397		self
398	}
399}
400
401impl<'v, 'a, T, A: Allocator> IntoIterator for &'v Vec<'a, T, A> {
402	type Item = &'v T;
403	type IntoIter = std::slice::Iter<'v, T>;
404	#[inline]
405	fn into_iter(self) -> Self::IntoIter {
406		self.iter()
407	}
408}
409
410impl<'v, 'a, T, A: Allocator> IntoIterator for &'v mut Vec<'a, T, A> {
411	type Item = &'v mut T;
412	type IntoIter = std::slice::IterMut<'v, T>;
413	#[inline]
414	fn into_iter(self) -> Self::IntoIter {
415		self.iter_mut()
416	}
417}
418
419impl<'a, T: 'a, A: Allocator> IntoIterator for Vec<'a, T, A> {
420	type Item = T;
421	type IntoIter = IntoIter<'a, T>;
422	#[inline]
423	fn into_iter(self) -> Self::IntoIter {
424		let iter =
425			IntoIter { ptr: self.raw.ptr.as_ptr(), index: 0, len: self.raw.len, marker: std::marker::PhantomData };
426		std::mem::forget(self);
427		iter
428	}
429}
430
431/// By-value iterator produced by [`Vec::into_iter`].
432pub struct IntoIter<'a, T: 'a> {
433	ptr: *mut T,
434	index: u32,
435	len: u32,
436	marker: std::marker::PhantomData<&'a mut T>,
437}
438
439impl<'a, T> Iterator for IntoIter<'a, T> {
440	type Item = T;
441	#[inline]
442	fn next(&mut self) -> Option<T> {
443		if self.index == self.len {
444			return None;
445		}
446		let value = unsafe { self.ptr.add(self.index as usize).read() };
447		self.index += 1;
448		Some(value)
449	}
450
451	#[inline]
452	fn size_hint(&self) -> (usize, Option<usize>) {
453		let remaining = (self.len - self.index) as usize;
454		(remaining, Some(remaining))
455	}
456}
457
458impl<'a, T> Drop for IntoIter<'a, T> {
459	fn drop(&mut self) {
460		while self.next().is_some() {}
461	}
462}
463
464/// By-value iterator produced by [`Vec::drain`].
465pub struct Drain<'v, T> {
466	/// Base pointer of the source vector's buffer.
467	ptr: *mut T,
468	/// Index of the next element to yield (advances towards `end`).
469	index: u32,
470	/// One past the last index in the drained range.
471	end: u32,
472	/// Original length of the source vector (one past the last live element before draining).
473	tail: u32,
474	/// Pointer to the source vector's `len` field, restored on drop.
475	vec_len: NonNull<u32>,
476	marker: std::marker::PhantomData<&'v mut T>,
477}
478
479impl<'v, T> Iterator for Drain<'v, T> {
480	type Item = T;
481	#[inline]
482	fn next(&mut self) -> Option<T> {
483		if self.index == self.end {
484			return None;
485		}
486		let value = unsafe { self.ptr.add(self.index as usize).read() };
487		self.index += 1;
488		Some(value)
489	}
490}
491
492impl<'v, T> Drop for Drain<'v, T> {
493	fn drop(&mut self) {
494		while self.index < self.end {
495			unsafe { self.ptr.add(self.index as usize).drop_in_place() };
496			self.index += 1;
497		}
498		let drained = self.end;
499		let tail = self.tail;
500		debug_assert!(drained <= tail, "drain end must not exceed the original length");
501		let count = tail - drained;
502		unsafe {
503			let start = *self.vec_len.as_ptr();
504			debug_assert!(start <= drained, "drain start must not exceed the drained region start");
505			if count > 0 {
506				std::ptr::copy(self.ptr.add(drained as usize), self.ptr.add(start as usize), count as usize);
507			}
508			*self.vec_len.as_ptr() = start + count;
509		}
510	}
511}
512
513#[cfg(feature = "serde")]
514impl<'a, T: serde::Serialize, A: Allocator> serde::Serialize for Vec<'a, T, A> {
515	fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
516		serializer.collect_seq(self.iter())
517	}
518}
519
520#[cfg(test)]
521mod test {
522	use super::Vec;
523	use crate::Arena;
524	use std::cell::Cell;
525	use std::panic::{AssertUnwindSafe, catch_unwind};
526	use std::rc::Rc;
527
528	#[derive(Clone)]
529	struct DropCounter {
530		id: u32,
531		drops: Rc<Cell<u32>>,
532	}
533
534	impl DropCounter {
535		fn new(id: u32, drops: &Rc<Cell<u32>>) -> Self {
536			Self { id, drops: Rc::clone(drops) }
537		}
538	}
539
540	impl Drop for DropCounter {
541		fn drop(&mut self) {
542			self.drops.set(self.drops.get() + 1);
543		}
544	}
545
546	#[test]
547	fn new_is_empty_and_allocates_nothing() {
548		let alloc = Arena::new();
549		let v: Vec<i32> = Vec::new_in(&alloc);
550		assert!(v.is_empty());
551		assert_eq!(v.len(), 0);
552		assert_eq!(v.capacity(), 0);
553		assert_eq!(v.as_slice(), &[] as &[i32]);
554	}
555
556	#[test]
557	fn with_capacity_reserves_but_stays_empty() {
558		let alloc = Arena::new();
559		let v: Vec<i32> = Vec::with_capacity_in(16, &alloc);
560		assert!(v.is_empty());
561		assert_eq!(v.len(), 0);
562		assert!(v.capacity() >= 16);
563	}
564
565	#[test]
566	fn with_capacity_zero_allocates_nothing() {
567		let alloc = Arena::new();
568		let v: Vec<i32> = Vec::with_capacity_in(0, &alloc);
569		assert_eq!(v.capacity(), 0);
570	}
571
572	#[test]
573	fn push_grows_and_preserves_order() {
574		let alloc = Arena::new();
575		let mut v: Vec<u32> = Vec::new_in(&alloc);
576		for i in 0..1000u32 {
577			v.push(i);
578		}
579		assert_eq!(v.len(), 1000);
580		assert!(v.capacity() >= 1000);
581		for (i, &value) in v.iter().enumerate() {
582			assert_eq!(value, i as u32, "element is still in vec");
583		}
584	}
585
586	#[test]
587	fn pop_returns_last_then_none() {
588		let alloc = Arena::new();
589		let mut v: Vec<i32> = Vec::new_in(&alloc);
590		v.extend([10, 20, 30]);
591		assert_eq!(v.pop(), Some(30));
592		assert_eq!(v.pop(), Some(20));
593		assert_eq!(v.pop(), Some(10));
594		assert_eq!(v.pop(), None);
595		assert!(v.is_empty());
596	}
597
598	#[test]
599	fn insert_at_boundaries_and_middle() {
600		let alloc = Arena::new();
601		let mut v: Vec<i32> = Vec::new_in(&alloc);
602		v.extend([1, 2, 3]);
603		v.insert(0, 0); // front
604		assert_eq!(&*v, &[0, 1, 2, 3]);
605		v.insert(v.len(), 4); // back (index == len)
606		assert_eq!(&*v, &[0, 1, 2, 3, 4]);
607		v.insert(2, 99); // middle
608		assert_eq!(&*v, &[0, 1, 99, 2, 3, 4]);
609	}
610
611	#[test]
612	fn insert_into_empty() {
613		let alloc = Arena::new();
614		let mut v: Vec<i32> = Vec::new_in(&alloc);
615		v.insert(0, 42);
616		assert_eq!(&*v, &[42]);
617	}
618
619	#[test]
620	fn insert_out_of_bounds_panics() {
621		let alloc = Arena::new();
622		let mut v: Vec<i32> = Vec::new_in(&alloc);
623		v.extend([1, 2]);
624		let result = catch_unwind(AssertUnwindSafe(|| v.insert(3, 0)));
625		assert!(result.is_err());
626	}
627
628	#[test]
629	fn remove_at_boundaries_and_middle() {
630		let alloc = Arena::new();
631		let mut v: Vec<i32> = Vec::new_in(&alloc);
632		v.extend([0, 1, 2, 3, 4]);
633		assert_eq!(v.remove(0), 0); // front
634		assert_eq!(&*v, &[1, 2, 3, 4]);
635		assert_eq!(v.remove(v.len() - 1), 4); // back
636		assert_eq!(&*v, &[1, 2, 3]);
637		assert_eq!(v.remove(1), 2); // middle
638		assert_eq!(&*v, &[1, 3]);
639	}
640
641	#[test]
642	fn remove_out_of_bounds_panics() {
643		let alloc = Arena::new();
644		let mut v: Vec<i32> = Vec::new_in(&alloc);
645		v.extend([1, 2]);
646		let result = catch_unwind(AssertUnwindSafe(|| v.remove(2)));
647		assert!(result.is_err());
648	}
649
650	#[test]
651	fn truncate_shortens_without_dropping() {
652		let alloc = Arena::new();
653		let drops = Rc::new(Cell::new(0));
654		let mut v: Vec<DropCounter> = Vec::new_in(&alloc);
655		for i in 0..5 {
656			v.push(DropCounter::new(i, &drops));
657		}
658		v.truncate(2);
659		assert_eq!(v.len(), 2);
660		assert_eq!(drops.get(), 0, "truncate must not run destructors");
661	}
662
663	#[test]
664	fn truncate_longer_than_len_is_noop() {
665		let alloc = Arena::new();
666		let mut v: Vec<i32> = Vec::new_in(&alloc);
667		v.extend([1, 2, 3]);
668		v.truncate(10);
669		assert_eq!(&*v, &[1, 2, 3]);
670	}
671
672	#[test]
673	fn clear_empties_without_dropping() {
674		let alloc = Arena::new();
675		let drops = Rc::new(Cell::new(0));
676		let mut v: Vec<DropCounter> = Vec::new_in(&alloc);
677		for i in 0..3 {
678			v.push(DropCounter::new(i, &drops));
679		}
680		v.clear();
681		assert!(v.is_empty());
682		assert_eq!(drops.get(), 0, "clear must not run destructors");
683	}
684
685	#[test]
686	fn extend_from_slice_clones_elements() {
687		let alloc = Arena::new();
688		let mut v: Vec<i32> = Vec::new_in(&alloc);
689		v.push(1);
690		v.extend_from_slice(&[2, 3, 4]);
691		assert_eq!(&*v, &[1, 2, 3, 4]);
692	}
693
694	#[test]
695	fn extend_with_accurate_size_hint_reserves_once() {
696		let alloc = Arena::new();
697		let mut v: Vec<u32> = Vec::new_in(&alloc);
698		v.extend(0..64u32);
699		assert_eq!(v.len(), 64);
700		for i in 0..64u32 {
701			assert_eq!(v[i as usize], i);
702		}
703	}
704
705	#[test]
706	fn extend_empty_iterator_is_noop() {
707		let alloc = Arena::new();
708		let mut v: Vec<u32> = Vec::new_in(&alloc);
709		v.extend(std::iter::empty::<u32>());
710		assert!(v.is_empty());
711		assert_eq!(v.capacity(), 0);
712	}
713
714	#[test]
715	fn retain_keeps_matching_and_shifts() {
716		let alloc = Arena::new();
717		let mut v: Vec<i32> = Vec::new_in(&alloc);
718		v.extend([0, 1, 2, 3, 4, 5, 6, 7]);
719		v.retain(|&x| x % 2 == 0);
720		assert_eq!(&*v, &[0, 2, 4, 6]);
721	}
722
723	#[test]
724	fn dedup_collapses_consecutive_runs_only() {
725		let alloc = Arena::new();
726		let mut v: Vec<i32> = Vec::new_in(&alloc);
727		v.extend([1, 1, 2, 3, 3, 3, 1, 1]);
728		v.dedup();
729		assert_eq!(&*v, &[1, 2, 3, 1]);
730	}
731
732	#[test]
733	fn dedup_leaves_short_and_distinct_vectors_alone() {
734		let alloc = Arena::new();
735		let mut v: Vec<i32> = Vec::new_in(&alloc);
736		v.dedup();
737		assert!(v.is_empty());
738		v.extend([1, 2, 3]);
739		v.dedup();
740		assert_eq!(&*v, &[1, 2, 3]);
741		let mut same: Vec<i32> = Vec::new_in(&alloc);
742		same.extend([7, 7, 7]);
743		same.dedup();
744		assert_eq!(&*same, &[7]);
745	}
746
747	#[test]
748	fn retain_all_and_none() {
749		let alloc = Arena::new();
750		let mut v: Vec<i32> = Vec::new_in(&alloc);
751		v.extend([1, 2, 3]);
752		v.retain(|_| true);
753		assert_eq!(&*v, &[1, 2, 3]);
754		v.retain(|_| false);
755		assert!(v.is_empty());
756	}
757
758	#[test]
759	fn retain_drops_removed_exactly_once() {
760		let alloc = Arena::new();
761		let drops = Rc::new(Cell::new(0));
762		let mut v: Vec<DropCounter> = Vec::new_in(&alloc);
763		for i in 0..6 {
764			v.push(DropCounter::new(i, &drops));
765		}
766		v.retain(|c| c.id % 2 == 1);
767		assert_eq!(v.len(), 3);
768		assert_eq!(drops.get(), 3, "each removed element dropped exactly once");
769		let ids: std::vec::Vec<u32> = v.iter().map(|c| c.id).collect();
770		assert_eq!(ids, vec![1, 3, 5], "survivors intact and in order after write-back");
771	}
772
773	#[test]
774	fn retain_panic_drops_no_element_twice() {
775		let alloc = Arena::new();
776		let drops = Rc::new(Cell::new(0));
777		let mut v: Vec<DropCounter> = Vec::new_in(&alloc);
778		for i in 0..5 {
779			v.push(DropCounter::new(i, &drops));
780		}
781		let drops_for_closure = Rc::clone(&drops);
782		let result = catch_unwind(AssertUnwindSafe(|| {
783			v.retain(|c| {
784				if c.id == 3 {
785					panic!("boom");
786				}
787				// Drop id 0 and id 1 before the panic.
788				c.id >= 2
789			});
790		}));
791		assert!(result.is_err());
792		let removed = drops_for_closure.get();
793		assert_eq!(removed, 2, "only the elements filtered out before the panic were dropped");
794		assert_eq!(v.len() as u32 + removed, 5, "no leaked or double-counted elements");
795	}
796
797	#[test]
798	fn drain_empty_range() {
799		let alloc = Arena::new();
800		let mut v: Vec<i32> = Vec::new_in(&alloc);
801		v.extend([1, 2, 3]);
802		let drained: std::vec::Vec<i32> = v.drain(1..1).collect();
803		assert!(drained.is_empty());
804		assert_eq!(&*v, &[1, 2, 3]);
805	}
806
807	#[test]
808	fn drain_suffix() {
809		let alloc = Arena::new();
810		let mut v: Vec<i32> = Vec::new_in(&alloc);
811		v.extend([0, 1, 2, 3, 4]);
812		let drained: std::vec::Vec<i32> = v.drain(3..).collect();
813		assert_eq!(drained, vec![3, 4]);
814		assert_eq!(&*v, &[0, 1, 2]);
815	}
816
817	#[test]
818	fn drain_inclusive_bound() {
819		let alloc = Arena::new();
820		let mut v: Vec<i32> = Vec::new_in(&alloc);
821		v.extend([0, 1, 2, 3, 4]);
822		let drained: std::vec::Vec<i32> = v.drain(1..=3).collect();
823		assert_eq!(drained, vec![1, 2, 3]);
824		assert_eq!(&*v, &[0, 4]);
825	}
826
827	#[test]
828	fn drain_start_after_end_panics() {
829		let alloc = Arena::new();
830		let mut v: Vec<i32> = Vec::new_in(&alloc);
831		v.extend([0, 1, 2]);
832		use std::ops::Bound;
833		let bad_range = (Bound::Included(2u32), Bound::Excluded(1u32));
834		let result = catch_unwind(AssertUnwindSafe(|| {
835			let _ = v.drain(bad_range);
836		}));
837		assert!(result.is_err());
838	}
839
840	#[test]
841	fn drain_out_of_bounds_panics() {
842		let alloc = Arena::new();
843		let mut v: Vec<i32> = Vec::new_in(&alloc);
844		v.extend([0, 1, 2]);
845		let result = catch_unwind(AssertUnwindSafe(|| {
846			let _ = v.drain(1..99);
847		}));
848		assert!(result.is_err());
849	}
850
851	#[test]
852	fn drain_yielded_and_remaining_drop_exactly_once() {
853		let alloc = Arena::new();
854		let drops = Rc::new(Cell::new(0));
855		let mut v: Vec<DropCounter> = Vec::new_in(&alloc);
856		for i in 0..6 {
857			v.push(DropCounter::new(i, &drops));
858		}
859		{
860			let mut d = v.drain(1..4);
861			let first = d.next().unwrap();
862			assert_eq!(first.id, 1);
863			drop(first); // 1 drop
864			// d dropped here: ids 2, 3 dropped by Drain::drop -> 2 more drops.
865		}
866		assert_eq!(drops.get(), 3, "drained range dropped exactly once total");
867		let ids: std::vec::Vec<u32> = v.iter().map(|c| c.id).collect();
868		assert_eq!(ids, vec![0, 4, 5], "tail shifted correctly after partial drain");
869	}
870
871	#[test]
872	fn drain_fully_consumed_then_no_extra_drops() {
873		let alloc = Arena::new();
874		let drops = Rc::new(Cell::new(0));
875		let mut v: Vec<DropCounter> = Vec::new_in(&alloc);
876		for i in 0..4 {
877			v.push(DropCounter::new(i, &drops));
878		}
879		let collected: std::vec::Vec<DropCounter> = v.drain(..).collect();
880		let ids: std::vec::Vec<u32> = collected.iter().map(|c| c.id).collect();
881		assert_eq!(ids, vec![0, 1, 2, 3]);
882		// The drained DropCounters were moved into `collected`; none dropped yet.
883		assert_eq!(drops.get(), 0);
884		assert!(v.is_empty());
885		drop(collected);
886		assert_eq!(drops.get(), 4, "each drained element dropped exactly once when the collection drops");
887	}
888
889	#[test]
890	fn drain_size_hint_not_relied_on_but_iteration_correct() {
891		let alloc = Arena::new();
892		let mut v: Vec<i32> = Vec::new_in(&alloc);
893		v.extend([5, 6, 7, 8]);
894		let mut iter = v.drain(0..4);
895		assert_eq!(iter.next(), Some(5));
896		assert_eq!(iter.next(), Some(6));
897		assert_eq!(iter.next(), Some(7));
898		assert_eq!(iter.next(), Some(8));
899		assert_eq!(iter.next(), None);
900	}
901
902	#[test]
903	fn drain_prefix_shifts_tail() {
904		let alloc = Arena::default();
905		let mut v: Vec<i32> = Vec::new_in(&alloc);
906		v.extend([0, 1, 2, 3, 4, 5]);
907		let drained: std::vec::Vec<i32> = v.drain(0..2).collect();
908		assert_eq!(drained, vec![0, 1]);
909		assert_eq!(&*v, &[2, 3, 4, 5]);
910	}
911
912	#[test]
913	fn drain_middle_shifts_tail() {
914		let alloc = Arena::default();
915		let mut v: Vec<i32> = Vec::new_in(&alloc);
916		v.extend([0, 1, 2, 3, 4, 5]);
917		let drained: std::vec::Vec<i32> = v.drain(2..4).collect();
918		assert_eq!(drained, vec![2, 3]);
919		assert_eq!(&*v, &[0, 1, 4, 5]);
920	}
921
922	#[test]
923	fn drain_full_range() {
924		let alloc = Arena::default();
925		let mut v: Vec<i32> = Vec::new_in(&alloc);
926		v.extend([1, 2, 3]);
927		let drained: std::vec::Vec<i32> = v.drain(..).collect();
928		assert_eq!(drained, vec![1, 2, 3]);
929		assert!(v.is_empty());
930	}
931
932	#[test]
933	fn drain_dropped_without_iterating_still_shifts() {
934		let alloc = Arena::default();
935		let mut v: Vec<i32> = Vec::new_in(&alloc);
936		v.extend([0, 1, 2, 3, 4]);
937		drop(v.drain(1..3));
938		assert_eq!(&*v, &[0, 3, 4]);
939	}
940
941	#[test]
942	fn retain_preserves_length_when_predicate_panics() {
943		let alloc = Arena::new();
944		let mut values = Vec::new_in(&alloc);
945		values.extend([0, 1, 2]);
946		let calls = Cell::new(0);
947
948		let result = catch_unwind(AssertUnwindSafe(|| {
949			values.retain(|_| {
950				let call = calls.get();
951				calls.set(call + 1);
952				match call {
953					0 => false,
954					1 => true,
955					_ => panic!("predicate failed"),
956				}
957			});
958		}));
959
960		assert!(result.is_err());
961		assert_eq!(values.len(), 2, "moved-from slots must not remain visible");
962	}
963
964	#[test]
965	fn into_iter_yields_all_in_order() {
966		let alloc = Arena::new();
967		let mut v: Vec<i32> = Vec::new_in(&alloc);
968		v.extend([1, 2, 3, 4]);
969		let collected: std::vec::Vec<i32> = v.into_iter().collect();
970		assert_eq!(collected, vec![1, 2, 3, 4]);
971	}
972
973	#[test]
974	fn into_iter_size_hint_is_exact() {
975		let alloc = Arena::new();
976		let mut v: Vec<i32> = Vec::new_in(&alloc);
977		v.extend([1, 2, 3]);
978		let mut iter = v.into_iter();
979		assert_eq!(iter.size_hint(), (3, Some(3)));
980		iter.next();
981		assert_eq!(iter.size_hint(), (2, Some(2)));
982	}
983
984	#[test]
985	fn into_iter_partial_consume_drops_remainder_once() {
986		let alloc = Arena::new();
987		let drops = Rc::new(Cell::new(0));
988		let mut v: Vec<DropCounter> = Vec::new_in(&alloc);
989		for i in 0..5 {
990			v.push(DropCounter::new(i, &drops));
991		}
992		{
993			let mut iter = v.into_iter();
994			let a = iter.next().unwrap();
995			let b = iter.next().unwrap();
996			assert_eq!((a.id, b.id), (0, 1));
997			drop(a); // 1
998			drop(b); // 1
999			// iter dropped here: ids 2, 3, 4 dropped by IntoIter::drop -> 3 more.
1000		}
1001		assert_eq!(drops.get(), 5, "every element dropped exactly once across manual + IntoIter drop");
1002	}
1003
1004	#[test]
1005	fn into_iter_fully_consumed_no_leak() {
1006		let alloc = Arena::new();
1007		let drops = Rc::new(Cell::new(0));
1008		let mut v: Vec<DropCounter> = Vec::new_in(&alloc);
1009		for i in 0..4 {
1010			v.push(DropCounter::new(i, &drops));
1011		}
1012		for c in v {
1013			let _ = c.id; // dropped at end of each loop iteration
1014		}
1015		assert_eq!(drops.get(), 4);
1016	}
1017
1018	#[test]
1019	fn clone_is_independent_copy() {
1020		let alloc = Arena::new();
1021		let mut v: Vec<i32> = Vec::new_in(&alloc);
1022		v.extend([1, 2, 3]);
1023		let mut c = v.clone();
1024		c.push(4);
1025		assert_eq!(&*v, &[1, 2, 3], "original unchanged after mutating clone");
1026		assert_eq!(&*c, &[1, 2, 3, 4]);
1027	}
1028
1029	#[test]
1030	fn eq_and_ord_delegate_to_slice() {
1031		let alloc = Arena::new();
1032		let mut a: Vec<i32> = Vec::new_in(&alloc);
1033		a.extend([1, 2, 3]);
1034		let mut b: Vec<i32> = Vec::new_in(&alloc);
1035		b.extend([1, 2, 3]);
1036		assert_eq!(a, b);
1037		let mut c: Vec<i32> = Vec::new_in(&alloc);
1038		c.extend([1, 2, 4]);
1039		assert!(a < c);
1040		assert_ne!(a, c);
1041	}
1042
1043	#[test]
1044	fn index_and_index_mut() {
1045		let alloc = Arena::new();
1046		let mut v: Vec<i32> = Vec::new_in(&alloc);
1047		v.extend([10, 20, 30]);
1048		assert_eq!(v[1], 20);
1049		v[1] = 99;
1050		assert_eq!(v[1], 99);
1051		assert_eq!(&v[0..2], &[10, 99]);
1052	}
1053
1054	#[test]
1055	fn hash_matches_equal_vecs() {
1056		use std::collections::hash_map::DefaultHasher;
1057		use std::hash::{Hash, Hasher};
1058		let alloc = Arena::new();
1059		let mut a: Vec<i32> = Vec::new_in(&alloc);
1060		a.extend([1, 2, 3]);
1061		let mut b: Vec<i32> = Vec::new_in(&alloc);
1062		b.extend([1, 2, 3]);
1063		let mut ha = DefaultHasher::new();
1064		let mut hb = DefaultHasher::new();
1065		a.hash(&mut ha);
1066		b.hash(&mut hb);
1067		assert_eq!(ha.finish(), hb.finish());
1068	}
1069
1070	#[test]
1071	fn realloc_preserves_boxed_contents() {
1072		let alloc = Arena::new();
1073		let mut v: Vec<std::boxed::Box<u32>> = Vec::new_in(&alloc);
1074		for i in 0..512u32 {
1075			v.push(std::boxed::Box::new(i));
1076		}
1077		for (i, b) in v.iter().enumerate() {
1078			assert_eq!(**b, i as u32);
1079		}
1080		let sum: u32 = v.into_iter().map(|b| *b).sum();
1081		assert_eq!(sum, (0..512u32).sum());
1082	}
1083
1084	#[test]
1085	fn zero_sized_type_push_pop_len() {
1086		let alloc = Arena::new();
1087		let mut v: Vec<()> = Vec::new_in(&alloc);
1088		for _ in 0..100 {
1089			v.push(());
1090		}
1091		assert_eq!(v.len(), 100);
1092		for _ in 0..100 {
1093			assert_eq!(v.pop(), Some(()));
1094		}
1095		assert_eq!(v.pop(), None);
1096	}
1097}