1#![allow(unsafe_code)]
6#![warn(missing_docs)]
7use core::fmt::Debug;
8use core::mem::MaybeUninit;
9use core::ops::Deref;
10use core::ptr::NonNull;
11
12use portable_atomic as atomic;
13
14#[repr(C)]
15struct SharedVectorHeader {
16 refcount: atomic::AtomicIsize,
17 size: usize,
18 capacity: usize,
19}
20
21#[repr(C)]
22struct SharedVectorInner<T> {
23 header: SharedVectorHeader,
24 data: MaybeUninit<T>,
25}
26
27fn compute_inner_layout<T>(capacity: usize) -> core::alloc::Layout {
28 core::alloc::Layout::new::<SharedVectorHeader>()
29 .extend(core::alloc::Layout::array::<T>(capacity).unwrap())
30 .unwrap()
31 .0
32}
33
34fn data_ptr<T>(inner: NonNull<SharedVectorInner<T>>) -> *mut T {
39 unsafe { &raw mut (*inner.as_ptr()).data as *mut T }
41}
42
43unsafe fn drop_inner<T>(inner: NonNull<SharedVectorInner<T>>) {
46 unsafe {
47 debug_assert_eq!((*inner.as_ptr()).header.refcount.load(atomic::Ordering::Relaxed), 0);
48 let data = data_ptr(inner);
49 let size = (*inner.as_ptr()).header.size;
50 for x in 0..size {
51 core::ptr::drop_in_place(data.add(x));
52 }
53 alloc::alloc::dealloc(
54 inner.as_ptr() as *mut u8,
55 compute_inner_layout::<T>((*inner.as_ptr()).header.capacity),
56 )
57 }
58}
59
60fn alloc_with_capacity<T>(capacity: usize) -> NonNull<SharedVectorInner<T>> {
62 let ptr = unsafe { ::alloc::alloc::alloc(compute_inner_layout::<T>(capacity)) };
63 assert!(!ptr.is_null(), "allocation of {capacity:?} bytes failed");
64 unsafe {
65 core::ptr::write(
66 ptr as *mut SharedVectorHeader,
67 SharedVectorHeader { refcount: 1.into(), size: 0, capacity },
68 );
69 }
70 NonNull::new(ptr).unwrap().cast()
71}
72
73fn capacity_for_grow(current_cap: usize, required_cap: usize, elem_size: usize) -> usize {
76 if current_cap >= required_cap {
77 return current_cap;
78 }
79 let cap = core::cmp::max(current_cap * 2, required_cap);
80 let min_non_zero_cap = if elem_size == 1 {
81 8
82 } else if elem_size <= 1024 {
83 4
84 } else {
85 1
86 };
87 core::cmp::max(min_non_zero_cap, cap)
88}
89
90#[repr(C)]
91pub struct SharedVector<T> {
93 inner: NonNull<SharedVectorInner<T>>,
94}
95
96unsafe impl<T: Send + Sync> Send for SharedVector<T> {}
98unsafe impl<T: Send + Sync> Sync for SharedVector<T> {}
100
101impl<T> Drop for SharedVector<T> {
102 fn drop(&mut self) {
103 unsafe {
105 let header = &raw const (*self.inner.as_ptr()).header;
106 if (*header).refcount.load(atomic::Ordering::Relaxed) < 0 {
107 return;
108 }
109 if (*header).refcount.fetch_sub(1, atomic::Ordering::SeqCst) == 1 {
110 drop_inner(self.inner)
111 }
112 }
113 }
114}
115
116impl<T> Clone for SharedVector<T> {
117 fn clone(&self) -> Self {
118 unsafe {
120 let header = &raw const (*self.inner.as_ptr()).header;
121 if (*header).refcount.load(atomic::Ordering::Relaxed) > 0 {
122 (*header).refcount.fetch_add(1, atomic::Ordering::SeqCst);
123 }
124 SharedVector { inner: self.inner }
125 }
126 }
127}
128
129impl<T> SharedVector<T> {
130 pub fn with_capacity(capacity: usize) -> Self {
132 Self { inner: alloc_with_capacity(capacity) }
133 }
134
135 fn as_ptr(&self) -> *const T {
136 data_ptr(self.inner)
137 }
138
139 pub fn len(&self) -> usize {
141 unsafe { (*self.inner.as_ptr()).header.size }
143 }
144
145 pub fn is_empty(&self) -> bool {
147 self.len() == 0
148 }
149
150 pub fn as_slice(&self) -> &[T] {
152 if self.is_empty() {
153 &[]
154 } else {
155 unsafe { core::slice::from_raw_parts(self.as_ptr(), self.len()) }
157 }
158 }
159
160 fn capacity(&self) -> usize {
162 unsafe { (*self.inner.as_ptr()).header.capacity }
164 }
165}
166
167impl<T: Clone + PartialEq> SharedVector<T> {
168 pub(crate) fn replace_range(&mut self, from: &[T], to: &[T], mut count: usize) {
171 if from.is_empty() || count == 0 || from.len() != to.len() {
172 return;
173 }
174 let s = self.make_mut_slice();
175 if s.len() < from.len() {
176 return;
177 }
178
179 let mut index = 0;
180 let from_len = from.len();
181 let max_start = s.len() - from_len;
182
183 while index <= max_start && count > 0 {
184 if s[index..index + from_len] == *from {
185 for (dst, src) in s[index..index + from_len].iter_mut().zip(to.iter()) {
186 *dst = src.clone();
187 }
188 count -= 1;
189 index += from_len;
190 } else {
191 index += 1;
192 }
193 }
194 }
195}
196
197impl<T: Clone> SharedVector<T> {
198 pub fn from_slice(slice: &[T]) -> SharedVector<T> {
200 Self::from(slice)
201 }
202
203 fn detach(&mut self, new_capacity: usize) {
206 let is_shared =
209 unsafe { (*self.inner.as_ptr()).header.refcount.load(atomic::Ordering::Acquire) } != 1;
210 if !is_shared && new_capacity <= self.capacity() {
211 return;
212 }
213 let mut new_array = SharedVector::with_capacity(new_capacity);
214 core::mem::swap(&mut self.inner, &mut new_array.inner);
215 let mut size = 0;
216 for x in new_array.into_iter() {
217 assert_ne!(size, new_capacity);
218 unsafe {
219 core::ptr::write(data_ptr(self.inner).add(size), x);
220 size += 1;
221 (*self.inner.as_ptr()).header.size = size;
222 }
223 if size == new_capacity {
224 break;
225 }
226 }
227 }
228
229 pub fn make_mut_slice(&mut self) -> &mut [T] {
231 self.detach(self.len());
232 unsafe { core::slice::from_raw_parts_mut(self.as_ptr() as *mut T, self.len()) }
233 }
234
235 pub fn push(&mut self, value: T) {
237 self.detach(capacity_for_grow(self.capacity(), self.len() + 1, core::mem::size_of::<T>()));
238 unsafe {
240 let size = (*self.inner.as_ptr()).header.size;
241 core::ptr::write(data_ptr(self.inner).add(size), value);
242 (*self.inner.as_ptr()).header.size = size + 1;
243 }
244 }
245
246 pub fn remove(&mut self, row: usize) -> T {
251 let len = self.len();
252 if row >= len {
253 panic!("removal index (is {row}) should be < len (is {len})");
254 }
255 self.detach(len);
256 unsafe {
257 let data = data_ptr(self.inner);
258 let value = core::ptr::read(data.add(row));
259 let size = (*self.inner.as_ptr()).header.size;
260 core::ptr::copy(data.add(row + 1), data.add(row), size - 1 - row);
261 (*self.inner.as_ptr()).header.size = size - 1;
262 value
263 }
264 }
265
266 pub fn insert(&mut self, row: usize, value: T) {
271 let len = self.len();
272 if row > len {
273 panic!("insertion index (is {row}) should be <= len (is {len})");
274 }
275 self.detach(capacity_for_grow(self.capacity(), self.len() + 1, core::mem::size_of::<T>()));
276 unsafe {
277 let data = data_ptr(self.inner);
278 let size = (*self.inner.as_ptr()).header.size;
279 core::ptr::copy(data.add(row), data.add(row + 1), size - row);
280 core::ptr::write(data.add(row), value);
281 (*self.inner.as_ptr()).header.size = size + 1;
282 }
283 }
284
285 pub fn pop(&mut self) -> Option<T> {
288 if self.is_empty() {
289 None
290 } else {
291 self.detach(self.len());
292 unsafe {
294 let size = (*self.inner.as_ptr()).header.size - 1;
295 (*self.inner.as_ptr()).header.size = size;
296 Some(core::ptr::read(data_ptr(self.inner).add(size)))
297 }
298 }
299 }
300
301 pub fn resize(&mut self, new_len: usize, value: T) {
314 if self.len() == new_len {
315 return;
316 }
317 self.detach(new_len);
318 let header = unsafe { &mut (*self.inner.as_ptr()).header };
320
321 if header.size >= new_len {
322 self.shrink(new_len);
323 } else {
324 let data_ptr = data_ptr(self.inner);
325 while header.size < new_len {
326 unsafe {
328 core::ptr::write(data_ptr.add(header.size), value.clone());
329 }
330 header.size += 1;
331 }
332 }
333 }
334
335 fn shrink(&mut self, new_len: usize) {
336 if self.len() == new_len {
337 return;
338 }
339
340 assert!(
341 unsafe { (*self.inner.as_ptr()).header.refcount.load(atomic::Ordering::Relaxed) } == 1
342 );
343 let header = unsafe { &mut (*self.inner.as_ptr()).header };
345 let data_ptr = data_ptr(self.inner);
346
347 while header.size > new_len {
348 header.size -= 1;
349 unsafe {
351 core::ptr::drop_in_place(data_ptr.add(header.size));
352 }
353 }
354 }
355
356 pub fn clear(&mut self) {
358 let is_shared =
359 unsafe { (*self.inner.as_ptr()).header.refcount.load(atomic::Ordering::Acquire) } != 1;
360 if is_shared {
361 *self = SharedVector::default();
362 } else {
363 self.shrink(0)
364 }
365 }
366
367 pub fn reserve(&mut self, additional: usize) {
369 self.detach((self.len() + additional).max(self.capacity()))
370 }
371}
372
373impl<T> Deref for SharedVector<T> {
374 type Target = [T];
375 fn deref(&self) -> &Self::Target {
376 self.as_slice()
377 }
378}
379
380impl<T: Clone> From<&[T]> for SharedVector<T> {
388 fn from(slice: &[T]) -> Self {
389 let capacity = slice.len();
390 let result = Self::with_capacity(capacity);
391 for x in slice {
392 unsafe {
393 let size = (*result.inner.as_ptr()).header.size;
394 core::ptr::write(data_ptr(result.inner).add(size), x.clone());
395 (*result.inner.as_ptr()).header.size = size + 1;
396 }
397 }
398 result
399 }
400}
401
402impl<T, const N: usize> From<[T; N]> for SharedVector<T> {
403 fn from(array: [T; N]) -> Self {
404 array.into_iter().collect()
405 }
406}
407
408impl<T> FromIterator<T> for SharedVector<T> {
409 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
410 let mut iter = iter.into_iter();
411 let mut capacity = iter.size_hint().0;
412 let mut result = Self::with_capacity(capacity);
413 let mut size = 0;
414 while let Some(x) = iter.next() {
415 if size >= capacity {
416 capacity = capacity_for_grow(
417 capacity,
418 size + 1 + iter.size_hint().0,
419 core::mem::size_of::<T>(),
420 );
421 unsafe {
422 (*result.inner.as_ptr()).header.refcount.store(0, atomic::Ordering::Relaxed)
423 };
424 let mut iter = IntoIter(IntoIterInner::UnShared(result.inner, 0));
425 result.inner = alloc_with_capacity::<T>(capacity);
426 match &mut iter.0 {
427 IntoIterInner::UnShared(old_inner, begin) => {
428 let old_data = data_ptr(*old_inner);
429 while *begin < size {
430 unsafe {
431 core::ptr::write(
432 data_ptr(result.inner).add(*begin),
433 core::ptr::read(old_data.add(*begin)),
434 );
435 *begin += 1;
436 (*result.inner.as_ptr()).header.size = *begin;
437 }
438 }
439 }
440 _ => unreachable!(),
441 }
442 }
443 debug_assert_eq!(result.len(), size);
444 debug_assert!(result.capacity() > size);
445 unsafe {
446 core::ptr::write(data_ptr(result.inner).add(size), x);
447 size += 1;
448 (*result.inner.as_ptr()).header.size = size;
449 }
450 }
451 result
452 }
453}
454
455impl<T: Clone> Extend<T> for SharedVector<T> {
456 fn extend<X: IntoIterator<Item = T>>(&mut self, iter: X) {
457 let iter = iter.into_iter();
458 let hint = iter.size_hint().0;
459 if hint > 0 {
460 self.detach(capacity_for_grow(
461 self.capacity(),
462 self.len() + hint,
463 core::mem::size_of::<T>(),
464 ));
465 }
466 for item in iter {
467 self.push(item);
468 }
469 }
470}
471
472#[repr(C, align(16))]
477struct SharedNull(SharedVectorHeader);
478
479static SHARED_NULL: SharedNull =
480 SharedNull(SharedVectorHeader { refcount: atomic::AtomicIsize::new(-1), size: 0, capacity: 0 });
481
482impl<T> Default for SharedVector<T> {
483 fn default() -> Self {
484 const {
485 assert!(
486 core::mem::align_of::<SharedVectorInner<T>>()
487 <= core::mem::align_of::<SharedNull>(),
488 "SharedVector element type is more aligned than the empty singleton"
489 );
490 }
491 SharedVector { inner: NonNull::from(&SHARED_NULL).cast() }
492 }
493}
494
495impl<T: Debug> Debug for SharedVector<T> {
496 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
497 self.as_slice().fmt(f)
498 }
499}
500
501impl<T> AsRef<[T]> for SharedVector<T> {
502 #[inline]
503 fn as_ref(&self) -> &[T] {
504 self.as_slice()
505 }
506}
507
508impl<T, U> PartialEq<U> for SharedVector<T>
509where
510 U: ?Sized + AsRef<[T]>,
511 T: PartialEq,
512{
513 fn eq(&self, other: &U) -> bool {
514 self.as_slice() == other.as_ref()
515 }
516}
517
518impl<T: Eq> Eq for SharedVector<T> {}
519
520impl<T: Clone> IntoIterator for SharedVector<T> {
521 type Item = T;
522 type IntoIter = IntoIter<T>;
523 fn into_iter(self) -> Self::IntoIter {
524 IntoIter(unsafe {
525 if (*self.inner.as_ptr()).header.refcount.load(atomic::Ordering::Acquire) == 1 {
526 let inner = self.inner;
527 core::mem::forget(self);
528 (*inner.as_ptr()).header.refcount.store(0, atomic::Ordering::Relaxed);
529 IntoIterInner::UnShared(inner, 0)
530 } else {
531 IntoIterInner::Shared(self, 0)
532 }
533 })
534 }
535}
536
537#[cfg(feature = "serde")]
538use serde::ser::SerializeSeq;
539#[cfg(feature = "serde")]
540impl<T> serde::Serialize for SharedVector<T>
541where
542 T: serde::Serialize,
543{
544 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
545 where
546 S: serde::Serializer,
547 {
548 let mut seq = serializer.serialize_seq(Some(self.len()))?;
549 for item in self.iter() {
550 seq.serialize_element(item)?;
551 }
552 seq.end()
553 }
554}
555
556#[cfg(feature = "serde")]
557impl<'de, T> serde::Deserialize<'de> for SharedVector<T>
558where
559 T: Clone + serde::Deserialize<'de>,
560{
561 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
562 where
563 D: serde::Deserializer<'de>,
564 {
565 let mut elements: alloc::vec::Vec<T> = serde::Deserialize::deserialize(deserializer)?;
566 let mut shared_vec = SharedVector::with_capacity(elements.len());
567 for elem in elements.drain(..) {
568 shared_vec.push(elem);
569 }
570 Ok(shared_vec)
571 }
572}
573
574enum IntoIterInner<T> {
575 Shared(SharedVector<T>, usize),
576 UnShared(NonNull<SharedVectorInner<T>>, usize),
578}
579
580impl<T> Drop for IntoIterInner<T> {
581 fn drop(&mut self) {
582 match self {
583 IntoIterInner::Shared(..) => { }
584 IntoIterInner::UnShared(inner, begin) => unsafe {
585 debug_assert_eq!(
586 (*inner.as_ptr()).header.refcount.load(atomic::Ordering::Relaxed),
587 0
588 );
589 let data_ptr = data_ptr(*inner);
590 for x in (*begin)..(*inner.as_ptr()).header.size {
591 core::ptr::drop_in_place(data_ptr.add(x));
592 }
593 ::alloc::alloc::dealloc(
594 inner.as_ptr() as *mut u8,
595 compute_inner_layout::<T>((*inner.as_ptr()).header.capacity),
596 )
597 },
598 }
599 }
600}
601
602pub struct IntoIter<T>(IntoIterInner<T>);
607
608impl<T: Clone> Iterator for IntoIter<T> {
609 type Item = T;
610
611 fn next(&mut self) -> Option<Self::Item> {
612 match &mut self.0 {
613 IntoIterInner::Shared(array, moved) => {
614 let result = array.as_slice().get(*moved).cloned();
615 *moved += 1;
616 result
617 }
618 IntoIterInner::UnShared(inner, begin) => unsafe {
619 if *begin < (*inner.as_ptr()).header.size {
620 let data_ptr = data_ptr(*inner);
621 let r = core::ptr::read(data_ptr.add(*begin));
622 *begin += 1;
623 Some(r)
624 } else {
625 None
626 }
627 },
628 }
629 }
630}
631
632#[test]
633fn simple_test() {
634 let x: SharedVector<i32> = SharedVector::from([1, 2, 3]);
635 let y: SharedVector<i32> = SharedVector::from([3, 2, 1]);
636 assert_eq!(x, x.clone());
637 assert_ne!(x, y);
638 let z: [i32; 3] = [1, 2, 3];
639 assert_eq!(z, x.as_slice());
640 let vec: std::vec::Vec<i32> = std::vec![1, 2, 3];
641 assert_eq!(x, vec);
642 let def: SharedVector<i32> = Default::default();
643 assert_eq!(def, SharedVector::<i32>::default());
644 assert_ne!(def, x);
645}
646
647#[test]
648fn push_test() {
649 let mut x: SharedVector<i32> = SharedVector::from([1, 2, 3]);
650 let y = x.clone();
651 x.push(4);
652 x.push(5);
653 x.push(6);
654 assert_eq!(x.as_slice(), &[1, 2, 3, 4, 5, 6]);
655 assert_eq!(y.as_slice(), &[1, 2, 3]);
656}
657
658#[test]
659fn remove_test() {
660 let mut x: SharedVector<i32> = SharedVector::from([1, 2, 3, 4, 5, 6]);
661 let y = x.clone();
662 assert_eq!(x.remove(0), 1);
663 assert_eq!(x.remove(1), 3);
664 x.push(42);
665 assert_eq!(x.remove(2), 5);
666 assert_eq!(x.as_slice(), &[2, 4, 6, 42]);
667 assert_eq!(y.as_slice(), &[1, 2, 3, 4, 5, 6]);
668}
669
670#[test]
671#[should_panic(expected = "removal index (is 3) should be < len (is 3)")]
672fn remove_out_of_bounds_test() {
673 let mut x: SharedVector<i32> = SharedVector::from([1, 2, 3]);
674 x.remove(3);
675}
676
677#[test]
678fn insert_test() {
679 let mut x: SharedVector<i32> = SharedVector::from([1, 2, 3]);
680 let y = x.clone();
681 x.insert(0, 42);
682 assert_eq!(x.as_slice(), &[42, 1, 2, 3]);
683 x.insert(2, 24);
684 x.insert(5, 84);
685 assert_eq!(x.as_slice(), &[42, 1, 24, 2, 3, 84]);
686 assert_eq!(y.as_slice(), &[1, 2, 3]);
687}
688
689#[test]
690#[should_panic(expected = "insertion index (is 4) should be <= len (is 3)")]
691fn insert_out_of_bounds_test() {
692 let mut x: SharedVector<i32> = SharedVector::from([1, 2, 3]);
693 x.insert(4, 42);
694}
695
696#[test]
697#[should_panic]
698#[cfg_attr(miri, ignore)] fn invalid_capacity_test() {
700 let _: SharedVector<u8> = SharedVector::with_capacity(usize::MAX / 2 - 1000);
701}
702
703#[test]
704fn collect_from_iter_with_no_size_hint() {
705 use std::string::{String, ToString};
706 struct NoSizeHintIter<'a> {
707 data: &'a [&'a str],
708 i: usize,
709 }
710
711 impl Iterator for NoSizeHintIter<'_> {
712 type Item = String;
713
714 fn next(&mut self) -> Option<Self::Item> {
715 if self.i >= self.data.len() {
716 return None;
717 }
718 let item = self.data[self.i];
719 self.i += 1;
720 Some(item.to_string())
721 }
722
723 fn size_hint(&self) -> (usize, Option<usize>) {
724 (0, None)
725 }
726 }
727
728 let input = NoSizeHintIter { data: &["Hello", "sweet", "world", "of", "iterators"], i: 0 };
730
731 let shared_vec: SharedVector<String> = input.collect();
732 assert_eq!(shared_vec.as_slice(), &["Hello", "sweet", "world", "of", "iterators"]);
733}
734
735#[test]
736fn test_capacity_grows_only_when_needed() {
737 let mut vec: SharedVector<u8> = SharedVector::with_capacity(2);
738 vec.push(0);
739 assert_eq!(vec.capacity(), 2);
740 vec.push(0);
741 assert_eq!(vec.capacity(), 2);
742 vec.push(0);
743 assert_eq!(vec.len(), 3);
744 assert!(vec.capacity() > 2);
745}
746
747#[test]
748fn test_vector_clear() {
749 let mut vec: SharedVector<std::string::String> = Default::default();
750 vec.clear();
751 vec.push("Hello".into());
752 vec.push("World".into());
753 vec.push("of".into());
754 vec.push("Vectors".into());
755
756 let mut copy = vec.clone();
757
758 assert_eq!(vec.len(), 4);
759 let orig_cap = vec.capacity();
760 assert!(orig_cap >= vec.len());
761 vec.clear();
762 assert_eq!(vec.len(), 0);
763 assert_eq!(vec.capacity(), 0); vec.push("Welcome back".into());
765 assert_eq!(vec.len(), 1);
766 assert!(vec.capacity() >= vec.len());
767
768 assert_eq!(copy.len(), 4);
769 assert_eq!(copy.capacity(), orig_cap);
770 copy.clear(); assert_eq!(copy.capacity(), orig_cap);
772}
773
774#[test]
775fn pop_test() {
776 let mut x: SharedVector<i32> = SharedVector::from([1, 2, 3]);
777 let y = x.clone();
778 assert_eq!(x.pop(), Some(3));
779 assert_eq!(x.pop(), Some(2));
780 assert_eq!(x.pop(), Some(1));
781 assert_eq!(x.pop(), None);
782 assert!(x.is_empty());
783 assert_eq!(y.as_slice(), &[1, 2, 3]);
784}
785
786#[cfg(feature = "ffi")]
787pub(crate) mod ffi {
788 use super::*;
789
790 #[unsafe(no_mangle)]
791 pub unsafe extern "C" fn slint_shared_vector_allocate(size: usize, align: usize) -> *mut u8 {
793 unsafe { alloc::alloc::alloc(alloc::alloc::Layout::from_size_align(size, align).unwrap()) }
794 }
795
796 #[unsafe(no_mangle)]
797 pub unsafe extern "C" fn slint_shared_vector_free(ptr: *mut u8, size: usize, align: usize) {
799 unsafe {
800 alloc::alloc::dealloc(ptr, alloc::alloc::Layout::from_size_align(size, align).unwrap())
801 }
802 }
803
804 #[unsafe(no_mangle)]
805 pub unsafe extern "C" fn slint_shared_vector_empty() -> *const u8 {
807 &SHARED_NULL as *const _ as *const u8
808 }
809}
810
811#[cfg(feature = "serde")]
812#[test]
813fn test_serialize_deserialize_sharedvector() {
814 let v = SharedVector::from([1, 2, 3]);
815 let serialized = serde_json::to_string(&v).unwrap();
816 let deserialized: SharedVector<i32> = serde_json::from_str(&serialized).unwrap();
817 assert_eq!(v, deserialized);
818}
819
820#[test]
821fn test_reserve() {
822 let mut v = SharedVector::from([1, 2, 3]);
823 assert_eq!(v.capacity(), 3);
824 v.reserve(1);
825 assert_eq!(v.capacity(), 4);
826 assert_eq!(v.len(), 3);
827 v.push(4);
828 v.push(5);
829 assert_eq!(v.len(), 5);
830 assert_eq!(v.capacity(), 8);
831 v.reserve(1);
832 assert_eq!(v.capacity(), 8);
833 v.reserve(8);
834 assert_eq!(v.len(), 5);
835 assert_eq!(v.capacity(), 13);
836}
837
838#[test]
839fn test_replace_range_all_matches() {
840 let mut v = SharedVector::from([1, 2, 3, 1, 2, 3, 1, 2, 3]);
841 v.replace_range(&[1, 2, 3], &[4, 5, 6], usize::MAX);
842 assert_eq!(v.as_slice(), &[4, 5, 6, 4, 5, 6, 4, 5, 6]);
843}
844
845#[test]
846fn test_replace_range_count_limit() {
847 let mut v = SharedVector::from([1, 2, 3, 1, 2, 3, 1, 2, 3]);
848 v.replace_range(&[1, 2, 3], &[4, 5, 6], 2);
849 assert_eq!(v.as_slice(), &[4, 5, 6, 4, 5, 6, 1, 2, 3]);
850}
851
852#[test]
853fn test_replace_range_non_overlapping() {
854 let mut v = SharedVector::from([1, 1, 1]);
855 v.replace_range(&[1, 1], &[2, 2], usize::MAX);
856 assert_eq!(v.as_slice(), &[2, 2, 1]);
857}
858
859#[test]
860fn test_replace_range() {
861 let mut v = SharedVector::from([1, 2, 3, 4]);
862 v.replace_range(&[2, 3, 4, 5], &[7, 8, 9, 9], 1);
863 assert_eq!(v.as_slice(), &[1, 2, 3, 4]);
864}
865
866#[test]
867fn test_aligned_element_type() {
868 #[repr(align(16))]
873 #[derive(Clone, Debug, PartialEq)]
874 struct Aligned(u8);
875
876 let mut x: SharedVector<Aligned> = Default::default();
877 assert!(x.is_empty());
878 for i in 0..8 {
879 x.push(Aligned(i));
880 }
881 let y = x.clone();
882 assert_eq!(x.pop(), Some(Aligned(7)));
883 x.resize(4, Aligned(0));
884 x.clear();
885 assert!(x.is_empty());
886 assert_eq!(y.len(), 8);
887 assert_eq!(
888 y.as_slice().iter().map(|a| a.0).collect::<std::vec::Vec<_>>(),
889 std::vec![0, 1, 2, 3, 4, 5, 6, 7]
890 );
891}