Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 48 additions & 30 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ where R: core::ops::RangeBounds<usize> {
#[repr(C)]
pub struct SmallVec<T, const N: usize, A: Allocator = Global> {
len: TaggedLen<T>,
raw: RawSmallVec<T, N, A>
raw: RawSmallVec<T, N>,
allocator: A
}

unsafe impl<T: Send, const N: usize, A: Allocator + Send> Send for SmallVec<T, N, A> {}
Expand Down Expand Up @@ -252,7 +253,8 @@ pub struct IntoIter<T, const N: usize, A: Allocator = Global> {
// `end` decides whether the data lives on the heap or not
//
// The members from begin..end are initialized
raw: RawSmallVec<T, N, A>,
raw: RawSmallVec<T, N>,
allocator: A,
begin: usize,
end: TaggedLen<T>
}
Expand Down Expand Up @@ -371,7 +373,8 @@ impl<T, const N: usize> SmallVec<T, N> {
// SAFETY: all the members in 0..S are initialized
Self {
len: TaggedLen::new(S, false),
raw: RawSmallVec::new_inline(buf, Global)
raw: RawSmallVec::new_inline(buf),
allocator: Global
}
}

Expand All @@ -381,7 +384,8 @@ impl<T, const N: usize> SmallVec<T, N> {
// SAFETY: all the members in 0..len are initialized
let mut vec = Self {
len: TaggedLen::new(len, false),
raw: RawSmallVec::new_inline(MaybeUninit::new(buf), Global)
raw: RawSmallVec::new_inline(MaybeUninit::new(buf)),
allocator: Global
};
// Deallocate the remaining elements so no memory is leaked.
unsafe {
Expand Down Expand Up @@ -427,7 +431,8 @@ impl<T, const N: usize> SmallVec<T, N> {
debug_assert!(len <= N);
Self {
len: TaggedLen::new(len, false),
raw: RawSmallVec::new_inline(buf, Global)
raw: RawSmallVec::new_inline(buf),
allocator: Global
}
}

Expand All @@ -452,7 +457,8 @@ impl<T, const N: usize> SmallVec<T, N> {
unsafe { vec.set_len(0) };
Self {
len: TaggedLen::new(len, false),
raw: RawSmallVec::new(Global)
raw: RawSmallVec::new(),
allocator: Global
}
} else {
let mut vec = ManuallyDrop::new(vec);
Expand All @@ -464,7 +470,8 @@ impl<T, const N: usize> SmallVec<T, N> {

Self {
len: TaggedLen::new(len, true),
raw: RawSmallVec::new_heap(ptr, cap, Global)
raw: RawSmallVec::new_heap(ptr, cap),
allocator: Global
}
}
}
Expand Down Expand Up @@ -556,7 +563,8 @@ impl<T, const N: usize> SmallVec<T, N> {

SmallVec {
len: TaggedLen::new(length, true),
raw: RawSmallVec::new_heap(ptr, capacity, Global)
raw: RawSmallVec::new_heap(ptr, capacity),
allocator: Global
}
}
}
Expand Down Expand Up @@ -623,7 +631,7 @@ impl<T, const N: usize, A: Allocator> SmallVec<T, N, A> {

#[inline]
pub const fn inline_size() -> usize {
RawSmallVec::<T, N, A>::INLINE_CAP
RawSmallVec::<T, N>::INLINE_CAP
}

#[inline]
Expand Down Expand Up @@ -885,7 +893,10 @@ impl<T, const N: usize, A: Allocator> SmallVec<T, N, A> {

if new_capacity > Self::inline_size() {
// SAFETY: we checked all the preconditions
let result = unsafe { self.raw.try_grow_raw(self.len, new_capacity) };
let result = unsafe {
self.raw
.try_grow_raw(self.len, new_capacity, &self.allocator)
};

if result.is_ok() {
// SAFETY: the allocation succeeded, so self.raw.heap is now
Expand All @@ -898,7 +909,7 @@ impl<T, const N: usize, A: Allocator> SmallVec<T, N, A> {
if on_heap {
unsafe {
// SAFETY: heap member is active
let (ptr, old_cap) = self.raw.inner.heap;
let (ptr, old_cap) = self.raw.heap;
// inline member is now active

// SAFETY: len <= new_capacity <= Self::inline_size()
Expand All @@ -908,7 +919,7 @@ impl<T, const N: usize, A: Allocator> SmallVec<T, N, A> {
ptr: ptr.cast(),
size_bytes: old_cap * size_of::<T>(),
align: align_of::<T>(),
alloc: &self.raw.alloc
alloc: &self.allocator
});
self.set_inline();
}
Expand Down Expand Up @@ -980,10 +991,10 @@ impl<T, const N: usize, A: Allocator> SmallVec<T, N, A> {
if len <= Self::inline_size() {
// SAFETY: on_heap is true, so we're on the heap
unsafe {
let (ptr, capacity) = self.raw.inner.heap;
let (ptr, capacity) = self.raw.heap;
copy_nonoverlapping(ptr.as_ptr(), self.raw.as_mut_ptr_inline(), len);
self.set_inline();
self.raw.alloc.deallocate(
self.allocator.deallocate(
ptr.cast(),
Layout::from_size_align_unchecked(capacity * size_of::<T>(), align_of::<T>())
);
Expand All @@ -994,7 +1005,7 @@ impl<T, const N: usize, A: Allocator> SmallVec<T, N, A> {
// T can't be a ZST because SmallVec<ZST, N> is never spilled.
unsafe {
self.raw
.try_grow_raw(self.len, len)
.try_grow_raw(self.len, len, &self.allocator)
.unwrap_or_else(SmallVecError::handle)
};
}
Expand All @@ -1007,16 +1018,16 @@ impl<T, const N: usize, A: Allocator> SmallVec<T, N, A> {
return;
}
// SAFETY: the vector is on the heap
let capacity = unsafe { self.raw.inner.heap.1 };
let capacity = unsafe { self.raw.heap.1 };
if capacity > min_capacity {
let target = core::cmp::max(len, min_capacity);
if target <= Self::inline_size() {
// SAFETY: on_heap is true, so we're on the heap
unsafe {
let (ptr, capacity) = self.raw.inner.heap;
let (ptr, capacity) = self.raw.heap;
copy_nonoverlapping(ptr.as_ptr(), self.raw.as_mut_ptr_inline(), len);
self.set_inline();
self.raw.alloc.deallocate(
self.allocator.deallocate(
ptr.cast(),
Layout::from_size_align_unchecked(
capacity * size_of::<T>(),
Expand All @@ -1030,7 +1041,7 @@ impl<T, const N: usize, A: Allocator> SmallVec<T, N, A> {
// T can't be a ZST because SmallVec<ZST, N> is never spilled.
unsafe {
self.raw
.try_grow_raw(self.len, target)
.try_grow_raw(self.len, target, &self.allocator)
.unwrap_or_else(SmallVecError::handle)
};
}
Expand Down Expand Up @@ -1226,7 +1237,7 @@ impl<T, const N: usize, A: Allocator> SmallVec<T, N, A> {
// - the first `len` entries are proper `T`-values
// - the allocation is not larger than `isize::MAX`
unsafe {
let (ptr, cap) = this.raw.inner.heap;
let (ptr, cap) = this.raw.heap;
Vec::from_raw_parts(ptr.as_ptr(), len, cap)
}
}
Expand Down Expand Up @@ -1577,15 +1588,19 @@ impl<T, const N: usize, A: Allocator> SmallVec<T, N, A> {
pub const fn new_in(alloc: A) -> SmallVec<T, N, A> {
Self {
len: TaggedLen::new(0, false),
raw: RawSmallVec::new(alloc)
raw: RawSmallVec::new(),
allocator: alloc
}
}

pub fn try_with_capacity_in(capacity: usize, alloc: A) -> Result<Self, SmallVecError> {
let mut this = Self::new_in(alloc);
if capacity > Self::inline_size() && !Self::IS_ZST {
// SAFETY: we checked all the preconditions
unsafe { this.raw.try_grow_raw(TaggedLen::new(0, false), capacity) }?;
unsafe {
this.raw
.try_grow_raw(TaggedLen::new(0, false), capacity, &this.allocator)
}?;

// SAFETY: the allocation succeeded, so self.raw.heap is now active
unsafe { this.set_on_heap() };
Expand Down Expand Up @@ -1671,7 +1686,7 @@ impl<T, const N: usize, A: Allocator + Clone> SmallVec<T, N, A> {
assert!(at <= len);

let other_len = len - at;
let mut other = Self::with_capacity_in(other_len, self.raw.alloc.clone());
let mut other = Self::with_capacity_in(other_len, self.allocator.clone());

// Unsafely `set_len` and copy items to `other`.
unsafe {
Expand Down Expand Up @@ -1726,12 +1741,12 @@ impl<T, const N: usize, A: Allocator> Drop for SmallVec<T, N, A> {
// SAFETY: see above
unsafe {
let _drop_dealloc = if on_heap {
let capacity = self.raw.inner.heap.1;
let capacity = self.raw.heap.1;
Some(DropDealloc {
ptr: NonNull::new_unchecked(ptr as *mut u8),
size_bytes: capacity * size_of::<T>(),
align: align_of::<T>(),
alloc: &self.raw.alloc
alloc: &self.allocator
})
} else {
None
Expand All @@ -1749,12 +1764,12 @@ impl<T, const N: usize, A: Allocator> Drop for IntoIter<T, N, A> {
let begin = self.begin;
let ptr = self.raw.as_mut_ptr(on_heap);
let _drop_dealloc = if on_heap {
let capacity = self.raw.inner.heap.1;
let capacity = self.raw.heap.1;
Some(DropDealloc {
ptr: NonNull::new_unchecked(ptr as *mut u8),
size_bytes: capacity * size_of::<T>(),
align: align_of::<T>(),
alloc: &self.raw.alloc
alloc: &self.allocator
})
} else {
None
Expand Down Expand Up @@ -1962,7 +1977,8 @@ impl<T: Clone, const N: usize, A: Allocator + Clone> Clone for SmallVec<T, N, A>
fn clone(&self) -> SmallVec<T, N, A> {
let mut vec = SmallVec {
len: TaggedLen::new(0, false),
raw: RawSmallVec::new(self.raw.alloc.clone())
raw: RawSmallVec::new(),
allocator: self.allocator.clone()
};

vec.extend(self);
Expand All @@ -1989,7 +2005,8 @@ impl<T: Clone, const N: usize, A: Allocator + Clone> Clone for IntoIter<T, N, A>
fn clone(&self) -> IntoIter<T, N, A> {
let mut vec = SmallVec {
len: TaggedLen::new(0, false),
raw: RawSmallVec::new(self.raw.alloc.clone())
raw: RawSmallVec::new(),
allocator: self.allocator.clone()
};

vec.extend(self.as_slice());
Expand Down Expand Up @@ -2055,7 +2072,8 @@ impl<T, const N: usize, A: Allocator> IntoIterator for SmallVec<T, N, A> {
// the elements
let this = ManuallyDrop::new(self);
IntoIter {
raw: (&this.raw as *const RawSmallVec<T, N, A>).read(),
raw: (&raw const this.raw).read(),
allocator: (&raw const this.allocator).read(),
begin: 0,
end: this.len
}
Expand Down
Loading
Loading