use alloc::format;
use core::{
alloc::Layout,
fmt::Debug,
mem::MaybeUninit,
ops::{Deref, DerefMut},
ptr::NonNull,
};
use iceoryx2_bb_elementary_traits::allocator::{AllocationError, BaseAllocator};
use iceoryx2_log::fail;
pub use crate::vector::Vector;
use crate::vector::internal;
pub struct PolymorphicVec<'a, T, Allocator: BaseAllocator> {
data_ptr: *mut MaybeUninit<T>,
len: u64,
capacity: u64,
allocator: &'a Allocator,
}
impl<T: Debug, Allocator: BaseAllocator> Debug for PolymorphicVec<'_, T, Allocator> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(
f,
"PolymorphicVec<{}, {}> {{ capacity: {}, len: {} content: [ ",
core::any::type_name::<T>(),
core::any::type_name::<Allocator>(),
self.capacity,
self.len,
)?;
if !self.is_empty() {
write!(f, "{:?}", self[0])?;
}
for idx in 1..self.len() {
write!(f, ", {:?}", self[idx])?;
}
write!(f, " ] }}")
}
}
impl<T, Allocator: BaseAllocator> Drop for PolymorphicVec<'_, T, Allocator> {
fn drop(&mut self) {
self.clear();
unsafe {
self.allocator.deallocate(
NonNull::new_unchecked(self.data_ptr.cast()),
Layout::array::<MaybeUninit<T>>(self.capacity as _).unwrap(),
)
};
}
}
impl<T, Allocator: BaseAllocator> Deref for PolymorphicVec<'_, T, Allocator> {
type Target = [T];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl<T, Allocator: BaseAllocator> DerefMut for PolymorphicVec<'_, T, Allocator> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut_slice()
}
}
impl<T: PartialEq, Allocator: BaseAllocator> PartialEq for PolymorphicVec<'_, T, Allocator> {
fn eq(&self, other: &Self) -> bool {
if self.len != other.len {
return false;
}
for i in 0..self.len() {
if other[i] != self[i] {
return false;
}
}
true
}
}
impl<T: Eq, Allocator: BaseAllocator> Eq for PolymorphicVec<'_, T, Allocator> {}
unsafe impl<T: Send, Allocator: BaseAllocator> Send for PolymorphicVec<'_, T, Allocator> {}
impl<'a, T, Allocator: BaseAllocator> PolymorphicVec<'a, T, Allocator> {
pub fn new(allocator: &'a Allocator, capacity: usize) -> Result<Self, AllocationError> {
let layout = Layout::array::<MaybeUninit<T>>(capacity as _)
.expect("Memory size for the array is smaller than isize::MAX");
let mut data_ptr = match allocator.allocate(layout) {
Ok(ptr) => ptr,
Err(e) => {
let origin = format!(
"PolymorphicVec::<{}, {}>::new(.., {})",
core::any::type_name::<T>(),
core::any::type_name::<Allocator>(),
capacity
);
fail!(from origin, with e,
"Failed to create new PolymorphicVec due to a failure while allocating memory ({e:?}).");
}
};
Ok(Self {
data_ptr: unsafe { data_ptr.as_mut() }.as_mut_ptr().cast(),
len: 0,
capacity: capacity as _,
allocator,
})
}
pub fn from_fn<F: FnMut(usize) -> T>(
allocator: &'a Allocator,
capacity: usize,
mut func: F,
) -> Result<Self, AllocationError> {
let mut new_self = Self::new(allocator, capacity)?;
for n in 0..capacity {
unsafe { new_self.push_unchecked(func(n)) };
}
Ok(new_self)
}
}
impl<T: Clone, Allocator: BaseAllocator> PolymorphicVec<'_, T, Allocator> {
pub fn try_clone(&self) -> Result<Self, AllocationError> {
let layout = Layout::array::<MaybeUninit<T>>(self.capacity as _)
.expect("Memory size for the array is smaller than isize::MAX");
let mut data_ptr = match self.allocator.allocate(layout) {
Ok(ptr) => ptr,
Err(e) => {
let origin = format!(
"PolymorphicVec::<{}, {}>::try_clone()",
core::any::type_name::<T>(),
core::any::type_name::<Allocator>(),
);
fail!(from origin, with e,
"Failed to clone PolymorphicVec due to a failure while allocating memory ({e:?}).");
}
};
let mut new_self = Self {
data_ptr: unsafe { data_ptr.as_mut() }.as_mut_ptr().cast(),
len: 0,
capacity: self.capacity,
allocator: self.allocator,
};
unsafe { new_self.extend_from_slice_unchecked(self.as_slice()) };
Ok(new_self)
}
}
impl<T, Allocator: BaseAllocator> internal::VectorView<T> for PolymorphicVec<'_, T, Allocator> {
fn data(&self) -> &[MaybeUninit<T>] {
unsafe { core::slice::from_raw_parts(self.data_ptr, self.capacity()) }
}
unsafe fn data_mut(&mut self) -> &mut [MaybeUninit<T>] {
unsafe { core::slice::from_raw_parts_mut(self.data_ptr, self.capacity()) }
}
unsafe fn set_len(&mut self, len: u64) {
self.len = len
}
}
impl<T, Allocator: BaseAllocator> Vector<T> for PolymorphicVec<'_, T, Allocator> {
fn capacity(&self) -> usize {
self.capacity as _
}
fn len(&self) -> usize {
self.len as usize
}
}