#![allow(unsafe_code)]
use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps};
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use std::ptr::NonNull;
use std::{fmt, mem};
use to_shmem::{SharedMemoryBuilder, ToShmem};
#[repr(C)]
pub struct OwnedArray<T, const N: usize> {
ptr: NonNull<T>,
_phantom: PhantomData<T>,
}
impl<T, const N: usize> Drop for OwnedArray<T, N> {
#[inline]
fn drop(&mut self) {
unsafe {
drop(Box::from_raw(self.ptr.as_ptr() as *mut [T; N]));
}
}
}
unsafe impl<T: Send, const N: usize> Send for OwnedArray<T, N> {}
unsafe impl<T: Sync, const N: usize> Sync for OwnedArray<T, N> {}
impl<T: Clone, const N: usize> Clone for OwnedArray<T, N> {
#[inline]
fn clone(&self) -> Self {
std::array::from_fn(|i| self[i].clone()).into()
}
}
impl<T: fmt::Debug, const N: usize> fmt::Debug for OwnedArray<T, N> {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
self.deref().fmt(formatter)
}
}
impl<T: PartialEq, const N: usize> PartialEq for OwnedArray<T, N> {
fn eq(&self, other: &Self) -> bool {
self.deref().eq(other.deref())
}
}
impl<T: Eq, const N: usize> Eq for OwnedArray<T, N> {}
impl<T, const N: usize> OwnedArray<T, N> {
#[inline]
pub fn into_box(self) -> Box<[T; N]> {
let b = unsafe { Box::from_raw(self.ptr.as_ptr() as *mut [T; N]) };
mem::forget(self);
b
}
#[inline]
pub fn into_array(self) -> [T; N] {
*self.into_box()
}
}
impl<T, const N: usize> Deref for OwnedArray<T, N> {
type Target = [T; N];
#[inline(always)]
fn deref(&self) -> &Self::Target {
unsafe { &*(self.ptr.as_ptr() as *const [T; N]) }
}
}
impl<T, const N: usize> DerefMut for OwnedArray<T, N> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *(self.ptr.as_ptr() as *mut [T; N]) }
}
}
impl<T, const N: usize> From<[T; N]> for OwnedArray<T, N> {
#[inline]
fn from(values: [T; N]) -> Self {
Box::new(values).into()
}
}
impl<T, const N: usize> From<Box<[T; N]>> for OwnedArray<T, N> {
#[inline]
fn from(b: Box<[T; N]>) -> Self {
let ptr = unsafe { NonNull::new_unchecked(Box::into_raw(b) as *mut T) };
Self {
ptr,
_phantom: PhantomData,
}
}
}
impl<T: Sized, const N: usize> MallocShallowSizeOf for OwnedArray<T, N> {
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
unsafe { ops.malloc_size_of(self.ptr.as_ptr()) }
}
}
impl<T: MallocSizeOf + Sized, const N: usize> MallocSizeOf for OwnedArray<T, N> {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
self.shallow_size_of(ops) + (**self).size_of(ops)
}
}
impl<T: ToShmem + Sized, const N: usize> ToShmem for OwnedArray<T, N> {
fn to_shmem(&self, builder: &mut SharedMemoryBuilder) -> to_shmem::Result<Self> {
unsafe {
let dest = to_shmem::to_shmem_slice(self.iter(), builder)?;
Ok(mem::ManuallyDrop::new(Self::from(Box::from_raw(
dest as *mut [T; N],
))))
}
}
}