#![allow(
clippy::len_without_is_empty, // This is really an internal interface...
)]
use core::marker::PhantomData;
use core::ptr::NonNull;
use core::ffi::c_void;
use crate::{CollectorId};
#[derive(Copy, Clone, Debug)]
pub enum ArrayPtrKind {
Fat,
Thin
}
pub unsafe trait GcArrayPtr: Copy + sealed::Sealed {
type Id: CollectorId;
const UNCHECKED_KIND: ArrayPtrKind;
unsafe fn from_raw_parts<T>(ptr: NonNull<T>, len: usize) -> Self;
fn as_raw_ptr(&self) -> *mut c_void;
fn len(&self) -> Option<usize>;
}
#[repr(transparent)]
pub struct FatArrayPtr<Id: CollectorId> {
slice: NonNull<[c_void]>,
marker: PhantomData<Id>
}
impl<Id: CollectorId> self::sealed::Sealed for FatArrayPtr<Id> {}
impl<Id: CollectorId> FatArrayPtr<Id> {
#[inline]
pub const fn len(&self) -> usize {
unsafe { (&*self.slice.as_ptr()).len() }
}
}
impl<Id: CollectorId> Copy for FatArrayPtr<Id> {}
impl<Id: CollectorId> Clone for FatArrayPtr<Id> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
unsafe impl<Id: CollectorId> GcArrayPtr for FatArrayPtr<Id> {
type Id = Id;
const UNCHECKED_KIND: ArrayPtrKind = ArrayPtrKind::Fat;
#[inline]
unsafe fn from_raw_parts<T>(ptr: NonNull<T>, len: usize) -> Self {
FatArrayPtr {
slice: NonNull::new_unchecked(
core::ptr::slice_from_raw_parts(
ptr.as_ptr() as *const T, len
) as *mut [T] as *mut [c_void]
),
marker: PhantomData
}
}
#[inline]
fn as_raw_ptr(&self) -> *mut c_void {
self.slice.as_ptr() as *mut c_void
}
#[inline]
fn len(&self) -> Option<usize> {
Some(self.len()) }
}
#[repr(transparent)]
pub struct ThinArrayPtr<Id: CollectorId> {
elements: NonNull<c_void>,
marker: PhantomData<Id>
}
impl<Id: CollectorId> Copy for ThinArrayPtr<Id> {}
impl<Id: CollectorId> Clone for ThinArrayPtr<Id> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl<Id: CollectorId> self::sealed::Sealed for ThinArrayPtr<Id> {}
unsafe impl<Id: CollectorId> GcArrayPtr for ThinArrayPtr<Id> {
type Id = Id;
const UNCHECKED_KIND: ArrayPtrKind = ArrayPtrKind::Thin;
#[inline]
unsafe fn from_raw_parts<T>(ptr: NonNull<T>, _len: usize) -> Self {
ThinArrayPtr { elements: ptr.cast(), marker: PhantomData }
}
#[inline]
fn as_raw_ptr(&self) -> *mut c_void {
self.elements.as_ptr()
}
#[inline]
fn len(&self) -> Option<usize> {
None
}
}
mod sealed {
pub trait Sealed {}
}