diff --git a/src/allocator/boxed.rs b/src/allocator/boxed.rs new file mode 100644 index 00000000..7fa4cf9a --- /dev/null +++ b/src/allocator/boxed.rs @@ -0,0 +1,19 @@ +use { + super::{ + Allocator, + like::Like, + requirement::Requirement + }, + core::marker::PhantomData +}; + +pub struct Box(PhantomData<(Heap, Item)>); + +impl Like for Box { + #[cfg(not(feature = "allocator-api"))] + type Type = alloc::boxed::Box; + #[cfg(all(feature = "allocator-api", not(feature = "allocator-api2")))] + type Type = alloc::boxed::Box; + #[cfg(feature = "allocator-api2")] + type Type = allocator_api2::boxed::Box; +} diff --git a/src/allocator/global.rs b/src/allocator/global.rs new file mode 100644 index 00000000..67af50c6 --- /dev/null +++ b/src/allocator/global.rs @@ -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; diff --git a/src/allocator/base.rs b/src/allocator/implementations/base.rs similarity index 94% rename from src/allocator/base.rs rename to src/allocator/implementations/base.rs index 76ec54e8..996586fd 100644 --- a/src/allocator/base.rs +++ b/src/allocator/implementations/base.rs @@ -1,5 +1,8 @@ use { - super::Allocator, + super::super::{ + Allocator, + global::Global + }, alloc::alloc::{ alloc, dealloc, @@ -11,9 +14,6 @@ use { } }; -#[derive(Clone)] -pub struct Global; - impl Allocator for Global { #[inline] fn allocate(&self, layout: Layout) -> Option> { diff --git a/src/allocator/external.rs b/src/allocator/implementations/external.rs similarity index 96% rename from src/allocator/external.rs rename to src/allocator/implementations/external.rs index 635a8697..72083f23 100644 --- a/src/allocator/external.rs +++ b/src/allocator/implementations/external.rs @@ -1,5 +1,5 @@ use { - super::Allocator, + super::super::Allocator, allocator_api2::alloc::Allocator as External, core::{ alloc::Layout, diff --git a/src/allocator/implementations/mod.rs b/src/allocator/implementations/mod.rs new file mode 100644 index 00000000..59ab2e1e --- /dev/null +++ b/src/allocator/implementations/mod.rs @@ -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; diff --git a/src/allocator/native.rs b/src/allocator/implementations/native.rs similarity index 96% rename from src/allocator/native.rs rename to src/allocator/implementations/native.rs index 77603616..70ef0866 100644 --- a/src/allocator/native.rs +++ b/src/allocator/implementations/native.rs @@ -1,5 +1,5 @@ use { - super::Allocator, + super::super::Allocator, alloc::alloc::Allocator as Native, core::{ alloc::Layout, diff --git a/src/allocator/like.rs b/src/allocator/like.rs new file mode 100644 index 00000000..593bdbef --- /dev/null +++ b/src/allocator/like.rs @@ -0,0 +1,3 @@ +pub trait Like { + type Type; +} diff --git a/src/allocator/mod.rs b/src/allocator/mod.rs index 5e67a3a8..074f7190 100644 --- a/src/allocator/mod.rs +++ b/src/allocator/mod.rs @@ -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>; unsafe fn deallocate(&self, pointer: NonNull, layout: Layout); diff --git a/src/allocator/requirement.rs b/src/allocator/requirement.rs new file mode 100644 index 00000000..23529e2c --- /dev/null +++ b/src/allocator/requirement.rs @@ -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; diff --git a/src/allocator/vec.rs b/src/allocator/vec.rs new file mode 100644 index 00000000..a7801449 --- /dev/null +++ b/src/allocator/vec.rs @@ -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(PhantomData<(Heap, Item)>); + +impl Like for Vec { + #[cfg(not(feature = "allocator-api"))] + type Type = alloc::vec::Vec; + #[cfg(all(feature = "allocator-api", not(feature = "allocator-api2")))] + type Type = alloc::vec::Vec; + #[cfg(feature = "allocator-api2")] + type Type = allocator_api2::vec::Vec; +} diff --git a/src/conversions.rs b/src/conversions.rs index 13cde585..4f60800a 100644 --- a/src/conversions.rs +++ b/src/conversions.rs @@ -4,7 +4,8 @@ use { Box, Global, SmallVec, - Vec + Vec, + allocator::like::Like }, core::{ mem::ManuallyDrop, @@ -17,7 +18,7 @@ impl From<&[T]> for SmallVec { 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( as Like>::Type::from(slice)) } else { // SAFETY: The precondition is checked in the initial comparison // above. @@ -62,7 +63,7 @@ impl From<[T; M]> for SmallVec 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( as Like>::Type::from(array)) } else { // M <= N let mut this = Self::new(); @@ -97,17 +98,17 @@ impl TryFrom> } } -impl From> for SmallVec { - fn from(array: Vec) -> Self { +impl From< as Like>::Type> for SmallVec { + fn from(array: as Like>::Type) -> Self { Self::from_vec(array) } } -impl From> for Vec { +impl From> for as Like>::Type { fn from(this: SmallVec) -> Self { let (length, on_heap) = this.length.parts(); if !on_heap { - let mut vec = Vec::with_capacity(length); + let mut vec = 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 @@ -129,14 +130,14 @@ impl From> for Vec { // - the allocation is not larger than `isize::MAX` unsafe { let (ptr, cap) = this.raw.heap; - Vec::from_raw_parts(ptr.as_ptr(), length, cap) + as Like>::Type::from_raw_parts(ptr.as_ptr(), length, cap) } } } } -impl From> for Box<[T]> { +impl From> for as Like>::Type { fn from(this: SmallVec) -> Self { - Vec::from(this).into_boxed_slice() + as Like>::Type::from(this).into_boxed_slice() } } diff --git a/src/iterators/mod.rs b/src/iterators/mod.rs index 40585e0c..78953514 100644 --- a/src/iterators/mod.rs +++ b/src/iterators/mod.rs @@ -1,7 +1,6 @@ pub mod drain; pub mod extractif; pub mod intoiter; -pub mod splice; - #[cfg(feature = "rayon")] mod rayon; +pub mod splice; diff --git a/src/lib.rs b/src/lib.rs index 9f391826..cb4c3ff7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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, @@ -220,7 +223,7 @@ impl SmallVec { } #[inline] - pub fn from_vec(vec: Vec) -> Self { + pub fn from_vec(vec: as Like>::Type) -> Self { if vec.capacity() == 0 { return Self::new(); } @@ -757,7 +760,8 @@ impl SmallVec { let (ptr, capacity) = self.raw.heap; copy_nonoverlapping(ptr.as_ptr(), self.raw.as_mut_ptr_inline(), length); self.length.set_location::(); - self.allocator.deallocate( + Allocator::deallocate( + &self.allocator, ptr.cast(), Layout::from_size_align_unchecked(capacity * size_of::(), align_of::()) ); @@ -791,7 +795,8 @@ impl SmallVec { let (ptr, capacity) = self.raw.heap; copy_nonoverlapping(ptr.as_ptr(), self.raw.as_mut_ptr_inline(), length); self.length.set_location::(); - self.allocator.deallocate( + Allocator::deallocate( + &self.allocator, ptr.cast(), Layout::from_size_align_unchecked( capacity * size_of::(), @@ -980,13 +985,13 @@ impl SmallVec { #[inline] #[deprecated(since = "2.0.0", note = "use `Into::>::into` instead")] - pub fn into_vec(self) -> Vec { + pub fn into_vec(self) -> as Like>::Type { self.into() } #[inline] #[deprecated(since = "2.0.0", note = "use `Into::>::into` instead")] - pub fn into_boxed_slice(self) -> Box<[T]> { + pub fn into_boxed_slice(self) -> as Like>::Type { self.into() } @@ -1466,7 +1471,8 @@ impl 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) ); diff --git a/src/rawsmallvec.rs b/src/rawsmallvec.rs index 0330bc2e..45f21aab 100644 --- a/src/rawsmallvec.rs +++ b/src/rawsmallvec.rs @@ -126,8 +126,7 @@ impl RawSmallVec { 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) }; @@ -149,9 +148,9 @@ impl RawSmallVec { // with Layout::array unsafe { (if self.heap.1 < new_capacity { - A::grow + ::grow } else { - A::shrink + ::shrink })( allocator, NonNull::new(ptr as *mut u8).unwrap(),