use crate::ops::{Begin, BeginMut, End, EndMut, Increment, Indirection};
use crate::vector_ops::{Data, DataMut, Size};
use crate::{
cpp_iter, CppBox, CppDeletable, CppIterator, DynamicCast, Ref, StaticDowncast, StaticUpcast,
};
use std::ops::Deref;
use std::{fmt, slice};
pub struct Ptr<T>(*mut T);
impl<T> Clone for Ptr<T> {
fn clone(&self) -> Self {
Ptr(self.0)
}
}
impl<T> Copy for Ptr<T> {}
impl<T> fmt::Debug for Ptr<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Ptr({:?})", self.0)
}
}
impl<T> Ptr<T> {
pub unsafe fn from_raw(ptr: *const T) -> Self {
Ptr(ptr as *mut T)
}
pub unsafe fn null() -> Self {
Ptr(std::ptr::null_mut())
}
pub fn as_mut_raw_ptr(self) -> *mut T {
self.0 as *mut T
}
pub fn as_raw_ptr(self) -> *const T {
self.0
}
pub unsafe fn as_ref(self) -> Option<Ref<T>> {
Ref::from_raw(self.0)
}
pub unsafe fn as_raw_ref<'a>(self) -> Option<&'a T> {
self.as_ref().map(|r| r.as_raw_ref())
}
pub unsafe fn as_mut_raw_ref<'a>(self) -> Option<&'a mut T> {
self.as_ref().map(|r| r.as_mut_raw_ref())
}
pub fn is_null(self) -> bool {
self.0.is_null()
}
pub unsafe fn static_upcast<U>(self) -> Ptr<U>
where
T: StaticUpcast<U>,
{
StaticUpcast::static_upcast(self)
}
pub unsafe fn static_downcast<U>(self) -> Ptr<U>
where
T: StaticDowncast<U>,
{
StaticDowncast::static_downcast(self)
}
pub unsafe fn dynamic_cast<U>(self) -> Ptr<U>
where
T: DynamicCast<U>,
{
DynamicCast::dynamic_cast(self)
}
}
impl<V, T> Ptr<V>
where
V: Data<Output = *const T> + Size,
{
pub unsafe fn as_slice<'a>(self) -> &'a [T] {
let ptr = self.data();
let size = self.size();
slice::from_raw_parts(ptr, size)
}
}
impl<V, T> Ptr<V>
where
V: DataMut<Output = *mut T> + Size,
{
pub unsafe fn as_mut_slice<'a>(self) -> &'a mut [T] {
let ptr = self.data_mut();
let size = self.size();
slice::from_raw_parts_mut(ptr, size)
}
}
impl<T, T1, T2> Ptr<T>
where
T: Begin<Output = CppBox<T1>> + End<Output = CppBox<T2>>,
T1: CppDeletable + PartialEq<Ref<T2>> + Increment + Indirection,
T2: CppDeletable,
{
pub unsafe fn iter(self) -> CppIterator<T1, T2> {
cpp_iter(self.begin(), self.end())
}
}
impl<T, T1, T2> Ptr<T>
where
T: BeginMut<Output = CppBox<T1>> + EndMut<Output = CppBox<T2>>,
T1: CppDeletable + PartialEq<Ref<T2>> + Increment + Indirection,
T2: CppDeletable,
{
pub unsafe fn iter_mut(self) -> CppIterator<T1, T2> {
cpp_iter(self.begin_mut(), self.end_mut())
}
}
impl<T> Deref for Ptr<T> {
type Target = T;
fn deref(&self) -> &T {
if self.0.is_null() {
panic!("attempted to deref a null Ptr<T>");
}
unsafe { &(*self.0) }
}
}
impl<T: CppDeletable> Ptr<T> {
pub unsafe fn to_box(self) -> Option<CppBox<T>> {
CppBox::new(self)
}
}
pub struct NullPtr;
#[test]
fn ptr_deref() {
let i = 42;
unsafe {
let ptr: Ptr<i32> = Ptr::from_raw(&i);
assert_eq!(*ptr, 42);
}
}