1use std::alloc::{alloc, dealloc, realloc, Layout};
27use std::fmt;
28use std::iter::FromIterator;
29use std::mem::{self, ManuallyDrop};
30use std::ops::{Deref, DerefMut, Index, IndexMut};
31use std::ptr::{self, NonNull};
32use std::slice;
33
34pub struct CompactVec<T> {
37 ptr: NonNull<T>,
38 len_cap: u64,
40}
41
42unsafe impl<T: Send> Send for CompactVec<T> {}
45unsafe impl<T: Sync> Sync for CompactVec<T> {}
48
49impl<T> CompactVec<T> {
50 const MAX_CAPACITY: usize = u32::MAX as usize;
51
52 #[track_caller]
53 fn assert_capacity_representable(capacity: usize) {
54 assert!(
55 capacity <= Self::MAX_CAPACITY,
56 "CompactVec capacity exceeds u32::MAX"
57 );
58 }
59
60 #[inline(always)]
62 const fn pack(len: u32, cap: u32) -> u64 {
63 (len as u64) | ((cap as u64) << 32)
64 }
65
66 #[inline(always)]
68 const fn unpack_len(len_cap: u64) -> u32 {
69 len_cap as u32
70 }
71
72 #[inline(always)]
74 const fn unpack_cap(len_cap: u64) -> u32 {
75 (len_cap >> 32) as u32
76 }
77
78 #[inline]
80 pub const fn new() -> Self {
81 Self {
82 ptr: NonNull::dangling(),
83 len_cap: 0,
84 }
85 }
86
87 #[inline]
89 pub fn with_capacity(capacity: usize) -> Self {
90 Self::assert_capacity_representable(capacity);
91 if capacity == 0 {
92 return Self::new();
93 }
94
95 let cap = capacity as u32;
96
97 if mem::size_of::<T>() == 0 {
98 return Self {
99 ptr: NonNull::dangling(),
100 len_cap: Self::pack(0, cap),
101 };
102 }
103
104 let layout = Layout::array::<T>(cap as usize).unwrap();
106 let ptr = unsafe { alloc(layout) as *mut T };
108
109 if ptr.is_null() {
110 std::alloc::handle_alloc_error(layout);
111 }
112
113 Self {
114 ptr: unsafe { NonNull::new_unchecked(ptr) },
116 len_cap: Self::pack(0, cap),
117 }
118 }
119
120 #[inline(always)]
122 pub const fn len(&self) -> usize {
123 Self::unpack_len(self.len_cap) as usize
124 }
125
126 #[inline(always)]
128 pub const fn is_empty(&self) -> bool {
129 Self::unpack_len(self.len_cap) == 0
130 }
131
132 #[inline(always)]
134 pub const fn capacity(&self) -> usize {
135 Self::unpack_cap(self.len_cap) as usize
136 }
137
138 #[inline(always)]
146 pub unsafe fn set_len(&mut self, new_len: usize) {
147 let cap = Self::unpack_cap(self.len_cap);
148 self.len_cap = Self::pack(new_len as u32, cap);
149 }
150
151 #[inline(always)]
153 pub fn as_ptr(&self) -> *const T {
154 self.ptr.as_ptr()
155 }
156
157 #[inline(always)]
159 pub fn as_mut_ptr(&mut self) -> *mut T {
160 self.ptr.as_ptr()
161 }
162
163 #[inline]
165 pub fn push(&mut self, value: T) {
166 let len = Self::unpack_len(self.len_cap) as usize;
168 let cap = Self::unpack_cap(self.len_cap) as usize;
169
170 if len == cap {
171 self.grow();
172 }
173
174 unsafe {
177 ptr::write(self.ptr.as_ptr().add(len), value);
178 self.set_len(len + 1);
179 }
180 }
181
182 #[inline]
184 pub fn pop(&mut self) -> Option<T> {
185 let len = self.len();
186 if len == 0 {
187 return None;
188 }
189
190 unsafe {
194 self.set_len(len - 1);
195 Some(ptr::read(self.ptr.as_ptr().add(len - 1)))
196 }
197 }
198
199 #[inline]
201 pub fn clear(&mut self) {
202 let len = self.len();
203 if len == 0 {
204 return;
205 }
206
207 unsafe {
211 self.set_len(0);
212 ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.ptr.as_ptr(), len));
213 }
214 }
215
216 #[inline]
218 pub fn reserve(&mut self, additional: usize) {
219 let len = Self::unpack_len(self.len_cap) as usize;
221 let cap = Self::unpack_cap(self.len_cap) as usize;
222 let required = len
223 .checked_add(additional)
224 .expect("CompactVec capacity exceeds usize::MAX");
225 Self::assert_capacity_representable(required);
226
227 if required > cap {
228 self.realloc(required);
229 }
230 }
231
232 fn grow(&mut self) {
234 let cap = self.capacity();
235 let new_cap = if cap == 0 {
236 4
237 } else {
238 assert!(
239 cap < Self::MAX_CAPACITY,
240 "CompactVec capacity exceeds u32::MAX"
241 );
242 cap.saturating_mul(2).min(Self::MAX_CAPACITY)
243 };
244
245 self.realloc(new_cap);
246 }
247
248 fn realloc(&mut self, new_cap: usize) {
250 Self::assert_capacity_representable(new_cap);
251 let len = self.len();
252 let old_cap = self.capacity();
253 let new_cap = new_cap as u32;
254
255 if mem::size_of::<T>() == 0 {
256 self.len_cap = Self::pack(len as u32, new_cap);
258 return;
259 }
260
261 let new_layout = Layout::array::<T>(new_cap as usize).unwrap();
262
263 let new_ptr = if old_cap == 0 {
264 unsafe { alloc(new_layout) as *mut T }
267 } else {
268 let old_layout = Layout::array::<T>(old_cap).unwrap();
270 unsafe {
273 realloc(self.ptr.as_ptr() as *mut u8, old_layout, new_layout.size()) as *mut T
274 }
275 };
276
277 if new_ptr.is_null() {
278 std::alloc::handle_alloc_error(new_layout);
279 }
280
281 self.ptr = unsafe { NonNull::new_unchecked(new_ptr) };
283 self.len_cap = Self::pack(len as u32, new_cap);
284 }
285
286 #[inline]
288 pub fn truncate(&mut self, len: usize) {
289 let current_len = self.len();
290 if len >= current_len {
291 return;
292 }
293
294 unsafe {
298 let remaining = current_len - len;
299 self.set_len(len);
300 ptr::drop_in_place(ptr::slice_from_raw_parts_mut(
301 self.ptr.as_ptr().add(len),
302 remaining,
303 ));
304 }
305 }
306
307 #[inline]
309 pub fn remove(&mut self, index: usize) -> T {
310 let len = self.len();
311 assert!(index < len, "removal index out of bounds");
312
313 unsafe {
316 let ptr = self.ptr.as_ptr().add(index);
317 let value = ptr::read(ptr);
318
319 ptr::copy(ptr.add(1), ptr, len - index - 1);
321 self.set_len(len - 1);
322
323 value
324 }
325 }
326
327 #[inline]
329 pub fn swap_remove(&mut self, index: usize) -> T {
330 let len = self.len();
331 assert!(index < len, "swap_remove index out of bounds");
332
333 unsafe {
336 let ptr = self.ptr.as_ptr();
337 let value = ptr::read(ptr.add(index));
338
339 if index < len - 1 {
341 ptr::copy_nonoverlapping(ptr.add(len - 1), ptr.add(index), 1);
342 }
343
344 self.set_len(len - 1);
345 value
346 }
347 }
348
349 #[inline]
354 pub fn insert(&mut self, index: usize, element: T) {
355 let len = self.len();
356 assert!(index <= len, "insertion index out of bounds");
357
358 if len == self.capacity() {
360 self.grow();
361 }
362
363 unsafe {
366 let ptr = self.ptr.as_ptr().add(index);
367
368 if index < len {
370 ptr::copy(ptr, ptr.add(1), len - index);
371 }
372
373 ptr::write(ptr, element);
375 self.set_len(len + 1);
376 }
377 }
378
379 #[inline]
385 pub fn retain<F>(&mut self, mut f: F)
386 where
387 F: FnMut(&T) -> bool,
388 {
389 let original_len = self.len();
390 if original_len == 0 {
391 return;
392 }
393
394 struct BackshiftOnDrop<'a, T> {
395 vec: &'a mut CompactVec<T>,
396 original_len: usize,
397 processed_len: usize,
398 deleted_count: usize,
399 }
400
401 impl<T> Drop for BackshiftOnDrop<'_, T> {
402 fn drop(&mut self) {
403 unsafe {
408 if self.deleted_count > 0 {
409 let base = self.vec.ptr.as_ptr();
410 ptr::copy(
411 base.add(self.processed_len),
412 base.add(self.processed_len - self.deleted_count),
413 self.original_len - self.processed_len,
414 );
415 }
416 self.vec.set_len(self.original_len - self.deleted_count);
417 }
418 }
419 }
420
421 unsafe {
425 self.set_len(0);
426 }
427 let mut guard = BackshiftOnDrop {
428 vec: self,
429 original_len,
430 processed_len: 0,
431 deleted_count: 0,
432 };
433
434 while guard.processed_len < original_len {
435 unsafe {
437 let current = guard.vec.ptr.as_ptr().add(guard.processed_len);
438 if f(&*current) {
439 if guard.deleted_count > 0 {
440 ptr::copy_nonoverlapping(current, current.sub(guard.deleted_count), 1);
441 }
442 guard.processed_len += 1;
443 } else {
444 guard.processed_len += 1;
446 guard.deleted_count += 1;
447 ptr::drop_in_place(current);
448 }
449 }
450 }
451 }
452
453 #[inline]
455 pub fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
456 let iter = iter.into_iter();
457 let (lower, upper) = iter.size_hint();
458
459 if Some(lower) == upper && lower > 0 {
461 self.reserve(lower);
462 let original_len = self.len();
463 let cap = self.capacity();
464
465 struct ExtendGuard<'a, T> {
468 vec: &'a mut CompactVec<T>,
469 written_count: usize,
470 }
471
472 impl<T> Drop for ExtendGuard<'_, T> {
473 fn drop(&mut self) {
474 unsafe {
479 self.vec.set_len(self.written_count);
480 }
481 }
482 }
483
484 let mut guard = ExtendGuard {
485 vec: self,
486 written_count: original_len,
487 };
488
489 unsafe {
495 let ptr = guard.vec.ptr.as_ptr();
496 for item in iter {
497 if guard.written_count >= cap {
498 let count = guard.written_count;
501 guard.vec.set_len(count);
502 guard.vec.push(item);
503 guard.written_count = guard.vec.len();
504 continue;
505 }
506 ptr::write(ptr.add(guard.written_count), item);
507 guard.written_count += 1;
508 }
509 }
510
511 let final_len = guard.written_count;
513 mem::forget(guard);
514 unsafe {
517 self.set_len(final_len);
518 }
519 } else {
520 self.reserve(lower);
522 for item in iter {
523 self.push(item);
524 }
525 }
526 }
527
528 #[inline]
537 pub fn extend_clone(&mut self, slice: &[T])
538 where
539 T: Clone,
540 {
541 let slice_len = slice.len();
542 if slice_len == 0 {
543 return;
544 }
545 self.reserve(slice_len);
546 let original_len = self.len();
547
548 struct ExtendCloneGuard<'a, T> {
551 vec: &'a mut CompactVec<T>,
552 written_count: usize,
553 }
554
555 impl<T> Drop for ExtendCloneGuard<'_, T> {
556 fn drop(&mut self) {
557 unsafe {
562 self.vec.set_len(self.written_count);
563 }
564 }
565 }
566
567 let mut guard = ExtendCloneGuard {
568 vec: self,
569 written_count: original_len,
570 };
571
572 unsafe {
575 let mut dst = guard.vec.ptr.as_ptr().add(original_len);
576 for item in slice {
577 ptr::write(dst, item.clone());
578 guard.written_count += 1;
579 dst = dst.add(1);
580 }
581 }
582
583 let final_len = guard.written_count;
585 mem::forget(guard);
586 unsafe {
589 self.set_len(final_len);
590 }
591 }
592
593 #[inline(always)]
595 pub fn as_slice(&self) -> &[T] {
596 unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len()) }
598 }
599
600 #[inline(always)]
602 pub fn as_mut_slice(&mut self) -> &mut [T] {
603 unsafe { &mut *ptr::slice_from_raw_parts_mut(self.ptr.as_ptr(), self.len()) }
605 }
606
607 #[inline]
609 pub fn iter(&self) -> slice::Iter<'_, T> {
610 self.as_slice().iter()
611 }
612
613 #[inline]
615 pub fn iter_mut(&mut self) -> slice::IterMut<'_, T> {
616 self.as_mut_slice().iter_mut()
617 }
618
619 #[inline]
622 pub fn drain(&mut self, range: std::ops::RangeFrom<usize>) -> Drain<'_, T> {
623 let start = range.start;
624 let len = self.len();
625 assert!(start <= len, "drain start index out of bounds");
626
627 Drain {
628 vec: self,
629 start,
630 current: start,
631 end: len,
632 }
633 }
634
635 #[inline(always)]
637 pub fn get(&self, index: usize) -> Option<&T> {
638 if index < self.len() {
639 unsafe { Some(&*self.ptr.as_ptr().add(index)) }
641 } else {
642 None
643 }
644 }
645
646 #[inline(always)]
648 pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
649 if index < self.len() {
650 unsafe { Some(&mut *self.ptr.as_ptr().add(index)) }
652 } else {
653 None
654 }
655 }
656
657 #[inline]
659 pub fn into_vec(self) -> Vec<T> {
660 let len = self.len();
661 let cap = self.capacity();
662
663 if cap == 0 {
664 mem::forget(self);
665 return Vec::new();
666 }
667
668 let ptr = self.ptr.as_ptr();
669 mem::forget(self);
670
671 if mem::size_of::<T>() == 0 {
672 return unsafe { Vec::from_raw_parts(ptr, len, len) };
675 }
676
677 unsafe { Vec::from_raw_parts(ptr, len, cap) }
680 }
681
682 #[inline]
684 pub fn into_boxed_slice(self) -> Box<[T]> {
685 self.into_vec().into_boxed_slice()
686 }
687
688 #[inline]
690 pub fn from_vec(vec: Vec<T>) -> Self {
691 Self::assert_capacity_representable(vec.len());
692 if mem::size_of::<T>() == 0 {
693 let len = vec.len() as u32;
694 let mut vec = ManuallyDrop::new(vec);
695 return Self {
696 ptr: unsafe { NonNull::new_unchecked(vec.as_mut_ptr()) },
697 len_cap: Self::pack(len, len),
698 };
699 }
700 Self::assert_capacity_representable(vec.capacity());
701 let len = vec.len() as u32;
702 let cap = vec.capacity() as u32;
703
704 if cap == 0 {
705 mem::forget(vec);
706 return Self::new();
707 }
708
709 let mut vec = ManuallyDrop::new(vec);
710 let ptr = vec.as_mut_ptr();
711
712 Self {
713 ptr: unsafe { NonNull::new_unchecked(ptr) },
715 len_cap: Self::pack(len, cap),
716 }
717 }
718}
719
720impl<T: Clone> CompactVec<T> {
721 pub fn resize(&mut self, new_len: usize, value: T) {
723 let len = self.len();
724
725 if new_len > len {
726 self.reserve(new_len - len);
727 for _ in len..new_len {
728 self.push(value.clone());
729 }
730 } else {
731 self.truncate(new_len);
732 }
733 }
734}
735
736impl<T> Drop for CompactVec<T> {
737 fn drop(&mut self) {
738 if self.capacity() == 0 {
739 return;
740 }
741
742 let len = self.len();
744 if len > 0 {
745 unsafe {
747 ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.ptr.as_ptr(), len));
748 }
749 }
750
751 if mem::size_of::<T>() > 0 {
753 let layout = Layout::array::<T>(self.capacity()).unwrap();
754 unsafe {
756 dealloc(self.ptr.as_ptr() as *mut u8, layout);
757 }
758 }
759 }
760}
761
762impl<T: Clone> Clone for CompactVec<T> {
763 fn clone(&self) -> Self {
764 let len = self.len();
765 if len == 0 {
766 return Self::new();
767 }
768
769 let mut new_vec = Self::with_capacity(len);
770
771 struct CloneGuard<'a, T> {
774 vec: &'a mut CompactVec<T>,
775 cloned_count: usize,
776 }
777
778 impl<T> Drop for CloneGuard<'_, T> {
779 fn drop(&mut self) {
780 unsafe {
785 self.vec.set_len(self.cloned_count);
786 }
787 }
788 }
789
790 let mut guard = CloneGuard {
791 vec: &mut new_vec,
792 cloned_count: 0,
793 };
794
795 unsafe {
801 let src = self.ptr.as_ptr();
802 let dst = guard.vec.ptr.as_ptr();
803 for i in 0..len {
804 ptr::write(dst.add(i), (*src.add(i)).clone());
805 guard.cloned_count += 1;
806 }
807 }
808
809 let cloned = guard.cloned_count;
811 mem::forget(guard);
812 unsafe {
815 new_vec.set_len(cloned);
816 }
817 new_vec
818 }
819}
820
821impl<T> Default for CompactVec<T> {
822 #[inline]
823 fn default() -> Self {
824 Self::new()
825 }
826}
827
828impl<T: fmt::Debug> fmt::Debug for CompactVec<T> {
829 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
830 f.debug_list().entries(self.iter()).finish()
831 }
832}
833
834impl<T> Deref for CompactVec<T> {
835 type Target = [T];
836
837 #[inline(always)]
838 fn deref(&self) -> &[T] {
839 self.as_slice()
840 }
841}
842
843impl<T> DerefMut for CompactVec<T> {
844 #[inline(always)]
845 fn deref_mut(&mut self) -> &mut [T] {
846 self.as_mut_slice()
847 }
848}
849
850impl<T> Index<usize> for CompactVec<T> {
851 type Output = T;
852
853 #[inline(always)]
854 fn index(&self, index: usize) -> &T {
855 &self.as_slice()[index]
856 }
857}
858
859impl<T> IndexMut<usize> for CompactVec<T> {
860 #[inline(always)]
861 fn index_mut(&mut self, index: usize) -> &mut T {
862 &mut self.as_mut_slice()[index]
863 }
864}
865
866impl<T> Index<std::ops::Range<usize>> for CompactVec<T> {
867 type Output = [T];
868
869 #[inline(always)]
870 fn index(&self, range: std::ops::Range<usize>) -> &[T] {
871 &self.as_slice()[range]
872 }
873}
874
875impl<T> Index<std::ops::RangeFrom<usize>> for CompactVec<T> {
876 type Output = [T];
877
878 #[inline(always)]
879 fn index(&self, range: std::ops::RangeFrom<usize>) -> &[T] {
880 &self.as_slice()[range]
881 }
882}
883
884impl<T> Index<std::ops::RangeTo<usize>> for CompactVec<T> {
885 type Output = [T];
886
887 #[inline(always)]
888 fn index(&self, range: std::ops::RangeTo<usize>) -> &[T] {
889 &self.as_slice()[range]
890 }
891}
892
893impl<T> Index<std::ops::RangeFull> for CompactVec<T> {
894 type Output = [T];
895
896 #[inline(always)]
897 fn index(&self, _range: std::ops::RangeFull) -> &[T] {
898 self.as_slice()
899 }
900}
901
902impl<T> FromIterator<T> for CompactVec<T> {
903 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
904 let iter = iter.into_iter();
905 let (lower, upper) = iter.size_hint();
906
907 if Some(lower) == upper && lower > 0 {
909 let mut vec = Self::with_capacity(lower);
910 let cap = vec.capacity();
911
912 struct FromIterGuard<'a, T> {
915 vec: &'a mut CompactVec<T>,
916 written_count: usize,
917 }
918
919 impl<T> Drop for FromIterGuard<'_, T> {
920 fn drop(&mut self) {
921 unsafe {
926 self.vec.set_len(self.written_count);
927 }
928 }
929 }
930
931 let mut guard = FromIterGuard {
932 vec: &mut vec,
933 written_count: 0,
934 };
935
936 unsafe {
942 let ptr = guard.vec.ptr.as_ptr();
943 for item in iter {
944 if guard.written_count >= cap {
945 let count = guard.written_count;
947 guard.vec.set_len(count);
948 guard.vec.push(item);
949 guard.written_count = guard.vec.len();
950 continue;
951 }
952 ptr::write(ptr.add(guard.written_count), item);
953 guard.written_count += 1;
954 }
955 }
956
957 let final_len = guard.written_count;
959 mem::forget(guard);
960 unsafe {
963 vec.set_len(final_len);
964 }
965 vec
966 } else {
967 let mut vec = Self::with_capacity(lower);
969 for item in iter {
970 vec.push(item);
971 }
972 vec
973 }
974 }
975}
976
977impl<T> IntoIterator for CompactVec<T> {
978 type Item = T;
979 type IntoIter = IntoIter<T>;
980
981 fn into_iter(self) -> IntoIter<T> {
982 IntoIter::new(self)
983 }
984}
985
986impl<'a, T> IntoIterator for &'a CompactVec<T> {
987 type Item = &'a T;
988 type IntoIter = slice::Iter<'a, T>;
989
990 fn into_iter(self) -> slice::Iter<'a, T> {
991 self.iter()
992 }
993}
994
995impl<'a, T> IntoIterator for &'a mut CompactVec<T> {
996 type Item = &'a mut T;
997 type IntoIter = slice::IterMut<'a, T>;
998
999 fn into_iter(self) -> slice::IterMut<'a, T> {
1000 self.iter_mut()
1001 }
1002}
1003
1004impl<T: PartialEq> PartialEq for CompactVec<T> {
1005 fn eq(&self, other: &Self) -> bool {
1006 self.as_slice() == other.as_slice()
1007 }
1008}
1009
1010impl<T: Eq> Eq for CompactVec<T> {}
1011
1012impl<T> From<Vec<T>> for CompactVec<T> {
1013 fn from(vec: Vec<T>) -> Self {
1014 Self::from_vec(vec)
1015 }
1016}
1017
1018impl<T> From<CompactVec<T>> for Vec<T> {
1019 fn from(vec: CompactVec<T>) -> Self {
1020 vec.into_vec()
1021 }
1022}
1023
1024pub struct Drain<'a, T> {
1027 vec: &'a mut CompactVec<T>,
1028 start: usize,
1029 current: usize,
1030 end: usize,
1031}
1032
1033impl<'a, T> Iterator for Drain<'a, T> {
1034 type Item = T;
1035
1036 #[inline]
1037 fn next(&mut self) -> Option<T> {
1038 if self.current < self.end {
1039 let item = unsafe { ptr::read(self.vec.ptr.as_ptr().add(self.current)) };
1042 self.current += 1;
1043 Some(item)
1044 } else {
1045 None
1046 }
1047 }
1048
1049 fn size_hint(&self) -> (usize, Option<usize>) {
1050 let remaining = self.end - self.current;
1051 (remaining, Some(remaining))
1052 }
1053}
1054
1055impl<'a, T> ExactSizeIterator for Drain<'a, T> {
1056 fn len(&self) -> usize {
1057 self.end - self.current
1058 }
1059}
1060
1061impl<'a, T> Drop for Drain<'a, T> {
1062 fn drop(&mut self) {
1063 while self.current < self.end {
1065 unsafe {
1067 ptr::drop_in_place(self.vec.ptr.as_ptr().add(self.current));
1068 }
1069 self.current += 1;
1070 }
1071
1072 unsafe {
1075 self.vec.set_len(self.start);
1076 }
1077 }
1078}
1079
1080pub struct IntoIter<T> {
1082 vec: CompactVec<T>,
1083 index: usize,
1084}
1085
1086impl<T> IntoIter<T> {
1087 fn new(vec: CompactVec<T>) -> Self {
1088 Self { vec, index: 0 }
1089 }
1090}
1091
1092impl<T> Iterator for IntoIter<T> {
1093 type Item = T;
1094
1095 fn next(&mut self) -> Option<T> {
1096 if self.index < self.vec.len() {
1097 let item = unsafe { ptr::read(self.vec.ptr.as_ptr().add(self.index)) };
1100 self.index += 1;
1101 Some(item)
1102 } else {
1103 None
1104 }
1105 }
1106
1107 fn size_hint(&self) -> (usize, Option<usize>) {
1108 let remaining = self.vec.len() - self.index;
1109 (remaining, Some(remaining))
1110 }
1111}
1112
1113impl<T> ExactSizeIterator for IntoIter<T> {
1114 fn len(&self) -> usize {
1115 self.vec.len() - self.index
1116 }
1117}
1118
1119impl<T> Drop for IntoIter<T> {
1120 fn drop(&mut self) {
1121 let len = self.vec.len();
1122 if self.index < len {
1123 unsafe {
1128 let remaining = len - self.index;
1129 ptr::drop_in_place(ptr::slice_from_raw_parts_mut(
1130 self.vec.ptr.as_ptr().add(self.index),
1131 remaining,
1132 ));
1133 }
1134 }
1135
1136 unsafe {
1138 self.vec.set_len(0);
1139 }
1140 }
1141}
1142
1143#[macro_export]
1152macro_rules! compact_vec {
1153 () => {
1154 $crate::CompactVec::new()
1155 };
1156 ($($elem:expr),+ $(,)?) => {{
1157 let arr = [$($elem),+];
1159 let mut vec = $crate::CompactVec::with_capacity(arr.len());
1160 for elem in arr {
1161 vec.push(elem);
1162 }
1163 vec
1164 }};
1165}
1166
1167#[cfg(test)]
1168mod tests {
1169 use super::*;
1170
1171 struct PanicOnFirstDrop {
1172 panicked: std::rc::Rc<std::cell::Cell<bool>>,
1173 }
1174
1175 impl Drop for PanicOnFirstDrop {
1176 fn drop(&mut self) {
1177 if !self.panicked.replace(true) {
1178 panic!("intentional drop panic");
1179 }
1180 }
1181 }
1182
1183 fn panic_drop_vec(len: usize) -> std::mem::ManuallyDrop<CompactVec<PanicOnFirstDrop>> {
1184 let panicked = std::rc::Rc::new(std::cell::Cell::new(false));
1185 std::mem::ManuallyDrop::new(
1186 (0..len)
1187 .map(|_| PanicOnFirstDrop {
1188 panicked: std::rc::Rc::clone(&panicked),
1189 })
1190 .collect(),
1191 )
1192 }
1193
1194 #[test]
1195 fn test_mutation_state_before_unwind_compact_vec_clear() {
1196 let mut vec = panic_drop_vec(3);
1197 let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| vec.clear()));
1198
1199 assert!(result.is_err());
1200 assert_eq!(vec.len(), 0, "clear must publish empty state before Drop");
1201 }
1202
1203 #[test]
1204 fn test_mutation_state_before_unwind_compact_vec_truncate() {
1205 let mut vec = panic_drop_vec(3);
1206 let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| vec.truncate(1)));
1207
1208 assert!(result.is_err());
1209 assert_eq!(vec.len(), 1, "truncate must publish new length before Drop");
1210 }
1211
1212 #[test]
1213 fn test_mutation_state_before_unwind_compact_vec_retain() {
1214 let mut vec: CompactVec<i32> = [0, 1, 2].into_iter().collect();
1215 let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
1216 vec.retain(|value| match *value {
1217 0 => false,
1218 1 => panic!("intentional predicate panic"),
1219 _ => true,
1220 });
1221 }));
1222
1223 assert!(result.is_err());
1224 assert_eq!(vec.as_slice(), &[1, 2]);
1225 }
1226
1227 #[test]
1228 fn test_size() {
1229 assert_eq!(std::mem::size_of::<CompactVec<u8>>(), 16);
1230 assert_eq!(std::mem::size_of::<CompactVec<u64>>(), 16);
1231 assert_eq!(std::mem::size_of::<Vec<u8>>(), 24);
1232 }
1233
1234 #[test]
1235 fn test_basic_operations() {
1236 let mut vec = CompactVec::new();
1237 assert!(vec.is_empty());
1238 assert_eq!(vec.len(), 0);
1239
1240 vec.push(1);
1241 vec.push(2);
1242 vec.push(3);
1243
1244 assert_eq!(vec.len(), 3);
1245 assert_eq!(vec[0], 1);
1246 assert_eq!(vec[1], 2);
1247 assert_eq!(vec[2], 3);
1248
1249 assert_eq!(vec.pop(), Some(3));
1250 assert_eq!(vec.len(), 2);
1251 }
1252
1253 #[test]
1254 fn test_with_capacity() {
1255 let vec: CompactVec<i32> = CompactVec::with_capacity(100);
1256 assert!(vec.is_empty());
1257 assert!(vec.capacity() >= 100);
1258 }
1259
1260 #[cfg(target_pointer_width = "64")]
1261 #[test]
1262 fn test_capacity_above_u32_is_rejected_without_allocation() {
1263 let unrepresentable = u32::MAX as usize + 1;
1264
1265 assert!(std::panic::catch_unwind(|| {
1266 let _ = CompactVec::<()>::with_capacity(unrepresentable);
1267 })
1268 .is_err());
1269
1270 assert!(std::panic::catch_unwind(|| {
1271 let mut vec = CompactVec::<()>::new();
1272 vec.reserve(unrepresentable);
1273 })
1274 .is_err());
1275
1276 assert_eq!(Vec::<()>::new().capacity(), usize::MAX);
1277 let compact = CompactVec::from_vec(Vec::<()>::new());
1278 assert!(compact.is_empty());
1279 }
1280
1281 #[test]
1282 fn zst_capacity_conversion_and_growth_are_allocation_free() {
1283 let mut compact = CompactVec::<()>::with_capacity(2);
1284 assert_eq!(compact.capacity(), 2);
1285 compact.push(());
1286 compact.push(());
1287 compact.push(());
1288 assert_eq!(compact.len(), 3);
1289 assert!(compact.capacity() >= 3);
1290
1291 let standard = compact.into_vec();
1292 assert_eq!(standard.len(), 3);
1293 assert_eq!(standard.capacity(), usize::MAX);
1294
1295 let round_trip = CompactVec::from_vec(standard);
1296 assert_eq!(round_trip.len(), 3);
1297 assert_eq!(round_trip.into_vec().len(), 3);
1298 }
1299
1300 #[test]
1301 fn test_clone() {
1302 let mut vec = CompactVec::new();
1303 vec.push(1);
1304 vec.push(2);
1305 vec.push(3);
1306
1307 let cloned = vec.clone();
1308 assert_eq!(vec.as_slice(), cloned.as_slice());
1309 }
1310
1311 #[test]
1312 fn test_iteration() {
1313 let mut vec = CompactVec::new();
1314 vec.push(1);
1315 vec.push(2);
1316 vec.push(3);
1317
1318 let sum: i32 = vec.iter().sum();
1319 assert_eq!(sum, 6);
1320
1321 let collected: Vec<i32> = vec.into_iter().collect();
1322 assert_eq!(collected, vec![1, 2, 3]);
1323 }
1324
1325 #[test]
1326 fn test_from_iterator() {
1327 let vec: CompactVec<i32> = (0..5).collect();
1328 assert_eq!(vec.len(), 5);
1329 assert_eq!(vec.as_slice(), &[0, 1, 2, 3, 4]);
1330 }
1331
1332 #[test]
1333 fn test_extend() {
1334 let mut vec = CompactVec::new();
1335 vec.push(1);
1336 vec.extend(vec![2, 3, 4]);
1337 assert_eq!(vec.as_slice(), &[1, 2, 3, 4]);
1338 }
1339
1340 #[test]
1341 fn test_truncate() {
1342 let mut vec: CompactVec<i32> = (0..10).collect();
1343 vec.truncate(5);
1344 assert_eq!(vec.len(), 5);
1345 assert_eq!(vec.as_slice(), &[0, 1, 2, 3, 4]);
1346 }
1347
1348 #[test]
1349 fn test_clear() {
1350 let mut vec: CompactVec<i32> = (0..10).collect();
1351 let cap = vec.capacity();
1352 vec.clear();
1353 assert!(vec.is_empty());
1354 assert_eq!(vec.capacity(), cap); }
1356
1357 #[test]
1358 fn test_swap_remove() {
1359 let mut vec = CompactVec::new();
1360 vec.push(1);
1361 vec.push(2);
1362 vec.push(3);
1363
1364 assert_eq!(vec.swap_remove(0), 1);
1365 assert_eq!(vec.as_slice(), &[3, 2]);
1366 }
1367
1368 #[test]
1369 fn test_into_vec_and_back() {
1370 let compact: CompactVec<i32> = (0..5).collect();
1371 let std_vec: Vec<i32> = compact.into_vec();
1372 assert_eq!(std_vec, vec![0, 1, 2, 3, 4]);
1373
1374 let compact_again = CompactVec::from_vec(std_vec);
1375 assert_eq!(compact_again.as_slice(), &[0, 1, 2, 3, 4]);
1376 }
1377
1378 #[test]
1379 fn test_with_strings() {
1380 let mut vec = CompactVec::new();
1381 vec.push(String::from("hello"));
1382 vec.push(String::from("world"));
1383
1384 assert_eq!(vec[0], "hello");
1385 assert_eq!(vec[1], "world");
1386
1387 let cloned = vec.clone();
1388 assert_eq!(cloned[0], "hello");
1389 }
1390
1391 #[test]
1393 fn test_clone_panic_safety() {
1394 use std::sync::atomic::{AtomicUsize, Ordering};
1395
1396 static DROP_COUNT: AtomicUsize = AtomicUsize::new(0);
1397 static CLONE_COUNT: AtomicUsize = AtomicUsize::new(0);
1398
1399 #[derive(Debug)]
1400 struct PanicOnThirdClone(usize);
1401
1402 impl Clone for PanicOnThirdClone {
1403 fn clone(&self) -> Self {
1404 let count = CLONE_COUNT.fetch_add(1, Ordering::SeqCst);
1405 if count == 2 {
1406 panic!("Intentional panic on third clone");
1407 }
1408 PanicOnThirdClone(self.0)
1409 }
1410 }
1411
1412 impl Drop for PanicOnThirdClone {
1413 fn drop(&mut self) {
1414 DROP_COUNT.fetch_add(1, Ordering::SeqCst);
1415 }
1416 }
1417
1418 DROP_COUNT.store(0, Ordering::SeqCst);
1420 CLONE_COUNT.store(0, Ordering::SeqCst);
1421
1422 let mut vec = CompactVec::new();
1423 vec.push(PanicOnThirdClone(1));
1424 vec.push(PanicOnThirdClone(2));
1425 vec.push(PanicOnThirdClone(3));
1426 vec.push(PanicOnThirdClone(4));
1427
1428 let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
1430 let _cloned = vec.clone();
1431 }));
1432
1433 assert!(result.is_err(), "Should have panicked");
1434
1435 let drops_from_cleanup = DROP_COUNT.load(Ordering::SeqCst);
1438 assert_eq!(
1439 drops_from_cleanup, 2,
1440 "Should have dropped 2 successfully cloned elements, got {}",
1441 drops_from_cleanup
1442 );
1443
1444 drop(vec);
1446 let total_drops = DROP_COUNT.load(Ordering::SeqCst);
1447 assert_eq!(
1448 total_drops, 6,
1449 "Total drops should be 6 (2 from cleanup + 4 from original), got {}",
1450 total_drops
1451 );
1452 }
1453
1454 #[test]
1456 fn test_extend_clone_panic_safety() {
1457 use std::sync::atomic::{AtomicUsize, Ordering};
1458
1459 static DROP_COUNT: AtomicUsize = AtomicUsize::new(0);
1460 static CLONE_COUNT: AtomicUsize = AtomicUsize::new(0);
1461
1462 #[derive(Debug)]
1463 struct PanicOnThirdClone(usize);
1464
1465 impl Clone for PanicOnThirdClone {
1466 fn clone(&self) -> Self {
1467 let count = CLONE_COUNT.fetch_add(1, Ordering::SeqCst);
1468 if count == 2 {
1469 panic!("Intentional panic on third clone");
1470 }
1471 PanicOnThirdClone(self.0)
1472 }
1473 }
1474
1475 impl Drop for PanicOnThirdClone {
1476 fn drop(&mut self) {
1477 DROP_COUNT.fetch_add(1, Ordering::SeqCst);
1478 }
1479 }
1480
1481 DROP_COUNT.store(0, Ordering::SeqCst);
1483 CLONE_COUNT.store(0, Ordering::SeqCst);
1484
1485 let source = [
1487 PanicOnThirdClone(1),
1488 PanicOnThirdClone(2),
1489 PanicOnThirdClone(3),
1490 PanicOnThirdClone(4),
1491 ];
1492
1493 let mut vec: CompactVec<PanicOnThirdClone> = CompactVec::new();
1494
1495 let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
1497 vec.extend_clone(&source);
1498 }));
1499
1500 assert!(result.is_err(), "Should have panicked");
1501
1502 assert_eq!(
1505 vec.len(),
1506 2,
1507 "Guard should have set length to 2 (elements cloned before panic)"
1508 );
1509
1510 drop(vec);
1512 let drops_after_vec_drop = DROP_COUNT.load(Ordering::SeqCst);
1513 assert_eq!(
1514 drops_after_vec_drop, 2,
1515 "Should have dropped 2 successfully cloned elements when vec dropped, got {}",
1516 drops_after_vec_drop
1517 );
1518
1519 drop(source);
1521 let total_drops = DROP_COUNT.load(Ordering::SeqCst);
1522 assert_eq!(
1523 total_drops, 6,
1524 "Total drops should be 6 (2 from vec + 4 from source), got {}",
1525 total_drops
1526 );
1527 }
1528
1529 #[test]
1531 fn test_from_iter_panic_safety() {
1532 use std::sync::atomic::{AtomicUsize, Ordering};
1533
1534 static DROP_COUNT: AtomicUsize = AtomicUsize::new(0);
1535
1536 #[derive(Debug)]
1537 #[allow(dead_code)] struct PanicOnThirdNext(usize);
1539
1540 impl Drop for PanicOnThirdNext {
1541 fn drop(&mut self) {
1542 DROP_COUNT.fetch_add(1, Ordering::SeqCst);
1543 }
1544 }
1545
1546 struct PanickingIter {
1548 current: usize,
1549 max: usize,
1550 }
1551
1552 impl Iterator for PanickingIter {
1553 type Item = PanicOnThirdNext;
1554
1555 fn next(&mut self) -> Option<Self::Item> {
1556 if self.current >= self.max {
1557 return None;
1558 }
1559 self.current += 1;
1560 if self.current == 3 {
1561 panic!("Intentional panic on third next()");
1562 }
1563 Some(PanicOnThirdNext(self.current))
1564 }
1565
1566 fn size_hint(&self) -> (usize, Option<usize>) {
1567 let remaining = self.max - self.current;
1568 (remaining, Some(remaining))
1569 }
1570 }
1571
1572 impl ExactSizeIterator for PanickingIter {}
1573
1574 DROP_COUNT.store(0, Ordering::SeqCst);
1576
1577 let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
1579 let _vec: CompactVec<PanicOnThirdNext> = PanickingIter { current: 0, max: 5 }.collect();
1580 }));
1581
1582 assert!(result.is_err(), "Should have panicked");
1583
1584 let drops_after_panic = DROP_COUNT.load(Ordering::SeqCst);
1586 assert_eq!(
1587 drops_after_panic, 2,
1588 "Should have dropped 2 successfully written elements, got {}",
1589 drops_after_panic
1590 );
1591 }
1592}