Remove specialization from async/sequence methods
This commit is contained in:
parent
0d082961aa
commit
d678093509
|
@ -955,6 +955,14 @@ impl pyo3::class::methods::HasMethodsInventory for MyClass {
|
|||
type Methods = Pyo3MethodsInventoryForMyClass;
|
||||
}
|
||||
pyo3::inventory::collect!(Pyo3MethodsInventoryForMyClass);
|
||||
|
||||
impl pyo3::class::proto_methods::HasProtoRegistry for MyClass {
|
||||
fn registory() -> &'static pyo3::class::proto_methods::PyProtoRegistry {
|
||||
static REGISTRY: pyo3::class::proto_methods::PyProtoRegistry
|
||||
= pyo3::class::proto_methods::PyProtoRegistry::new();
|
||||
®ISTRY
|
||||
}
|
||||
}
|
||||
# let gil = Python::acquire_gil();
|
||||
# let py = gil.python();
|
||||
# let cls = py.get_type::<MyClass>();
|
||||
|
|
|
@ -147,8 +147,8 @@ pub const OBJECT: Proto = Proto {
|
|||
|
||||
pub const ASYNC: Proto = Proto {
|
||||
name: "Async",
|
||||
slot_table: "",
|
||||
set_slot_table: "",
|
||||
slot_table: "pyo3::ffi::PyAsyncMethods",
|
||||
set_slot_table: "set_async_methods",
|
||||
methods: &[
|
||||
MethodProto::Unary {
|
||||
name: "__await__",
|
||||
|
@ -188,7 +188,11 @@ pub const ASYNC: Proto = Proto {
|
|||
"pyo3::class::pyasync::PyAsyncAexitProtocolImpl",
|
||||
),
|
||||
],
|
||||
slot_setters: &[],
|
||||
slot_setters: &[
|
||||
SlotSetter::new(&["__await__"], "set_await"),
|
||||
SlotSetter::new(&["__aiter__"], "set_aiter"),
|
||||
SlotSetter::new(&["__anext__"], "set_anext"),
|
||||
],
|
||||
};
|
||||
|
||||
pub const BUFFER: Proto = Proto {
|
||||
|
@ -390,8 +394,8 @@ pub const MAPPING: Proto = Proto {
|
|||
|
||||
pub const SEQ: Proto = Proto {
|
||||
name: "Sequence",
|
||||
slot_table: "",
|
||||
set_slot_table: "",
|
||||
slot_table: "pyo3::ffi::PySequenceMethods",
|
||||
set_slot_table: "set_sequence_methods",
|
||||
methods: &[
|
||||
MethodProto::Unary {
|
||||
name: "__len__",
|
||||
|
@ -449,7 +453,22 @@ pub const SEQ: Proto = Proto {
|
|||
},
|
||||
],
|
||||
py_methods: &[],
|
||||
slot_setters: &[],
|
||||
slot_setters: &[
|
||||
SlotSetter::new(&["__len__"], "set_len"),
|
||||
SlotSetter::new(&["__concat__"], "set_concat"),
|
||||
SlotSetter::new(&["__repeat__"], "set_repeat"),
|
||||
SlotSetter::new(&["__getitem__"], "set_getitem"),
|
||||
SlotSetter {
|
||||
proto_names: &["__setitem__", "__delitem__"],
|
||||
set_function: "set_setdelitem",
|
||||
skipped_setters: &["set_setitem", "set_delitem"],
|
||||
},
|
||||
SlotSetter::new(&["__setitem__"], "set_setitem"),
|
||||
SlotSetter::new(&["__delitem__"], "set_delitem"),
|
||||
SlotSetter::new(&["__contains__"], "set_contains"),
|
||||
SlotSetter::new(&["__inplace_concat__"], "set_inplace_concat"),
|
||||
SlotSetter::new(&["__inplace_repeat__"], "set_inplace_repeat"),
|
||||
],
|
||||
};
|
||||
|
||||
pub const NUM: Proto = Proto {
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use crate::class::{
|
||||
basic::PyObjectMethods, descr::PyDescrMethods, gc::PyGCMethods, iter::PyIterMethods,
|
||||
};
|
||||
use crate::ffi::{PyBufferProcs, PyMappingMethods, PyNumberMethods};
|
||||
use crate::ffi::{
|
||||
PyAsyncMethods, PyBufferProcs, PyMappingMethods, PyNumberMethods, PySequenceMethods,
|
||||
};
|
||||
use std::{
|
||||
ptr::{self, NonNull},
|
||||
sync::atomic::{AtomicPtr, Ordering},
|
||||
|
@ -10,6 +12,9 @@ use std::{
|
|||
/// Defines what we need for method protocols.
|
||||
/// Stub implementations are for rust-numpy.
|
||||
pub trait PyProtoMethods {
|
||||
fn async_methods() -> Option<NonNull<PyAsyncMethods>> {
|
||||
None
|
||||
}
|
||||
fn basic_methods() -> Option<NonNull<PyObjectMethods>> {
|
||||
None
|
||||
}
|
||||
|
@ -31,6 +36,9 @@ pub trait PyProtoMethods {
|
|||
fn iter_methods() -> Option<NonNull<PyIterMethods>> {
|
||||
None
|
||||
}
|
||||
fn sequence_methods() -> Option<NonNull<PySequenceMethods>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Indicates that a type has a protocol registory.
|
||||
|
@ -40,6 +48,9 @@ pub trait HasProtoRegistry: Sized + 'static {
|
|||
}
|
||||
|
||||
impl<T: HasProtoRegistry> PyProtoMethods for T {
|
||||
fn async_methods() -> Option<NonNull<PyAsyncMethods>> {
|
||||
NonNull::new(Self::registory().async_methods.load(Ordering::SeqCst))
|
||||
}
|
||||
fn basic_methods() -> Option<NonNull<PyObjectMethods>> {
|
||||
NonNull::new(Self::registory().basic_methods.load(Ordering::SeqCst))
|
||||
}
|
||||
|
@ -61,10 +72,15 @@ impl<T: HasProtoRegistry> PyProtoMethods for T {
|
|||
fn iter_methods() -> Option<NonNull<PyIterMethods>> {
|
||||
NonNull::new(Self::registory().iter_methods.load(Ordering::SeqCst))
|
||||
}
|
||||
fn sequence_methods() -> Option<NonNull<PySequenceMethods>> {
|
||||
NonNull::new(Self::registory().sequence_methods.load(Ordering::SeqCst))
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct PyProtoRegistry {
|
||||
/// Async protocols.
|
||||
async_methods: AtomicPtr<PyAsyncMethods>,
|
||||
/// Basic protocols.
|
||||
basic_methods: AtomicPtr<PyObjectMethods>,
|
||||
/// Buffer protocols.
|
||||
|
@ -79,11 +95,14 @@ pub struct PyProtoRegistry {
|
|||
number_methods: AtomicPtr<PyNumberMethods>,
|
||||
/// Iterator protocols.
|
||||
iter_methods: AtomicPtr<PyIterMethods>,
|
||||
/// Sequence protocols.
|
||||
sequence_methods: AtomicPtr<PySequenceMethods>,
|
||||
}
|
||||
|
||||
impl PyProtoRegistry {
|
||||
pub const fn new() -> Self {
|
||||
PyProtoRegistry {
|
||||
async_methods: AtomicPtr::new(ptr::null_mut()),
|
||||
basic_methods: AtomicPtr::new(ptr::null_mut()),
|
||||
buffer_methods: AtomicPtr::new(ptr::null_mut()),
|
||||
descr_methods: AtomicPtr::new(ptr::null_mut()),
|
||||
|
@ -91,8 +110,13 @@ impl PyProtoRegistry {
|
|||
mapping_methods: AtomicPtr::new(ptr::null_mut()),
|
||||
number_methods: AtomicPtr::new(ptr::null_mut()),
|
||||
iter_methods: AtomicPtr::new(ptr::null_mut()),
|
||||
sequence_methods: AtomicPtr::new(ptr::null_mut()),
|
||||
}
|
||||
}
|
||||
pub fn set_async_methods(&self, methods: PyAsyncMethods) {
|
||||
self.async_methods
|
||||
.store(Box::into_raw(Box::new(methods)), Ordering::SeqCst)
|
||||
}
|
||||
pub fn set_basic_methods(&self, methods: PyObjectMethods) {
|
||||
self.basic_methods
|
||||
.store(Box::into_raw(Box::new(methods)), Ordering::SeqCst)
|
||||
|
@ -121,4 +145,8 @@ impl PyProtoRegistry {
|
|||
self.iter_methods
|
||||
.store(Box::into_raw(Box::new(methods)), Ordering::SeqCst)
|
||||
}
|
||||
pub fn set_sequence_methods(&self, methods: PySequenceMethods) {
|
||||
self.sequence_methods
|
||||
.store(Box::into_raw(Box::new(methods)), Ordering::SeqCst)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,92 +85,29 @@ pub trait PyAsyncAexitProtocol<'p>: PyAsyncProtocol<'p> {
|
|||
type Result: Into<PyResult<Self::Success>>;
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PyAsyncProtocolImpl {
|
||||
fn tp_as_async() -> Option<ffi::PyAsyncMethods>;
|
||||
}
|
||||
|
||||
impl<T> PyAsyncProtocolImpl for T {
|
||||
default fn tp_as_async() -> Option<ffi::PyAsyncMethods> {
|
||||
None
|
||||
impl ffi::PyAsyncMethods {
|
||||
pub fn set_await<T>(&mut self)
|
||||
where
|
||||
T: for<'p> PyAsyncAwaitProtocol<'p>,
|
||||
{
|
||||
self.am_await = py_unary_func!(PyAsyncAwaitProtocol, T::__await__);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p, T> PyAsyncProtocolImpl for T
|
||||
where
|
||||
T: PyAsyncProtocol<'p>,
|
||||
{
|
||||
#[inline]
|
||||
fn tp_as_async() -> Option<ffi::PyAsyncMethods> {
|
||||
Some(ffi::PyAsyncMethods {
|
||||
am_await: Self::am_await(),
|
||||
am_aiter: Self::am_aiter(),
|
||||
am_anext: Self::am_anext(),
|
||||
})
|
||||
pub fn set_aiter<T>(&mut self)
|
||||
where
|
||||
T: for<'p> PyAsyncAiterProtocol<'p>,
|
||||
{
|
||||
self.am_aiter = py_unary_func!(PyAsyncAiterProtocol, T::__aiter__);
|
||||
}
|
||||
}
|
||||
|
||||
trait PyAsyncAwaitProtocolImpl {
|
||||
fn am_await() -> Option<ffi::unaryfunc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyAsyncAwaitProtocolImpl for T
|
||||
where
|
||||
T: PyAsyncProtocol<'p>,
|
||||
{
|
||||
default fn am_await() -> Option<ffi::unaryfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PyAsyncAwaitProtocolImpl for T
|
||||
where
|
||||
T: for<'p> PyAsyncAwaitProtocol<'p>,
|
||||
{
|
||||
#[inline]
|
||||
fn am_await() -> Option<ffi::unaryfunc> {
|
||||
py_unary_func!(PyAsyncAwaitProtocol, T::__await__)
|
||||
}
|
||||
}
|
||||
|
||||
trait PyAsyncAiterProtocolImpl {
|
||||
fn am_aiter() -> Option<ffi::unaryfunc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyAsyncAiterProtocolImpl for T
|
||||
where
|
||||
T: PyAsyncProtocol<'p>,
|
||||
{
|
||||
default fn am_aiter() -> Option<ffi::unaryfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PyAsyncAiterProtocolImpl for T
|
||||
where
|
||||
T: for<'p> PyAsyncAiterProtocol<'p>,
|
||||
{
|
||||
#[inline]
|
||||
fn am_aiter() -> Option<ffi::unaryfunc> {
|
||||
py_unary_func!(PyAsyncAiterProtocol, T::__aiter__)
|
||||
}
|
||||
}
|
||||
|
||||
trait PyAsyncAnextProtocolImpl {
|
||||
fn am_anext() -> Option<ffi::unaryfunc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PyAsyncAnextProtocolImpl for T
|
||||
where
|
||||
T: PyAsyncProtocol<'p>,
|
||||
{
|
||||
default fn am_anext() -> Option<ffi::unaryfunc> {
|
||||
None
|
||||
pub fn set_anext<T>(&mut self)
|
||||
where
|
||||
T: for<'p> PyAsyncAnextProtocol<'p>,
|
||||
{
|
||||
self.am_anext = anext::am_anext::<T>();
|
||||
}
|
||||
}
|
||||
|
||||
mod anext {
|
||||
use super::{PyAsyncAnextProtocol, PyAsyncAnextProtocolImpl};
|
||||
use super::PyAsyncAnextProtocol;
|
||||
use crate::callback::IntoPyCallbackOutput;
|
||||
use crate::err::PyResult;
|
||||
use crate::IntoPyPointer;
|
||||
|
@ -191,19 +128,17 @@ mod anext {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> PyAsyncAnextProtocolImpl for T
|
||||
#[inline]
|
||||
pub(super) fn am_anext<T>() -> Option<ffi::unaryfunc>
|
||||
where
|
||||
T: for<'p> PyAsyncAnextProtocol<'p>,
|
||||
{
|
||||
#[inline]
|
||||
fn am_anext() -> Option<ffi::unaryfunc> {
|
||||
py_unary_func!(
|
||||
PyAsyncAnextProtocol,
|
||||
T::__anext__,
|
||||
call_mut,
|
||||
*mut crate::ffi::PyObject,
|
||||
IterANextOutput
|
||||
)
|
||||
}
|
||||
py_unary_func!(
|
||||
PyAsyncAnextProtocol,
|
||||
T::__anext__,
|
||||
call_mut,
|
||||
*mut crate::ffi::PyObject,
|
||||
IterANextOutput
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,78 +126,75 @@ pub trait PySequenceInplaceRepeatProtocol<'p>: PySequenceProtocol<'p> + IntoPy<P
|
|||
type Result: Into<PyResult<Self>>;
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait PySequenceProtocolImpl {
|
||||
fn tp_as_sequence() -> Option<ffi::PySequenceMethods>;
|
||||
}
|
||||
|
||||
impl<T> PySequenceProtocolImpl for T {
|
||||
default fn tp_as_sequence() -> Option<ffi::PySequenceMethods> {
|
||||
None
|
||||
impl ffi::PySequenceMethods {
|
||||
pub fn set_len<T>(&mut self)
|
||||
where
|
||||
T: for<'p> PySequenceLenProtocol<'p>,
|
||||
{
|
||||
self.sq_length = py_len_func!(PySequenceLenProtocol, T::__len__);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p, T> PySequenceProtocolImpl for T
|
||||
where
|
||||
T: PySequenceProtocol<'p>,
|
||||
{
|
||||
fn tp_as_sequence() -> Option<ffi::PySequenceMethods> {
|
||||
Some(ffi::PySequenceMethods {
|
||||
sq_length: Self::sq_length(),
|
||||
sq_concat: Self::sq_concat(),
|
||||
sq_repeat: Self::sq_repeat(),
|
||||
sq_item: Self::sq_item(),
|
||||
was_sq_slice: ::std::ptr::null_mut(),
|
||||
sq_ass_item: sq_ass_item_impl::sq_ass_item::<Self>(),
|
||||
was_sq_ass_slice: ::std::ptr::null_mut(),
|
||||
sq_contains: Self::sq_contains(),
|
||||
sq_inplace_concat: Self::sq_inplace_concat(),
|
||||
sq_inplace_repeat: Self::sq_inplace_repeat(),
|
||||
})
|
||||
pub fn set_concat<T>(&mut self)
|
||||
where
|
||||
T: for<'p> PySequenceConcatProtocol<'p>,
|
||||
{
|
||||
self.sq_concat = py_binary_func!(PySequenceConcatProtocol, T::__concat__);
|
||||
}
|
||||
}
|
||||
|
||||
trait PySequenceLenProtocolImpl {
|
||||
fn sq_length() -> Option<ffi::lenfunc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PySequenceLenProtocolImpl for T
|
||||
where
|
||||
T: PySequenceProtocol<'p>,
|
||||
{
|
||||
default fn sq_length() -> Option<ffi::lenfunc> {
|
||||
None
|
||||
pub fn set_repeat<T>(&mut self)
|
||||
where
|
||||
T: for<'p> PySequenceRepeatProtocol<'p>,
|
||||
{
|
||||
self.sq_repeat = py_ssizearg_func!(PySequenceRepeatProtocol, T::__repeat__);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PySequenceLenProtocolImpl for T
|
||||
where
|
||||
T: for<'p> PySequenceLenProtocol<'p>,
|
||||
{
|
||||
fn sq_length() -> Option<ffi::lenfunc> {
|
||||
py_len_func!(PySequenceLenProtocol, T::__len__)
|
||||
pub fn set_getitem<T>(&mut self)
|
||||
where
|
||||
T: for<'p> PySequenceGetItemProtocol<'p>,
|
||||
{
|
||||
self.sq_item = py_ssizearg_func!(PySequenceGetItemProtocol, T::__getitem__);
|
||||
}
|
||||
}
|
||||
|
||||
trait PySequenceGetItemProtocolImpl {
|
||||
fn sq_item() -> Option<ffi::ssizeargfunc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PySequenceGetItemProtocolImpl for T
|
||||
where
|
||||
T: PySequenceProtocol<'p>,
|
||||
{
|
||||
default fn sq_item() -> Option<ffi::ssizeargfunc> {
|
||||
None
|
||||
pub fn set_setitem<T>(&mut self)
|
||||
where
|
||||
T: for<'p> PySequenceSetItemProtocol<'p>,
|
||||
{
|
||||
self.sq_ass_item = sq_ass_item_impl::set_item::<T>();
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PySequenceGetItemProtocolImpl for T
|
||||
where
|
||||
T: for<'p> PySequenceGetItemProtocol<'p>,
|
||||
{
|
||||
fn sq_item() -> Option<ffi::ssizeargfunc> {
|
||||
py_ssizearg_func!(PySequenceGetItemProtocol, T::__getitem__)
|
||||
pub fn set_delitem<T>(&mut self)
|
||||
where
|
||||
T: for<'p> PySequenceDelItemProtocol<'p>,
|
||||
{
|
||||
self.sq_ass_item = sq_ass_item_impl::del_item::<T>();
|
||||
}
|
||||
pub fn set_setdelitem<T>(&mut self)
|
||||
where
|
||||
T: for<'p> PySequenceDelItemProtocol<'p> + for<'p> PySequenceSetItemProtocol<'p>,
|
||||
{
|
||||
self.sq_ass_item = sq_ass_item_impl::set_del_item::<T>();
|
||||
}
|
||||
pub fn set_contains<T>(&mut self)
|
||||
where
|
||||
T: for<'p> PySequenceContainsProtocol<'p>,
|
||||
{
|
||||
self.sq_contains = py_binary_func!(PySequenceContainsProtocol, T::__contains__, c_int);
|
||||
}
|
||||
pub fn set_inplace_concat<T>(&mut self)
|
||||
where
|
||||
T: for<'p> PySequenceInplaceConcatProtocol<'p>,
|
||||
{
|
||||
self.sq_inplace_concat = py_binary_func!(
|
||||
PySequenceInplaceConcatProtocol,
|
||||
T::__inplace_concat__,
|
||||
*mut ffi::PyObject,
|
||||
call_mut
|
||||
)
|
||||
}
|
||||
pub fn set_inplace_repeat<T>(&mut self)
|
||||
where
|
||||
T: for<'p> PySequenceInplaceRepeatProtocol<'p>,
|
||||
{
|
||||
self.sq_inplace_repeat = py_ssizearg_func!(
|
||||
PySequenceInplaceRepeatProtocol,
|
||||
T::__inplace_repeat__,
|
||||
call_mut
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,275 +204,90 @@ where
|
|||
mod sq_ass_item_impl {
|
||||
use super::*;
|
||||
|
||||
/// ssizeobjargproc PySequenceMethods.sq_ass_item
|
||||
///
|
||||
/// This function is used by PySequence_SetItem() and has the same signature. It is also used
|
||||
/// by PyObject_SetItem() and PyObject_DelItem(), after trying the item assignment and deletion
|
||||
/// via the mp_ass_subscript slot. This slot may be left to NULL if the object does not support
|
||||
/// item assignment and deletion.
|
||||
pub(super) fn sq_ass_item<'p, T>() -> Option<ffi::ssizeobjargproc>
|
||||
where
|
||||
T: PySequenceProtocol<'p>,
|
||||
{
|
||||
if let Some(del_set_item) = T::del_set_item() {
|
||||
Some(del_set_item)
|
||||
} else if let Some(del_item) = T::del_item() {
|
||||
Some(del_item)
|
||||
} else if let Some(set_item) = T::set_item() {
|
||||
Some(set_item)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
trait SetItem {
|
||||
fn set_item() -> Option<ffi::ssizeobjargproc>;
|
||||
}
|
||||
|
||||
impl<'p, T> SetItem for T
|
||||
where
|
||||
T: PySequenceProtocol<'p>,
|
||||
{
|
||||
default fn set_item() -> Option<ffi::ssizeobjargproc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> SetItem for T
|
||||
pub(super) fn set_item<T>() -> Option<ffi::ssizeobjargproc>
|
||||
where
|
||||
T: for<'p> PySequenceSetItemProtocol<'p>,
|
||||
{
|
||||
fn set_item() -> Option<ffi::ssizeobjargproc> {
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
key: ffi::Py_ssize_t,
|
||||
value: *mut ffi::PyObject,
|
||||
) -> c_int
|
||||
where
|
||||
T: for<'p> PySequenceSetItemProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
key: ffi::Py_ssize_t,
|
||||
value: *mut ffi::PyObject,
|
||||
) -> c_int
|
||||
where
|
||||
T: for<'p> PySequenceSetItemProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
|
||||
|
||||
if value.is_null() {
|
||||
return Err(PyErr::new::<exceptions::NotImplementedError, _>(format!(
|
||||
"Item deletion is not supported by {:?}",
|
||||
stringify!(T)
|
||||
)));
|
||||
}
|
||||
if value.is_null() {
|
||||
return Err(PyErr::new::<exceptions::NotImplementedError, _>(format!(
|
||||
"Item deletion is not supported by {:?}",
|
||||
stringify!(T)
|
||||
)));
|
||||
}
|
||||
|
||||
let mut slf = slf.try_borrow_mut()?;
|
||||
let value = py.from_borrowed_ptr::<PyAny>(value);
|
||||
let value = value.extract()?;
|
||||
slf.__setitem__(key.into(), value).into()
|
||||
})
|
||||
}
|
||||
Some(wrap::<T>)
|
||||
let mut slf = slf.try_borrow_mut()?;
|
||||
let value = py.from_borrowed_ptr::<PyAny>(value);
|
||||
let value = value.extract()?;
|
||||
slf.__setitem__(key.into(), value).into()
|
||||
})
|
||||
}
|
||||
Some(wrap::<T>)
|
||||
}
|
||||
|
||||
trait DelItem {
|
||||
fn del_item() -> Option<ffi::ssizeobjargproc>;
|
||||
}
|
||||
|
||||
impl<'p, T> DelItem for T
|
||||
where
|
||||
T: PySequenceProtocol<'p>,
|
||||
{
|
||||
default fn del_item() -> Option<ffi::ssizeobjargproc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DelItem for T
|
||||
pub(super) fn del_item<T>() -> Option<ffi::ssizeobjargproc>
|
||||
where
|
||||
T: for<'p> PySequenceDelItemProtocol<'p>,
|
||||
{
|
||||
fn del_item() -> Option<ffi::ssizeobjargproc> {
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
key: ffi::Py_ssize_t,
|
||||
value: *mut ffi::PyObject,
|
||||
) -> c_int
|
||||
where
|
||||
T: for<'p> PySequenceDelItemProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
key: ffi::Py_ssize_t,
|
||||
value: *mut ffi::PyObject,
|
||||
) -> c_int
|
||||
where
|
||||
T: for<'p> PySequenceDelItemProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
|
||||
|
||||
if value.is_null() {
|
||||
slf.borrow_mut().__delitem__(key.into()).into()
|
||||
} else {
|
||||
Err(PyErr::new::<exceptions::NotImplementedError, _>(format!(
|
||||
"Item assignment not supported by {:?}",
|
||||
stringify!(T)
|
||||
)))
|
||||
}
|
||||
})
|
||||
}
|
||||
Some(wrap::<T>)
|
||||
if value.is_null() {
|
||||
slf.borrow_mut().__delitem__(key.into()).into()
|
||||
} else {
|
||||
Err(PyErr::new::<exceptions::NotImplementedError, _>(format!(
|
||||
"Item assignment not supported by {:?}",
|
||||
stringify!(T)
|
||||
)))
|
||||
}
|
||||
})
|
||||
}
|
||||
Some(wrap::<T>)
|
||||
}
|
||||
|
||||
trait DelSetItem {
|
||||
fn del_set_item() -> Option<ffi::ssizeobjargproc>;
|
||||
}
|
||||
|
||||
impl<'p, T> DelSetItem for T
|
||||
where
|
||||
T: PySequenceProtocol<'p>,
|
||||
{
|
||||
default fn del_set_item() -> Option<ffi::ssizeobjargproc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DelSetItem for T
|
||||
pub(super) fn set_del_item<T>() -> Option<ffi::ssizeobjargproc>
|
||||
where
|
||||
T: for<'p> PySequenceSetItemProtocol<'p> + for<'p> PySequenceDelItemProtocol<'p>,
|
||||
{
|
||||
fn del_set_item() -> Option<ffi::ssizeobjargproc> {
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
key: ffi::Py_ssize_t,
|
||||
value: *mut ffi::PyObject,
|
||||
) -> c_int
|
||||
where
|
||||
T: for<'p> PySequenceSetItemProtocol<'p> + for<'p> PySequenceDelItemProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
|
||||
unsafe extern "C" fn wrap<T>(
|
||||
slf: *mut ffi::PyObject,
|
||||
key: ffi::Py_ssize_t,
|
||||
value: *mut ffi::PyObject,
|
||||
) -> c_int
|
||||
where
|
||||
T: for<'p> PySequenceSetItemProtocol<'p> + for<'p> PySequenceDelItemProtocol<'p>,
|
||||
{
|
||||
crate::callback_body!(py, {
|
||||
let slf = py.from_borrowed_ptr::<PyCell<T>>(slf);
|
||||
|
||||
if value.is_null() {
|
||||
call_mut!(slf, __delitem__; key.into())
|
||||
} else {
|
||||
let value = py.from_borrowed_ptr::<PyAny>(value);
|
||||
let mut slf_ = slf.try_borrow_mut()?;
|
||||
let value = value.extract()?;
|
||||
slf_.__setitem__(key.into(), value).into()
|
||||
}
|
||||
})
|
||||
}
|
||||
Some(wrap::<T>)
|
||||
if value.is_null() {
|
||||
call_mut!(slf, __delitem__; key.into())
|
||||
} else {
|
||||
let value = py.from_borrowed_ptr::<PyAny>(value);
|
||||
let mut slf_ = slf.try_borrow_mut()?;
|
||||
let value = value.extract()?;
|
||||
slf_.__setitem__(key.into(), value).into()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait PySequenceContainsProtocolImpl {
|
||||
fn sq_contains() -> Option<ffi::objobjproc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PySequenceContainsProtocolImpl for T
|
||||
where
|
||||
T: PySequenceProtocol<'p>,
|
||||
{
|
||||
default fn sq_contains() -> Option<ffi::objobjproc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PySequenceContainsProtocolImpl for T
|
||||
where
|
||||
T: for<'p> PySequenceContainsProtocol<'p>,
|
||||
{
|
||||
fn sq_contains() -> Option<ffi::objobjproc> {
|
||||
py_binary_func!(PySequenceContainsProtocol, T::__contains__, c_int)
|
||||
}
|
||||
}
|
||||
|
||||
trait PySequenceConcatProtocolImpl {
|
||||
fn sq_concat() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PySequenceConcatProtocolImpl for T
|
||||
where
|
||||
T: PySequenceProtocol<'p>,
|
||||
{
|
||||
default fn sq_concat() -> Option<ffi::binaryfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PySequenceConcatProtocolImpl for T
|
||||
where
|
||||
T: for<'p> PySequenceConcatProtocol<'p>,
|
||||
{
|
||||
fn sq_concat() -> Option<ffi::binaryfunc> {
|
||||
py_binary_func!(PySequenceConcatProtocol, T::__concat__)
|
||||
}
|
||||
}
|
||||
|
||||
trait PySequenceRepeatProtocolImpl {
|
||||
fn sq_repeat() -> Option<ffi::ssizeargfunc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PySequenceRepeatProtocolImpl for T
|
||||
where
|
||||
T: PySequenceProtocol<'p>,
|
||||
{
|
||||
default fn sq_repeat() -> Option<ffi::ssizeargfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PySequenceRepeatProtocolImpl for T
|
||||
where
|
||||
T: for<'p> PySequenceRepeatProtocol<'p>,
|
||||
{
|
||||
fn sq_repeat() -> Option<ffi::ssizeargfunc> {
|
||||
py_ssizearg_func!(PySequenceRepeatProtocol, T::__repeat__)
|
||||
}
|
||||
}
|
||||
|
||||
trait PySequenceInplaceConcatProtocolImpl {
|
||||
fn sq_inplace_concat() -> Option<ffi::binaryfunc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PySequenceInplaceConcatProtocolImpl for T
|
||||
where
|
||||
T: PySequenceProtocol<'p>,
|
||||
{
|
||||
default fn sq_inplace_concat() -> Option<ffi::binaryfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PySequenceInplaceConcatProtocolImpl for T
|
||||
where
|
||||
T: for<'p> PySequenceInplaceConcatProtocol<'p>,
|
||||
{
|
||||
fn sq_inplace_concat() -> Option<ffi::binaryfunc> {
|
||||
py_binary_func!(
|
||||
PySequenceInplaceConcatProtocol,
|
||||
T::__inplace_concat__,
|
||||
*mut ffi::PyObject,
|
||||
call_mut
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
trait PySequenceInplaceRepeatProtocolImpl {
|
||||
fn sq_inplace_repeat() -> Option<ffi::ssizeargfunc>;
|
||||
}
|
||||
|
||||
impl<'p, T> PySequenceInplaceRepeatProtocolImpl for T
|
||||
where
|
||||
T: PySequenceProtocol<'p>,
|
||||
{
|
||||
default fn sq_inplace_repeat() -> Option<ffi::ssizeargfunc> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PySequenceInplaceRepeatProtocolImpl for T
|
||||
where
|
||||
T: for<'p> PySequenceInplaceRepeatProtocol<'p>,
|
||||
{
|
||||
fn sq_inplace_repeat() -> Option<ffi::ssizeargfunc> {
|
||||
py_ssizearg_func!(
|
||||
PySequenceInplaceRepeatProtocol,
|
||||
T::__inplace_repeat__,
|
||||
call_mut
|
||||
)
|
||||
Some(wrap::<T>)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -157,21 +157,14 @@ where
|
|||
unsafe { basic.as_ref() }.update_typeobj(type_object);
|
||||
}
|
||||
|
||||
fn to_ptr<T>(value: Option<T>) -> *mut T {
|
||||
value
|
||||
.map(|v| Box::into_raw(Box::new(v)))
|
||||
.unwrap_or_else(ptr::null_mut)
|
||||
}
|
||||
|
||||
// number methods
|
||||
type_object.tp_as_number = T::number_methods().map_or_else(ptr::null_mut, |p| p.as_ptr());
|
||||
// mapping methods
|
||||
type_object.tp_as_mapping = T::mapping_methods().map_or_else(ptr::null_mut, |p| p.as_ptr());
|
||||
// sequence methods
|
||||
type_object.tp_as_sequence =
|
||||
to_ptr(<T as class::sequence::PySequenceProtocolImpl>::tp_as_sequence());
|
||||
type_object.tp_as_sequence = T::sequence_methods().map_or_else(ptr::null_mut, |p| p.as_ptr());
|
||||
// async methods
|
||||
type_object.tp_as_async = to_ptr(<T as class::pyasync::PyAsyncProtocolImpl>::tp_as_async());
|
||||
type_object.tp_as_async = T::async_methods().map_or_else(ptr::null_mut, |p| p.as_ptr());
|
||||
// buffer protocol
|
||||
type_object.tp_as_buffer = T::buffer_methods().map_or_else(ptr::null_mut, |p| p.as_ptr());
|
||||
|
||||
|
|
Loading…
Reference in a new issue