use std::alloc::{alloc, alloc_zeroed, dealloc, Layout};
use std::any::TypeId;
use std::fmt::Debug;
use std::marker::{PhantomData};
use std::mem::{transmute, transmute_copy};
use std::ops::{Deref, DerefMut};
use std::ptr::copy_nonoverlapping;
use crate::forbid_void;
use crate::unsafe_std::ptrs::into_raw_ptr::IntoRawPtr;
use super::*;
#[repr(transparent)]
#[derive(Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct RawPtr<T: ?Sized> {
ptr: *mut T,
_marker: PhantomData<T>,
}
impl<T: Sized> RawPtr<T> {
const NULL: RawPtr<T> = RawPtr::null();
#[inline(always)]
pub const fn null() -> RawPtr<T> {
Self {
ptr: 0 as *mut T,
_marker: PhantomData,
}
}
#[inline(always)]
pub const unsafe fn index<'a>(self, index: isize) -> &'a T {
&*self.ptr.offset(index)
}
#[inline(always)]
pub const unsafe fn index_mut<'a>(self, index: isize) -> &'a mut T {
&mut *self.ptr.offset(index)
}
#[inline(always)]
pub const unsafe fn copy_to(self, other: &mut Self) {
copy_nonoverlapping(self.ptr, other.ptr, size_of::<T>());
}
#[inline(always)]
pub unsafe fn mem_copy_to<D : IntoRawPtr>(self, other: D, size: usize)
where <D as IntoRawPtr>::Pointee: 'static
{
copy_nonoverlapping(self.ptr, other.to_ptr().cast().ptr, size)
}
#[inline(always)]
pub unsafe fn assign(mut self, value: T) {
*self.ptr = value;
}
#[inline(always)]
pub unsafe fn assign_cast<D: 'static>(mut self, value: D) {
forbid_void!(D);
self.assign(transmute_copy(&value));
}
#[inline(always)]
pub unsafe fn assign_check(mut self, value: T) -> ptr_utils::PtrState {
if self.ptr.is_null() {
ptr_utils::PtrState::Null
} else {
*self.ptr = value;
ptr_utils::PtrState::Val
}
}
#[inline(always)]
pub const unsafe fn cast_raw<U>(self) -> *mut U {
transmute(self.ptr)
}
#[inline(always)]
pub const unsafe fn cast_const_raw<U>(mut self) -> *const U {
transmute(self.ptr)
}
#[inline(always)]
pub const unsafe fn cast<U>(self) -> RawPtr<U> {
transmute(self)
}
#[inline(always)]
pub unsafe fn alloc() -> RawPtr<T> {
Self {
ptr: alloc_zeroed(Layout::new::<T>()) as *mut T,
_marker: PhantomData,
}
}
#[inline(always)]
pub unsafe fn calloc(amount: usize) -> RawPtr<T> {
Self {
ptr: alloc_zeroed(Layout::array::<T>(amount).unwrap()) as *mut T,
_marker: PhantomData,
}
}
#[inline(always)]
pub unsafe fn malloc(size: usize) -> RawPtr<T> {
Self {
ptr: alloc(Layout::array::<u8>(size).unwrap()) as *mut T,
_marker: PhantomData,
}
}
#[inline(always)]
pub unsafe fn rclone(&self) -> RawPtr<T> {
unsafe {
let mut new_ptr = RawPtr::alloc();
self.to_owned().copy_to(&mut new_ptr);
new_ptr
}
}
}
impl<T: ?Sized> RawPtr<T> {
#[inline(always)]
pub const fn new(value: &mut T) -> RawPtr<T> {
Self {
ptr: value as *mut T,
_marker: PhantomData,
}
}
#[inline(always)]
pub const unsafe fn from_raw(raw: *mut T) -> RawPtr<T> {
transmute(raw)
}
#[inline(always)]
pub unsafe fn free(self) {
dealloc(self.ptr as *mut u8, Layout::new::<Self>());
}
#[inline(always)]
pub const fn get_const_raw(self) -> *const T {
self.ptr as *const T
}
#[inline(always)]
pub const fn is_null(self) -> bool {
self.ptr.is_null()
}
#[inline(always)]
pub const unsafe fn as_ref<'a>(self) -> Option<&'a T> {
self.ptr.as_ref()
}
#[inline(always)]
pub const unsafe fn as_mut<'a>(mut self) -> Option<&'a mut T> {
self.ptr.as_mut()
}
#[inline(always)]
pub const unsafe fn as_raw(self) -> Option<*mut T> {
if self.ptr.is_null() {
None
} else {
Some(self.ptr)
}
}
#[inline(always)]
pub const unsafe fn as_const_raw(self) -> Option<*const T> {
if self.ptr.is_null() {
None
} else {
Some(self.ptr as *const T)
}
}
#[inline(always)]
pub const unsafe fn cast_ref<'a, U>(self) -> &'a U {
transmute(self.ptr as *const U)
}
#[inline(always)]
pub const unsafe fn cast_mut<'a, U>(mut self) -> &'a mut U {
transmute(self.ptr as *mut U)
}
#[inline(always)]
pub const unsafe fn to_owned(&self) -> RawPtr<T> {
RawPtr::<T>::from_raw(self.ptr)
}
}
impl<T> Deref for RawPtr<T> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &Self::Target {
unsafe { transmute(self.ptr) }
}
}
impl<T> DerefMut for RawPtr<T> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { transmute(self.ptr) }
}
}
impl<T: ?Sized> From<*mut T> for RawPtr<T> {
#[inline(always)]
fn from(value: *mut T) -> Self {
unsafe { transmute(value) }
}
}
impl<T: ?Sized> From<*const T> for RawPtr<T> {
#[inline(always)]
fn from(value: *const T) -> Self {
unsafe { transmute(value) }
}
}
impl<T: ?Sized> Clone for RawPtr<T> {
#![allow(useless_deprecated)]
#[deprecated (since = "0.0.0", note = "this is a blanket impl to allow the copy trait, please refer to the rclone method instead")]
fn clone(&self) -> Self {
unsafe {
unreachable!("this is a blanket impl to allow the copy trait, please refer to the rclone method instead")
}
}
}
impl<T: ?Sized> Copy for RawPtr<T> {}
unsafe impl<T: ?Sized> Send for RawPtr<T> {}
#[cfg(test)]
mod tests {
#[cfg(test)]
mod ptr {
use std::fmt::Debug;
use std::mem::transmute;
use super::super::*;
#[test]
fn new_and_null() {
let mut x = 32;
let p_x: RawPtr<i32> = RawPtr::new(&mut x);
unsafe { assert_eq!(*p_x, 32); }
let thin_null: *mut () = std::ptr::null_mut();
let wide_null: *mut dyn Debug = thin_null as *mut dyn Debug;
let p_null: RawPtr<i32> = RawPtr::NULL;
unsafe {
assert_eq!(p_null, transmute(std::ptr::null_mut::<RawPtr<i32>>()));
}
}
}
}