From a27d96231228cfcb9facc1cc49efe6cb1c16b535 Mon Sep 17 00:00:00 2001 From: Marvin Loebel Date: Thu, 14 May 2020 19:23:44 +0200 Subject: [PATCH 1/6] Fix FFI divergence between python27-sys and python3-sys --- python3-sys/src/memoryobject.rs | 1 + python3-sys/src/object.rs | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/python3-sys/src/memoryobject.rs b/python3-sys/src/memoryobject.rs index 27d60d05..56c5af35 100644 --- a/python3-sys/src/memoryobject.rs +++ b/python3-sys/src/memoryobject.rs @@ -21,6 +21,7 @@ extern "C" { size: Py_ssize_t, flags: c_int, ) -> *mut PyObject; + pub fn PyMemoryView_FromBuffer(view: *mut Py_buffer) -> *mut PyObject; pub fn PyMemoryView_GetContiguous( base: *mut PyObject, buffertype: c_int, diff --git a/python3-sys/src/object.rs b/python3-sys/src/object.rs index 09df770b..8f4ca006 100644 --- a/python3-sys/src/object.rs +++ b/python3-sys/src/object.rs @@ -430,6 +430,10 @@ mod typeobject { unsafe { core::mem::zeroed() } } } + pub const PyBufferProcs_INIT: PyBufferProcs = PyBufferProcs { + bf_getbuffer: None, + bf_releasebuffer: None, + }; #[repr(C)] #[derive(Copy)] From 5b7c30562c75c40c10f5f69a906be3b7bb22bde5 Mon Sep 17 00:00:00 2001 From: Marvin Loebel Date: Thu, 14 May 2020 19:24:51 +0200 Subject: [PATCH 2/6] Add support for the buffer protocol for read-only byte arrays --- python3-sys/src/object.rs | 4 +- src/buffer.rs | 54 ++++++ src/py_class/py_class.rs | 8 + src/py_class/py_class_impl.py | 20 +- src/py_class/py_class_impl2.rs | 331 ++++++++++++++++++--------------- src/py_class/py_class_impl3.rs | 331 ++++++++++++++++++--------------- src/py_class/slots.rs | 166 +++++++++++++++++ tests/test_class.rs | 147 +++++++++++++++ 8 files changed, 757 insertions(+), 304 deletions(-) diff --git a/python3-sys/src/object.rs b/python3-sys/src/object.rs index 8f4ca006..3fd67bf6 100644 --- a/python3-sys/src/object.rs +++ b/python3-sys/src/object.rs @@ -109,13 +109,13 @@ mod bufferinfo { } } - pub type getbufferproc = extern "C" fn( + pub type getbufferproc = unsafe extern "C" fn( arg1: *mut crate::object::PyObject, arg2: *mut Py_buffer, arg3: c_int, ) -> c_int; pub type releasebufferproc = - extern "C" fn(arg1: *mut crate::object::PyObject, arg2: *mut Py_buffer) -> (); + unsafe extern "C" fn(arg1: *mut crate::object::PyObject, arg2: *mut Py_buffer) -> (); /// Maximum number of dimensions pub const PyBUF_MAX_NDIM: c_int = 64; diff --git a/src/buffer.rs b/src/buffer.rs index 4c0662c2..a411c67d 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -661,6 +661,60 @@ impl_element!(isize, SignedInteger); impl_element!(f32, Float); impl_element!(f64, Float); +/// Trait for the backing storage of a PyBuffer provided from a Rust binding. +/// +/// It is unsafe because its implementation needs to uphold certain invariants. +/// See the method docs for more details. +// TODO: +// - Buffer request can not fail yet +// - Buffer can not actually store data inside the object itself, only in a +// standalone owned object, which usually means a heap allocated reference counted +// container. +pub unsafe trait BufferHandle: 'static + Send { + /// Returns the data of `Self` as a continous array of bytes. + /// + /// # Safety + /// + /// This needs to return an address that remains valid + /// and stable if `self` gets moved or transformed to or from a void pointer. + fn as_bytes(&self) -> &[u8]; + + /// Convert `self` into an owned void pointer. + /// + /// # Safety + /// + /// The returned pointer has to be a valid pointer that + /// can be converted back to `Self`. + fn to_owned_void_pointer(self) -> *mut libc::c_void; + + /// Convert an owned void pointer back to `Self`. This takes owenrship of the pointer. + /// + /// # Safety + /// + /// The passed `ptr` has been created by this trait, and is only + /// used at most once to convert back to `Self`. + unsafe fn from_owned_void_pointer(ptr: *mut libc::c_void) -> Self; +} + +#[doc(hidden)] +pub struct BufferHandleRaw { + pub buf: *mut libc::c_void, + pub len: crate::Py_ssize_t, + pub owner: *mut libc::c_void, +} + +impl BufferHandleRaw { + #[doc(hidden)] + #[inline] + pub unsafe fn new(handle: T) -> Self { + let slice = handle.as_bytes(); + let buf = slice.as_ptr() as *mut libc::c_void; + let len = slice.len() as crate::Py_ssize_t; + let owner = handle.to_owned_void_pointer(); + Self { buf, len, owner } + } +} + #[cfg(test)] mod test { use super::PyBuffer; diff --git a/src/py_class/py_class.rs b/src/py_class/py_class.rs index 80d6d64e..d3ce34bc 100644 --- a/src/py_class/py_class.rs +++ b/src/py_class/py_class.rs @@ -465,6 +465,10 @@ macro_rules! py_class { /* as_number */ [ /* slot: expr, */ ] /* as_sequence */ [ /* slot: expr, */ ] /* as_mapping */ [ /* slot: expr, */ ] + /* as_buffer */ [ + bf_getbuffer: {}, + bf_releasebuffer: {}, + ] /* setitem_delitem */ [ sdi_setitem: {}, sdi_delitem: {}, @@ -495,6 +499,10 @@ macro_rules! py_class { /* as_number */ [ /* slot: expr, */ ] /* as_sequence */ [ /* slot: expr, */ ] /* as_mapping */ [ /* slot: expr, */ ] + /* as_buffer */ [ + bf_getbuffer: {}, + bf_releasebuffer: {}, + ] /* setitem_delitem */ [ sdi_setitem: {}, sdi_delitem: {}, diff --git a/src/py_class/py_class_impl.py b/src/py_class/py_class_impl.py index c70fc4d7..6aee72ce 100644 --- a/src/py_class/py_class_impl.py +++ b/src/py_class/py_class_impl.py @@ -247,7 +247,8 @@ def write(text): ('nb', 'as_number', None), ('sq', 'as_sequence', None), ('mp', 'as_mapping', None), - ('sdi', 'setdelitem', ['sdi_setitem', 'sdi_delitem']) + ('bf', 'as_buffer', ['bf_getbuffer', 'bf_releasebuffer']), + ('sdi', 'setdelitem', ['sdi_setitem', 'sdi_delitem']), ) def generate_case(pattern, old_info=None, new_info=None, new_impl=None, new_slots=None, new_members=None, new_props=None): @@ -723,6 +724,19 @@ def inplace_numeric_operator(special_name, slot): operator(slot=slot, args=[Argument('other')])(special_name) +@special_method +def buffer_protocol(special_name, enabled): + if enabled: + pattern = 'def %s (&$slf:ident) -> $res_type:ty $body:block' % special_name + new_slots = [] + for slot in ['bf_getbuffer', 'bf_releasebuffer']: + new_slots.append((slot, '$crate::py_class_buffer_slot!(%s, $class::%s)' % (slot, special_name))) + generate_case(pattern, new_slots=new_slots, new_impl=''' + impl $class { + fn %s(&$slf, $py: $crate::Python<'_>) -> $res_type $body + } + ''' % special_name) + special_names = { '__init__': error('__init__ is not supported by py_class!; use __new__ instead.'), '__new__': special_class_method( @@ -870,6 +884,9 @@ def inplace_numeric_operator(special_name, slot): '__aiter__': unimplemented(), '__aenter__': unimplemented(), '__aexit__': unimplemented(), + + # Buffer protocol + '__buffer__': buffer_protocol(not PY2), } def main(): @@ -907,4 +924,3 @@ def main(): if __name__ == '__main__': main() - diff --git a/src/py_class/py_class_impl2.rs b/src/py_class/py_class_impl2.rs index b87e57dc..975676dc 100644 --- a/src/py_class/py_class_impl2.rs +++ b/src/py_class/py_class_impl2.rs @@ -341,7 +341,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -353,7 +353,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_clear: $crate::py_class_tp_clear!($class), ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -370,7 +370,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -383,7 +383,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_absolute: $crate::py_class_unary_slot!($class::__abs__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -400,7 +400,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -413,7 +413,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_add: $crate::py_class_binary_numeric_slot!($class::__add__), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -442,7 +442,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -455,7 +455,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_and: $crate::py_class_binary_numeric_slot!($class::__and__), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -476,7 +476,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -489,7 +489,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_nonzero: $crate::py_class_unary_slot!($class::__bool__, $crate::_detail::libc::c_int, $crate::py_class::slots::BoolConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -501,11 +501,42 @@ macro_rules! py_class_impl { { { def __bool__ $($tail:tt)* } $( $stuff:tt )* } => { $crate::py_error! { "Invalid signature for operator __bool__" } }; + { { def __buffer__ (&$slf:ident) -> $res_type:ty $body:block $($tail:tt)* } + $class:ident $py:ident $info:tt + /* slots: */ { + $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt + /* as_buffer */ [ + bf_getbuffer: {}, + bf_releasebuffer: {}, + ] + $setdelitem:tt + } + { $( $imp:item )* } + $members:tt $props:tt + } => { $crate::py_class_impl! { + { $($tail)* } + $class $py $info + /* slots: */ { + $type_slots $as_number $as_sequence $as_mapping + /* as_buffer */ [ + bf_getbuffer: { $crate::py_class_buffer_slot!(bf_getbuffer, $class::__buffer__) }, + bf_releasebuffer: { $crate::py_class_buffer_slot!(bf_releasebuffer, $class::__buffer__) }, + ] + $setdelitem + } + /* impl: */ { + $($imp)* + impl $class { + fn __buffer__(&$slf, $py: $crate::Python<'_>) -> $res_type $body + } + } + $members $props + }}; { { def __call__ (&$slf:ident) -> $res_type:ty { $( $body:tt )* } $($tail:tt)* } $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -517,7 +548,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_call: $crate::py_class_call_slot!{$class::__call__ []}, ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -529,7 +560,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -541,7 +572,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_call: $crate::py_argparse_parse_plist_impl!{py_class_call_slot {$class::__call__} [] ($($p)+,)}, ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -569,7 +600,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt $as_number:tt /* as_sequence */ [ $( $sq_slot_name:ident : $sq_slot_value:expr, )* ] - $as_mapping:tt $setdelitem:tt + $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -582,7 +613,7 @@ macro_rules! py_class_impl { $( $sq_slot_name : $sq_slot_value, )* sq_contains: $crate::py_class_contains_slot!($class::__contains__, [Option<&$item_name>]), ] - $as_mapping $setdelitem + $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -595,7 +626,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt $as_number:tt /* as_sequence */ [ $( $sq_slot_name:ident : $sq_slot_value:expr, )* ] - $as_mapping:tt $setdelitem:tt + $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -608,7 +639,7 @@ macro_rules! py_class_impl { $( $sq_slot_name : $sq_slot_value, )* sq_contains: $crate::py_class_contains_slot!($class::__contains__, [&$item_name]), ] - $as_mapping $setdelitem + $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -621,7 +652,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt $as_number:tt /* as_sequence */ [ $( $sq_slot_name:ident : $sq_slot_value:expr, )* ] - $as_mapping:tt $setdelitem:tt + $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -634,7 +665,7 @@ macro_rules! py_class_impl { $( $sq_slot_name : $sq_slot_value, )* sq_contains: $crate::py_class_contains_slot!($class::__contains__, [$item_name]), ] - $as_mapping $setdelitem + $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -661,7 +692,7 @@ macro_rules! py_class_impl { { { def __delitem__(&$slf:ident, $key:ident : Option<&$key_name:ty>) -> $res_type:ty { $($body:tt)* } $($tail:tt)* } $class:ident $py:ident $info:tt /* slots: */ { - $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt + $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt /* setdelitem */ [ sdi_setitem: $sdi_setitem_slot_value:tt, sdi_delitem: {}, @@ -673,7 +704,7 @@ macro_rules! py_class_impl { { $($tail)* } $class $py $info /* slots: */ { - $type_slots $as_number $as_sequence $as_mapping + $type_slots $as_number $as_sequence $as_mapping $as_buffer /* setdelitem */ [ sdi_setitem: $sdi_setitem_slot_value, sdi_delitem: { $crate::py_class_binary_slot!($class::__delitem__, [Option<&$key_name>], $crate::_detail::libc::c_int, $crate::py_class::slots::UnitCallbackConverter) }, @@ -688,7 +719,7 @@ macro_rules! py_class_impl { { { def __delitem__(&$slf:ident, $key:ident : &$key_name:ty) -> $res_type:ty { $($body:tt)* } $($tail:tt)* } $class:ident $py:ident $info:tt /* slots: */ { - $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt + $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt /* setdelitem */ [ sdi_setitem: $sdi_setitem_slot_value:tt, sdi_delitem: {}, @@ -700,7 +731,7 @@ macro_rules! py_class_impl { { $($tail)* } $class $py $info /* slots: */ { - $type_slots $as_number $as_sequence $as_mapping + $type_slots $as_number $as_sequence $as_mapping $as_buffer /* setdelitem */ [ sdi_setitem: $sdi_setitem_slot_value, sdi_delitem: { $crate::py_class_binary_slot!($class::__delitem__, [&$key_name], $crate::_detail::libc::c_int, $crate::py_class::slots::UnitCallbackConverter) }, @@ -715,7 +746,7 @@ macro_rules! py_class_impl { { { def __delitem__(&$slf:ident, $key:ident : $key_name:ty) -> $res_type:ty { $($body:tt)* } $($tail:tt)* } $class:ident $py:ident $info:tt /* slots: */ { - $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt + $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt /* setdelitem */ [ sdi_setitem: $sdi_setitem_slot_value:tt, sdi_delitem: {}, @@ -727,7 +758,7 @@ macro_rules! py_class_impl { { $($tail)* } $class $py $info /* slots: */ { - $type_slots $as_number $as_sequence $as_mapping + $type_slots $as_number $as_sequence $as_mapping $as_buffer /* setdelitem */ [ sdi_setitem: $sdi_setitem_slot_value, sdi_delitem: { $crate::py_class_binary_slot!($class::__delitem__, [$key_name], $crate::_detail::libc::c_int, $crate::py_class::slots::UnitCallbackConverter) }, @@ -789,7 +820,7 @@ macro_rules! py_class_impl { $type_slots:tt $as_number:tt /* as_sequence */ [ $( $sq_slot_name:ident : $sq_slot_value:expr, )* ] /* as_mapping */ [ $( $mp_slot_name:ident : $mp_slot_value:expr, )* ] - $setdelitem:tt + $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -806,7 +837,7 @@ macro_rules! py_class_impl { $( $mp_slot_name : $mp_slot_value, )* mp_subscript: $crate::py_class_binary_slot!($class::__getitem__, [Option<&$key_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $setdelitem + $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -820,7 +851,7 @@ macro_rules! py_class_impl { $type_slots:tt $as_number:tt /* as_sequence */ [ $( $sq_slot_name:ident : $sq_slot_value:expr, )* ] /* as_mapping */ [ $( $mp_slot_name:ident : $mp_slot_value:expr, )* ] - $setdelitem:tt + $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -837,7 +868,7 @@ macro_rules! py_class_impl { $( $mp_slot_name : $mp_slot_value, )* mp_subscript: $crate::py_class_binary_slot!($class::__getitem__, [&$key_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $setdelitem + $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -851,7 +882,7 @@ macro_rules! py_class_impl { $type_slots:tt $as_number:tt /* as_sequence */ [ $( $sq_slot_name:ident : $sq_slot_value:expr, )* ] /* as_mapping */ [ $( $mp_slot_name:ident : $mp_slot_value:expr, )* ] - $setdelitem:tt + $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -868,7 +899,7 @@ macro_rules! py_class_impl { $( $mp_slot_name : $mp_slot_value, )* mp_subscript: $crate::py_class_binary_slot!($class::__getitem__, [$key_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $setdelitem + $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -888,7 +919,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -900,7 +931,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_hash: $crate::py_class_unary_slot!($class::__hash__, $crate::Py_hash_t, $crate::py_class::slots::HashConverter), ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -917,7 +948,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -930,7 +961,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_add: $crate::py_class_binary_slot!($class::__iadd__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -943,7 +974,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -956,7 +987,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_add: $crate::py_class_binary_slot!($class::__iadd__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -969,7 +1000,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -982,7 +1013,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_add: $crate::py_class_binary_slot!($class::__iadd__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -999,7 +1030,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1012,7 +1043,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_and: $crate::py_class_binary_slot!($class::__iand__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1025,7 +1056,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1038,7 +1069,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_and: $crate::py_class_binary_slot!($class::__iand__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1051,7 +1082,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1064,7 +1095,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_and: $crate::py_class_binary_slot!($class::__iand__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1085,7 +1116,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1098,7 +1129,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_floor_divide: $crate::py_class_binary_slot!($class::__ifloordiv__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1111,7 +1142,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1124,7 +1155,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_floor_divide: $crate::py_class_binary_slot!($class::__ifloordiv__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1137,7 +1168,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1150,7 +1181,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_floor_divide: $crate::py_class_binary_slot!($class::__ifloordiv__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1167,7 +1198,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1180,7 +1211,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_lshift: $crate::py_class_binary_slot!($class::__ilshift__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1193,7 +1224,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1206,7 +1237,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_lshift: $crate::py_class_binary_slot!($class::__ilshift__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1219,7 +1250,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1232,7 +1263,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_lshift: $crate::py_class_binary_slot!($class::__ilshift__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1249,7 +1280,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1262,7 +1293,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_matrix_multiply: $crate::py_class_binary_slot!($class::__imatmul__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1275,7 +1306,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1288,7 +1319,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_matrix_multiply: $crate::py_class_binary_slot!($class::__imatmul__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1301,7 +1332,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1314,7 +1345,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_matrix_multiply: $crate::py_class_binary_slot!($class::__imatmul__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1331,7 +1362,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1344,7 +1375,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_remainder: $crate::py_class_binary_slot!($class::__imod__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1357,7 +1388,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1370,7 +1401,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_remainder: $crate::py_class_binary_slot!($class::__imod__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1383,7 +1414,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1396,7 +1427,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_remainder: $crate::py_class_binary_slot!($class::__imod__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1413,7 +1444,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1426,7 +1457,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_multiply: $crate::py_class_binary_slot!($class::__imul__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1439,7 +1470,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1452,7 +1483,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_multiply: $crate::py_class_binary_slot!($class::__imul__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1465,7 +1496,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1478,7 +1509,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_multiply: $crate::py_class_binary_slot!($class::__imul__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1511,7 +1542,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1524,7 +1555,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_invert: $crate::py_class_unary_slot!($class::__invert__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1541,7 +1572,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1554,7 +1585,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_or: $crate::py_class_binary_slot!($class::__ior__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1567,7 +1598,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1580,7 +1611,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_or: $crate::py_class_binary_slot!($class::__ior__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1593,7 +1624,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1606,7 +1637,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_or: $crate::py_class_binary_slot!($class::__ior__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1627,7 +1658,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1640,7 +1671,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_rshift: $crate::py_class_binary_slot!($class::__irshift__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1653,7 +1684,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1666,7 +1697,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_rshift: $crate::py_class_binary_slot!($class::__irshift__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1679,7 +1710,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1692,7 +1723,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_rshift: $crate::py_class_binary_slot!($class::__irshift__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1709,7 +1740,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1722,7 +1753,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_subtract: $crate::py_class_binary_slot!($class::__isub__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1735,7 +1766,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1748,7 +1779,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_subtract: $crate::py_class_binary_slot!($class::__isub__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1761,7 +1792,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1774,7 +1805,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_subtract: $crate::py_class_binary_slot!($class::__isub__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1790,7 +1821,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1802,7 +1833,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_iter: $crate::py_class_unary_slot!($class::__iter__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1819,7 +1850,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1832,7 +1863,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_true_divide: $crate::py_class_binary_slot!($class::__itruediv__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1845,7 +1876,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1858,7 +1889,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_true_divide: $crate::py_class_binary_slot!($class::__itruediv__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1871,7 +1902,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1884,7 +1915,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_true_divide: $crate::py_class_binary_slot!($class::__itruediv__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1901,7 +1932,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1914,7 +1945,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_xor: $crate::py_class_binary_slot!($class::__ixor__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1927,7 +1958,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1940,7 +1971,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_xor: $crate::py_class_binary_slot!($class::__ixor__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1953,7 +1984,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1966,7 +1997,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_xor: $crate::py_class_binary_slot!($class::__ixor__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1988,7 +2019,7 @@ macro_rules! py_class_impl { $type_slots:tt $as_number:tt /* as_sequence */ [ $( $sq_slot_name:ident : $sq_slot_value:expr, )* ] /* as_mapping */ [ $( $mp_slot_name:ident : $mp_slot_value:expr, )* ] - $setdelitem:tt + $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2005,7 +2036,7 @@ macro_rules! py_class_impl { $( $mp_slot_name : $mp_slot_value, )* mp_length: Some($crate::_detail::ffi::PySequence_Size), ] - $setdelitem + $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2026,7 +2057,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2039,7 +2070,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_lshift: $crate::py_class_binary_numeric_slot!($class::__lshift__), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2068,7 +2099,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2081,7 +2112,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_multiply: $crate::py_class_binary_numeric_slot!($class::__mul__), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2102,7 +2133,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2115,7 +2146,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_negative: $crate::py_class_unary_slot!($class::__neg__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2131,7 +2162,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2143,7 +2174,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_new: $crate::py_class_wrap_newfunc!{$class::__new__ []}, ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2155,7 +2186,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2167,7 +2198,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_new: $crate::py_argparse_parse_plist_impl!{py_class_wrap_newfunc {$class::__new__} [] ($($p)+,)}, ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2182,7 +2213,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2194,7 +2225,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_iternext: $crate::py_class_unary_slot!($class::__next__, *mut $crate::_detail::ffi::PyObject, $crate::py_class::slots::IterNextResultConverter), ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2215,7 +2246,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2228,7 +2259,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_or: $crate::py_class_binary_numeric_slot!($class::__or__), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2245,7 +2276,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2258,7 +2289,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_positive: $crate::py_class_unary_slot!($class::__pos__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2294,7 +2325,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2306,7 +2337,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_repr: $crate::py_class_unary_slot!($class::__repr__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PythonObjectCallbackConverter::<$crate::PyString>(std::marker::PhantomData)), ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2326,7 +2357,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2338,7 +2369,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_richcompare: $crate::py_class_richcompare_slot!($class::__richcmp__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2350,7 +2381,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2362,7 +2393,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_richcompare: $crate::py_class_richcompare_slot!($class::__richcmp__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2374,7 +2405,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2386,7 +2417,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_richcompare: $crate::py_class_richcompare_slot!($class::__richcmp__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2435,7 +2466,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2448,7 +2479,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_rshift: $crate::py_class_binary_numeric_slot!($class::__rshift__), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2483,7 +2514,7 @@ macro_rules! py_class_impl { { { def __setitem__(&$slf:ident, $key:ident : Option<&$key_name:ty>, $value:ident : $value_name:ty) -> $res_type:ty { $($body:tt)* } $($tail:tt)* } $class:ident $py:ident $info:tt /* slots: */ { - $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt + $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt /* setdelitem */ [ sdi_setitem: {}, sdi_delitem: $sdi_delitem_slot_value:tt, @@ -2495,7 +2526,7 @@ macro_rules! py_class_impl { { $($tail)* } $class $py $info /* slots: */ { - $type_slots $as_number $as_sequence $as_mapping + $type_slots $as_number $as_sequence $as_mapping $as_buffer /* setdelitem */ [ sdi_setitem: { $crate::py_class_ternary_slot!($class::__setitem__, [Option<&$key_name>], $value_name, $crate::_detail::libc::c_int, $crate::py_class::slots::UnitCallbackConverter) }, sdi_delitem: $sdi_delitem_slot_value, @@ -2510,7 +2541,7 @@ macro_rules! py_class_impl { { { def __setitem__(&$slf:ident, $key:ident : &$key_name:ty, $value:ident : $value_name:ty) -> $res_type:ty { $($body:tt)* } $($tail:tt)* } $class:ident $py:ident $info:tt /* slots: */ { - $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt + $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt /* setdelitem */ [ sdi_setitem: {}, sdi_delitem: $sdi_delitem_slot_value:tt, @@ -2522,7 +2553,7 @@ macro_rules! py_class_impl { { $($tail)* } $class $py $info /* slots: */ { - $type_slots $as_number $as_sequence $as_mapping + $type_slots $as_number $as_sequence $as_mapping $as_buffer /* setdelitem */ [ sdi_setitem: { $crate::py_class_ternary_slot!($class::__setitem__, [&$key_name], $value_name, $crate::_detail::libc::c_int, $crate::py_class::slots::UnitCallbackConverter) }, sdi_delitem: $sdi_delitem_slot_value, @@ -2537,7 +2568,7 @@ macro_rules! py_class_impl { { { def __setitem__(&$slf:ident, $key:ident : $key_name:ty, $value:ident : $value_name:ty) -> $res_type:ty { $($body:tt)* } $($tail:tt)* } $class:ident $py:ident $info:tt /* slots: */ { - $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt + $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt /* setdelitem */ [ sdi_setitem: {}, sdi_delitem: $sdi_delitem_slot_value:tt, @@ -2549,7 +2580,7 @@ macro_rules! py_class_impl { { $($tail)* } $class $py $info /* slots: */ { - $type_slots $as_number $as_sequence $as_mapping + $type_slots $as_number $as_sequence $as_mapping $as_buffer /* setdelitem */ [ sdi_setitem: { $crate::py_class_ternary_slot!($class::__setitem__, [$key_name], $value_name, $crate::_detail::libc::c_int, $crate::py_class::slots::UnitCallbackConverter) }, sdi_delitem: $sdi_delitem_slot_value, @@ -2569,7 +2600,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2581,7 +2612,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_str: $crate::py_class_unary_slot!($class::__str__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PythonObjectCallbackConverter::<$crate::PyString>(std::marker::PhantomData)), ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2598,7 +2629,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2611,7 +2642,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_subtract: $crate::py_class_binary_numeric_slot!($class::__sub__), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2636,7 +2667,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2649,7 +2680,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_xor: $crate::py_class_binary_numeric_slot!($class::__xor__), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* diff --git a/src/py_class/py_class_impl3.rs b/src/py_class/py_class_impl3.rs index d3923ebf..84752357 100644 --- a/src/py_class/py_class_impl3.rs +++ b/src/py_class/py_class_impl3.rs @@ -341,7 +341,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -353,7 +353,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_clear: $crate::py_class_tp_clear!($class), ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -370,7 +370,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -383,7 +383,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_absolute: $crate::py_class_unary_slot!($class::__abs__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -400,7 +400,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -413,7 +413,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_add: $crate::py_class_binary_numeric_slot!($class::__add__), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -442,7 +442,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -455,7 +455,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_and: $crate::py_class_binary_numeric_slot!($class::__and__), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -476,7 +476,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -489,7 +489,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_bool: $crate::py_class_unary_slot!($class::__bool__, $crate::_detail::libc::c_int, $crate::py_class::slots::BoolConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -501,11 +501,42 @@ macro_rules! py_class_impl { { { def __bool__ $($tail:tt)* } $( $stuff:tt )* } => { $crate::py_error! { "Invalid signature for operator __bool__" } }; + { { def __buffer__ (&$slf:ident) -> $res_type:ty $body:block $($tail:tt)* } + $class:ident $py:ident $info:tt + /* slots: */ { + $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt + /* as_buffer */ [ + bf_getbuffer: {}, + bf_releasebuffer: {}, + ] + $setdelitem:tt + } + { $( $imp:item )* } + $members:tt $props:tt + } => { $crate::py_class_impl! { + { $($tail)* } + $class $py $info + /* slots: */ { + $type_slots $as_number $as_sequence $as_mapping + /* as_buffer */ [ + bf_getbuffer: { $crate::py_class_buffer_slot!(bf_getbuffer, $class::__buffer__) }, + bf_releasebuffer: { $crate::py_class_buffer_slot!(bf_releasebuffer, $class::__buffer__) }, + ] + $setdelitem + } + /* impl: */ { + $($imp)* + impl $class { + fn __buffer__(&$slf, $py: $crate::Python<'_>) -> $res_type $body + } + } + $members $props + }}; { { def __call__ (&$slf:ident) -> $res_type:ty { $( $body:tt )* } $($tail:tt)* } $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -517,7 +548,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_call: $crate::py_class_call_slot!{$class::__call__ []}, ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -529,7 +560,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -541,7 +572,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_call: $crate::py_argparse_parse_plist_impl!{py_class_call_slot {$class::__call__} [] ($($p)+,)}, ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -569,7 +600,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt $as_number:tt /* as_sequence */ [ $( $sq_slot_name:ident : $sq_slot_value:expr, )* ] - $as_mapping:tt $setdelitem:tt + $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -582,7 +613,7 @@ macro_rules! py_class_impl { $( $sq_slot_name : $sq_slot_value, )* sq_contains: $crate::py_class_contains_slot!($class::__contains__, [Option<&$item_name>]), ] - $as_mapping $setdelitem + $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -595,7 +626,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt $as_number:tt /* as_sequence */ [ $( $sq_slot_name:ident : $sq_slot_value:expr, )* ] - $as_mapping:tt $setdelitem:tt + $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -608,7 +639,7 @@ macro_rules! py_class_impl { $( $sq_slot_name : $sq_slot_value, )* sq_contains: $crate::py_class_contains_slot!($class::__contains__, [&$item_name]), ] - $as_mapping $setdelitem + $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -621,7 +652,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt $as_number:tt /* as_sequence */ [ $( $sq_slot_name:ident : $sq_slot_value:expr, )* ] - $as_mapping:tt $setdelitem:tt + $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -634,7 +665,7 @@ macro_rules! py_class_impl { $( $sq_slot_name : $sq_slot_value, )* sq_contains: $crate::py_class_contains_slot!($class::__contains__, [$item_name]), ] - $as_mapping $setdelitem + $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -661,7 +692,7 @@ macro_rules! py_class_impl { { { def __delitem__(&$slf:ident, $key:ident : Option<&$key_name:ty>) -> $res_type:ty { $($body:tt)* } $($tail:tt)* } $class:ident $py:ident $info:tt /* slots: */ { - $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt + $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt /* setdelitem */ [ sdi_setitem: $sdi_setitem_slot_value:tt, sdi_delitem: {}, @@ -673,7 +704,7 @@ macro_rules! py_class_impl { { $($tail)* } $class $py $info /* slots: */ { - $type_slots $as_number $as_sequence $as_mapping + $type_slots $as_number $as_sequence $as_mapping $as_buffer /* setdelitem */ [ sdi_setitem: $sdi_setitem_slot_value, sdi_delitem: { $crate::py_class_binary_slot!($class::__delitem__, [Option<&$key_name>], $crate::_detail::libc::c_int, $crate::py_class::slots::UnitCallbackConverter) }, @@ -688,7 +719,7 @@ macro_rules! py_class_impl { { { def __delitem__(&$slf:ident, $key:ident : &$key_name:ty) -> $res_type:ty { $($body:tt)* } $($tail:tt)* } $class:ident $py:ident $info:tt /* slots: */ { - $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt + $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt /* setdelitem */ [ sdi_setitem: $sdi_setitem_slot_value:tt, sdi_delitem: {}, @@ -700,7 +731,7 @@ macro_rules! py_class_impl { { $($tail)* } $class $py $info /* slots: */ { - $type_slots $as_number $as_sequence $as_mapping + $type_slots $as_number $as_sequence $as_mapping $as_buffer /* setdelitem */ [ sdi_setitem: $sdi_setitem_slot_value, sdi_delitem: { $crate::py_class_binary_slot!($class::__delitem__, [&$key_name], $crate::_detail::libc::c_int, $crate::py_class::slots::UnitCallbackConverter) }, @@ -715,7 +746,7 @@ macro_rules! py_class_impl { { { def __delitem__(&$slf:ident, $key:ident : $key_name:ty) -> $res_type:ty { $($body:tt)* } $($tail:tt)* } $class:ident $py:ident $info:tt /* slots: */ { - $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt + $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt /* setdelitem */ [ sdi_setitem: $sdi_setitem_slot_value:tt, sdi_delitem: {}, @@ -727,7 +758,7 @@ macro_rules! py_class_impl { { $($tail)* } $class $py $info /* slots: */ { - $type_slots $as_number $as_sequence $as_mapping + $type_slots $as_number $as_sequence $as_mapping $as_buffer /* setdelitem */ [ sdi_setitem: $sdi_setitem_slot_value, sdi_delitem: { $crate::py_class_binary_slot!($class::__delitem__, [$key_name], $crate::_detail::libc::c_int, $crate::py_class::slots::UnitCallbackConverter) }, @@ -789,7 +820,7 @@ macro_rules! py_class_impl { $type_slots:tt $as_number:tt /* as_sequence */ [ $( $sq_slot_name:ident : $sq_slot_value:expr, )* ] /* as_mapping */ [ $( $mp_slot_name:ident : $mp_slot_value:expr, )* ] - $setdelitem:tt + $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -806,7 +837,7 @@ macro_rules! py_class_impl { $( $mp_slot_name : $mp_slot_value, )* mp_subscript: $crate::py_class_binary_slot!($class::__getitem__, [Option<&$key_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $setdelitem + $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -820,7 +851,7 @@ macro_rules! py_class_impl { $type_slots:tt $as_number:tt /* as_sequence */ [ $( $sq_slot_name:ident : $sq_slot_value:expr, )* ] /* as_mapping */ [ $( $mp_slot_name:ident : $mp_slot_value:expr, )* ] - $setdelitem:tt + $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -837,7 +868,7 @@ macro_rules! py_class_impl { $( $mp_slot_name : $mp_slot_value, )* mp_subscript: $crate::py_class_binary_slot!($class::__getitem__, [&$key_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $setdelitem + $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -851,7 +882,7 @@ macro_rules! py_class_impl { $type_slots:tt $as_number:tt /* as_sequence */ [ $( $sq_slot_name:ident : $sq_slot_value:expr, )* ] /* as_mapping */ [ $( $mp_slot_name:ident : $mp_slot_value:expr, )* ] - $setdelitem:tt + $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -868,7 +899,7 @@ macro_rules! py_class_impl { $( $mp_slot_name : $mp_slot_value, )* mp_subscript: $crate::py_class_binary_slot!($class::__getitem__, [$key_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $setdelitem + $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -888,7 +919,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -900,7 +931,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_hash: $crate::py_class_unary_slot!($class::__hash__, $crate::Py_hash_t, $crate::py_class::slots::HashConverter), ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -917,7 +948,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -930,7 +961,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_add: $crate::py_class_binary_slot!($class::__iadd__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -943,7 +974,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -956,7 +987,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_add: $crate::py_class_binary_slot!($class::__iadd__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -969,7 +1000,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -982,7 +1013,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_add: $crate::py_class_binary_slot!($class::__iadd__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -999,7 +1030,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1012,7 +1043,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_and: $crate::py_class_binary_slot!($class::__iand__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1025,7 +1056,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1038,7 +1069,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_and: $crate::py_class_binary_slot!($class::__iand__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1051,7 +1082,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1064,7 +1095,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_and: $crate::py_class_binary_slot!($class::__iand__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1085,7 +1116,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1098,7 +1129,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_floor_divide: $crate::py_class_binary_slot!($class::__ifloordiv__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1111,7 +1142,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1124,7 +1155,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_floor_divide: $crate::py_class_binary_slot!($class::__ifloordiv__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1137,7 +1168,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1150,7 +1181,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_floor_divide: $crate::py_class_binary_slot!($class::__ifloordiv__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1167,7 +1198,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1180,7 +1211,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_lshift: $crate::py_class_binary_slot!($class::__ilshift__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1193,7 +1224,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1206,7 +1237,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_lshift: $crate::py_class_binary_slot!($class::__ilshift__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1219,7 +1250,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1232,7 +1263,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_lshift: $crate::py_class_binary_slot!($class::__ilshift__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1249,7 +1280,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1262,7 +1293,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_matrix_multiply: $crate::py_class_binary_slot!($class::__imatmul__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1275,7 +1306,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1288,7 +1319,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_matrix_multiply: $crate::py_class_binary_slot!($class::__imatmul__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1301,7 +1332,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1314,7 +1345,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_matrix_multiply: $crate::py_class_binary_slot!($class::__imatmul__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1331,7 +1362,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1344,7 +1375,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_remainder: $crate::py_class_binary_slot!($class::__imod__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1357,7 +1388,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1370,7 +1401,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_remainder: $crate::py_class_binary_slot!($class::__imod__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1383,7 +1414,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1396,7 +1427,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_remainder: $crate::py_class_binary_slot!($class::__imod__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1413,7 +1444,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1426,7 +1457,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_multiply: $crate::py_class_binary_slot!($class::__imul__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1439,7 +1470,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1452,7 +1483,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_multiply: $crate::py_class_binary_slot!($class::__imul__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1465,7 +1496,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1478,7 +1509,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_multiply: $crate::py_class_binary_slot!($class::__imul__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1511,7 +1542,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1524,7 +1555,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_invert: $crate::py_class_unary_slot!($class::__invert__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1541,7 +1572,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1554,7 +1585,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_or: $crate::py_class_binary_slot!($class::__ior__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1567,7 +1598,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1580,7 +1611,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_or: $crate::py_class_binary_slot!($class::__ior__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1593,7 +1624,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1606,7 +1637,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_or: $crate::py_class_binary_slot!($class::__ior__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1627,7 +1658,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1640,7 +1671,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_rshift: $crate::py_class_binary_slot!($class::__irshift__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1653,7 +1684,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1666,7 +1697,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_rshift: $crate::py_class_binary_slot!($class::__irshift__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1679,7 +1710,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1692,7 +1723,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_rshift: $crate::py_class_binary_slot!($class::__irshift__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1709,7 +1740,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1722,7 +1753,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_subtract: $crate::py_class_binary_slot!($class::__isub__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1735,7 +1766,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1748,7 +1779,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_subtract: $crate::py_class_binary_slot!($class::__isub__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1761,7 +1792,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1774,7 +1805,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_subtract: $crate::py_class_binary_slot!($class::__isub__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1790,7 +1821,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1802,7 +1833,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_iter: $crate::py_class_unary_slot!($class::__iter__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1819,7 +1850,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1832,7 +1863,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_true_divide: $crate::py_class_binary_slot!($class::__itruediv__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1845,7 +1876,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1858,7 +1889,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_true_divide: $crate::py_class_binary_slot!($class::__itruediv__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1871,7 +1902,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1884,7 +1915,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_true_divide: $crate::py_class_binary_slot!($class::__itruediv__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1901,7 +1932,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1914,7 +1945,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_xor: $crate::py_class_binary_slot!($class::__ixor__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1927,7 +1958,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1940,7 +1971,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_xor: $crate::py_class_binary_slot!($class::__ixor__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1953,7 +1984,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -1966,7 +1997,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_inplace_xor: $crate::py_class_binary_slot!($class::__ixor__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -1988,7 +2019,7 @@ macro_rules! py_class_impl { $type_slots:tt $as_number:tt /* as_sequence */ [ $( $sq_slot_name:ident : $sq_slot_value:expr, )* ] /* as_mapping */ [ $( $mp_slot_name:ident : $mp_slot_value:expr, )* ] - $setdelitem:tt + $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2005,7 +2036,7 @@ macro_rules! py_class_impl { $( $mp_slot_name : $mp_slot_value, )* mp_length: Some($crate::_detail::ffi::PySequence_Size), ] - $setdelitem + $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2026,7 +2057,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2039,7 +2070,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_lshift: $crate::py_class_binary_numeric_slot!($class::__lshift__), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2068,7 +2099,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2081,7 +2112,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_multiply: $crate::py_class_binary_numeric_slot!($class::__mul__), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2102,7 +2133,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2115,7 +2146,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_negative: $crate::py_class_unary_slot!($class::__neg__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2131,7 +2162,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2143,7 +2174,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_new: $crate::py_class_wrap_newfunc!{$class::__new__ []}, ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2155,7 +2186,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2167,7 +2198,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_new: $crate::py_argparse_parse_plist_impl!{py_class_wrap_newfunc {$class::__new__} [] ($($p)+,)}, ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2182,7 +2213,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2194,7 +2225,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_iternext: $crate::py_class_unary_slot!($class::__next__, *mut $crate::_detail::ffi::PyObject, $crate::py_class::slots::IterNextResultConverter), ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2215,7 +2246,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2228,7 +2259,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_or: $crate::py_class_binary_numeric_slot!($class::__or__), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2245,7 +2276,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2258,7 +2289,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_positive: $crate::py_class_unary_slot!($class::__pos__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2294,7 +2325,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2306,7 +2337,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_repr: $crate::py_class_unary_slot!($class::__repr__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PythonObjectCallbackConverter::<$crate::PyString>(std::marker::PhantomData)), ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2326,7 +2357,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2338,7 +2369,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_richcompare: $crate::py_class_richcompare_slot!($class::__richcmp__, [Option<&$other_name>], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2350,7 +2381,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2362,7 +2393,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_richcompare: $crate::py_class_richcompare_slot!($class::__richcmp__, [&$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2374,7 +2405,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2386,7 +2417,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_richcompare: $crate::py_class_richcompare_slot!($class::__richcmp__, [$other_name], *mut $crate::_detail::ffi::PyObject, $crate::_detail::PyObjectCallbackConverter), ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2435,7 +2466,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2448,7 +2479,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_rshift: $crate::py_class_binary_numeric_slot!($class::__rshift__), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2483,7 +2514,7 @@ macro_rules! py_class_impl { { { def __setitem__(&$slf:ident, $key:ident : Option<&$key_name:ty>, $value:ident : $value_name:ty) -> $res_type:ty { $($body:tt)* } $($tail:tt)* } $class:ident $py:ident $info:tt /* slots: */ { - $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt + $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt /* setdelitem */ [ sdi_setitem: {}, sdi_delitem: $sdi_delitem_slot_value:tt, @@ -2495,7 +2526,7 @@ macro_rules! py_class_impl { { $($tail)* } $class $py $info /* slots: */ { - $type_slots $as_number $as_sequence $as_mapping + $type_slots $as_number $as_sequence $as_mapping $as_buffer /* setdelitem */ [ sdi_setitem: { $crate::py_class_ternary_slot!($class::__setitem__, [Option<&$key_name>], $value_name, $crate::_detail::libc::c_int, $crate::py_class::slots::UnitCallbackConverter) }, sdi_delitem: $sdi_delitem_slot_value, @@ -2510,7 +2541,7 @@ macro_rules! py_class_impl { { { def __setitem__(&$slf:ident, $key:ident : &$key_name:ty, $value:ident : $value_name:ty) -> $res_type:ty { $($body:tt)* } $($tail:tt)* } $class:ident $py:ident $info:tt /* slots: */ { - $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt + $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt /* setdelitem */ [ sdi_setitem: {}, sdi_delitem: $sdi_delitem_slot_value:tt, @@ -2522,7 +2553,7 @@ macro_rules! py_class_impl { { $($tail)* } $class $py $info /* slots: */ { - $type_slots $as_number $as_sequence $as_mapping + $type_slots $as_number $as_sequence $as_mapping $as_buffer /* setdelitem */ [ sdi_setitem: { $crate::py_class_ternary_slot!($class::__setitem__, [&$key_name], $value_name, $crate::_detail::libc::c_int, $crate::py_class::slots::UnitCallbackConverter) }, sdi_delitem: $sdi_delitem_slot_value, @@ -2537,7 +2568,7 @@ macro_rules! py_class_impl { { { def __setitem__(&$slf:ident, $key:ident : $key_name:ty, $value:ident : $value_name:ty) -> $res_type:ty { $($body:tt)* } $($tail:tt)* } $class:ident $py:ident $info:tt /* slots: */ { - $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt + $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt /* setdelitem */ [ sdi_setitem: {}, sdi_delitem: $sdi_delitem_slot_value:tt, @@ -2549,7 +2580,7 @@ macro_rules! py_class_impl { { $($tail)* } $class $py $info /* slots: */ { - $type_slots $as_number $as_sequence $as_mapping + $type_slots $as_number $as_sequence $as_mapping $as_buffer /* setdelitem */ [ sdi_setitem: { $crate::py_class_ternary_slot!($class::__setitem__, [$key_name], $value_name, $crate::_detail::libc::c_int, $crate::py_class::slots::UnitCallbackConverter) }, sdi_delitem: $sdi_delitem_slot_value, @@ -2569,7 +2600,7 @@ macro_rules! py_class_impl { $class:ident $py:ident $info:tt /* slots: */ { /* type_slots */ [ $( $tp_slot_name:ident : $tp_slot_value:expr, )* ] - $as_number:tt $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_number:tt $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2581,7 +2612,7 @@ macro_rules! py_class_impl { $( $tp_slot_name : $tp_slot_value, )* tp_str: $crate::py_class_unary_slot!($class::__str__, *mut $crate::_detail::ffi::PyObject, $crate::_detail::PythonObjectCallbackConverter::<$crate::PyString>(std::marker::PhantomData)), ] - $as_number $as_sequence $as_mapping $setdelitem + $as_number $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2598,7 +2629,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2611,7 +2642,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_subtract: $crate::py_class_binary_numeric_slot!($class::__sub__), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* @@ -2636,7 +2667,7 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots:tt /* as_number */ [ $( $nb_slot_name:ident : $nb_slot_value:expr, )* ] - $as_sequence:tt $as_mapping:tt $setdelitem:tt + $as_sequence:tt $as_mapping:tt $as_buffer:tt $setdelitem:tt } { $( $imp:item )* } $members:tt $props:tt @@ -2649,7 +2680,7 @@ macro_rules! py_class_impl { $( $nb_slot_name : $nb_slot_value, )* nb_xor: $crate::py_class_binary_numeric_slot!($class::__xor__), ] - $as_sequence $as_mapping $setdelitem + $as_sequence $as_mapping $as_buffer $setdelitem } /* impl: */ { $($imp)* diff --git a/src/py_class/slots.rs b/src/py_class/slots.rs index ac6e24bd..cb4f5317 100644 --- a/src/py_class/slots.rs +++ b/src/py_class/slots.rs @@ -18,8 +18,10 @@ use libc::{c_char, c_int}; use std::ffi::CString; +use std::marker::PhantomData; use std::{isize, mem, ptr}; +use crate::buffer::BufferHandleRaw; use crate::conversion::ToPyObject; use crate::err::{PyErr, PyResult}; use crate::exc; @@ -40,6 +42,7 @@ macro_rules! py_class_type_object_static_init { $as_number:tt $as_sequence:tt $as_mapping:tt + $as_buffer:tt $setdelitem:tt }) => ( $crate::_detail::ffi::PyTypeObject { @@ -86,6 +89,7 @@ macro_rules! py_class_type_object_dynamic_init { $as_number:tt $as_sequence:tt $as_mapping:tt + $as_buffer:tt $setdelitem:tt } $props:tt @@ -101,6 +105,7 @@ macro_rules! py_class_type_object_dynamic_init { *(unsafe { &mut $type_object.tp_as_sequence }) = $crate::py_class_as_sequence!($as_sequence); *(unsafe { &mut $type_object.tp_as_number }) = $crate::py_class_as_number!($as_number); + *(unsafe { &mut $type_object.tp_as_buffer }) = $crate::py_class_as_buffer!($as_buffer); $crate::py_class_as_mapping!($type_object, $as_mapping, $setdelitem); *(unsafe { &mut $type_object.tp_getset }) = $crate::py_class_tp_getset!($class, $props); }; @@ -184,6 +189,29 @@ macro_rules! py_class_as_number { }} } +#[macro_export] +#[doc(hidden)] +macro_rules! py_class_as_buffer { + ([ + bf_getbuffer: {}, + bf_releasebuffer: {}, + ]) => { + 0 as *mut $crate::_detail::ffi::PyBufferProcs + }; + ([ + bf_getbuffer: $bf_getbuffer:expr, + bf_releasebuffer: $bf_releasebuffer:expr, + ]) => {{ + static mut BUFFER_PROCS: $crate::_detail::ffi::PyBufferProcs = + $crate::_detail::ffi::PyBufferProcs { + bf_getbuffer: $bf_getbuffer, + bf_releasebuffer: $bf_releasebuffer, + ..$crate::_detail::ffi::PyBufferProcs_INIT + }; + unsafe { &mut BUFFER_PROCS } + }}; +} + #[macro_export] #[doc(hidden)] macro_rules! py_class_as_mapping { @@ -538,6 +566,144 @@ macro_rules! py_class_binary_numeric_slot { }}; } +pub struct BufferHandleConverter; + +impl CallbackConverter for BufferHandleConverter { + type R = Option; + + #[inline] + fn convert(val: BufferHandleRaw, _: Python) -> Option { + Some(val) + } + + #[inline] + fn error_value() -> Option { + None + } +} +/// This is a bit of a hack to get the actual type of the Rust Buffer from +/// the py_class's method return type. +#[doc(hidden)] +pub struct BufferType(PhantomData); +impl BufferType { + #[doc(hidden)] + #[inline] + pub fn of(_: fn(&C, Python) -> PyResult) -> Self { + Self(PhantomData) + } + + #[doc(hidden)] + #[inline] + pub fn assert_same_type(self, _: &T) {} + + #[doc(hidden)] + #[inline] + pub unsafe fn drop_buffer(self, ptr: *mut libc::c_void) { + T::from_owned_void_pointer(ptr); + } +} + +#[macro_export] +#[doc(hidden)] +macro_rules! py_class_buffer_slot { + (bf_getbuffer, $class:ident :: $f:ident) => {{ + unsafe extern "C" fn getbufferproc( + exporter: *mut $crate::_detail::ffi::PyObject, + view: *mut $crate::_detail::ffi::Py_buffer, + flags: $crate::_detail::libc::c_int, + ) -> $crate::_detail::libc::c_int { + /* + According to https://docs.python.org/3/c-api/typeobj.html#c.PyBufferProcs, + the implementation of this function needs to behave like this: + + 1. Check if the request can be met. If not, raise PyExc_BufferError, + set view->obj to NULL and return -1. + 2. Fill in the requested fields. + 3. Increment an internal counter for the number of exports. + 4. Set view->obj to exporter and increment view->obj. + 5. Return 0. + + We handle 1) by trying to get a buffer via the Rust API, and 2) and 4) + via `PyBuffer_FillInfo`. Instead of doing 3) by tracking the number of + exported buffers in `exporter`, we take ownership of a handle for the + buffer and store it in `view.internal`. + */ + + const LOCATION: &'static str = concat!(stringify!($class), ".", stringify!($f), "()"); + let res = $crate::_detail::handle_callback( + LOCATION, + $crate::py_class::slots::BufferHandleConverter, + |py| { + let slf = $crate::PyObject::from_borrowed_ptr(py, exporter) + .unchecked_cast_into::<$class>(); + + let buf_handle = slf.__buffer__(py)?; + + // assert that we are working with the same type as in + // `releasebufferproc` + $crate::py_class::slots::BufferType::of($class::__buffer__) + .assert_same_type(&buf_handle); + + let buf_handle_raw = $crate::buffer::BufferHandleRaw::new(buf_handle); + Ok(buf_handle_raw) + }, + ); + match res { + None => -1, + Some($crate::buffer::BufferHandleRaw { buf, len, owner }) => { + let readonly = 0x1; + let ret = $crate::_detail::ffi::PyBuffer_FillInfo( + view, exporter, buf, len, readonly, flags, + ); + if ret == 0 { + (*view).internal = owner; + } + ret + } + } + } + Some(getbufferproc) + }}; + (bf_releasebuffer, $class:ident :: $f:ident) => {{ + unsafe extern "C" fn releasebufferproc( + exporter: *mut $crate::_detail::ffi::PyObject, + view: *mut $crate::_detail::ffi::Py_buffer, + ) { + /* + According to https://docs.python.org/3/c-api/typeobj.html#c.PyBufferProcs, + the implementation of this function needs to (optionally) behave like this: + + 1. Decrement an internal counter for the number of exports. + 2. If the counter is 0, free all memory associated with view. + + However, we are not reference counting the buffer inside the export object, + but rather handle this by carrying around a owned handle in `view.internal`, + which we drop here again. + */ + + const LOCATION: &'static str = concat!(stringify!($class), ".", stringify!($f), "()"); + $crate::_detail::handle_callback( + LOCATION, + $crate::py_class::slots::UnitCallbackConverter, + |py| { + let owner = (*view).internal; + + // zeroing out the buffer fields should not be needed here, + // but we do so defensivly to catch bugs. + (*view).internal = 0 as *mut _; + (*view).buf = 0 as *mut _; + (*view).len = 0; + + $crate::py_class::slots::BufferType::of($class::__buffer__).drop_buffer(owner); + + Ok(()) + }, + ); + } + Some(releasebufferproc) + }}; +} + pub struct UnitCallbackConverter; impl CallbackConverter<()> for UnitCallbackConverter { diff --git a/tests/test_class.rs b/tests/test_class.rs index b448c5a6..aacb6bb6 100644 --- a/tests/test_class.rs +++ b/tests/test_class.rs @@ -1276,3 +1276,150 @@ fn properties() { py_run!(py, c, "del c.prop_by_opt_ref"); py_run!(py, c, "repr(c) == 'P(42, \"testing\" \"DELETED\")'"); } + +#[cfg(feature = "python3-sys")] +mod py3_only { + use self::RefCountLog::*; + use super::*; + use std::sync::Mutex; + + #[derive(PartialEq, Debug)] + enum RefCountLog { + Plus, + Minus, + } + + struct SharedBuffer { + buf: Vec, + log: Mutex>, + } + + impl SharedBuffer { + fn new(buf: Vec) -> Arc { + Arc::new(SharedBuffer { + buf, + log: Mutex::new(vec![]), + }) + } + } + + struct TestBuffer { + ptr: Arc, + count_drop: bool, + } + + impl TestBuffer { + fn new(ptr: &Arc) -> Self { + ptr.log.lock().unwrap().push(RefCountLog::Plus); + Self::from_arc(ptr.clone()) + } + fn into_arc(mut self) -> Arc { + self.count_drop = false; + self.ptr.clone() + } + fn from_arc(ptr: Arc) -> Self { + Self { + ptr: ptr.clone(), + count_drop: true, + } + } + } + impl Drop for TestBuffer { + fn drop(&mut self) { + if self.count_drop { + self.ptr.log.lock().unwrap().push(RefCountLog::Minus); + } + } + } + + unsafe impl buffer::BufferHandle for TestBuffer { + fn as_bytes(&self) -> &[u8] { + &self.ptr.buf + } + fn to_owned_void_pointer(self) -> *mut libc::c_void { + let raw = Arc::into_raw(self.into_arc()); + assert_eq!( + std::mem::size_of::<*mut libc::c_void>(), + std::mem::size_of_val(&raw) + ); + raw as *const libc::c_void as *mut libc::c_void + } + unsafe fn from_owned_void_pointer(ptr: *mut libc::c_void) -> Self { + TestBuffer::from_arc(Arc::from_raw(ptr as *const libc::c_void as *const _)) + } + } + + py_class!(class BufferProtocol |py| { + data ptr: Arc; + + def __buffer__(&self) -> PyResult { + Ok(TestBuffer::new(self.ptr(py))) + } + }); + + #[test] + fn buffer_protocol() { + let gil = Python::acquire_gil(); + let py = gil.python(); + + let buf = SharedBuffer::new(vec![1, 2, 42]); + let log_access = buf.clone(); + + let c = BufferProtocol::create_instance(py, buf).unwrap(); + + macro_rules! check_log { + ($($e:expr),+; $($r:expr),+) => { + py_run!(py, c, &[$($e),+].join("\n")[..]); + { + let should_log = &[$($r),+]; + let mut log = log_access.log.lock().unwrap(); + assert_eq!(&**log, should_log); + log.clear(); + } + } + } + + check_log!("memoryview(c)"; Plus, Minus); + check_log!("assert memoryview(c).readonly"; Plus, Minus); + check_log!("assert len(memoryview(c)) == 3"; Plus, Minus); + check_log!("assert memoryview(c)[0] == 1"; Plus, Minus); + check_log!("assert memoryview(c)[2] == 42"; Plus, Minus); + check_log!("assert list(memoryview(c)) == [1, 2, 42]"; Plus, Minus); + check_log!( + "a = memoryview(c)", + "b = memoryview(c)", + "assert a == b"; + Plus, Plus, Minus, Minus); + check_log!( + "a = memoryview(c)", + "b = memoryview(a)", + "assert a == b"; + Plus, Minus); + check_log!( + "def foo(x):", + " a = memoryview(x)", + " assert a[1] == 2", + "foo(c)", + "foo(c)"; + Plus, Minus, Plus, Minus); + check_log!( + "def foo(x):", + " a = memoryview(x)", + " assert a[1] == 2", + "foo(c)", + "e = memoryview(c)", + "f = memoryview(c)", + "assert e[2] == f[2] == 42"; + Plus, Minus, Plus, Plus, Minus, Minus); + + check_log!( + "with memoryview(c):", + " pass", + "with memoryview(c):", + " pass"; + Plus, Minus, Plus, Minus); + + py_expect_exception!(py, c, "memoryview(c)[3]", IndexError); + py_expect_exception!(py, c, "memoryview(c)[2] = 413", TypeError); + } +} From 9239342f3c049ee4806b91d15f043d2d14ebd751 Mon Sep 17 00:00:00 2001 From: Marvin Loebel Date: Mon, 18 May 2020 19:56:03 +0200 Subject: [PATCH 3/6] Remove TODO comment --- src/buffer.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/buffer.rs b/src/buffer.rs index a411c67d..7eff330b 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -665,11 +665,6 @@ impl_element!(f64, Float); /// /// It is unsafe because its implementation needs to uphold certain invariants. /// See the method docs for more details. -// TODO: -// - Buffer request can not fail yet -// - Buffer can not actually store data inside the object itself, only in a -// standalone owned object, which usually means a heap allocated reference counted -// container. pub unsafe trait BufferHandle: 'static + Send { /// Returns the data of `Self` as a continous array of bytes. /// From e4f3d965e3a080138eaa1b1951841357af3f9591 Mon Sep 17 00:00:00 2001 From: Marvin Loebel Date: Mon, 25 May 2020 11:25:25 +0200 Subject: [PATCH 4/6] Use macro parameter for magic method name --- src/py_class/slots.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/py_class/slots.rs b/src/py_class/slots.rs index cb4f5317..08973d67 100644 --- a/src/py_class/slots.rs +++ b/src/py_class/slots.rs @@ -637,11 +637,11 @@ macro_rules! py_class_buffer_slot { let slf = $crate::PyObject::from_borrowed_ptr(py, exporter) .unchecked_cast_into::<$class>(); - let buf_handle = slf.__buffer__(py)?; + let buf_handle = slf.$f(py)?; // assert that we are working with the same type as in // `releasebufferproc` - $crate::py_class::slots::BufferType::of($class::__buffer__) + $crate::py_class::slots::BufferType::of($class::$f) .assert_same_type(&buf_handle); let buf_handle_raw = $crate::buffer::BufferHandleRaw::new(buf_handle); @@ -694,7 +694,7 @@ macro_rules! py_class_buffer_slot { (*view).buf = 0 as *mut _; (*view).len = 0; - $crate::py_class::slots::BufferType::of($class::__buffer__).drop_buffer(owner); + $crate::py_class::slots::BufferType::of($class::$f).drop_buffer(owner); Ok(()) }, From a1cd84c6f399f954014b89f3b883b34313d43825 Mon Sep 17 00:00:00 2001 From: Marvin Loebel Date: Mon, 25 May 2020 20:38:36 +0200 Subject: [PATCH 5/6] Add alternative API "__direct_buffer__" for consumers that can not handle releasable PyBuffers --- src/buffer.rs | 13 +++++-- src/py_class/py_class_impl.py | 30 +++++++++++----- src/py_class/py_class_impl2.rs | 31 ---------------- src/py_class/py_class_impl3.rs | 35 ++++++++++++++++-- src/py_class/slots.rs | 65 ++++++++++++++++++++++++++++++++-- tests/test_class.rs | 61 ++++++++++++++++++++++++++++++- 6 files changed, 187 insertions(+), 48 deletions(-) diff --git a/src/buffer.rs b/src/buffer.rs index 7eff330b..68f2d9e5 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -18,7 +18,7 @@ use libc; use std::ffi::CStr; -use std::{cell, mem, slice}; +use std::{cell, mem, ptr, slice}; use crate::err::{self, PyResult}; use crate::exc; @@ -701,13 +701,22 @@ pub struct BufferHandleRaw { impl BufferHandleRaw { #[doc(hidden)] #[inline] - pub unsafe fn new(handle: T) -> Self { + pub unsafe fn new_owned(handle: T) -> Self { let slice = handle.as_bytes(); let buf = slice.as_ptr() as *mut libc::c_void; let len = slice.len() as crate::Py_ssize_t; let owner = handle.to_owned_void_pointer(); Self { buf, len, owner } } + + #[doc(hidden)] + #[inline] + pub unsafe fn new_borrowed(slice: &[u8]) -> Self { + let buf = slice.as_ptr() as *mut libc::c_void; + let len = slice.len() as crate::Py_ssize_t; + let owner = ptr::null_mut(); + Self { buf, len, owner } + } } #[cfg(test)] diff --git a/src/py_class/py_class_impl.py b/src/py_class/py_class_impl.py index 6aee72ce..131a916a 100644 --- a/src/py_class/py_class_impl.py +++ b/src/py_class/py_class_impl.py @@ -725,17 +725,28 @@ def inplace_numeric_operator(special_name, slot): args=[Argument('other')])(special_name) @special_method -def buffer_protocol(special_name, enabled): +def buffer_protocol(special_name, enabled, mode): if enabled: - pattern = 'def %s (&$slf:ident) -> $res_type:ty $body:block' % special_name + if mode == "direct": + pattern = 'def %s <$gil_lt:lifetime>(&$slf_lt:lifetime $slf:ident) -> $res_type:ty $body:block' % special_name + new_impl=''' + impl $class { + fn %s<$gil_lt>(&$slf_lt $slf, $py: $crate::Python<$gil_lt>) -> $res_type $body + } + ''' % special_name + + if mode == "handle": + pattern = 'def %s (&$slf:ident) -> $res_type:ty $body:block' % special_name + new_impl=''' + impl $class { + fn %s(&$slf, $py: $crate::Python<'_>) -> $res_type $body + } + ''' % special_name + new_slots = [] for slot in ['bf_getbuffer', 'bf_releasebuffer']: - new_slots.append((slot, '$crate::py_class_buffer_slot!(%s, $class::%s)' % (slot, special_name))) - generate_case(pattern, new_slots=new_slots, new_impl=''' - impl $class { - fn %s(&$slf, $py: $crate::Python<'_>) -> $res_type $body - } - ''' % special_name) + new_slots.append((slot, '$crate::py_class_buffer_slot!(%s, %s, $class::%s)' % (mode, slot, special_name))) + generate_case(pattern, new_slots=new_slots, new_impl=new_impl) special_names = { '__init__': error('__init__ is not supported by py_class!; use __new__ instead.'), @@ -886,7 +897,8 @@ def buffer_protocol(special_name, enabled): '__aexit__': unimplemented(), # Buffer protocol - '__buffer__': buffer_protocol(not PY2), + '__buffer__': buffer_protocol(not PY2, "handle"), + '__direct_buffer__': buffer_protocol(not PY2, "direct"), } def main(): diff --git a/src/py_class/py_class_impl2.rs b/src/py_class/py_class_impl2.rs index 975676dc..a166116a 100644 --- a/src/py_class/py_class_impl2.rs +++ b/src/py_class/py_class_impl2.rs @@ -501,37 +501,6 @@ macro_rules! py_class_impl { { { def __bool__ $($tail:tt)* } $( $stuff:tt )* } => { $crate::py_error! { "Invalid signature for operator __bool__" } }; - { { def __buffer__ (&$slf:ident) -> $res_type:ty $body:block $($tail:tt)* } - $class:ident $py:ident $info:tt - /* slots: */ { - $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt - /* as_buffer */ [ - bf_getbuffer: {}, - bf_releasebuffer: {}, - ] - $setdelitem:tt - } - { $( $imp:item )* } - $members:tt $props:tt - } => { $crate::py_class_impl! { - { $($tail)* } - $class $py $info - /* slots: */ { - $type_slots $as_number $as_sequence $as_mapping - /* as_buffer */ [ - bf_getbuffer: { $crate::py_class_buffer_slot!(bf_getbuffer, $class::__buffer__) }, - bf_releasebuffer: { $crate::py_class_buffer_slot!(bf_releasebuffer, $class::__buffer__) }, - ] - $setdelitem - } - /* impl: */ { - $($imp)* - impl $class { - fn __buffer__(&$slf, $py: $crate::Python<'_>) -> $res_type $body - } - } - $members $props - }}; { { def __call__ (&$slf:ident) -> $res_type:ty { $( $body:tt )* } $($tail:tt)* } $class:ident $py:ident $info:tt /* slots: */ { diff --git a/src/py_class/py_class_impl3.rs b/src/py_class/py_class_impl3.rs index 84752357..9fcbcfe5 100644 --- a/src/py_class/py_class_impl3.rs +++ b/src/py_class/py_class_impl3.rs @@ -519,8 +519,8 @@ macro_rules! py_class_impl { /* slots: */ { $type_slots $as_number $as_sequence $as_mapping /* as_buffer */ [ - bf_getbuffer: { $crate::py_class_buffer_slot!(bf_getbuffer, $class::__buffer__) }, - bf_releasebuffer: { $crate::py_class_buffer_slot!(bf_releasebuffer, $class::__buffer__) }, + bf_getbuffer: { $crate::py_class_buffer_slot!(handle, bf_getbuffer, $class::__buffer__) }, + bf_releasebuffer: { $crate::py_class_buffer_slot!(handle, bf_releasebuffer, $class::__buffer__) }, ] $setdelitem } @@ -778,6 +778,37 @@ macro_rules! py_class_impl { { { def __dir__ $($tail:tt)* } $( $stuff:tt )* } => { $crate::py_error! { "__dir__ is not supported by py_class! yet." } }; + { { def __direct_buffer__ <$gil_lt:lifetime>(&$slf_lt:lifetime $slf:ident) -> $res_type:ty $body:block $($tail:tt)* } + $class:ident $py:ident $info:tt + /* slots: */ { + $type_slots:tt $as_number:tt $as_sequence:tt $as_mapping:tt + /* as_buffer */ [ + bf_getbuffer: {}, + bf_releasebuffer: {}, + ] + $setdelitem:tt + } + { $( $imp:item )* } + $members:tt $props:tt + } => { $crate::py_class_impl! { + { $($tail)* } + $class $py $info + /* slots: */ { + $type_slots $as_number $as_sequence $as_mapping + /* as_buffer */ [ + bf_getbuffer: { $crate::py_class_buffer_slot!(direct, bf_getbuffer, $class::__direct_buffer__) }, + bf_releasebuffer: { $crate::py_class_buffer_slot!(direct, bf_releasebuffer, $class::__direct_buffer__) }, + ] + $setdelitem + } + /* impl: */ { + $($imp)* + impl $class { + fn __direct_buffer__<$gil_lt>(&$slf_lt $slf, $py: $crate::Python<$gil_lt>) -> $res_type $body + } + } + $members $props + }}; { { def __div__ $($tail:tt)* } $( $stuff:tt )* } => { $crate::py_error! { "__div__ is not supported by py_class! yet." } diff --git a/src/py_class/slots.rs b/src/py_class/slots.rs index 08973d67..7d8eb978 100644 --- a/src/py_class/slots.rs +++ b/src/py_class/slots.rs @@ -30,6 +30,7 @@ use crate::function::CallbackConverter; use crate::objects::PyObject; use crate::py_class::CompareOp; use crate::python::{Python, PythonObject}; +use crate::PySharedRef; use crate::Py_hash_t; #[macro_export] @@ -603,10 +604,14 @@ impl BufferType { } } +#[doc(hidden)] +#[inline] +pub fn assert_buffer_type_direct(_: for<'a> fn(&'a C, Python<'a>) -> PyResult<&'a [u8]>) {} + #[macro_export] #[doc(hidden)] macro_rules! py_class_buffer_slot { - (bf_getbuffer, $class:ident :: $f:ident) => {{ + (handle, bf_getbuffer, $class:ident :: $f:ident) => {{ unsafe extern "C" fn getbufferproc( exporter: *mut $crate::_detail::ffi::PyObject, view: *mut $crate::_detail::ffi::Py_buffer, @@ -644,7 +649,7 @@ macro_rules! py_class_buffer_slot { $crate::py_class::slots::BufferType::of($class::$f) .assert_same_type(&buf_handle); - let buf_handle_raw = $crate::buffer::BufferHandleRaw::new(buf_handle); + let buf_handle_raw = $crate::buffer::BufferHandleRaw::new_owned(buf_handle); Ok(buf_handle_raw) }, ); @@ -664,7 +669,7 @@ macro_rules! py_class_buffer_slot { } Some(getbufferproc) }}; - (bf_releasebuffer, $class:ident :: $f:ident) => {{ + (handle, bf_releasebuffer, $class:ident :: $f:ident) => {{ unsafe extern "C" fn releasebufferproc( exporter: *mut $crate::_detail::ffi::PyObject, view: *mut $crate::_detail::ffi::Py_buffer, @@ -702,6 +707,60 @@ macro_rules! py_class_buffer_slot { } Some(releasebufferproc) }}; + (direct, bf_getbuffer, $class:ident :: $f:ident) => {{ + unsafe extern "C" fn getbufferproc( + exporter: *mut $crate::_detail::ffi::PyObject, + view: *mut $crate::_detail::ffi::Py_buffer, + flags: $crate::_detail::libc::c_int, + ) -> $crate::_detail::libc::c_int { + /* + According to https://docs.python.org/3/c-api/typeobj.html#c.PyBufferProcs, + the implementation of this function needs to behave like this: + + 1. Check if the request can be met. If not, raise PyExc_BufferError, + set view->obj to NULL and return -1. + 2. Fill in the requested fields. + 3. Increment an internal counter for the number of exports. + 4. Set view->obj to exporter and increment view->obj. + 5. Return 0. + + We handle 1) by trying to get a buffer via the Rust API, and 2) and 4) + via `PyBuffer_FillInfo`. Instead of doing 3) by tracking the number of + exported buffers in `exporter`, we just do nothing. + */ + + const LOCATION: &'static str = concat!(stringify!($class), ".", stringify!($f), "()"); + let res = $crate::_detail::handle_callback( + LOCATION, + $crate::py_class::slots::BufferHandleConverter, + |py| { + let slf = $crate::PyObject::from_borrowed_ptr(py, exporter) + .unchecked_cast_into::<$class>(); + + // assert that we are borrowing bytes from the refcounted $class object + $crate::py_class::slots::assert_buffer_type_direct($class::$f); + + let buf_slice = slf.$f(py)?; + + let buf_handle_raw = $crate::buffer::BufferHandleRaw::new_borrowed(buf_slice); + Ok(buf_handle_raw) + }, + ); + match res { + None => -1, + Some($crate::buffer::BufferHandleRaw { buf, len, owner }) => { + let readonly = 0x1; + $crate::_detail::ffi::PyBuffer_FillInfo( + view, exporter, buf, len, readonly, flags, + ) + } + } + } + Some(getbufferproc) + }}; + (direct, bf_releasebuffer, $class:ident :: $f:ident) => {{ + None + }}; } pub struct UnitCallbackConverter; diff --git a/tests/test_class.rs b/tests/test_class.rs index aacb6bb6..7e2074e7 100644 --- a/tests/test_class.rs +++ b/tests/test_class.rs @@ -1358,7 +1358,7 @@ mod py3_only { }); #[test] - fn buffer_protocol() { + fn test_buffer() { let gil = Python::acquire_gil(); let py = gil.python(); @@ -1422,4 +1422,63 @@ mod py3_only { py_expect_exception!(py, c, "memoryview(c)[3]", IndexError); py_expect_exception!(py, c, "memoryview(c)[2] = 413", TypeError); } + + py_class!(class DirectBufferProtocol |py| { + data ptr: Arc>; + + def __direct_buffer__<'a>(&'a self) -> PyResult<&'a [u8]> { + Ok(self.ptr(py)) + } + }); + + #[test] + fn test_direct_buffer() { + let gil = Python::acquire_gil(); + let py = gil.python(); + + let buf = Arc::new(vec![1, 2, 42]); + + let c = DirectBufferProtocol::create_instance(py, buf).unwrap(); + + macro_rules! check_log { + ($($e:expr),+) => { + py_run!(py, c, &[$($e),+].join("\n")[..]); + } + } + + check_log!("memoryview(c)"); + check_log!("assert memoryview(c).readonly"); + check_log!("assert len(memoryview(c)) == 3"); + check_log!("assert memoryview(c)[0] == 1"); + check_log!("assert memoryview(c)[2] == 42"); + check_log!("assert list(memoryview(c)) == [1, 2, 42]"); + check_log!("a = memoryview(c)", "b = memoryview(c)", "assert a == b"); + check_log!("a = memoryview(c)", "b = memoryview(a)", "assert a == b"); + check_log!( + "def foo(x):", + " a = memoryview(x)", + " assert a[1] == 2", + "foo(c)", + "foo(c)" + ); + check_log!( + "def foo(x):", + " a = memoryview(x)", + " assert a[1] == 2", + "foo(c)", + "e = memoryview(c)", + "f = memoryview(c)", + "assert e[2] == f[2] == 42" + ); + + check_log!( + "with memoryview(c):", + " pass", + "with memoryview(c):", + " pass" + ); + + py_expect_exception!(py, c, "memoryview(c)[3]", IndexError); + py_expect_exception!(py, c, "memoryview(c)[2] = 413", TypeError); + } } From 2e243f7622a8d33bca3fb321db25d4be4c26397d Mon Sep 17 00:00:00 2001 From: Marvin Loebel Date: Thu, 28 May 2020 10:46:13 +0200 Subject: [PATCH 6/6] Changed consuming `to_...` method name to `into_...`. Also moved slots.rs specific data structures into the same module. --- src/buffer.rs | 30 +----------------------------- src/py_class/slots.rs | 40 +++++++++++++++++++++++++++++++++++----- tests/test_class.rs | 2 +- 3 files changed, 37 insertions(+), 35 deletions(-) diff --git a/src/buffer.rs b/src/buffer.rs index 68f2d9e5..a268234b 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -680,7 +680,7 @@ pub unsafe trait BufferHandle: 'static + Send { /// /// The returned pointer has to be a valid pointer that /// can be converted back to `Self`. - fn to_owned_void_pointer(self) -> *mut libc::c_void; + fn into_owned_void_pointer(self) -> *mut libc::c_void; /// Convert an owned void pointer back to `Self`. This takes owenrship of the pointer. /// @@ -691,34 +691,6 @@ pub unsafe trait BufferHandle: 'static + Send { unsafe fn from_owned_void_pointer(ptr: *mut libc::c_void) -> Self; } -#[doc(hidden)] -pub struct BufferHandleRaw { - pub buf: *mut libc::c_void, - pub len: crate::Py_ssize_t, - pub owner: *mut libc::c_void, -} - -impl BufferHandleRaw { - #[doc(hidden)] - #[inline] - pub unsafe fn new_owned(handle: T) -> Self { - let slice = handle.as_bytes(); - let buf = slice.as_ptr() as *mut libc::c_void; - let len = slice.len() as crate::Py_ssize_t; - let owner = handle.to_owned_void_pointer(); - Self { buf, len, owner } - } - - #[doc(hidden)] - #[inline] - pub unsafe fn new_borrowed(slice: &[u8]) -> Self { - let buf = slice.as_ptr() as *mut libc::c_void; - let len = slice.len() as crate::Py_ssize_t; - let owner = ptr::null_mut(); - Self { buf, len, owner } - } -} - #[cfg(test)] mod test { use super::PyBuffer; diff --git a/src/py_class/slots.rs b/src/py_class/slots.rs index 7d8eb978..cb25091f 100644 --- a/src/py_class/slots.rs +++ b/src/py_class/slots.rs @@ -21,7 +21,7 @@ use std::ffi::CString; use std::marker::PhantomData; use std::{isize, mem, ptr}; -use crate::buffer::BufferHandleRaw; +use crate::buffer::BufferHandle; use crate::conversion::ToPyObject; use crate::err::{PyErr, PyResult}; use crate::exc; @@ -567,6 +567,34 @@ macro_rules! py_class_binary_numeric_slot { }}; } +#[doc(hidden)] +pub struct BufferHandleRaw { + pub buf: *mut libc::c_void, + pub len: crate::Py_ssize_t, + pub owner: *mut libc::c_void, +} + +impl BufferHandleRaw { + #[doc(hidden)] + #[inline] + pub unsafe fn new_owned(handle: T) -> Self { + let slice = handle.as_bytes(); + let buf = slice.as_ptr() as *mut libc::c_void; + let len = slice.len() as crate::Py_ssize_t; + let owner = handle.into_owned_void_pointer(); + Self { buf, len, owner } + } + + #[doc(hidden)] + #[inline] + pub unsafe fn new_borrowed(slice: &[u8]) -> Self { + let buf = slice.as_ptr() as *mut libc::c_void; + let len = slice.len() as crate::Py_ssize_t; + let owner = ptr::null_mut(); + Self { buf, len, owner } + } +} + pub struct BufferHandleConverter; impl CallbackConverter for BufferHandleConverter { @@ -649,13 +677,14 @@ macro_rules! py_class_buffer_slot { $crate::py_class::slots::BufferType::of($class::$f) .assert_same_type(&buf_handle); - let buf_handle_raw = $crate::buffer::BufferHandleRaw::new_owned(buf_handle); + let buf_handle_raw = + $crate::py_class::slots::BufferHandleRaw::new_owned(buf_handle); Ok(buf_handle_raw) }, ); match res { None => -1, - Some($crate::buffer::BufferHandleRaw { buf, len, owner }) => { + Some($crate::py_class::slots::BufferHandleRaw { buf, len, owner }) => { let readonly = 0x1; let ret = $crate::_detail::ffi::PyBuffer_FillInfo( view, exporter, buf, len, readonly, flags, @@ -742,13 +771,14 @@ macro_rules! py_class_buffer_slot { let buf_slice = slf.$f(py)?; - let buf_handle_raw = $crate::buffer::BufferHandleRaw::new_borrowed(buf_slice); + let buf_handle_raw = + $crate::py_class::slots::BufferHandleRaw::new_borrowed(buf_slice); Ok(buf_handle_raw) }, ); match res { None => -1, - Some($crate::buffer::BufferHandleRaw { buf, len, owner }) => { + Some($crate::py_class::slots::BufferHandleRaw { buf, len, owner }) => { let readonly = 0x1; $crate::_detail::ffi::PyBuffer_FillInfo( view, exporter, buf, len, readonly, flags, diff --git a/tests/test_class.rs b/tests/test_class.rs index 7e2074e7..a3233395 100644 --- a/tests/test_class.rs +++ b/tests/test_class.rs @@ -1336,7 +1336,7 @@ mod py3_only { fn as_bytes(&self) -> &[u8] { &self.ptr.buf } - fn to_owned_void_pointer(self) -> *mut libc::c_void { + fn into_owned_void_pointer(self) -> *mut libc::c_void { let raw = Arc::into_raw(self.into_arc()); assert_eq!( std::mem::size_of::<*mut libc::c_void>(),