Skip to content
Open
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
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ v.sort();
## Feature List

- `allocator-api` (nightly): uses the `allocator-api` backend
for the allocator API
for the allocator API
- `allocator-api2`: uses the `allocator-api2` backend for the allocator API
- `arbitrary`: implements `Arbitrary` for any `SmallVec` storing elements
that implement `Arbitrary`
that implement `Arbitrary`
- `borsh`: implements `BorshSerialize`, `BorshDeserialize` and `BorshSchema`
- `bytes`: implements `BufMut` for SmallVec
- `defmt`: implements `defmt::Format` for SmallVec
Expand All @@ -64,7 +64,7 @@ v.sort();
- `rayon`: implements parallel iteration
- `serde`: implements serde's serialization and deserialization
- `specialization` (nightly): enables specialization,
improving performance on some cases
improving performance on some cases
- `std`: implements the `std::io::Write` type for `SmallVec<u8, INLINE>`
- `zeroize`: implements `zeroize::Zeroize`, erasing elements and storage

Expand All @@ -73,4 +73,4 @@ v.sort();
> - SmallVec without any features enabled does not make use of the standard library.
> - The `rayon` and `proptest` features implicitly require `std`.
> - The `allocator-api2` feature requires `allocator-api`, though it does not
require `nightly`
> require `nightly`
38 changes: 31 additions & 7 deletions src/allocator/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,42 @@ use {
super::{
Allocator,
like::Like,
requirement::Requirement
vec::Vec
},
core::marker::PhantomData
core::{
marker::PhantomData,
mem::MaybeUninit,
ptr::NonNull
}
};

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

impl<Item: ?Sized, Heap: Allocator + Requirement> Like for Box<Item, Heap> {
impl<Item, Heap: Allocator> Like for Box<[Item], Heap> {
type Heap = Heap;
type Item = Item;
#[cfg(not(feature = "allocator-api"))]
type Type = alloc::boxed::Box<Item>;
type Type = alloc::boxed::Box<[Item]>;
#[cfg(all(feature = "allocator-api", not(feature = "allocator-api2")))]
type Type = alloc::boxed::Box<Item, Heap>;
type Type = alloc::boxed::Box<[Item], Heap>;
#[cfg(feature = "allocator-api2")]
type Type = allocator_api2::boxed::Box<Item, Heap>;
type Type = allocator_api2::boxed::Box<[Item], Heap>;

fn destruct(
value: Self::Type
) -> (
Option<NonNull<[MaybeUninit<Self::Item>]>>,
usize,
Self::Heap
) {
<Vec<Item, Heap> as Like>::destruct(value.into_vec())
}

fn construct(
pointer: Option<NonNull<[MaybeUninit<Self::Item>]>>,
length: usize,
allocator: Self::Heap
) -> Self::Type {
<Vec<Item, Heap> as Like>::construct(pointer, length, allocator).into_boxed_slice()
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
#[cfg(not(feature = "allocator-api"))]
use {
super::super::{
Allocator,
global::Global
},
super::global::Global,
alloc::alloc::{
alloc,
dealloc,
realloc
}
};
use {
super::{
Allocator,
requirement::Requirement
},
core::{
alloc::Layout,
ptr::NonNull
}
};

impl Allocator for Global {
#[cfg(not(feature = "allocator-api"))]
impl Requirement for Global {}

#[cfg(not(feature = "allocator-api"))]
impl<Type: Requirement> Allocator for Type {
#[inline]
fn allocate(&self, layout: Layout) -> Option<NonNull<[u8]>> {
Some(NonNull::slice_from_raw_parts(
Expand Down Expand Up @@ -49,3 +57,31 @@ impl Allocator for Global {
))
}
}

#[cfg(feature = "allocator-api")]
impl<Type: Requirement> Allocator for Type {
#[inline]
fn allocate(&self, layout: Layout) -> Option<NonNull<[u8]>> {
Requirement::allocate(&self, layout).ok()
}

#[inline]
unsafe fn deallocate(&self, pointer: NonNull<u8>, layout: Layout) {
unsafe { Requirement::deallocate(&self, pointer, layout) }
}

#[inline]
unsafe fn grow(&self, pointer: NonNull<u8>, old: Layout, new: Layout) -> Option<NonNull<[u8]>> {
unsafe { Requirement::grow(&self, pointer, old, new).ok() }
}

#[inline]
unsafe fn shrink(
&self,
pointer: NonNull<u8>,
old: Layout,
new: Layout
) -> Option<NonNull<[u8]>> {
unsafe { Requirement::shrink(&self, pointer, old, new).ok() }
}
}
35 changes: 0 additions & 35 deletions src/allocator/implementations/external.rs

This file was deleted.

6 changes: 0 additions & 6 deletions src/allocator/implementations/mod.rs

This file was deleted.

35 changes: 0 additions & 35 deletions src/allocator/implementations/native.rs

This file was deleted.

22 changes: 22 additions & 0 deletions src/allocator/like.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
use {
super::Allocator,
core::{
mem::MaybeUninit,
ptr::NonNull
}
};

pub trait Like {
type Type;
type Item;
type Heap: Allocator;
fn destruct(
value: Self::Type
) -> (
Option<NonNull<[MaybeUninit<Self::Item>]>>,
usize,
Self::Heap
);
fn construct(
pointer: Option<NonNull<[MaybeUninit<Self::Item>]>>,
length: usize,
allocator: Self::Heap
) -> Self::Type;
}
15 changes: 9 additions & 6 deletions src/allocator/mod.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
pub mod boxed;
pub mod global;
mod implementations;
pub mod implementations;
pub mod like;
pub mod proxy;
mod requirement;
pub mod requirement;
pub mod vec;

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

pub trait Allocator {
pub trait Allocator: Requirement {
fn allocate(&self, layout: Layout) -> Option<NonNull<[u8]>>;
unsafe fn deallocate(&self, pointer: NonNull<u8>, layout: Layout);
unsafe fn grow(&self, pointer: NonNull<u8>, old: Layout, new: Layout) -> Option<NonNull<[u8]>>;
Expand Down
86 changes: 68 additions & 18 deletions src/allocator/proxy.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,87 @@
use {
super::Allocator,
core::{
alloc::Layout,
ptr::NonNull
}
use super::{
Allocator,
requirement::Requirement
};
#[cfg(all(feature = "allocator-api", not(feature = "allocator-api2")))]
use alloc::alloc::AllocError;
#[cfg(feature = "allocator-api2")]
use allocator_api2::alloc::AllocError;
#[cfg(feature = "allocator-api")]
use core::{
alloc::Layout,
ptr::NonNull
};

#[repr(transparent)]
pub struct Proxy<'valid, Heap: Allocator>(pub &'valid Heap);

impl<'valid, Heap: Allocator> Allocator for Proxy<'valid, Heap> {
#[cfg(not(feature = "allocator-api"))]
impl<'valid, Heap: Allocator> Requirement for Proxy<'valid, Heap> {}
#[cfg(all(feature = "allocator-api", not(feature = "allocator-api2")))]
unsafe impl<'valid, Heap: Allocator> Requirement for Proxy<'valid, Heap> {
#[inline]
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
Requirement::allocate(&self, layout)
}

#[inline]
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
unsafe {
Requirement::deallocate(&self, ptr, layout);
}
}

#[inline]
unsafe fn grow(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout
) -> Result<NonNull<[u8]>, AllocError> {
unsafe { Requirement::grow(&self, ptr, old_layout, new_layout) }
}

#[inline]
fn allocate(&self, layout: Layout) -> Option<NonNull<[u8]>> {
self.0.allocate(layout)
unsafe fn shrink(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout
) -> Result<NonNull<[u8]>, AllocError> {
unsafe { Requirement::shrink(&self, ptr, old_layout, new_layout) }
}
}
#[cfg(feature = "allocator-api2")]
unsafe impl<'valid, Heap: Allocator> Requirement for Proxy<'valid, Heap> {
#[inline]
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
Requirement::allocate(&self, layout)
}

#[inline]
unsafe fn deallocate(&self, pointer: NonNull<u8>, layout: Layout) {
unsafe { self.0.deallocate(pointer, layout) };
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
unsafe {
Requirement::deallocate(&self, ptr, layout);
}
}

#[inline]
unsafe fn grow(&self, pointer: NonNull<u8>, old: Layout, new: Layout) -> Option<NonNull<[u8]>> {
unsafe { self.0.grow(pointer, old, new) }
unsafe fn grow(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout
) -> Result<NonNull<[u8]>, AllocError> {
unsafe { Requirement::grow(&self, ptr, old_layout, new_layout) }
}

#[inline]
unsafe fn shrink(
&self,
pointer: NonNull<u8>,
old: Layout,
new: Layout
) -> Option<NonNull<[u8]>> {
unsafe { self.0.shrink(pointer, old, new) }
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout
) -> Result<NonNull<[u8]>, AllocError> {
unsafe { Requirement::shrink(&self, ptr, old_layout, new_layout) }
}
}
2 changes: 1 addition & 1 deletion src/allocator/requirement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ 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;
pub trait Requirement {}
Loading
Loading