use nstd_alloc::deps::nstd_core;
use nstd_core::slice::NSTDSlice;
use std::{
mem::ManuallyDrop,
os::raw::{c_int, c_void},
ptr::{self, addr_of_mut},
};
#[repr(C)]
#[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct NSTDVec {
pub size: usize,
pub capacity: usize,
pub element_size: usize,
pub data: *mut u8,
}
impl NSTDVec {
#[inline]
pub fn total_byte_count(&self) -> usize {
self.capacity * self.element_size
}
#[inline]
pub fn byte_count(&self) -> usize {
self.size * self.element_size
}
#[inline]
pub unsafe fn end_unchecked(&self) -> *mut u8 {
self.data.add(self.byte_count())
}
pub unsafe fn drop_from_vec<T>(&mut self) -> c_int {
let data_ptr = self.data as *mut ManuallyDrop<T>;
let data_slice = std::slice::from_raw_parts_mut(data_ptr, self.size);
for element in data_slice {
ManuallyDrop::<T>::drop(element);
}
nstd_collections_vec_free(self)
}
}
impl Default for NSTDVec {
#[inline]
fn default() -> Self {
Self {
size: 0,
capacity: 0,
element_size: 0,
data: ptr::null_mut(),
}
}
}
impl Clone for NSTDVec {
fn clone(&self) -> Self {
unsafe {
let mut new_vec =
nstd_collections_vec_new_with_capacity(self.element_size, self.capacity);
if !new_vec.data.is_null() {
let byte_count = self.byte_count();
let data = std::slice::from_raw_parts(self.data, byte_count);
let new_data = std::slice::from_raw_parts_mut(new_vec.data, byte_count);
new_data.copy_from_slice(data);
new_vec.size = self.size;
}
new_vec
}
}
}
impl<T> From<Vec<T>> for NSTDVec {
fn from(vec: Vec<T>) -> Self {
unsafe {
let element_size = std::mem::size_of::<ManuallyDrop<T>>();
let mut nstd_vec = nstd_collections_vec_new_with_capacity(element_size, vec.len());
if !nstd_vec.data.is_null() {
for element in vec {
let element = ManuallyDrop::new(element);
let element = &element as *const ManuallyDrop<T> as *const c_void;
nstd_collections_vec_push(&mut nstd_vec, element);
}
}
nstd_vec
}
}
}
#[inline]
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_collections_vec_new(element_size: usize) -> NSTDVec {
const INITIAL_CAPACITY: usize = 1;
NSTDVec {
size: 0,
capacity: INITIAL_CAPACITY,
element_size,
data: nstd_alloc::nstd_alloc_allocate(INITIAL_CAPACITY * element_size).cast(),
}
}
#[inline]
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_collections_vec_new_with_capacity(
element_size: usize,
capacity: usize,
) -> NSTDVec {
NSTDVec {
size: 0,
capacity,
element_size,
data: nstd_alloc::nstd_alloc_allocate(capacity * element_size).cast(),
}
}
#[inline]
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_collections_vec_as_slice(vec: &NSTDVec) -> NSTDSlice {
nstd_core::slice::nstd_core_slice_new(vec.size, vec.element_size, vec.data as *mut c_void)
}
#[inline]
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_collections_vec_get(vec: &NSTDVec, pos: usize) -> *mut c_void {
match vec.size > pos {
true => vec.data.add(pos * vec.element_size) as *mut c_void,
false => ptr::null_mut(),
}
}
#[inline]
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_collections_vec_first(vec: &NSTDVec) -> *mut c_void {
match vec.size > 0 {
true => vec.data as *mut c_void,
false => ptr::null_mut(),
}
}
#[inline]
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_collections_vec_last(vec: &NSTDVec) -> *mut c_void {
match vec.size > 0 {
true => vec.end_unchecked().sub(vec.element_size) as *mut c_void,
false => ptr::null_mut(),
}
}
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_collections_vec_push(
vec: &mut NSTDVec,
element: *const c_void,
) -> c_int {
if vec.size == vec.capacity {
let new_cap = (vec.capacity as f32 * 1.5).ceil() as usize;
match nstd_collections_vec_reserve(vec, new_cap) {
0 => (),
errc => return errc,
}
vec.capacity = new_cap;
}
let element = std::slice::from_raw_parts(element as *const u8, vec.element_size);
let data = std::slice::from_raw_parts_mut(vec.end_unchecked(), vec.element_size);
data.copy_from_slice(element);
vec.size += 1;
0
}
#[inline]
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_collections_vec_pop(vec: &mut NSTDVec) -> *mut c_void {
match vec.size > 0 {
true => {
vec.size -= 1;
vec.end_unchecked() as *mut c_void
}
false => ptr::null_mut(),
}
}
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_collections_vec_extend(
vec: &mut NSTDVec,
slice: &NSTDSlice,
) -> c_int {
if vec.element_size == slice.ptr.size {
if slice.size > 0 {
nstd_collections_vec_reserve(vec, vec.size + slice.size);
let mut ptr = slice.ptr.raw;
for _ in 0..slice.size {
nstd_collections_vec_push(vec, ptr);
ptr = ptr.add(slice.ptr.size);
}
}
return 0;
}
1
}
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_collections_vec_insert(
vec: &mut NSTDVec,
element: *const c_void,
index: usize,
) -> c_int {
if vec.size > index {
if vec.size == vec.capacity {
match nstd_collections_vec_reserve(vec, vec.capacity + 1) {
0 => (),
errc => return errc,
}
}
let index_pointer = nstd_collections_vec_get(vec, index) as *mut u8;
let next_index_pointer = index_pointer.add(vec.element_size);
let copy_size = (vec.size - index) * vec.element_size;
ptr::copy(index_pointer, next_index_pointer, copy_size);
let element = std::slice::from_raw_parts(element as *const u8, vec.element_size);
let data = std::slice::from_raw_parts_mut(index_pointer, vec.element_size);
data.copy_from_slice(element);
vec.size += 1;
0
}
else if vec.size == index {
nstd_collections_vec_push(vec, element)
}
else {
1
}
}
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_collections_vec_remove(vec: &mut NSTDVec, index: usize) -> c_int {
match vec.size > index {
true => {
let index_pointer = nstd_collections_vec_get(vec, index) as *mut u8;
let next_index_pointer = index_pointer.add(vec.element_size);
let copy_size = (vec.size - index - 1) * vec.element_size;
ptr::copy(next_index_pointer, index_pointer, copy_size);
vec.size -= 1;
0
}
false => 1,
}
}
#[inline]
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_collections_vec_clear(vec: &mut NSTDVec) {
vec.size = 0;
}
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_collections_vec_resize(vec: &mut NSTDVec, new_size: usize) -> c_int {
if vec.size < new_size {
if vec.capacity < new_size {
match nstd_collections_vec_reserve(vec, new_size) {
0 => (),
errc => return errc,
}
}
let new_bytes = (new_size - vec.size) * vec.element_size;
std::slice::from_raw_parts_mut(vec.end_unchecked(), new_bytes).fill(0);
}
vec.size = new_size;
0
}
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_collections_vec_reserve(vec: &mut NSTDVec, new_cap: usize) -> c_int {
if vec.capacity < new_cap {
let old_byte_count = vec.total_byte_count();
let new_byte_count = new_cap * vec.element_size;
match nstd_alloc::nstd_alloc_reallocate(
addr_of_mut!(vec.data).cast(),
old_byte_count,
new_byte_count,
) {
0 => {
vec.capacity = new_cap;
0
}
errc => errc,
}
} else {
1
}
}
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_collections_vec_shrink(vec: &mut NSTDVec) -> c_int {
if vec.size > 0 {
let old_byte_count = vec.total_byte_count();
let new_byte_count = vec.byte_count();
match nstd_alloc::nstd_alloc_reallocate(
addr_of_mut!(vec.data).cast(),
old_byte_count,
new_byte_count,
) {
0 => {
vec.capacity = vec.size;
0
}
errc => errc,
}
} else {
1
}
}
#[inline]
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_collections_vec_free(vec: &mut NSTDVec) -> c_int {
nstd_alloc::nstd_alloc_deallocate(addr_of_mut!(vec.data).cast(), vec.total_byte_count())
}