use core::ptr;
use core::slice;
use core::str;
use super::{ArrayIter, CacheAligned};
use core::mem::size_of;
#[cfg(any(stable_maybe_uninit, feature = "unstable"))]
use core::mem::MaybeUninit;
#[cfg(feature = "std")]
use std::ffi::CStr;
#[cfg(any(feature = "std", feature = "alloc", feature = "unstable"))]
use super::{Box, Vec};
pub unsafe trait ByteData: Sized {}
unsafe impl ByteData for u8 {}
unsafe impl ByteData for u16 {}
unsafe impl ByteData for u32 {}
unsafe impl ByteData for u64 {}
#[cfg(any(stable128, feature = "unstable"))]
unsafe impl ByteData for u128 {}
unsafe impl ByteData for usize {}
unsafe impl ByteData for i8 {}
unsafe impl ByteData for i16 {}
unsafe impl ByteData for i32 {}
unsafe impl ByteData for i64 {}
#[cfg(any(stable128, feature = "unstable"))]
unsafe impl ByteData for i128 {}
unsafe impl ByteData for isize {}
unsafe impl ByteData for CacheAligned {}
#[cfg(any(stable_maybe_uninit, feature = "unstable"))]
unsafe impl<T: ByteData> ByteData for MaybeUninit<T> {}
pub unsafe trait Array {
type Item: Sized;
fn as_slice(&self) -> &[Self::Item];
fn as_mut_slice(&mut self) -> &mut [Self::Item];
}
pub trait Buffer {
fn as_bytes(&self) -> &[u8];
fn as_bytes_mut(&mut self) -> &mut [u8];
}
impl<T> Buffer for T
where
T: Array,
<T as Array>::Item: ByteData,
{
#[inline]
fn as_bytes(&self) -> &[u8] {
let data = self.as_slice();
unsafe {
slice::from_raw_parts(
data.as_ptr() as *const u8,
data.len() * size_of::<<T as Array>::Item>(),
)
}
}
#[inline]
fn as_bytes_mut(&mut self) -> &mut [u8] {
let data = self.as_mut_slice();
unsafe {
slice::from_raw_parts_mut(
data.as_mut_ptr() as *mut u8,
data.len() * size_of::<<T as Array>::Item>(),
)
}
}
}
impl<'a, T> Buffer for &'a mut [T]
where
T: ByteData,
{
#[inline]
fn as_bytes(&self) -> &[u8] {
unsafe {
slice::from_raw_parts(
self.as_ptr() as *const u8,
self.len() * size_of::<T>(),
)
}
}
#[inline]
fn as_bytes_mut(&mut self) -> &mut [u8] {
unsafe {
slice::from_raw_parts_mut(
self.as_mut_ptr() as *mut u8,
self.len() * size_of::<T>(),
)
}
}
}
#[cfg(any(feature = "std", feature = "alloc", feature = "unstable"))]
impl<T> Buffer for Box<[T]>
where
T: ByteData,
{
#[inline]
fn as_bytes(&self) -> &[u8] {
let data = self.as_ref();
unsafe {
slice::from_raw_parts(
data.as_ptr() as *const u8,
data.len() * size_of::<T>(),
)
}
}
#[inline]
fn as_bytes_mut(&mut self) -> &mut [u8] {
let data = self.as_mut();
unsafe {
slice::from_raw_parts_mut(
data.as_mut_ptr() as *mut u8,
data.len() * size_of::<T>(),
)
}
}
}
pub unsafe trait StaticBuffer: Buffer + Array {}
unsafe impl<T> StaticBuffer for T
where
T: Array,
<T as Array>::Item: ByteData,
{
}
pub trait Tracking: Sized {
fn capacity(&self) -> usize;
fn set(&mut self, index: usize, value: usize);
fn get(&self, index: usize) -> usize;
}
impl<T> Tracking for T
where
T: Buffer,
{
#[inline]
fn capacity(&self) -> usize {
self.as_bytes().len() / size_of::<usize>()
}
#[cfg_attr(
feature = "cargo-clippy",
allow(clippy::cast_ptr_alignment, clippy::size_of_in_element_count)
)]
#[inline]
fn set(&mut self, index: usize, value: usize) {
let bytes = self.as_bytes_mut();
unsafe {
let contents = slice::from_raw_parts_mut(
bytes.as_mut_ptr() as *mut usize,
bytes.len() / size_of::<usize>(),
);
ptr::write_unaligned(&mut contents[index], value);
}
}
#[cfg_attr(
feature = "cargo-clippy",
allow(clippy::cast_ptr_alignment, clippy::size_of_in_element_count)
)]
#[inline]
fn get(&self, index: usize) -> usize {
let bytes = self.as_bytes();
unsafe {
let contents = slice::from_raw_parts(
bytes.as_ptr() as *const usize,
bytes.len() / size_of::<usize>(),
);
ptr::read_unaligned(&contents[index])
}
}
}
pub trait SliceLike {
type Element: Sized;
fn as_element_slice(&self) -> &[Self::Element];
unsafe fn as_element_slice_mut(&mut self) -> &mut [Self::Element];
unsafe fn from_element_slice(slice: &[Self::Element]) -> &Self;
unsafe fn from_element_slice_mut(
slice: &mut [Self::Element],
) -> &mut Self;
}
impl<T> SliceLike for [T] {
type Element = T;
#[inline]
fn as_element_slice(&self) -> &[Self::Element] {
self
}
#[inline]
unsafe fn as_element_slice_mut(&mut self) -> &mut [Self::Element] {
self
}
#[inline]
unsafe fn from_element_slice(slice: &[Self::Element]) -> &Self {
slice
}
#[inline]
unsafe fn from_element_slice_mut(
slice: &mut [Self::Element],
) -> &mut Self {
slice
}
}
impl SliceLike for str {
type Element = u8;
#[inline]
fn as_element_slice(&self) -> &[Self::Element] {
self.as_bytes()
}
#[inline]
unsafe fn as_element_slice_mut(&mut self) -> &mut [Self::Element] {
self.as_bytes_mut()
}
#[inline]
unsafe fn from_element_slice(slice: &[Self::Element]) -> &Self {
str::from_utf8_unchecked(slice)
}
#[inline]
unsafe fn from_element_slice_mut(
slice: &mut [Self::Element],
) -> &mut Self {
str::from_utf8_unchecked_mut(slice)
}
}
#[cfg(feature = "std")]
impl SliceLike for CStr {
type Element = u8;
#[inline]
fn as_element_slice(&self) -> &[Self::Element] {
self.to_bytes_with_nul()
}
#[inline]
unsafe fn as_element_slice_mut(&mut self) -> &mut [Self::Element] {
#[cfg_attr(feature = "cargo-clippy", allow(clippy::cast_ref_to_mut))]
&mut *(self.to_bytes_with_nul() as *const [u8] as *mut [u8])
}
#[inline]
unsafe fn from_element_slice(slice: &[Self::Element]) -> &Self {
CStr::from_bytes_with_nul_unchecked(slice)
}
#[inline]
unsafe fn from_element_slice_mut(
slice: &mut [Self::Element],
) -> &mut Self {
#[cfg_attr(feature = "cargo-clippy", allow(clippy::cast_ref_to_mut))]
&mut *(CStr::from_bytes_with_nul_unchecked(slice) as *const CStr
as *mut CStr)
}
}
pub trait ConcatenateSlice: SliceLike {}
impl<T> ConcatenateSlice for [T] {}
impl ConcatenateSlice for str {}
pub unsafe trait IntoMutSliceLikePtr<T>
where
T: SliceLike + ?Sized,
{
#[cfg_attr(
feature = "cargo-clippy",
allow(clippy::wrong_self_convention)
)]
fn into_mut_slice_like_ptr(ptr: *mut Self) -> *mut T;
}
unsafe impl<T> IntoMutSliceLikePtr<[T]> for T {
#[cfg_attr(
feature = "cargo-clippy",
allow(clippy::not_unsafe_ptr_arg_deref)
)]
#[inline]
fn into_mut_slice_like_ptr(ptr: *mut T) -> *mut [T] {
unsafe { slice::from_raw_parts_mut(ptr, 1) }
}
}
unsafe impl<T> IntoMutSliceLikePtr<T> for T
where
T: SliceLike + ?Sized,
{
#[inline]
fn into_mut_slice_like_ptr(ptr: *mut T) -> *mut T {
ptr
}
}
unsafe impl IntoMutSliceLikePtr<[u8]> for str {
#[cfg_attr(
feature = "cargo-clippy",
allow(clippy::not_unsafe_ptr_arg_deref)
)]
#[inline]
fn into_mut_slice_like_ptr(ptr: *mut str) -> *mut [u8] {
unsafe { (*ptr).as_bytes_mut() }
}
}
#[cfg(feature = "std")]
unsafe impl IntoMutSliceLikePtr<[u8]> for CStr {
#[cfg_attr(
feature = "cargo-clippy",
allow(clippy::not_unsafe_ptr_arg_deref)
)]
#[inline]
fn into_mut_slice_like_ptr(ptr: *mut CStr) -> *mut [u8] {
unsafe { (*ptr).as_element_slice_mut() }
}
}
pub trait SliceSource<T>
where
T: SliceLike + ?Sized,
{
fn as_slice_like(&self) -> &T;
#[inline(always)]
fn as_slice_like_ptr(&self) -> *const T {
self.as_slice_like()
}
}
impl<T> SliceSource<[<T as Array>::Item]> for T
where
T: Array,
{
#[inline]
fn as_slice_like(&self) -> &[<T as Array>::Item] {
self.as_slice()
}
}
impl<'a, T> SliceSource<T> for &'a T
where
T: SliceLike + ?Sized,
{
#[inline]
fn as_slice_like(&self) -> &T {
*self
}
}
#[cfg(any(feature = "std", feature = "alloc", feature = "unstable"))]
impl<T> SliceSource<T> for Box<T>
where
T: SliceLike + ?Sized,
{
#[inline]
fn as_slice_like(&self) -> &T {
&**self
}
}
#[cfg(any(feature = "std", feature = "alloc", feature = "unstable"))]
impl<T> SliceSource<[T]> for Vec<T> {
#[inline]
fn as_slice_like(&self) -> &[T] {
self.as_slice()
}
}
#[cfg(any(feature = "std", feature = "alloc", feature = "unstable"))]
impl<'a, T> SliceSource<T> for &'a Box<T>
where
T: SliceLike + ?Sized,
{
#[inline]
fn as_slice_like(&self) -> &T {
&***self
}
}
#[cfg(any(feature = "std", feature = "alloc", feature = "unstable"))]
impl<'a, T> SliceSource<[T]> for &'a Vec<T> {
#[inline]
fn as_slice_like(&self) -> &[T] {
self.as_slice()
}
}
pub trait SliceMoveSource<T>: SliceSource<T>
where
T: SliceLike + ?Sized,
{
fn move_elements<F>(self, f: F)
where
Self: Sized,
F: FnMut(<T as SliceLike>::Element);
}
impl<T> SliceMoveSource<[<T as Array>::Item]> for T
where
T: Array,
{
fn move_elements<F>(self, mut f: F)
where
F: FnMut(<T as Array>::Item),
{
for item in ArrayIter::new(self) {
f(item);
}
}
}
impl<'a, T> SliceMoveSource<T> for &'a T
where
T: SliceLike + ?Sized,
<T as SliceLike>::Element: Copy,
{
fn move_elements<F>(self, mut f: F)
where
F: FnMut(<T as SliceLike>::Element),
{
for item in self.as_element_slice() {
f(*item);
}
}
}
#[cfg(any(feature = "std", feature = "alloc", feature = "unstable"))]
impl<T> SliceMoveSource<T> for Box<T>
where
T: SliceLike + ?Sized,
{
fn move_elements<F>(self, mut f: F)
where
F: FnMut(<T as SliceLike>::Element),
{
let boxed_slice = unsafe {
Box::from_raw((*Box::into_raw(self)).as_element_slice_mut()
as *mut [T::Element])
};
for item in boxed_slice.into_vec() {
f(item);
}
}
}
#[cfg(any(feature = "std", feature = "alloc", feature = "unstable"))]
impl<T> SliceMoveSource<[T]> for Vec<T> {
fn move_elements<F>(self, mut f: F)
where
F: FnMut(T),
{
for item in self {
f(item);
}
}
}
#[cfg(any(feature = "std", feature = "alloc", feature = "unstable"))]
impl<'a, T> SliceMoveSource<T> for &'a Box<T>
where
T: SliceLike + ?Sized,
<T as SliceLike>::Element: Copy,
{
fn move_elements<F>(self, mut f: F)
where
F: FnMut(<T as SliceLike>::Element),
{
for item in self.as_element_slice() {
f(*item);
}
}
}
#[cfg(any(feature = "std", feature = "alloc", feature = "unstable"))]
impl<'a, T> SliceMoveSource<[T]> for &'a Vec<T>
where
T: Copy,
{
fn move_elements<F>(self, mut f: F)
where
F: FnMut(T),
{
for item in self {
f(*item);
}
}
}
pub trait SliceSourceCollection<T>
where
T: SliceLike + ?Sized,
{
fn for_each<F>(&self, f: F)
where
F: for<'a> FnMut(&'a SliceSource<T>);
}
impl<T, U> SliceSourceCollection<T> for U
where
T: SliceLike + ?Sized,
U: Array,
<U as Array>::Item: SliceSource<T>,
{
fn for_each<F>(&self, mut f: F)
where
F: for<'a> FnMut(&'a SliceSource<T>),
{
for source in self.as_slice() {
f(source);
}
}
}
impl<'b, T, U> SliceSourceCollection<T> for &'b [U]
where
T: SliceLike + ?Sized,
U: SliceSource<T>,
{
fn for_each<F>(&self, mut f: F)
where
F: for<'a> FnMut(&'a SliceSource<T>),
{
for source in *self {
f(source);
}
}
}
#[cfg(any(feature = "std", feature = "alloc", feature = "unstable"))]
impl<T, U> SliceSourceCollection<T> for Box<[U]>
where
T: SliceLike + ?Sized,
U: SliceSource<T>,
{
fn for_each<F>(&self, mut f: F)
where
F: for<'a> FnMut(&'a SliceSource<T>),
{
for source in &**self {
f(source);
}
}
}
#[cfg(any(feature = "std", feature = "alloc", feature = "unstable"))]
impl<T, U> SliceSourceCollection<T> for Vec<U>
where
T: SliceLike + ?Sized,
U: SliceSource<T>,
{
fn for_each<F>(&self, mut f: F)
where
F: for<'a> FnMut(&'a SliceSource<T>),
{
for source in self {
f(source);
}
}
}
#[cfg(any(feature = "std", feature = "alloc", feature = "unstable"))]
impl<'b, T, U> SliceSourceCollection<T> for &'b Box<[U]>
where
T: SliceLike + ?Sized,
U: SliceSource<T>,
{
fn for_each<F>(&self, mut f: F)
where
F: for<'a> FnMut(&'a SliceSource<T>),
{
for source in &***self {
f(source);
}
}
}
#[cfg(any(feature = "std", feature = "alloc", feature = "unstable"))]
impl<'b, T, U> SliceSourceCollection<T> for &'b Vec<U>
where
T: SliceLike + ?Sized,
U: SliceSource<T>,
{
fn for_each<F>(&self, mut f: F)
where
F: for<'a> FnMut(&'a SliceSource<T>),
{
for source in *self {
f(source);
}
}
}
pub trait SliceMoveSourceCollection<T>: SliceSourceCollection<T>
where
T: SliceLike + ?Sized,
{
fn move_all_elements<F>(self, f: F)
where
Self: Sized,
F: FnMut(<T as SliceLike>::Element);
}
impl<T, U> SliceMoveSourceCollection<T> for U
where
T: SliceLike + ?Sized,
U: Array,
<U as Array>::Item: SliceMoveSource<T>,
{
fn move_all_elements<F>(self, mut f: F)
where
F: FnMut(<T as SliceLike>::Element),
{
for source in ArrayIter::new(self) {
source.move_elements(&mut f);
}
}
}
impl<'b, T, U> SliceMoveSourceCollection<T> for &'b [U]
where
T: SliceLike + ?Sized,
<T as SliceLike>::Element: Copy,
U: SliceSource<T>,
{
fn move_all_elements<F>(self, mut f: F)
where
F: FnMut(<T as SliceLike>::Element),
{
for source in self {
for item in source.as_slice_like().as_element_slice() {
f(*item);
}
}
}
}
#[cfg(any(feature = "std", feature = "alloc", feature = "unstable"))]
impl<T, U> SliceMoveSourceCollection<T> for Box<[U]>
where
T: SliceLike + ?Sized,
U: SliceMoveSource<T>,
{
fn move_all_elements<F>(self, mut f: F)
where
F: FnMut(<T as SliceLike>::Element),
{
for source in self.into_vec() {
source.move_elements(&mut f);
}
}
}
#[cfg(any(feature = "std", feature = "alloc", feature = "unstable"))]
impl<T, U> SliceMoveSourceCollection<T> for Vec<U>
where
T: SliceLike + ?Sized,
U: SliceMoveSource<T>,
{
fn move_all_elements<F>(self, mut f: F)
where
F: FnMut(<T as SliceLike>::Element),
{
for source in self {
source.move_elements(&mut f);
}
}
}
#[cfg(any(feature = "std", feature = "alloc", feature = "unstable"))]
impl<'b, T, U> SliceMoveSourceCollection<T> for &'b Box<[U]>
where
T: SliceLike + ?Sized,
<T as SliceLike>::Element: Copy,
U: SliceSource<T>,
{
fn move_all_elements<F>(self, mut f: F)
where
F: FnMut(<T as SliceLike>::Element),
{
for source in &**self {
for item in source.as_slice_like().as_element_slice() {
f(*item);
}
}
}
}
#[cfg(any(feature = "std", feature = "alloc", feature = "unstable"))]
impl<'b, T, U> SliceMoveSourceCollection<T> for &'b Vec<U>
where
T: SliceLike + ?Sized,
<T as SliceLike>::Element: Copy,
U: SliceSource<T>,
{
fn move_all_elements<F>(self, mut f: F)
where
F: FnMut(<T as SliceLike>::Element),
{
for source in self {
for item in source.as_slice_like().as_element_slice() {
f(*item);
}
}
}
}
macro_rules! generate_tuple_trait_impls {
($($name:ident,)+) => {
impl<T, $($name,)*> SliceSourceCollection<T> for ($($name,)*)
where
T: SliceLike + ?Sized,
$($name: SliceSource<T>,)*
{
#[allow(non_snake_case)]
fn for_each<F>(&self, mut f: F)
where
F: for<'a> FnMut(&'a SliceSource<T>)
{
let ($(ref $name,)*) = *self;
$(
f($name);
)*
}
}
#[allow(non_snake_case)]
impl<'b, T, $($name,)*> SliceSourceCollection<T> for &'b ($($name,)*)
where
T: SliceLike + ?Sized,
$($name: SliceSource<T>,)*
{
#[allow(non_snake_case)]
fn for_each<F>(&self, mut f: F)
where
F: for<'a> FnMut(&'a SliceSource<T>)
{
let ($(ref $name,)*) = **self;
$(
f($name);
)*
}
}
impl<T, $($name,)*> SliceMoveSourceCollection<T> for ($($name,)*)
where
T: SliceLike + ?Sized,
$($name: SliceMoveSource<T>,)*
{
#[allow(non_snake_case)]
fn move_all_elements<F>(self, mut f: F)
where
F: FnMut(<T as SliceLike>::Element),
{
let ($($name,)*) = self;
$(
$name.move_elements(&mut f);
)*
}
}
#[allow(non_snake_case)]
impl<'b, T, $($name,)*> SliceMoveSourceCollection<T>
for &'b ($($name,)*)
where
T: SliceLike + ?Sized,
<T as SliceLike>::Element: Copy,
$($name: SliceSource<T>,)*
{
#[allow(non_snake_case)]
fn move_all_elements<F>(self, mut f: F)
where
F: FnMut(<T as SliceLike>::Element),
{
let ($(ref $name,)*) = *self;
$(
for item in $name.as_slice_like().as_element_slice() {
f(*item);
}
)*
}
}
generate_tuple_trait_impls!([REDUCE] $($name,)*);
};
() => {};
([REDUCE] $name:ident, $($remaining:ident,)*) => {
generate_tuple_trait_impls!($($remaining,)*);
}
}
generate_tuple_trait_impls!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,);
macro_rules! generate_array_trait_impls {
($size:expr) => {
unsafe impl<T> Array for [T; $size]
where
T: Sized,
{
type Item = T;
#[inline]
fn as_slice(&self) -> &[T] {
&self[..]
}
#[inline]
fn as_mut_slice(&mut self) -> &mut [T] {
&mut self[..]
}
}
unsafe impl<T> IntoMutSliceLikePtr<[T]> for [T; $size] {
#[cfg_attr(feature = "cargo-clippy", allow(clippy::not_unsafe_ptr_arg_deref))]
#[inline]
fn into_mut_slice_like_ptr(ptr: *mut [T; $size]) -> *mut [T] {
unsafe { &mut (*ptr)[..] }
}
}
};
($size:expr, $($other:tt)*) => {
generate_array_trait_impls!($size);
generate_array_trait_impls!($($other)*);
};
() => {};
}
generate_array_trait_impls!(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
generate_array_trait_impls!(11, 12, 13, 14, 15, 16, 17, 18, 19, 20);
generate_array_trait_impls!(21, 22, 23, 24, 25, 26, 27, 28, 29, 30);
generate_array_trait_impls!(31, 32, 33, 34, 35, 36, 37, 38, 39, 40);
generate_array_trait_impls!(41, 42, 43, 44, 45, 46, 47, 48, 49, 50);
generate_array_trait_impls!(51, 52, 53, 54, 55, 56, 57, 58, 59, 60);
generate_array_trait_impls!(61, 62, 63, 64);
generate_array_trait_impls!(0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000);
generate_array_trait_impls!(
0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000
);
generate_array_trait_impls!(
0x10_0000, 0x20_0000, 0x40_0000, 0x80_0000, 0x100_0000
);
generate_array_trait_impls!(0x200_0000, 0x400_0000, 0x800_0000, 0x1000_0000);
generate_array_trait_impls!(0x2000_0000, 0x4000_0000);