use crate::{QObject, QPtr};
use cpp_core::{
CastFrom, CastInto, CppBox, CppDeletable, DynamicCast, Ptr, Ref, StaticDowncast, StaticUpcast,
};
use std::ops::Deref;
use std::{fmt, mem};
pub struct QBox<T: StaticUpcast<QObject> + CppDeletable>(QPtr<T>);
impl<T: StaticUpcast<QObject> + CppDeletable> QBox<T> {
pub unsafe fn from_q_ptr(target: QPtr<T>) -> Self {
QBox(target)
}
pub unsafe fn new(target: impl CastInto<Ptr<T>>) -> Self {
QBox::from_q_ptr(QPtr::new(target))
}
pub unsafe fn from_raw(target: *const T) -> Self {
QBox::from_q_ptr(QPtr::from_raw(target))
}
pub unsafe fn null() -> Self {
QBox::from_q_ptr(QPtr::<T>::null())
}
pub unsafe fn is_null(&self) -> bool {
self.0.is_null()
}
pub unsafe fn as_ptr(&self) -> Ptr<T> {
self.0.as_ptr()
}
pub unsafe fn as_raw_ptr(&self) -> *const T {
self.0.as_raw_ptr()
}
pub unsafe fn as_mut_raw_ptr(&self) -> *mut T {
self.0.as_mut_raw_ptr()
}
pub unsafe fn as_ref(&self) -> Option<Ref<T>> {
self.0.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 into_box(self) -> Option<CppBox<T>> {
self.into_q_ptr().to_box()
}
pub unsafe fn into_q_ptr(mut self) -> QPtr<T> {
mem::replace(&mut self.0, QPtr::null())
}
pub unsafe fn into_ptr(self) -> Ptr<T> {
self.into_q_ptr().as_ptr()
}
pub unsafe fn into_raw_ptr(self) -> *mut T {
self.into_q_ptr().as_mut_raw_ptr()
}
}
impl<T: StaticUpcast<QObject> + CppDeletable> fmt::Debug for QBox<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "QBox({:?})", unsafe { self.as_raw_ptr() })
}
}
impl<T: StaticUpcast<QObject> + CppDeletable> Deref for QBox<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 QBox<T>");
}
&*ptr
}
}
}
impl<'a, T, U> CastFrom<&'a QBox<U>> for Ptr<T>
where
U: StaticUpcast<T> + StaticUpcast<QObject> + CppDeletable,
{
unsafe fn cast_from(value: &'a QBox<U>) -> Self {
CastFrom::cast_from(value.as_ptr())
}
}
impl<T: StaticUpcast<QObject> + CppDeletable> Drop for QBox<T> {
fn drop(&mut self) {
unsafe {
let ptr = self.as_ptr();
if !ptr.is_null() && ptr.static_upcast().parent().is_null() {
T::delete(&*ptr.as_raw_ptr());
}
}
}
}