use super::*;
use bindings::*;
pub struct Array<T: RuntimeType> {
data: *mut T::DefaultType,
len: u32,
}
impl<T: RuntimeType> Default for Array<T> {
fn default() -> Self {
Array { data: std::ptr::null_mut(), len: 0 }
}
}
impl<T: RuntimeType> Array<T> {
pub fn new() -> Self {
Self::default()
}
pub fn with_len(len: usize) -> Self {
assert!(len < std::u32::MAX as usize);
let bytes_amount = len.checked_mul(std::mem::size_of::<T>()).expect("Attempted to allocate too large an Array");
let data = unsafe { CoTaskMemAlloc(bytes_amount) as *mut T::DefaultType };
assert!(!data.is_null(), "Could not successfully allocate for Array");
unsafe {
std::ptr::write_bytes(data, 0, len);
}
let len = len as u32;
Self { data, len }
}
pub fn from_slice(values: &[T::DefaultType]) -> Self
where
T::DefaultType: Clone,
{
let mut array = Self::with_len(values.len());
array.clone_from_slice(values);
array
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn len(&self) -> usize {
self.len as usize
}
pub fn clear(&mut self) {
if self.is_empty() {
return;
}
let mut data = std::ptr::null_mut();
let mut len = 0;
std::mem::swap(&mut data, &mut self.data);
std::mem::swap(&mut len, &mut self.len);
unsafe {
std::ptr::drop_in_place(std::slice::from_raw_parts_mut(data, len as usize));
CoTaskMemFree(data as _);
}
}
#[doc(hidden)]
pub unsafe fn set_abi_len(&mut self) -> *mut u32 {
&mut self.len
}
#[doc(hidden)]
pub fn into_abi(self) -> (*mut T::Abi, u32) {
let abi = (self.data as *mut _, self.len);
std::mem::forget(self);
abi
}
}
impl<T: RuntimeType> std::ops::Deref for Array<T> {
type Target = [T::DefaultType];
fn deref(&self) -> &[T::DefaultType] {
if self.is_empty() {
return &[];
}
unsafe { std::slice::from_raw_parts(self.data, self.len as usize) }
}
}
impl<T: RuntimeType> std::ops::DerefMut for Array<T> {
fn deref_mut(&mut self) -> &mut [T::DefaultType] {
if self.is_empty() {
return &mut [];
}
unsafe { std::slice::from_raw_parts_mut(self.data, self.len as usize) }
}
}
impl<T: RuntimeType> Drop for Array<T> {
fn drop(&mut self) {
self.clear();
}
}
#[doc(hidden)]
pub struct ArrayProxy<T: RuntimeType> {
data: *mut *mut T::DefaultType,
len: *mut u32,
temp: std::mem::ManuallyDrop<Array<T>>,
}
impl<T: RuntimeType> ArrayProxy<T> {
pub fn from_raw_parts(data: *mut *mut T::DefaultType, len: *mut u32) -> Self {
Self { data, len, temp: std::mem::ManuallyDrop::new(Array::new()) }
}
pub fn as_array(&mut self) -> &mut Array<T> {
&mut self.temp
}
}
impl<T: RuntimeType> Drop for ArrayProxy<T> {
fn drop(&mut self) {
unsafe {
*self.data = self.temp.data;
*self.len = self.temp.len;
}
}
}