use crate::{QBox, QObject, QPointerOfQObject};
use cpp_core::{
CastFrom, CastInto, CppBox, CppDeletable, DynamicCast, Ptr, Ref, StaticDowncast, StaticUpcast,
};
use std::fmt;
use std::ops::Deref;
pub struct QPtr<T: StaticUpcast<QObject>> {
q_pointer: Option<CppBox<QPointerOfQObject>>,
target: Ptr<T>,
}
impl<T: StaticUpcast<QObject>> QPtr<T> {
pub unsafe fn new(target: impl CastInto<Ptr<T>>) -> Self {
let target = target.cast_into();
QPtr {
q_pointer: if target.is_null() {
None
} else {
Some(QPointerOfQObject::new_1a(Ptr::from_raw(
target.as_raw_ptr(),
)))
},
target,
}
}
pub unsafe fn from_raw(target: *const T) -> Self {
Self::new(Ptr::from_raw(target))
}
pub unsafe fn null() -> Self {
Self::new(Ptr::<T>::null())
}
pub unsafe fn is_null(&self) -> bool {
self.q_pointer.as_ref().map_or(true, |p| p.is_null())
}
pub unsafe fn as_ptr(&self) -> Ptr<T> {
if self.is_null() {
Ptr::null()
} else {
self.target
}
}
pub unsafe fn as_raw_ptr(&self) -> *const T {
self.as_ptr().as_raw_ptr()
}
pub unsafe fn as_mut_raw_ptr(&self) -> *mut T {
self.as_ptr().as_mut_raw_ptr()
}
pub unsafe fn as_ref(&self) -> Option<Ref<T>> {
self.as_ptr().as_ref()
}
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 unsafe fn static_upcast<U>(&self) -> QPtr<U>
where
T: StaticUpcast<U>,
U: StaticUpcast<QObject>,
{
QPtr::<U>::new(self.as_ptr().static_upcast::<U>())
}
pub unsafe fn static_downcast<U>(&self) -> QPtr<U>
where
T: StaticDowncast<U>,
U: StaticUpcast<QObject>,
{
QPtr::<U>::new(self.as_ptr().static_downcast())
}
pub unsafe fn dynamic_cast<U>(&self) -> QPtr<U>
where
T: DynamicCast<U>,
U: StaticUpcast<QObject>,
{
QPtr::<U>::new(self.as_ptr().dynamic_cast())
}
pub unsafe fn to_box(&self) -> Option<CppBox<T>>
where
T: CppDeletable,
{
self.as_ptr().to_box()
}
pub unsafe fn into_q_box(self) -> QBox<T>
where
T: CppDeletable,
{
QBox::from_q_ptr(self)
}
}
impl<T: StaticUpcast<QObject>> Clone for QPtr<T> {
fn clone(&self) -> Self {
unsafe { QPtr::<T>::new(self.as_ptr()) }
}
}
impl<T: StaticUpcast<QObject>> fmt::Debug for QPtr<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "QPtr({:?})", unsafe { self.as_raw_ptr() })
}
}
impl<T: StaticUpcast<QObject>> Deref for QPtr<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe {
let ptr = self.as_raw_ptr();
if ptr.is_null() {
panic!("attempted to deref a null QPtr<T>");
}
&*ptr
}
}
}
impl<'a, T, U> CastFrom<&'a QPtr<U>> for Ptr<T>
where
U: StaticUpcast<T> + StaticUpcast<QObject>,
{
unsafe fn cast_from(value: &'a QPtr<U>) -> Self {
CastFrom::cast_from(value.as_ptr())
}
}
impl<T, U> CastFrom<QPtr<U>> for Ptr<T>
where
U: StaticUpcast<T> + StaticUpcast<QObject>,
{
unsafe fn cast_from(value: QPtr<U>) -> Self {
CastFrom::cast_from(value.as_ptr())
}
}