Remove specialization from async/sequence methods

This commit is contained in:
kngwyu 2020-06-06 17:11:08 +09:00
parent 0d082961aa
commit d678093509
6 changed files with 219 additions and 424 deletions

View file

@ -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();
&REGISTRY
}
}
# let gil = Python::acquire_gil();
# let py = gil.python();
# let cls = py.get_type::<MyClass>();

View file

@ -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 {

View file

@ -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)
}
}

View file

@ -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
)
}
}

View file

@ -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>)
}
}

View file

@ -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());