Skip to content
19 changes: 19 additions & 0 deletions src/allocator/boxed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use {
super::{
Allocator,
like::Like,
requirement::Requirement
},
core::marker::PhantomData
};

pub struct Box<Item: ?Sized, Heap: Allocator + Requirement>(PhantomData<(Heap, Item)>);

impl<Item: ?Sized, Heap: Allocator + Requirement> Like for Box<Item, Heap> {
#[cfg(not(feature = "allocator-api"))]
type Type = alloc::boxed::Box<Item>;
#[cfg(all(feature = "allocator-api", not(feature = "allocator-api2")))]
type Type = alloc::boxed::Box<Item, Heap>;
#[cfg(feature = "allocator-api2")]
type Type = allocator_api2::boxed::Box<Item, Heap>;
}
7 changes: 7 additions & 0 deletions src/allocator/global.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#[cfg(not(feature = "allocator-api"))]
#[derive(Clone)]
pub struct Global;
#[cfg(all(feature = "allocator-api", not(feature = "allocator-api2")))]
pub use alloc::alloc::Global;
#[cfg(feature = "allocator-api2")]
pub use allocator_api2::alloc::Global;
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use {
super::Allocator,
super::super::{
Allocator,
global::Global
},
alloc::alloc::{
alloc,
dealloc,
Expand All @@ -11,9 +14,6 @@ use {
}
};

#[derive(Clone)]
pub struct Global;

impl Allocator for Global {
#[inline]
fn allocate(&self, layout: Layout) -> Option<NonNull<[u8]>> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use {
super::Allocator,
super::super::Allocator,
allocator_api2::alloc::Allocator as External,
core::{
alloc::Layout,
Expand Down
6 changes: 6 additions & 0 deletions src/allocator/implementations/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#[cfg(not(feature = "allocator-api"))]
mod base;
#[cfg(feature = "allocator-api2")]
mod external;
#[cfg(all(feature = "allocator-api", not(feature = "allocator-api2")))]
mod native;
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use {
super::Allocator,
super::super::Allocator,
alloc::alloc::Allocator as Native,
core::{
alloc::Layout,
Expand Down
3 changes: 3 additions & 0 deletions src/allocator/like.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub trait Like {
type Type;
}
39 changes: 6 additions & 33 deletions src/allocator/mod.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,16 @@
#[cfg(not(feature = "allocator-api"))]
mod base;
#[cfg(feature = "allocator-api2")]
mod external;
#[cfg(all(feature = "allocator-api", not(feature = "allocator-api2")))]
mod native;
pub mod boxed;
pub mod global;
mod implementations;
pub mod like;
pub mod proxy;
mod requirement;
pub mod vec;

use core::{
alloc::Layout,
ptr::NonNull
};

#[cfg(not(feature = "allocator-api"))]
#[rustfmt::skip]
pub use {
alloc::{
boxed::Box,
vec::Vec,
vec
},
base::Global
};
#[cfg(feature = "allocator-api2")]
#[rustfmt::skip]
pub use allocator_api2::{
alloc::Global,
boxed::Box,
vec::Vec,
vec
};
#[cfg(all(feature = "allocator-api", not(feature = "allocator-api2")))]
#[rustfmt::skip]
pub use alloc::{
alloc::Global,
boxed::Box,
vec::Vec,
vec
};

pub trait Allocator {
fn allocate(&self, layout: Layout) -> Option<NonNull<[u8]>>;
unsafe fn deallocate(&self, pointer: NonNull<u8>, layout: Layout);
Expand Down
6 changes: 6 additions & 0 deletions src/allocator/requirement.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#[cfg(all(feature = "allocator-api", not(feature = "allocator-api2")))]
pub use alloc::alloc::Allocator as Requirement;
#[cfg(feature = "allocator-api2")]
pub use allocator_api2::alloc::Allocator as Requirement;
#[cfg(not(feature = "allocator-api"))]
pub use core::marker::Sized as Requirement;
23 changes: 23 additions & 0 deletions src/allocator/vec.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#[cfg(not(feature = "allocator-api2"))]
pub use alloc::vec;
#[cfg(feature = "allocator-api2")]
pub use allocator_api2::vec;
use {
super::{
Allocator,
like::Like,
requirement::Requirement
},
core::marker::PhantomData
};

pub struct Vec<Item, Heap: Allocator + Requirement>(PhantomData<(Heap, Item)>);

impl<Item, Heap: Allocator + Requirement> Like for Vec<Item, Heap> {
#[cfg(not(feature = "allocator-api"))]
type Type = alloc::vec::Vec<Item>;
#[cfg(all(feature = "allocator-api", not(feature = "allocator-api2")))]
type Type = alloc::vec::Vec<Item, Heap>;
#[cfg(feature = "allocator-api2")]
type Type = allocator_api2::vec::Vec<Item, Heap>;
}
21 changes: 11 additions & 10 deletions src/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use {
Box,
Global,
SmallVec,
Vec
Vec,
allocator::like::Like
},
core::{
mem::ManuallyDrop,
Expand All @@ -17,7 +18,7 @@ impl<T: Clone, const N: usize> From<&[T]> for SmallVec<T, N, Global> {
fn from(slice: &[T]) -> Self {
if slice.len() > Self::inline_size() {
// Standard Rust vectors are already specialized.
Self::from_vec(Vec::from(slice))
Self::from_vec(<Vec<T, Global> as Like>::Type::from(slice))
} else {
// SAFETY: The precondition is checked in the initial comparison
// above.
Expand Down Expand Up @@ -62,7 +63,7 @@ impl<T, const N: usize, const M: usize> From<[T; M]> for SmallVec<T, N, Global>
if M > N {
// If M > N, we'd have to heap allocate anyway,
// so delegate for Vec for the allocation.
Self::from(Vec::from(array))
Self::from(<Vec<T, Global> as Like>::Type::from(array))
} else {
// M <= N
let mut this = Self::new();
Expand Down Expand Up @@ -97,17 +98,17 @@ impl<T, const N: usize, const M: usize, A: Allocator> TryFrom<SmallVec<T, N, A>>
}
}

impl<T, const N: usize> From<Vec<T>> for SmallVec<T, N, Global> {
fn from(array: Vec<T>) -> Self {
impl<T, const N: usize> From<<Vec<T, Global> as Like>::Type> for SmallVec<T, N, Global> {
fn from(array: <Vec<T, Global> as Like>::Type) -> Self {
Self::from_vec(array)
}
}

impl<T, const N: usize, A: Allocator> From<SmallVec<T, N, A>> for Vec<T> {
impl<T, const N: usize, A: Allocator> From<SmallVec<T, N, A>> for <Vec<T, Global> as Like>::Type {
fn from(this: SmallVec<T, N, A>) -> Self {
let (length, on_heap) = this.length.parts();
if !on_heap {
let mut vec = Vec::with_capacity(length);
let mut vec = <Vec<T, Global> as Like>::Type::with_capacity(length);
let this = ManuallyDrop::new(this);
// SAFETY: we create a new vector with sufficient capacity, copy our
// elements into it to transfer ownership and then set
Expand All @@ -129,14 +130,14 @@ impl<T, const N: usize, A: Allocator> From<SmallVec<T, N, A>> for Vec<T> {
// - the allocation is not larger than `isize::MAX`
unsafe {
let (ptr, cap) = this.raw.heap;
Vec::from_raw_parts(ptr.as_ptr(), length, cap)
<Vec<T, Global> as Like>::Type::from_raw_parts(ptr.as_ptr(), length, cap)
}
}
}
}

impl<T, const N: usize, A: Allocator> From<SmallVec<T, N, A>> for Box<[T]> {
impl<T, const N: usize, A: Allocator> From<SmallVec<T, N, A>> for <Box<[T], Global> as Like>::Type {
fn from(this: SmallVec<T, N, A>) -> Self {
Vec::from(this).into_boxed_slice()
<Vec<T, Global> as Like>::Type::from(this).into_boxed_slice()
}
}
3 changes: 1 addition & 2 deletions src/iterators/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
pub mod drain;
pub mod extractif;
pub mod intoiter;
pub mod splice;

#[cfg(feature = "rayon")]
mod rayon;
pub mod splice;
26 changes: 16 additions & 10 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,13 @@ use std::io;
use {
allocator::{
Allocator,
Box,
Global,
Vec,
vec
boxed::Box,
global::Global,
like::Like,
vec::{
Vec,
vec
}
},
core::{
alloc::Layout,
Expand Down Expand Up @@ -220,7 +223,7 @@ impl<T, const N: usize> SmallVec<T, N, Global> {
}

#[inline]
pub fn from_vec(vec: Vec<T>) -> Self {
pub fn from_vec(vec: <Vec<T, Global> as Like>::Type) -> Self {
if vec.capacity() == 0 {
return Self::new();
}
Expand Down Expand Up @@ -757,7 +760,8 @@ impl<T, const N: usize, A: Allocator> SmallVec<T, N, A> {
let (ptr, capacity) = self.raw.heap;
copy_nonoverlapping(ptr.as_ptr(), self.raw.as_mut_ptr_inline(), length);
self.length.set_location::<false>();
self.allocator.deallocate(
Allocator::deallocate(
&self.allocator,
ptr.cast(),
Layout::from_size_align_unchecked(capacity * size_of::<T>(), align_of::<T>())
);
Expand Down Expand Up @@ -791,7 +795,8 @@ impl<T, const N: usize, A: Allocator> SmallVec<T, N, A> {
let (ptr, capacity) = self.raw.heap;
copy_nonoverlapping(ptr.as_ptr(), self.raw.as_mut_ptr_inline(), length);
self.length.set_location::<false>();
self.allocator.deallocate(
Allocator::deallocate(
&self.allocator,
ptr.cast(),
Layout::from_size_align_unchecked(
capacity * size_of::<T>(),
Expand Down Expand Up @@ -980,13 +985,13 @@ impl<T, const N: usize, A: Allocator> SmallVec<T, N, A> {

#[inline]
#[deprecated(since = "2.0.0", note = "use `Into::<Vec<T>>::into` instead")]
pub fn into_vec(self) -> Vec<T> {
pub fn into_vec(self) -> <Vec<T, Global> as Like>::Type {
self.into()
}

#[inline]
#[deprecated(since = "2.0.0", note = "use `Into::<Box<[T]>>::into` instead")]
pub fn into_boxed_slice(self) -> Box<[T]> {
pub fn into_boxed_slice(self) -> <Box<[T], Global> as Like>::Type {
self.into()
}

Expand Down Expand Up @@ -1466,7 +1471,8 @@ impl<A: Allocator> Drop for DropDealloc<'_, A> {
fn drop(&mut self) {
unsafe {
if self.size_bytes > 0 {
self.allocator.deallocate(
Allocator::deallocate(
self.allocator,
self.ptr,
Layout::from_size_align_unchecked(self.size_bytes, self.align)
);
Expand Down
7 changes: 3 additions & 4 deletions src/rawsmallvec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,7 @@ impl<T, const N: usize> RawSmallVec<T, N> {
let new_ptr = if !was_on_heap {
// get a fresh allocation
// `new_layout` has nonzero size.
let new_ptr = allocator
.allocate(new_layout)
let new_ptr = Allocator::allocate(allocator, new_layout)
.ok_or(SmallVecError::AllocationError(new_layout))?
.cast();
unsafe { copy_nonoverlapping(ptr, new_ptr.as_ptr(), length) };
Expand All @@ -149,9 +148,9 @@ impl<T, const N: usize> RawSmallVec<T, N> {
// with Layout::array
unsafe {
(if self.heap.1 < new_capacity {
A::grow
<A as Allocator>::grow
} else {
A::shrink
<A as Allocator>::shrink
})(
allocator,
NonNull::new(ptr as *mut u8).unwrap(),
Expand Down
Loading