use crate::error::{Result, ZiporaError};
use crate::memory::SecureMemoryPool;
use std::fmt;
use std::mem;
use std::ops::{Index, IndexMut};
use std::ptr::{self, NonNull};
use std::slice;
use std::sync::Arc;
extern crate libc;
pub const MAX_CAPACITY: u32 = u32::MAX;
#[cfg(target_arch = "x86_64")]
pub const CACHE_LINE_SIZE: usize = 64;
#[cfg(target_arch = "aarch64")]
pub const CACHE_LINE_SIZE: usize = 128;
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
pub const CACHE_LINE_SIZE: usize = 64;
#[cfg(target_os = "linux")]
fn get_usable_size(ptr: *mut u8, size: usize) -> usize {
unsafe {
unsafe extern "C" {
fn malloc_usable_size(ptr: *mut std::ffi::c_void) -> usize;
}
if !ptr.is_null() {
malloc_usable_size(ptr as *mut std::ffi::c_void)
} else {
size
}
}
}
#[cfg(any(target_os = "macos", target_os = "ios"))]
fn get_usable_size(ptr: *mut u8, size: usize) -> usize {
unsafe {
unsafe extern "C" {
fn malloc_size(ptr: *mut std::ffi::c_void) -> usize;
}
if !ptr.is_null() {
malloc_size(ptr as *mut std::ffi::c_void)
} else {
size
}
}
}
#[cfg(target_os = "windows")]
fn get_usable_size(ptr: *mut u8, size: usize) -> usize {
unsafe {
unsafe extern "C" {
fn _msize(ptr: *mut std::ffi::c_void) -> usize;
}
if !ptr.is_null() {
_msize(ptr as *mut std::ffi::c_void)
} else {
size
}
}
}
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "ios", target_os = "windows")))]
fn get_usable_size(_ptr: *mut u8, size: usize) -> usize {
size
}
#[cfg(feature = "nightly")]
macro_rules! likely {
($e:expr) => {
$e
};
}
#[cfg(not(feature = "nightly"))]
macro_rules! likely {
($e:expr) => {
$e
};
}
#[inline]
fn larger_capacity(old_cap: u32) -> u32 {
if old_cap == 0 {
return 8; }
let new_cap = (old_cap as u64 * 103 / 64) as u32;
new_cap.min(MAX_CAPACITY)
}
#[repr(C)] pub struct ValVec32<T> {
ptr: NonNull<T>,
len: u32,
capacity: u32,
}
pub type ValVec32Iter<'a, T> = std::slice::Iter<'a, T>;
pub type ValVec32IterMut<'a, T> = std::slice::IterMut<'a, T>;
impl<T> ValVec32<T> {
pub fn new() -> Self {
Self {
ptr: NonNull::dangling(),
len: 0,
capacity: 0,
}
}
pub fn with_capacity(capacity: u32) -> Result<Self> {
if capacity == 0 || mem::size_of::<T>() == 0 {
return Ok(Self::new());
}
let capacity_usize = capacity as usize;
let size = capacity_usize * mem::size_of::<T>();
let ptr = unsafe {
let raw_ptr = libc::malloc(size);
if raw_ptr.is_null() {
return Err(ZiporaError::out_of_memory(size));
}
NonNull::new_unchecked(raw_ptr as *mut T)
};
let actual_size = get_usable_size(ptr.as_ptr() as *mut u8, size);
let actual_capacity = (actual_size / mem::size_of::<T>()).min(MAX_CAPACITY as usize);
Ok(Self {
ptr,
len: 0,
capacity: actual_capacity as u32,
})
}
pub fn with_secure_pool(capacity: u32, _pool: Arc<SecureMemoryPool>) -> Result<Self> {
Self::with_capacity(capacity)
}
#[inline]
pub fn len(&self) -> u32 {
self.len
}
#[inline]
pub fn len_usize(&self) -> usize {
self.len as usize
}
#[inline]
pub fn capacity(&self) -> u32 {
self.capacity
}
#[inline]
pub fn capacity_usize(&self) -> usize {
self.capacity as usize
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len == 0
}
#[inline]
pub fn reserve(&mut self, additional: u32) -> Result<()> {
let required = self
.len
.checked_add(additional)
.ok_or_else(|| ZiporaError::invalid_data("Capacity overflow"))?;
if required <= self.capacity {
return Ok(());
}
let new_capacity = self.calculate_new_capacity(required);
self.grow_to(new_capacity)
}
#[inline]
fn calculate_new_capacity(&self, min_capacity: u32) -> u32 {
let new_cap = larger_capacity(self.capacity).max(min_capacity);
new_cap.min(MAX_CAPACITY)
}
#[cold]
#[inline(never)]
fn grow_to(&mut self, new_capacity: u32) -> Result<()> {
if new_capacity <= self.capacity {
return Ok(());
}
if mem::size_of::<T>() == 0 {
self.capacity = MAX_CAPACITY;
return Ok(());
}
let new_capacity_usize = new_capacity as usize;
let elem_size = mem::size_of::<T>();
let new_size = new_capacity_usize.saturating_mul(elem_size);
let new_ptr = if self.capacity == 0 {
unsafe {
let raw_ptr = libc::malloc(new_size);
if raw_ptr.is_null() {
return Err(ZiporaError::out_of_memory(new_size));
}
NonNull::new_unchecked(raw_ptr as *mut T)
}
} else {
unsafe {
let old_ptr = self.ptr.as_ptr() as *mut libc::c_void;
let raw_ptr = libc::realloc(old_ptr, new_size);
if raw_ptr.is_null() {
return Err(ZiporaError::out_of_memory(new_size));
}
NonNull::new_unchecked(raw_ptr as *mut T)
}
};
self.ptr = new_ptr;
self.capacity = new_capacity;
Ok(())
}
#[inline(always)]
pub fn push(&mut self, value: T) -> Result<()> {
let oldsize = self.len;
if likely!(oldsize < self.capacity) {
let lp = self.ptr.as_ptr(); unsafe {
ptr::write(lp.add(oldsize as usize), value);
}
self.len = oldsize + 1;
Ok(())
} else {
self.push_slow(value)
}
}
#[inline(always)]
pub fn push_panic(&mut self, value: T) {
let oldsize = self.len;
if likely!(oldsize < self.capacity) {
let lp = self.ptr.as_ptr(); unsafe {
ptr::write(lp.add(oldsize as usize), value);
}
self.len = oldsize + 1;
} else {
self.push_slow_panic(value);
}
}
#[cold]
#[inline(never)]
fn push_slow_panic(&mut self, value: T) {
if self.len == MAX_CAPACITY {
panic!("ValVec32 at maximum capacity");
}
let new_capacity = self.calculate_new_capacity(self.len + 1);
if self.grow_to(new_capacity).is_err() {
let fallback_capacity = new_capacity / 2;
if fallback_capacity > self.len {
if let Err(e) = self.grow_to(fallback_capacity) {
panic!("Failed to allocate memory: {}", e);
}
} else {
panic!("Insufficient memory for growth");
}
}
unsafe {
let ptr = self.ptr.as_ptr().add(self.len as usize);
ptr::write(ptr, value);
self.len += 1;
}
}
#[inline(always)]
pub unsafe fn unchecked_push(&mut self, value: T) {
debug_assert!(self.len < self.capacity);
unsafe {
ptr::write(self.ptr.as_ptr().offset(self.len as isize), value);
}
self.len += 1;
}
#[inline(always)]
pub unsafe fn unchecked_push_copy(&mut self, value: T)
where
T: Copy
{
debug_assert!(self.len < self.capacity);
unsafe {
*self.ptr.as_ptr().offset(self.len as isize) = value;
}
self.len += 1;
}
#[cold]
#[inline(never)]
fn push_slow(&mut self, value: T) -> Result<()> {
if self.len == MAX_CAPACITY {
return Err(ZiporaError::invalid_data("Vector at maximum capacity"));
}
let new_capacity = self.calculate_new_capacity(self.len + 1);
self.grow_to(new_capacity)?;
unsafe {
let ptr = self.ptr.as_ptr().add(self.len as usize);
ptr::write(ptr, value);
self.len += 1;
}
Ok(())
}
pub fn pop(&mut self) -> Option<T> {
if self.len == 0 {
return None;
}
self.len -= 1;
Some(unsafe { ptr::read(self.ptr.as_ptr().add(self.len as usize)) })
}
#[inline]
pub fn get(&self, index: u32) -> Option<&T> {
if index < self.len {
let index_usize = index as usize;
Some(unsafe { &*self.ptr.as_ptr().add(index_usize) })
} else {
None
}
}
#[inline]
pub unsafe fn get_unchecked(&self, index: u32) -> &T {
debug_assert!(index < self.len);
unsafe { &*self.ptr.as_ptr().add(index as usize) }
}
#[inline]
pub unsafe fn get_unchecked_mut(&mut self, index: u32) -> &mut T {
debug_assert!(index < self.len);
unsafe { &mut *self.ptr.as_ptr().add(index as usize) }
}
#[inline]
pub fn get_mut(&mut self, index: u32) -> Option<&mut T> {
if index < self.len {
let index_usize = index as usize;
Some(unsafe { &mut *self.ptr.as_ptr().add(index_usize) })
} else {
None
}
}
pub fn set(&mut self, index: u32, value: T) -> Result<()> {
if index >= self.len {
return Err(ZiporaError::invalid_data(format!(
"Index {} out of bounds for length {}",
index, self.len
)));
}
unsafe {
ptr::write(self.ptr.as_ptr().add(index as usize), value);
}
Ok(())
}
pub fn clear(&mut self) {
for i in 0..(self.len as usize) {
unsafe {
ptr::drop_in_place(self.ptr.as_ptr().add(i));
}
}
self.len = 0;
}
#[inline]
pub fn as_slice(&self) -> &[T] {
if self.len == 0 || mem::size_of::<T>() == 0 {
return &[];
}
unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len as usize) }
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [T] {
if self.len == 0 || mem::size_of::<T>() == 0 {
return &mut [];
}
unsafe { slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len as usize) }
}
pub fn extend_from_slice(&mut self, slice: &[T]) -> Result<()>
where
T: Clone,
{
if slice.is_empty() {
return Ok(());
}
let additional = slice.len() as u32;
let new_len = self
.len
.checked_add(additional)
.ok_or_else(|| ZiporaError::invalid_data("Length overflow"))?;
self.reserve(additional)?;
unsafe {
let dst = self.ptr.as_ptr().add(self.len as usize);
for (i, item) in slice.iter().enumerate() {
ptr::write(dst.add(i), item.clone());
}
}
self.len = new_len;
Ok(())
}
#[inline]
pub fn extend_from_slice_copy(&mut self, slice: &[T]) -> Result<()>
where
T: Copy,
{
if slice.is_empty() {
return Ok(());
}
let additional = slice.len() as u32;
let new_len = self
.len
.checked_add(additional)
.ok_or_else(|| ZiporaError::invalid_data("Length overflow"))?;
self.reserve(additional)?;
unsafe {
let dst = self.ptr.as_ptr().add(self.len as usize);
ptr::copy_nonoverlapping(slice.as_ptr(), dst, slice.len());
}
self.len = new_len;
Ok(())
}
#[inline]
pub fn push_n_copy(&mut self, count: u32, value: T) -> Result<()>
where
T: Copy,
{
if count == 0 {
return Ok(());
}
let new_len = self
.len
.checked_add(count)
.ok_or_else(|| ZiporaError::invalid_data("Length overflow"))?;
self.reserve(count)?;
unsafe {
let dst = self.ptr.as_ptr().add(self.len as usize);
if count <= 16 {
for i in 0..count as usize {
ptr::write(dst.add(i), value);
}
} else {
ptr::write(dst, value);
let mut written = 1usize;
while written < count as usize {
let to_copy = written.min(count as usize - written);
ptr::copy_nonoverlapping(dst, dst.add(written), to_copy);
written += to_copy;
}
}
}
self.len = new_len;
Ok(())
}
pub fn iter(&self) -> ValVec32Iter<'_, T> {
self.as_slice().iter()
}
pub fn iter_mut(&mut self) -> ValVec32IterMut<'_, T> {
self.as_mut_slice().iter_mut()
}
}
impl<T> Default for ValVec32<T> {
fn default() -> Self {
Self::new()
}
}
impl<'a, T> IntoIterator for &'a ValVec32<T> {
type Item = &'a T;
type IntoIter = ValVec32Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T> IntoIterator for &'a mut ValVec32<T> {
type Item = &'a mut T;
type IntoIter = ValVec32IterMut<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<T> Drop for ValVec32<T> {
fn drop(&mut self) {
self.clear();
if self.capacity > 0 && mem::size_of::<T>() > 0 {
unsafe {
libc::free(self.ptr.as_ptr() as *mut libc::c_void);
}
}
}
}
impl<T> Index<usize> for ValVec32<T> {
type Output = T;
#[inline(always)]
fn index(&self, index: usize) -> &Self::Output {
assert!(index < self.len as usize);
unsafe { &*self.ptr.as_ptr().add(index) }
}
}
impl<T> IndexMut<usize> for ValVec32<T> {
#[inline(always)]
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
assert!(index < self.len as usize);
unsafe { &mut *self.ptr.as_ptr().add(index) }
}
}
impl<T> Index<u32> for ValVec32<T> {
type Output = T;
#[inline(always)]
fn index(&self, index: u32) -> &Self::Output {
&self[index as usize]
}
}
impl<T> IndexMut<u32> for ValVec32<T> {
#[inline(always)]
fn index_mut(&mut self, index: u32) -> &mut Self::Output {
&mut self[index as usize]
}
}
impl<T: fmt::Debug> fmt::Debug for ValVec32<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.as_slice()).finish()
}
}
impl<T: Clone> Clone for ValVec32<T> {
fn clone(&self) -> Self {
let mut new_vec = Self::with_capacity(self.len)
.expect("Memory allocation failed during clone");
if self.len > 0 {
unsafe {
for i in 0..(self.len as usize) {
let value = (*self.ptr.as_ptr().add(i)).clone();
ptr::write(new_vec.ptr.as_ptr().add(i), value);
}
new_vec.len = self.len;
}
}
new_vec
}
}
impl<T: PartialEq> PartialEq for ValVec32<T> {
fn eq(&self, other: &Self) -> bool {
self.as_slice() == other.as_slice()
}
}
impl<T: Eq> Eq for ValVec32<T> {}
unsafe impl<T: Send> Send for ValVec32<T> {}
unsafe impl<T: Sync> Sync for ValVec32<T> {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new() {
let vec: ValVec32<i32> = ValVec32::new();
assert_eq!(vec.len(), 0);
assert_eq!(vec.capacity(), 0);
assert!(vec.is_empty());
}
#[test]
fn test_with_capacity() -> Result<()> {
let vec: ValVec32<i32> = ValVec32::with_capacity(10)?;
assert_eq!(vec.len(), 0);
assert!(vec.capacity() >= 10);
assert!(vec.is_empty());
Ok(())
}
#[test]
fn test_with_capacity_zero() -> Result<()> {
let vec: ValVec32<i32> = ValVec32::with_capacity(0)?;
assert_eq!(vec.len(), 0);
assert_eq!(vec.capacity(), 0);
Ok(())
}
#[test]
fn test_with_capacity_max() {
let result: Result<ValVec32<i32>> = ValVec32::with_capacity(MAX_CAPACITY);
let _ = result;
}
#[test]
fn test_push_and_get() -> Result<()> {
let mut vec = ValVec32::<i32>::new();
vec.push(42)?;
vec.push(84)?;
vec.push(126)?;
assert_eq!(vec.len(), 3);
assert_eq!(vec.get(0), Some(&42));
assert_eq!(vec.get(1), Some(&84));
assert_eq!(vec.get(2), Some(&126));
assert_eq!(vec.get(3), None);
Ok(())
}
#[test]
fn test_indexing() -> Result<()> {
let mut vec = ValVec32::<i32>::new();
vec.push(10)?;
vec.push(20)?;
assert_eq!(vec[0usize], 10);
assert_eq!(vec[1usize], 20);
vec[0usize] = 15;
assert_eq!(vec[0usize], 15);
Ok(())
}
#[test]
#[should_panic(expected = "assertion failed")]
fn test_index_panic() {
let vec: ValVec32<i32> = ValVec32::new();
let _ = vec[2usize]; }
#[test]
fn test_pop() -> Result<()> {
let mut vec = ValVec32::<i32>::new();
assert_eq!(vec.pop(), None);
vec.push(42)?;
vec.push(84)?;
assert_eq!(vec.pop(), Some(84));
assert_eq!(vec.pop(), Some(42));
assert_eq!(vec.pop(), None);
assert!(vec.is_empty());
Ok(())
}
#[test]
fn test_set() -> Result<()> {
let mut vec = ValVec32::<i32>::new();
vec.push(42)?;
vec.set(0, 84)?;
assert_eq!(vec[0usize], 84);
let result = vec.set(1, 126);
assert!(result.is_err());
Ok(())
}
#[test]
fn test_clear() -> Result<()> {
let mut vec = ValVec32::<i32>::new();
vec.push(1)?;
vec.push(2)?;
vec.push(3)?;
assert_eq!(vec.len(), 3);
vec.clear();
assert_eq!(vec.len(), 0);
assert!(vec.is_empty());
Ok(())
}
#[test]
fn test_as_slice() -> Result<()> {
let mut vec = ValVec32::<i32>::new();
vec.push(1)?;
vec.push(2)?;
vec.push(3)?;
let slice = vec.as_slice();
assert_eq!(slice, &[1, 2, 3]);
Ok(())
}
#[test]
fn test_clone() -> Result<()> {
let mut vec = ValVec32::<i32>::new();
vec.push(1)?;
vec.push(2)?;
vec.push(3)?;
let cloned = vec.clone();
assert_eq!(vec, cloned);
assert_eq!(vec.as_slice(), cloned.as_slice());
Ok(())
}
#[test]
fn test_equality() -> Result<()> {
let mut vec1 = ValVec32::new();
let mut vec2 = ValVec32::new();
assert_eq!(vec1, vec2);
vec1.push(42)?;
assert_ne!(vec1, vec2);
vec2.push(42)?;
assert_eq!(vec1, vec2);
Ok(())
}
#[test]
fn test_clone_preserves_exact_length() -> Result<()> {
for &n in &[0, 1, 7, 64, 255, 1000, 10_000] {
let mut vec = ValVec32::<u32>::new();
for i in 0..n {
vec.push(i)?;
}
let cloned = vec.clone();
assert_eq!(cloned.len(), vec.len(),
"clone must preserve exact length for n={}", n);
assert_eq!(cloned.as_slice(), vec.as_slice(),
"clone must preserve all elements for n={}", n);
}
Ok(())
}
#[test]
fn test_clone_independence() -> Result<()> {
let mut vec = ValVec32::<i32>::new();
for i in 0..500 {
vec.push(i)?;
}
let mut cloned = vec.clone();
cloned.push(999)?;
assert_eq!(vec.len(), 500);
assert_eq!(cloned.len(), 501);
assert_eq!(cloned[500usize], 999);
assert_eq!(vec.as_slice(), &cloned.as_slice()[..500]);
Ok(())
}
#[test]
fn test_growth() -> Result<()> {
let mut vec = ValVec32::<i32>::new();
let initial_capacity = vec.capacity();
for i in 0..10 {
vec.push(i)?;
}
assert!(vec.capacity() > initial_capacity);
assert_eq!(vec.len(), 10);
for i in 0usize..10 {
assert_eq!(vec[i], i as i32);
}
Ok(())
}
#[test]
fn test_reserve() -> Result<()> {
let mut vec = ValVec32::<i32>::new();
vec.reserve(100)?;
assert!(vec.capacity() >= 100);
assert_eq!(vec.len(), 0);
Ok(())
}
#[test]
fn test_memory_efficiency() -> Result<()> {
let _vec32 = ValVec32::<u64>::new();
let _std_vec = Vec::<u64>::new();
let vec32_size = std::mem::size_of::<ValVec32<u64>>();
let std_vec_size = std::mem::size_of::<Vec<u64>>();
println!("ValVec32 size: {}, Vec size: {}", vec32_size, std_vec_size);
assert!(vec32_size > 0);
assert!(std_vec_size > 0);
Ok(())
}
#[test]
fn test_branch_prediction_hints() {
assert!(likely!(true));
assert!(!likely!(false));
}
#[test]
fn test_small_size_growth() -> Result<()> {
let mut vec = ValVec32::<i32>::new();
vec.push(1)?;
let initial_capacity = vec.capacity();
assert!(initial_capacity >= 4);
let cache_line_elements = 64 / std::mem::size_of::<i32>();
let max_reasonable = (cache_line_elements * 2).max(32) as u32; assert!(initial_capacity <= max_reasonable,
"initial_capacity {} > max_reasonable {}", initial_capacity, max_reasonable);
let mut count = 1;
let first_capacity = initial_capacity;
while count < first_capacity {
vec.push(count as i32)?;
count += 1;
}
vec.push(count as i32)?;
assert!(vec.capacity() > first_capacity);
Ok(())
}
#[test]
fn test_zero_sized_types() -> Result<()> {
let mut vec = ValVec32::<()>::new();
assert_eq!(vec.len(), 0);
assert_eq!(vec.capacity(), 0);
assert!(vec.is_empty());
for _ in 0..10 {
vec.push(())?;
}
assert_eq!(vec.len(), 10);
assert_eq!(vec.get(0), Some(&()));
assert_eq!(vec.get(9), Some(&()));
assert_eq!(vec.get(10), None);
assert_eq!(vec.pop(), Some(()));
assert_eq!(vec.len(), 9);
Ok(())
}
}