use core::ptr::NonNull;
use std::alloc::Layout;
use std::marker::PhantomData;
use std::mem;
use std::ops;
use std::ptr;
use std::slice;
pub struct Cable<T, H = ()> {
mem: NonNull<H>,
phantom: PhantomData<T>,
}
const fn max(a: usize, b: usize) -> usize {
[a, b][(a < b) as usize]
}
const fn pad(layout: Layout, align: usize) -> usize {
let len = layout.size();
let len_rounded_up = len.wrapping_add(align).wrapping_sub(1) & !align.wrapping_sub(1);
len_rounded_up.wrapping_sub(len)
}
impl<T, H> Cable<T, H> {
const SIZE_PADDING: usize = pad(Layout::new::<H>(), mem::align_of::<usize>());
const HEADER_LAYOUT: Layout = unsafe {
Layout::from_size_align_unchecked(
mem::size_of::<H>() + Self::SIZE_PADDING + mem::size_of::<usize>(),
max(mem::align_of::<H>(), mem::align_of::<usize>()),
)
};
const PAYLOAD_PADDING: usize = pad(Self::HEADER_LAYOUT, mem::align_of::<T>());
const BASE_LAYOUT: Layout = unsafe {
Layout::from_size_align_unchecked(
mem::size_of::<H>()
+ Self::SIZE_PADDING
+ mem::size_of::<usize>()
+ Self::PAYLOAD_PADDING,
max(mem::align_of::<H>(), mem::align_of::<usize>()),
)
};
const SIZE_OFFSET: isize = (mem::size_of::<H>() + Self::SIZE_PADDING) as isize;
const PAYLOAD_OFFSET: isize = (Self::BASE_LAYOUT.size()) as isize;
const HEADER_EXISTS: bool = mem::size_of::<H>() != 0;
}
impl<T, H> Cable<T, H> {
#[inline]
pub fn new() -> Self {
Cable {
mem: NonNull::new(unsafe { std::alloc::alloc_zeroed(Self::BASE_LAYOUT) as *mut H })
.expect("allocation failed"),
phantom: PhantomData,
}
}
#[inline]
pub fn with_header(value: H) -> Self {
let mut block = Cable {
mem: NonNull::new(unsafe { std::alloc::alloc_zeroed(Self::BASE_LAYOUT) as *mut H })
.expect("allocation failed"),
phantom: PhantomData,
};
block.set_header(value);
return block;
}
#[inline]
pub fn with_capacity(capacity: usize, header: H) -> Self {
let mut block = Cable {
mem: {
let layout = Self::BASE_LAYOUT
.extend(Layout::array::<T>(capacity).unwrap())
.unwrap()
.0;
NonNull::new(unsafe { std::alloc::alloc(layout) as *mut H })
.expect("allocation failed")
},
phantom: PhantomData,
};
block.set_header(header);
block.set_cap(capacity);
return block;
}
#[inline]
pub fn with_capacity_zeroed(capacity: usize, header: H) -> Self {
let mut block = Cable {
mem: {
let layout = Self::BASE_LAYOUT
.extend(Layout::array::<T>(capacity).unwrap())
.unwrap()
.0;
NonNull::new(unsafe { std::alloc::alloc_zeroed(layout) as *mut H })
.expect("allocation failed")
},
phantom: PhantomData,
};
block.set_header(header);
block.set_cap(capacity);
return block;
}
#[inline]
pub fn zero(&mut self) {
unsafe {
self.as_mut_ptr()
.write_bytes(0, mem::size_of::<T>() * self.cap());
}
}
#[inline]
pub unsafe fn copy_from_raw_parts(header: H, capacity: usize, ptr: *mut T) -> Self {
let mut block = Cable {
mem: {
let layout = Self::BASE_LAYOUT
.extend(Layout::array::<T>(capacity).unwrap())
.unwrap()
.0;
NonNull::new(std::alloc::alloc(layout) as *mut H).expect("allocation failed")
},
phantom: PhantomData,
};
ptr::copy_nonoverlapping(ptr, block.as_mut_ptr(), capacity);
block.set_cap(capacity);
block.set_header(header);
return block;
}
#[inline]
pub unsafe fn into_raw_parts(&self) -> (Option<&H>, usize, NonNull<T>) {
let me = mem::ManuallyDrop::new(self);
(me.header(), me.cap(), me.payload())
}
#[inline]
pub fn into_boxed_header(self) -> Option<Box<H>> {
if Self::HEADER_EXISTS {
unsafe {
let layout = Self::BASE_LAYOUT
.extend(Layout::array::<T>(self.cap()).ok()?)
.ok()?
.0;
let new_ptr =
std::alloc::realloc(self.mem.as_ptr().cast(), layout, mem::size_of::<H>());
Some(Box::from_raw(new_ptr.cast()))
}
} else {
None
}
}
#[inline]
pub fn into_boxed_slice(self) -> Option<Box<[T]>> {
let capacity = self.cap(); if capacity != 0 {
unsafe {
let old_layout = Self::BASE_LAYOUT
.extend(Layout::array::<T>(capacity).ok()?)
.ok()?
.0;
let new_layout = Layout::array::<T>(capacity).ok()?;
let me = mem::ManuallyDrop::new(self);
let new_ptr = std::alloc::alloc(new_layout);
ptr::copy_nonoverlapping(me.as_mut_ptr(), new_ptr.cast(), capacity);
std::alloc::dealloc(me.mem.as_ptr().cast(), old_layout);
let slice = slice::from_raw_parts_mut(new_ptr.cast(), capacity);
Some(Box::from_raw(slice))
}
} else {
None
}
}
#[inline]
pub fn is_empty(&self) -> bool {
self.cap() == 0
}
#[inline]
fn current_memory(&self) -> Option<(NonNull<H>, Layout)> {
if self.cap() == 0 {
None
} else {
Some((
self.mem,
Self::BASE_LAYOUT
.extend(Layout::array::<T>(self.cap()).ok()?)
.ok()?
.0,
))
}
}
pub fn reserve(&mut self, additional: usize, zeroed: bool) -> Option<Layout> {
if additional > 0 {
if let Some((ptr, old_layout)) = self.current_memory() {
let (new_layout, old_size) = old_layout
.extend(Layout::array::<T>(additional).ok()?)
.ok()?;
unsafe {
let new_size = new_layout.size();
let raw_ptr = std::alloc::realloc(ptr.as_ptr().cast(), new_layout, new_size);
self.mem = NonNull::new(raw_ptr as *mut H)?;
self.inc_cap(additional);
if zeroed {
raw_ptr.add(old_size).write_bytes(0, new_size - old_size)
}
}
Some(new_layout)
} else {
let new_layout = Layout::array::<T>(additional).ok()?;
unsafe {
let new_ptr = if zeroed {
std::alloc::alloc_zeroed(new_layout)
} else {
std::alloc::alloc(new_layout)
};
self.mem = NonNull::new(new_ptr as *mut H)?;
self.set_cap(additional);
}
Some(new_layout)
}
} else {
None
}
}
pub fn truncate(&mut self, capacity: usize) -> Option<Layout> {
if capacity > self.cap() {
return None;
}
unsafe {
let remove = Layout::array::<T>(self.cap() - capacity).ok()?;
let ptr = self.as_mut_ptr().add(capacity) as *mut u8;
std::alloc::dealloc(ptr, remove);
self.set_cap(capacity);
}
let layout = Self::BASE_LAYOUT
.extend(Layout::array::<T>(capacity).unwrap())
.unwrap()
.0;
Some(layout)
}
#[inline]
pub fn resize(&mut self, new_cap: usize) -> Option<Layout> {
if new_cap > self.cap() {
self.reserve(new_cap - self.cap(), false)
} else {
self.truncate(new_cap)
}
}
#[inline]
pub fn header(&self) -> Option<&H> {
if Self::HEADER_EXISTS {
Some(unsafe { &*self.mem.as_ptr() })
} else {
None
}
}
#[inline]
pub fn header_mut(&mut self) -> Option<&mut H> {
if Self::HEADER_EXISTS {
Some(unsafe { &mut *self.mem.as_ptr() })
} else {
None
}
}
#[inline]
pub fn set_header(&mut self, value: H) {
if Self::HEADER_EXISTS {
unsafe { *self.mem.as_ptr() = value }
}
}
#[inline]
pub fn cap(&self) -> usize {
unsafe {
let ptr = self.mem.as_ptr() as *mut u8;
*(ptr.offset(Self::SIZE_OFFSET) as *mut usize)
}
}
#[inline]
fn set_cap(&mut self, capacity: usize) {
unsafe {
let ptr = self.mem.as_ptr() as *mut u8;
*(ptr.offset(Self::SIZE_OFFSET) as *mut usize) = capacity;
}
}
#[inline]
fn inc_cap(&mut self, capacity: usize) {
unsafe {
let ptr = self.mem.as_ptr() as *mut u8;
*(ptr.offset(Self::SIZE_OFFSET) as *mut usize) += capacity;
}
}
#[inline]
pub fn footprint(&self) -> usize {
mem::size_of::<H>()
+ Self::SIZE_PADDING
+ mem::size_of::<usize>()
+ Self::PAYLOAD_PADDING
+ (mem::size_of::<T>() * self.cap())
}
#[inline]
pub unsafe fn payload(&self) -> NonNull<T> {
let ptr = self.mem.as_ptr() as *mut u8;
NonNull::new(ptr.offset(Self::PAYLOAD_OFFSET) as *mut T).unwrap()
}
#[inline]
pub unsafe fn as_ptr(&self) -> *const T {
let ptr = self.mem.as_ptr() as *mut u8;
ptr.offset(Self::PAYLOAD_OFFSET) as *const T
}
#[inline]
pub unsafe fn as_mut_ptr(&self) -> *mut T {
let ptr = self.mem.as_ptr() as *mut u8;
ptr.offset(Self::PAYLOAD_OFFSET) as *mut T
}
#[inline]
pub fn as_slice(&self) -> &[T] {
self
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [T] {
self
}
}
impl<T, H> ops::Deref for Cable<T, H> {
type Target = [T];
#[inline]
fn deref(&self) -> &[T] {
unsafe { slice::from_raw_parts(self.as_ptr(), self.cap()) }
}
}
impl<T, H> ops::DerefMut for Cable<T, H> {
#[inline]
fn deref_mut(&mut self) -> &mut [T] {
unsafe { slice::from_raw_parts_mut(self.as_mut_ptr(), self.cap()) }
}
}
impl<T, H, I: slice::SliceIndex<[T]>> ops::Index<I> for Cable<T, H> {
type Output = I::Output;
#[inline]
fn index(&self, index: I) -> &Self::Output {
ops::Index::index(&**self, index)
}
}
impl<T, H, I: slice::SliceIndex<[T]>> ops::IndexMut<I> for Cable<T, H> {
#[inline]
fn index_mut(&mut self, index: I) -> &mut Self::Output {
ops::IndexMut::index_mut(&mut **self, index)
}
}
impl<T, H> Cable<T, H> {
#[inline]
pub fn get(&self, index: usize) -> Option<&T> {
if index < self.cap() {
Some(unsafe { &*self.as_ptr().add(index) })
} else {
None
}
}
#[inline]
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
if index < self.cap() {
Some(unsafe { &mut *self.as_mut_ptr().add(index) })
} else {
None
}
}
#[inline]
pub unsafe fn get_unchecked(&self, index: usize) -> &T {
&*self.as_ptr().add(index)
}
#[inline]
pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
&mut *self.as_mut_ptr().add(index)
}
}
impl<T, H> Cable<T, H> {
#[inline]
pub fn set(&mut self, index: usize, value: T) -> Option<&mut T> {
if index < self.cap() {
unsafe {
let ptr = self.as_mut_ptr().add(index);
*ptr = value;
Some(&mut *ptr)
}
} else {
None
}
}
#[inline]
pub unsafe fn set_unchecked(&mut self, index: usize, value: T) -> &mut T {
let ptr = self.as_mut_ptr().add(index);
*ptr = value;
&mut *ptr
}
}