use crate::ffi_ptr_ext::FfiPtrExt;
#[cfg(feature = "experimental-inspect")]
use crate::inspect::{type_hint_identifier, PyStaticExpr};
use crate::types::{PyAny, PyType};
use crate::{ffi, Bound, Python};
use std::ptr;
pub unsafe trait PyLayout<T> {}
pub trait PySizedLayout<T>: PyLayout<T> + Sized {}
pub unsafe trait PyTypeInfo: Sized {
#[deprecated(
since = "0.28.0",
note = "prefer using `::type_object(py).name()` to get the correct runtime value"
)]
const NAME: &'static str;
#[deprecated(
since = "0.28.0",
note = "prefer using `::type_object(py).module()` to get the correct runtime value"
)]
const MODULE: Option<&'static str>;
#[cfg(feature = "experimental-inspect")]
const TYPE_HINT: PyStaticExpr = type_hint_identifier!("_typeshed", "Incomplete");
fn type_object_raw(py: Python<'_>) -> *mut ffi::PyTypeObject;
#[inline]
fn type_object(py: Python<'_>) -> Bound<'_, PyType> {
unsafe {
Self::type_object_raw(py)
.cast::<ffi::PyObject>()
.assume_borrowed_unchecked(py)
.to_owned()
.cast_into_unchecked()
}
}
#[inline]
fn is_type_of(object: &Bound<'_, PyAny>) -> bool {
unsafe { ffi::PyObject_TypeCheck(object.as_ptr(), Self::type_object_raw(object.py())) != 0 }
}
#[inline]
fn is_exact_type_of(object: &Bound<'_, PyAny>) -> bool {
unsafe {
ptr::eq(
ffi::Py_TYPE(object.as_ptr()),
Self::type_object_raw(object.py()),
)
}
}
}
pub unsafe trait PyTypeCheck {
#[deprecated(
since = "0.27.0",
note = "Use ::classinfo_object() instead and format the type name at runtime. Note that using built-in cast features is often better than manual PyTypeCheck usage."
)]
const NAME: &'static str;
#[cfg(feature = "experimental-inspect")]
const TYPE_HINT: PyStaticExpr;
fn type_check(object: &Bound<'_, PyAny>) -> bool;
fn classinfo_object(py: Python<'_>) -> Bound<'_, PyAny>;
}
unsafe impl<T> PyTypeCheck for T
where
T: PyTypeInfo,
{
#[allow(deprecated)]
const NAME: &'static str = T::NAME;
#[cfg(feature = "experimental-inspect")]
const TYPE_HINT: PyStaticExpr = <T as PyTypeInfo>::TYPE_HINT;
#[inline]
fn type_check(object: &Bound<'_, PyAny>) -> bool {
T::is_type_of(object)
}
#[inline]
fn classinfo_object(py: Python<'_>) -> Bound<'_, PyAny> {
T::type_object(py).into_any()
}
}