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	use super::Vec;
510	use crate::Arena;
511	use std::cell::Cell;
512	use std::panic::{AssertUnwindSafe, catch_unwind};
513	use std::rc::Rc;
514
515	#[derive(Clone)]
516	struct DropCounter {
517		id: u32,
518		drops: Rc<Cell<u32>>,
519	}
520
521	impl DropCounter {
522		fn new(id: u32, drops: &Rc<Cell<u32>>) -> Self {
523			Self { id, drops: Rc::clone(drops) }
524		}
525	}
526
527	impl Drop for DropCounter {
528		fn drop(&mut self) {
529			self.drops.set(self.drops.get() + 1);
530		}
531	}
532
533	#[test]
534	fn new_is_empty_and_allocates_nothing() {
535		let alloc = Arena::new();
536		let v: Vec<i32> = Vec::new_in(&alloc);
537		assert!(v.is_empty());
538		assert_eq!(v.len(), 0);
539		assert_eq!(v.capacity(), 0);
540		assert_eq!(v.as_slice(), &[] as &[i32]);
541	}
542
543	#[test]
544	fn with_capacity_reserves_but_stays_empty() {
545		let alloc = Arena::new();
546		let v: Vec<i32> = Vec::with_capacity_in(16, &alloc);
547		assert!(v.is_empty());
548		assert_eq!(v.len(), 0);
549		assert!(v.capacity() >= 16);
550	}
551
552	#[test]
553	fn with_capacity_zero_allocates_nothing() {
554		let alloc = Arena::new();
555		let v: Vec<i32> = Vec::with_capacity_in(0, &alloc);
556		assert_eq!(v.capacity(), 0);
557	}
558
559	#[test]
560	fn push_grows_and_preserves_order() {
561		let alloc = Arena::new();
562		let mut v: Vec<u32> = Vec::new_in(&alloc);
563		for i in 0..1000u32 {
564			v.push(i);
565		}
566		assert_eq!(v.len(), 1000);
567		assert!(v.capacity() >= 1000);
568		for (i, &value) in v.iter().enumerate() {
569			assert_eq!(value, i as u32, "element is still in vec");
570		}
571	}
572
573	#[test]
574	fn pop_returns_last_then_none() {
575		let alloc = Arena::new();
576		let mut v: Vec<i32> = Vec::new_in(&alloc);
577		v.extend([10, 20, 30]);
578		assert_eq!(v.pop(), Some(30));
579		assert_eq!(v.pop(), Some(20));
580		assert_eq!(v.pop(), Some(10));
581		assert_eq!(v.pop(), None);
582		assert!(v.is_empty());
583	}
584
585	#[test]
586	fn insert_at_boundaries_and_middle() {
587		let alloc = Arena::new();
588		let mut v: Vec<i32> = Vec::new_in(&alloc);
589		v.extend([1, 2, 3]);
590		v.insert(0, 0); // front
591		assert_eq!(&*v, &[0, 1, 2, 3]);
592		v.insert(v.len(), 4); // back (index == len)
593		assert_eq!(&*v, &[0, 1, 2, 3, 4]);
594		v.insert(2, 99); // middle
595		assert_eq!(&*v, &[0, 1, 99, 2, 3, 4]);
596	}
597
598	#[test]
599	fn insert_into_empty() {
600		let alloc = Arena::new();
601		let mut v: Vec<i32> = Vec::new_in(&alloc);
602		v.insert(0, 42);
603		assert_eq!(&*v, &[42]);
604	}
605
606	#[test]
607	fn insert_out_of_bounds_panics() {
608		let alloc = Arena::new();
609		let mut v: Vec<i32> = Vec::new_in(&alloc);
610		v.extend([1, 2]);
611		let result = catch_unwind(AssertUnwindSafe(|| v.insert(3, 0)));
612		assert!(result.is_err());
613	}
614
615	#[test]
616	fn remove_at_boundaries_and_middle() {
617		let alloc = Arena::new();
618		let mut v: Vec<i32> = Vec::new_in(&alloc);
619		v.extend([0, 1, 2, 3, 4]);
620		assert_eq!(v.remove(0), 0); // front
621		assert_eq!(&*v, &[1, 2, 3, 4]);
622		assert_eq!(v.remove(v.len() - 1), 4); // back
623		assert_eq!(&*v, &[1, 2, 3]);
624		assert_eq!(v.remove(1), 2); // middle
625		assert_eq!(&*v, &[1, 3]);
626	}
627
628	#[test]
629	fn remove_out_of_bounds_panics() {
630		let alloc = Arena::new();
631		let mut v: Vec<i32> = Vec::new_in(&alloc);
632		v.extend([1, 2]);
633		let result = catch_unwind(AssertUnwindSafe(|| v.remove(2)));
634		assert!(result.is_err());
635	}
636
637	#[test]
638	fn truncate_shortens_without_dropping() {
639		let alloc = Arena::new();
640		let drops = Rc::new(Cell::new(0));
641		let mut v: Vec<DropCounter> = Vec::new_in(&alloc);
642		for i in 0..5 {
643			v.push(DropCounter::new(i, &drops));
644		}
645		v.truncate(2);
646		assert_eq!(v.len(), 2);
647		assert_eq!(drops.get(), 0, "truncate must not run destructors");
648	}
649
650	#[test]
651	fn truncate_longer_than_len_is_noop() {
652		let alloc = Arena::new();
653		let mut v: Vec<i32> = Vec::new_in(&alloc);
654		v.extend([1, 2, 3]);
655		v.truncate(10);
656		assert_eq!(&*v, &[1, 2, 3]);
657	}
658
659	#[test]
660	fn clear_empties_without_dropping() {
661		let alloc = Arena::new();
662		let drops = Rc::new(Cell::new(0));
663		let mut v: Vec<DropCounter> = Vec::new_in(&alloc);
664		for i in 0..3 {
665			v.push(DropCounter::new(i, &drops));
666		}
667		v.clear();
668		assert!(v.is_empty());
669		assert_eq!(drops.get(), 0, "clear must not run destructors");
670	}
671
672	#[test]
673	fn extend_from_slice_clones_elements() {
674		let alloc = Arena::new();
675		let mut v: Vec<i32> = Vec::new_in(&alloc);
676		v.push(1);
677		v.extend_from_slice(&[2, 3, 4]);
678		assert_eq!(&*v, &[1, 2, 3, 4]);
679	}
680
681	#[test]
682	fn extend_with_accurate_size_hint_reserves_once() {
683		let alloc = Arena::new();
684		let mut v: Vec<u32> = Vec::new_in(&alloc);
685		v.extend(0..64u32);
686		assert_eq!(v.len(), 64);
687		for i in 0..64u32 {
688			assert_eq!(v[i as usize], i);
689		}
690	}
691
692	#[test]
693	fn extend_empty_iterator_is_noop() {
694		let alloc = Arena::new();
695		let mut v: Vec<u32> = Vec::new_in(&alloc);
696		v.extend(std::iter::empty::<u32>());
697		assert!(v.is_empty());
698		assert_eq!(v.capacity(), 0);
699	}
700
701	#[test]
702	fn retain_keeps_matching_and_shifts() {
703		let alloc = Arena::new();
704		let mut v: Vec<i32> = Vec::new_in(&alloc);
705		v.extend([0, 1, 2, 3, 4, 5, 6, 7]);
706		v.retain(|&x| x % 2 == 0);
707		assert_eq!(&*v, &[0, 2, 4, 6]);
708	}
709
710	#[test]
711	fn retain_all_and_none() {
712		let alloc = Arena::new();
713		let mut v: Vec<i32> = Vec::new_in(&alloc);
714		v.extend([1, 2, 3]);
715		v.retain(|_| true);
716		assert_eq!(&*v, &[1, 2, 3]);
717		v.retain(|_| false);
718		assert!(v.is_empty());
719	}
720
721	#[test]
722	fn retain_drops_removed_exactly_once() {
723		let alloc = Arena::new();
724		let drops = Rc::new(Cell::new(0));
725		let mut v: Vec<DropCounter> = Vec::new_in(&alloc);
726		for i in 0..6 {
727			v.push(DropCounter::new(i, &drops));
728		}
729		v.retain(|c| c.id % 2 == 1);
730		assert_eq!(v.len(), 3);
731		assert_eq!(drops.get(), 3, "each removed element dropped exactly once");
732		let ids: std::vec::Vec<u32> = v.iter().map(|c| c.id).collect();
733		assert_eq!(ids, vec![1, 3, 5], "survivors intact and in order after write-back");
734	}
735
736	#[test]
737	fn retain_panic_drops_no_element_twice() {
738		let alloc = Arena::new();
739		let drops = Rc::new(Cell::new(0));
740		let mut v: Vec<DropCounter> = Vec::new_in(&alloc);
741		for i in 0..5 {
742			v.push(DropCounter::new(i, &drops));
743		}
744		let drops_for_closure = Rc::clone(&drops);
745		let result = catch_unwind(AssertUnwindSafe(|| {
746			v.retain(|c| {
747				if c.id == 3 {
748					panic!("boom");
749				}
750				// Drop id 0 and id 1 before the panic.
751				c.id >= 2
752			});
753		}));
754		assert!(result.is_err());
755		let removed = drops_for_closure.get();
756		assert_eq!(removed, 2, "only the elements filtered out before the panic were dropped");
757		assert_eq!(v.len() as u32 + removed, 5, "no leaked or double-counted elements");
758	}
759
760	#[test]
761	fn drain_empty_range() {
762		let alloc = Arena::new();
763		let mut v: Vec<i32> = Vec::new_in(&alloc);
764		v.extend([1, 2, 3]);
765		let drained: std::vec::Vec<i32> = v.drain(1..1).collect();
766		assert!(drained.is_empty());
767		assert_eq!(&*v, &[1, 2, 3]);
768	}
769
770	#[test]
771	fn drain_suffix() {
772		let alloc = Arena::new();
773		let mut v: Vec<i32> = Vec::new_in(&alloc);
774		v.extend([0, 1, 2, 3, 4]);
775		let drained: std::vec::Vec<i32> = v.drain(3..).collect();
776		assert_eq!(drained, vec![3, 4]);
777		assert_eq!(&*v, &[0, 1, 2]);
778	}
779
780	#[test]
781	fn drain_inclusive_bound() {
782		let alloc = Arena::new();
783		let mut v: Vec<i32> = Vec::new_in(&alloc);
784		v.extend([0, 1, 2, 3, 4]);
785		let drained: std::vec::Vec<i32> = v.drain(1..=3).collect();
786		assert_eq!(drained, vec![1, 2, 3]);
787		assert_eq!(&*v, &[0, 4]);
788	}
789
790	#[test]
791	fn drain_start_after_end_panics() {
792		let alloc = Arena::new();
793		let mut v: Vec<i32> = Vec::new_in(&alloc);
794		v.extend([0, 1, 2]);
795		use std::ops::Bound;
796		let bad_range = (Bound::Included(2u32), Bound::Excluded(1u32));
797		let result = catch_unwind(AssertUnwindSafe(|| {
798			let _ = v.drain(bad_range);
799		}));
800		assert!(result.is_err());
801	}
802
803	#[test]
804	fn drain_out_of_bounds_panics() {
805		let alloc = Arena::new();
806		let mut v: Vec<i32> = Vec::new_in(&alloc);
807		v.extend([0, 1, 2]);
808		let result = catch_unwind(AssertUnwindSafe(|| {
809			let _ = v.drain(1..99);
810		}));
811		assert!(result.is_err());
812	}
813
814	#[test]
815	fn drain_yielded_and_remaining_drop_exactly_once() {
816		let alloc = Arena::new();
817		let drops = Rc::new(Cell::new(0));
818		let mut v: Vec<DropCounter> = Vec::new_in(&alloc);
819		for i in 0..6 {
820			v.push(DropCounter::new(i, &drops));
821		}
822		{
823			let mut d = v.drain(1..4);
824			let first = d.next().unwrap();
825			assert_eq!(first.id, 1);
826			drop(first); // 1 drop
827			// d dropped here: ids 2, 3 dropped by Drain::drop -> 2 more drops.
828		}
829		assert_eq!(drops.get(), 3, "drained range dropped exactly once total");
830		let ids: std::vec::Vec<u32> = v.iter().map(|c| c.id).collect();
831		assert_eq!(ids, vec![0, 4, 5], "tail shifted correctly after partial drain");
832	}
833
834	#[test]
835	fn drain_fully_consumed_then_no_extra_drops() {
836		let alloc = Arena::new();
837		let drops = Rc::new(Cell::new(0));
838		let mut v: Vec<DropCounter> = Vec::new_in(&alloc);
839		for i in 0..4 {
840			v.push(DropCounter::new(i, &drops));
841		}
842		let collected: std::vec::Vec<DropCounter> = v.drain(..).collect();
843		let ids: std::vec::Vec<u32> = collected.iter().map(|c| c.id).collect();
844		assert_eq!(ids, vec![0, 1, 2, 3]);
845		// The drained DropCounters were moved into `collected`; none dropped yet.
846		assert_eq!(drops.get(), 0);
847		assert!(v.is_empty());
848		drop(collected);
849		assert_eq!(drops.get(), 4, "each drained element dropped exactly once when the collection drops");
850	}
851
852	#[test]
853	fn drain_size_hint_not_relied_on_but_iteration_correct() {
854		let alloc = Arena::new();
855		let mut v: Vec<i32> = Vec::new_in(&alloc);
856		v.extend([5, 6, 7, 8]);
857		let mut iter = v.drain(0..4);
858		assert_eq!(iter.next(), Some(5));
859		assert_eq!(iter.next(), Some(6));
860		assert_eq!(iter.next(), Some(7));
861		assert_eq!(iter.next(), Some(8));
862		assert_eq!(iter.next(), None);
863	}
864
865	#[test]
866	fn drain_prefix_shifts_tail() {
867		let alloc = Arena::default();
868		let mut v: Vec<i32> = Vec::new_in(&alloc);
869		v.extend([0, 1, 2, 3, 4, 5]);
870		let drained: std::vec::Vec<i32> = v.drain(0..2).collect();
871		assert_eq!(drained, vec![0, 1]);
872		assert_eq!(&*v, &[2, 3, 4, 5]);
873	}
874
875	#[test]
876	fn drain_middle_shifts_tail() {
877		let alloc = Arena::default();
878		let mut v: Vec<i32> = Vec::new_in(&alloc);
879		v.extend([0, 1, 2, 3, 4, 5]);
880		let drained: std::vec::Vec<i32> = v.drain(2..4).collect();
881		assert_eq!(drained, vec![2, 3]);
882		assert_eq!(&*v, &[0, 1, 4, 5]);
883	}
884
885	#[test]
886	fn drain_full_range() {
887		let alloc = Arena::default();
888		let mut v: Vec<i32> = Vec::new_in(&alloc);
889		v.extend([1, 2, 3]);
890		let drained: std::vec::Vec<i32> = v.drain(..).collect();
891		assert_eq!(drained, vec![1, 2, 3]);
892		assert!(v.is_empty());
893	}
894
895	#[test]
896	fn drain_dropped_without_iterating_still_shifts() {
897		let alloc = Arena::default();
898		let mut v: Vec<i32> = Vec::new_in(&alloc);
899		v.extend([0, 1, 2, 3, 4]);
900		drop(v.drain(1..3));
901		assert_eq!(&*v, &[0, 3, 4]);
902	}
903
904	#[test]
905	fn retain_preserves_length_when_predicate_panics() {
906		let alloc = Arena::new();
907		let mut values = Vec::new_in(&alloc);
908		values.extend([0, 1, 2]);
909		let calls = Cell::new(0);
910
911		let result = catch_unwind(AssertUnwindSafe(|| {
912			values.retain(|_| {
913				let call = calls.get();
914				calls.set(call + 1);
915				match call {
916					0 => false,
917					1 => true,
918					_ => panic!("predicate failed"),
919				}
920			});
921		}));
922
923		assert!(result.is_err());
924		assert_eq!(values.len(), 2, "moved-from slots must not remain visible");
925	}
926
927	#[test]
928	fn into_iter_yields_all_in_order() {
929		let alloc = Arena::new();
930		let mut v: Vec<i32> = Vec::new_in(&alloc);
931		v.extend([1, 2, 3, 4]);
932		let collected: std::vec::Vec<i32> = v.into_iter().collect();
933		assert_eq!(collected, vec![1, 2, 3, 4]);
934	}
935
936	#[test]
937	fn into_iter_size_hint_is_exact() {
938		let alloc = Arena::new();
939		let mut v: Vec<i32> = Vec::new_in(&alloc);
940		v.extend([1, 2, 3]);
941		let mut iter = v.into_iter();
942		assert_eq!(iter.size_hint(), (3, Some(3)));
943		iter.next();
944		assert_eq!(iter.size_hint(), (2, Some(2)));
945	}
946
947	#[test]
948	fn into_iter_partial_consume_drops_remainder_once() {
949		let alloc = Arena::new();
950		let drops = Rc::new(Cell::new(0));
951		let mut v: Vec<DropCounter> = Vec::new_in(&alloc);
952		for i in 0..5 {
953			v.push(DropCounter::new(i, &drops));
954		}
955		{
956			let mut iter = v.into_iter();
957			let a = iter.next().unwrap();
958			let b = iter.next().unwrap();
959			assert_eq!((a.id, b.id), (0, 1));
960			drop(a); // 1
961			drop(b); // 1
962			// iter dropped here: ids 2, 3, 4 dropped by IntoIter::drop -> 3 more.
963		}
964		assert_eq!(drops.get(), 5, "every element dropped exactly once across manual + IntoIter drop");
965	}
966
967	#[test]
968	fn into_iter_fully_consumed_no_leak() {
969		let alloc = Arena::new();
970		let drops = Rc::new(Cell::new(0));
971		let mut v: Vec<DropCounter> = Vec::new_in(&alloc);
972		for i in 0..4 {
973			v.push(DropCounter::new(i, &drops));
974		}
975		for c in v {
976			let _ = c.id; // dropped at end of each loop iteration
977		}
978		assert_eq!(drops.get(), 4);
979	}
980
981	#[test]
982	fn clone_is_independent_copy() {
983		let alloc = Arena::new();
984		let mut v: Vec<i32> = Vec::new_in(&alloc);
985		v.extend([1, 2, 3]);
986		let mut c = v.clone();
987		c.push(4);
988		assert_eq!(&*v, &[1, 2, 3], "original unchanged after mutating clone");
989		assert_eq!(&*c, &[1, 2, 3, 4]);
990	}
991
992	#[test]
993	fn eq_and_ord_delegate_to_slice() {
994		let alloc = Arena::new();
995		let mut a: Vec<i32> = Vec::new_in(&alloc);
996		a.extend([1, 2, 3]);
997		let mut b: Vec<i32> = Vec::new_in(&alloc);
998		b.extend([1, 2, 3]);
999		assert_eq!(a, b);
1000		let mut c: Vec<i32> = Vec::new_in(&alloc);
1001		c.extend([1, 2, 4]);
1002		assert!(a < c);
1003		assert_ne!(a, c);
1004	}
1005
1006	#[test]
1007	fn index_and_index_mut() {
1008		let alloc = Arena::new();
1009		let mut v: Vec<i32> = Vec::new_in(&alloc);
1010		v.extend([10, 20, 30]);
1011		assert_eq!(v[1], 20);
1012		v[1] = 99;
1013		assert_eq!(v[1], 99);
1014		assert_eq!(&v[0..2], &[10, 99]);
1015	}
1016
1017	#[test]
1018	fn hash_matches_equal_vecs() {
1019		use std::collections::hash_map::DefaultHasher;
1020		use std::hash::{Hash, Hasher};
1021		let alloc = Arena::new();
1022		let mut a: Vec<i32> = Vec::new_in(&alloc);
1023		a.extend([1, 2, 3]);
1024		let mut b: Vec<i32> = Vec::new_in(&alloc);
1025		b.extend([1, 2, 3]);
1026		let mut ha = DefaultHasher::new();
1027		let mut hb = DefaultHasher::new();
1028		a.hash(&mut ha);
1029		b.hash(&mut hb);
1030		assert_eq!(ha.finish(), hb.finish());
1031	}
1032
1033	#[test]
1034	fn realloc_preserves_boxed_contents() {
1035		let alloc = Arena::new();
1036		let mut v: Vec<std::boxed::Box<u32>> = Vec::new_in(&alloc);
1037		for i in 0..512u32 {
1038			v.push(std::boxed::Box::new(i));
1039		}
1040		for (i, b) in v.iter().enumerate() {
1041			assert_eq!(**b, i as u32);
1042		}
1043		let sum: u32 = v.into_iter().map(|b| *b).sum();
1044		assert_eq!(sum, (0..512u32).sum());
1045	}
1046
1047	#[test]
1048	fn zero_sized_type_push_pop_len() {
1049		let alloc = Arena::new();
1050		let mut v: Vec<()> = Vec::new_in(&alloc);
1051		for _ in 0..100 {
1052			v.push(());
1053		}
1054		assert_eq!(v.len(), 100);
1055		for _ in 0..100 {
1056			assert_eq!(v.pop(), Some(()));
1057		}
1058		assert_eq!(v.pop(), None);
1059	}
1060
1061	#[test]
1062	fn parsing_beyond_default_arena_capacity_does_not_panic() {
1063		use crate::{ComponentValues, EmptyAtomSet, Parser};
1064		use css_lexer::Lexer;
1065
1066		let source = "a ".repeat(16_384);
1067		let result = catch_unwind(AssertUnwindSafe(|| {
1068			let arena = Arena::new();
1069			let lexer = Lexer::new(&EmptyAtomSet::ATOMS, &source);
1070			let mut parser = Parser::new(&arena, &source, lexer);
1071			let _ = parser.parse_entirely::<ComponentValues>();
1072		}));
1073
1074		assert!(result.is_ok(), "arena exhaustion must not abort parsing");
1075	}
1076}