Skip to main content

css_parse/
arena_vec.rs

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