mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Implement PyType_FromSpec & PyType_FromMetaclass (#9213)
* Implement `PyType_FromSpec` & `PyType_FromMetaclass` * Review
This commit is contained in:
1 parent
eb2ffc61dd
commit
c08375baeb
2 files changed
+113
-3
No files matched your search
@@ -5,7 +5,8 @@ use crate::pystate::with_vm;
|
||||
use crate::slots::{PySlot, PySlotKind, PySlotType};
|
||||
use crate::util::CStrExt;
|
||||
use crate::util::FfiPtrExt;
|
||||
use core::ffi::{c_char, c_int, c_ulong, c_void};
|
||||
use core::ffi::{c_char, c_int, c_uint, c_ulong, c_void};
|
||||
use core::ptr;
|
||||
use rustpython_vm::builtins::{PyStr, PyType};
|
||||
use rustpython_vm::function::{ItemDoc, PyMethodFlags};
|
||||
use rustpython_vm::types::{AtomicPyTypeFlags, PyTypeFlags, PyTypeSlots, SlotAccessor};
|
||||
@@ -22,6 +23,15 @@ pub struct PyType_Slot {
|
||||
pub pfunc: *mut c_void,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PyType_Spec {
|
||||
pub name: *const c_char,
|
||||
pub basicsize: c_int,
|
||||
pub itemsize: c_int,
|
||||
pub flags: c_uint,
|
||||
pub slots: *mut PyType_Slot,
|
||||
}
|
||||
|
||||
impl PyType_Slot {
|
||||
pub(crate) fn iter<'a>(mut slots: *const Self) -> impl Iterator<Item = &'a Self> {
|
||||
core::iter::from_fn(move || {
|
||||
@@ -104,11 +114,11 @@ pub unsafe extern "C" fn PyType_GetFullyQualifiedName(ptr: *mut PyTypeObject) ->
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn PyType_GetSlot(_ty: *const PyTypeObject, _slot: c_int) -> *mut c_void {
|
||||
core::ptr::null_mut()
|
||||
ptr::null_mut()
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn PyType_FromSlots(slots: *const PySlot) -> *mut PyObject {
|
||||
pub unsafe extern "C" fn PyType_FromSlots(slots: *const PySlot) -> *mut PyObject {
|
||||
with_vm(|vm| {
|
||||
let mut name = None;
|
||||
let mut base = None;
|
||||
@@ -254,6 +264,78 @@ pub extern "C" fn PyType_FromSlots(slots: *const PySlot) -> *mut PyObject {
|
||||
})
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn PyType_FromMetaclass(
|
||||
metaclass: *mut PyTypeObject,
|
||||
module: *mut PyObject,
|
||||
spec: *mut PyType_Spec,
|
||||
bases: *mut PyObject,
|
||||
) -> *mut PyObject {
|
||||
let &PyType_Spec {
|
||||
name,
|
||||
basicsize,
|
||||
itemsize,
|
||||
flags,
|
||||
slots: type_slots,
|
||||
} = unsafe { &*spec };
|
||||
let mut slots = [PySlot::SLOT_END; 9];
|
||||
let mut write_slot = {
|
||||
let mut iter = slots.iter_mut();
|
||||
move |slot| {
|
||||
debug_assert!(
|
||||
iter.len() >= 2,
|
||||
"PyType_FromMetaclass: last slot is reserved for SLOT_END"
|
||||
);
|
||||
let entry = iter
|
||||
.next()
|
||||
.expect("Too many slots for PyType_FromMetaclass");
|
||||
*entry = slot;
|
||||
}
|
||||
};
|
||||
|
||||
if !bases.is_null() {
|
||||
write_slot(PySlot::new(49, bases));
|
||||
}
|
||||
|
||||
if !metaclass.is_null() {
|
||||
write_slot(PySlot::new(107, metaclass));
|
||||
}
|
||||
|
||||
if !module.is_null() {
|
||||
write_slot(PySlot::new(108, module));
|
||||
}
|
||||
|
||||
write_slot(PySlot::new(95, name.cast_mut()));
|
||||
write_slot(PySlot::new(96, basicsize as isize));
|
||||
write_slot(PySlot::new(98, itemsize as isize));
|
||||
write_slot(PySlot::new(99, flags as u64));
|
||||
write_slot(PySlot::new(93, type_slots));
|
||||
|
||||
unsafe { PyType_FromSlots(slots.as_ptr()) }
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn PyType_FromModuleAndSpec(
|
||||
module: *mut PyObject,
|
||||
spec: *mut PyType_Spec,
|
||||
bases: *mut PyObject,
|
||||
) -> *mut PyObject {
|
||||
unsafe { PyType_FromMetaclass(ptr::null_mut(), module, spec, bases) }
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn PyType_FromSpecWithBases(
|
||||
spec: *mut PyType_Spec,
|
||||
bases: *mut PyObject,
|
||||
) -> *mut PyObject {
|
||||
unsafe { PyType_FromMetaclass(ptr::null_mut(), ptr::null_mut(), spec, bases) }
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn PyType_FromSpec(spec: *mut PyType_Spec) -> *mut PyObject {
|
||||
unsafe { PyType_FromMetaclass(ptr::null_mut(), ptr::null_mut(), spec, ptr::null_mut()) }
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn PyObject_GetTypeData(
|
||||
obj: *mut PyObject,
|
||||
|
||||
@@ -20,6 +20,16 @@ impl PySlot {
|
||||
const SLOT_OPTIONAL: u16 = 0x0001;
|
||||
const SLOT_STATIC: u16 = 0x0002;
|
||||
const SLOT_INTPTR: u16 = 0x0004;
|
||||
pub(crate) const SLOT_END: Self = unsafe { core::mem::zeroed() };
|
||||
|
||||
pub(crate) fn new(id: u16, value: impl Into<PySlotValue>) -> Self {
|
||||
Self {
|
||||
sl_id: id,
|
||||
sl_flags: 0,
|
||||
_reserved: 0,
|
||||
value: value.into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn iter<'a>(mut slots: *const Self) -> impl Iterator<Item = &'a Self> {
|
||||
core::iter::from_fn(move || {
|
||||
@@ -130,6 +140,24 @@ pub union PySlotValue {
|
||||
pub sl_uint64: u64,
|
||||
}
|
||||
|
||||
impl<T> From<*mut T> for PySlotValue {
|
||||
fn from(ptr: *mut T) -> Self {
|
||||
Self { sl_ptr: ptr.cast() }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<isize> for PySlotValue {
|
||||
fn from(size: isize) -> Self {
|
||||
Self { sl_size: size }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u64> for PySlotValue {
|
||||
fn from(value: u64) -> Self {
|
||||
Self { sl_uint64: value }
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub(crate) enum PySlotModule<'a> {
|
||||
|
||||
Reference in new issue
Block a user