Skip to content

Commit

Permalink
Modify CallbackConverter so that it can deal with try_borrow well
Browse files Browse the repository at this point in the history
  • Loading branch information
kngwyu committed Feb 22, 2020
1 parent 043b130 commit c2a40fb
Show file tree
Hide file tree
Showing 11 changed files with 202 additions and 254 deletions.
3 changes: 1 addition & 2 deletions pyo3-derive-backend/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,7 @@ fn function_c_wrapper(name: &Ident, spec: &method::FnSpec<'_>) -> TokenStream {

#body

pyo3::callback::cb_convert(
pyo3::callback::PyObjectCallbackConverter, _py, _result)
pyo3::callback::cb_obj_convert(_py, _result)
}
}
}
15 changes: 5 additions & 10 deletions pyo3-derive-backend/src/pymethod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,7 @@ fn impl_wrap_common(
pyo3::derive_utils::IntoPyResult::into_py_result(#body)
};

pyo3::callback::cb_convert(
pyo3::callback::PyObjectCallbackConverter, _py, _result)
pyo3::callback::cb_obj_convert(_py, _result)
}
}
} else {
Expand All @@ -138,8 +137,7 @@ fn impl_wrap_common(

#body

pyo3::callback::cb_convert(
pyo3::callback::PyObjectCallbackConverter, _py, _result)
pyo3::callback::cb_obj_convert(_py, _result)
}
}
}
Expand Down Expand Up @@ -169,8 +167,7 @@ pub fn impl_proto_wrap(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {

#body

pyo3::callback::cb_convert(
pyo3::callback::PyObjectCallbackConverter, _py, _result)
pyo3::callback::cb_obj_convert(_py, _result)
}
}
}
Expand Down Expand Up @@ -237,8 +234,7 @@ pub fn impl_wrap_class(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {

#body

pyo3::callback::cb_convert(
pyo3::callback::PyObjectCallbackConverter, _py, _result)
pyo3::callback::cb_obj_convert(_py, _result)
}
}
}
Expand Down Expand Up @@ -267,8 +263,7 @@ pub fn impl_wrap_static(cls: &syn::Type, spec: &FnSpec<'_>) -> TokenStream {

#body

pyo3::callback::cb_convert(
pyo3::callback::PyObjectCallbackConverter, _py, _result)
pyo3::callback::cb_obj_convert(_py, _result)
}
}
}
Expand Down
122 changes: 66 additions & 56 deletions src/callback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,81 +10,82 @@ use crate::{IntoPy, PyObject, Python};
use std::os::raw::c_int;
use std::{isize, ptr};

pub trait CallbackConverter<S> {
type R;
/// Convert the result of callback function into the appropriate return value.
pub trait CallbackConverter {
type Source;
type Result;
const ERR_VALUE: Self::Result;

fn convert(s: S, p: Python) -> Self::R;
fn error_value() -> Self::R;
fn convert(s: Self::Source, py: Python) -> Self::Result;

#[inline]
fn convert_result(py: Python, value: PyResult<Self::Source>) -> Self::Result {
match value {
Ok(val) => Self::convert(val, py),
Err(e) => {
e.restore(py);
Self::ERR_VALUE
}
}
}
}

pub struct PyObjectCallbackConverter;
pub struct PyObjectCallbackConverter<T>(pub std::marker::PhantomData<T>);

impl<S> CallbackConverter<S> for PyObjectCallbackConverter
impl<T> CallbackConverter for PyObjectCallbackConverter<T>
where
S: IntoPy<PyObject>,
T: IntoPy<PyObject>,
{
type R = *mut ffi::PyObject;

fn convert(val: S, py: Python) -> *mut ffi::PyObject {
val.into_py(py).into_ptr()
}
type Source = T;
type Result = *mut ffi::PyObject;
const ERR_VALUE: Self::Result = ptr::null_mut();

#[inline]
fn error_value() -> *mut ffi::PyObject {
ptr::null_mut()
fn convert(s: Self::Source, py: Python) -> Self::Result {
s.into_py(py).into_ptr()
}
}

pub struct BoolCallbackConverter;

impl CallbackConverter<bool> for BoolCallbackConverter {
type R = c_int;

#[inline]
fn convert(val: bool, _py: Python) -> c_int {
val as c_int
}
impl CallbackConverter for BoolCallbackConverter {
type Source = bool;
type Result = c_int;
const ERR_VALUE: Self::Result = -1;

#[inline]
fn error_value() -> c_int {
-1
fn convert(s: Self::Source, _py: Python) -> Self::Result {
s as c_int
}
}

pub struct LenResultConverter;

impl CallbackConverter<usize> for LenResultConverter {
type R = isize;
impl CallbackConverter for LenResultConverter {
type Source = usize;
type Result = isize;
const ERR_VALUE: Self::Result = -1;

fn convert(val: usize, py: Python) -> isize {
fn convert(val: Self::Source, py: Python) -> Self::Result {
if val <= (isize::MAX as usize) {
val as isize
} else {
OverflowError::py_err(()).restore(py);
-1
}
}

#[inline]
fn error_value() -> isize {
-1
}
}

pub struct UnitCallbackConverter;

impl CallbackConverter<()> for UnitCallbackConverter {
type R = c_int;
impl CallbackConverter for UnitCallbackConverter {
type Source = ();
type Result = c_int;
const ERR_VALUE: Self::Result = -1;

#[inline]
fn convert(_: (), _: Python) -> c_int {
fn convert(_s: Self::Source, _py: Python) -> Self::Result {
0
}

#[inline]
fn error_value() -> c_int {
-1
}
}

pub trait WrappingCastTo<T> {
Expand Down Expand Up @@ -112,13 +113,15 @@ wrapping_cast!(i32, Py_hash_t);
wrapping_cast!(isize, Py_hash_t);
wrapping_cast!(i64, Py_hash_t);

pub struct HashConverter;
pub struct HashConverter<T>(pub std::marker::PhantomData<T>);

impl<T> CallbackConverter<T> for HashConverter
impl<T> CallbackConverter for HashConverter<T>
where
T: WrappingCastTo<Py_hash_t>,
{
type R = Py_hash_t;
type Source = T;
type Result = Py_hash_t;
const ERR_VALUE: Self::Result = -1;

#[inline]
fn convert(val: T, _py: Python) -> Py_hash_t {
Expand All @@ -129,23 +132,30 @@ where
hash
}
}
}

#[inline]
fn error_value() -> Py_hash_t {
-1
}
// Short hands methods for macros
#[inline]
pub fn cb_convert<C, T>(_c: C, py: Python, value: PyResult<T>) -> C::Result
where
C: CallbackConverter<Source = T>,
{
C::convert_result(py, value)
}

#[inline]
pub unsafe fn cb_convert<C, T>(_c: C, py: Python, value: PyResult<T>) -> C::R
pub fn cb_obj_convert<T: IntoPy<PyObject>>(
py: Python,
value: PyResult<T>,
) -> <PyObjectCallbackConverter<T> as CallbackConverter>::Result {
PyObjectCallbackConverter::<T>::convert_result(py, value)
}

#[inline]
pub unsafe fn cb_err<C>(_c: C, py: Python, err: impl Into<crate::PyErr>) -> C::Result
where
C: CallbackConverter<T>,
C: CallbackConverter,
{
match value {
Ok(val) => C::convert(val, py),
Err(e) => {
e.restore(py);
C::error_value()
}
}
err.into().restore(py);
C::ERR_VALUE
}
19 changes: 10 additions & 9 deletions src/class/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,13 @@ where

let slf = py.from_borrowed_ptr::<crate::PyCell<T>>(slf);
let arg = py.from_borrowed_ptr::<crate::types::PyAny>(arg);
let result = call_ref!(slf, __getattr__, arg);
crate::callback::cb_convert(PyObjectCallbackConverter, py, result)
call_ref_with_converter!(
slf,
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData),
py,
__getattr__,
arg
)
}
Some(wrap::<T>)
}
Expand Down Expand Up @@ -355,8 +360,7 @@ where
py_unary_func!(
PyObjectStrProtocol,
T::__str__,
<T as PyObjectStrProtocol>::Success,
PyObjectCallbackConverter
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
}
}
Expand All @@ -380,8 +384,7 @@ where
py_unary_func!(
PyObjectReprProtocol,
T::__repr__,
T::Success,
PyObjectCallbackConverter
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
}
}
Expand Down Expand Up @@ -444,8 +447,7 @@ where
py_unary_func!(
PyObjectHashProtocol,
T::__hash__,
isize,
HashConverter,
HashConverter::<isize>(std::marker::PhantomData),
ffi::Py_hash_t
)
}
Expand All @@ -470,7 +472,6 @@ where
py_unary_func!(
PyObjectBoolProtocol,
T::__bool__,
bool,
BoolCallbackConverter,
c_int
)
Expand Down
11 changes: 2 additions & 9 deletions src/class/descr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,7 @@ where
py_ternary_func!(
PyDescrGetProtocol,
T::__get__,
T::Success,
PyObjectCallbackConverter
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
}
}
Expand All @@ -109,13 +108,7 @@ where
T: for<'p> PyDescrSetProtocol<'p>,
{
fn tp_descr_set() -> Option<ffi::descrsetfunc> {
py_ternary_func!(
PyDescrSetProtocol,
T::__set__,
(),
UnitCallbackConverter,
c_int
)
py_ternary_func!(PyDescrSetProtocol, T::__set__, UnitCallbackConverter, c_int)
}
}

Expand Down
21 changes: 8 additions & 13 deletions src/class/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ where
py_unary_refmut_func!(
PyIterIterProtocol,
T::__iter__,
T::Success,
PyObjectCallbackConverter
PyObjectCallbackConverter::<T::Success>(std::marker::PhantomData)
)
}
}
Expand All @@ -108,21 +107,22 @@ where
py_unary_refmut_func!(
PyIterNextProtocol,
T::__next__,
Option<T::Success>,
IterNextConverter
IterNextConverter::<T::Success>(std::marker::PhantomData)
)
}
}

struct IterNextConverter;
struct IterNextConverter<T>(std::marker::PhantomData<T>);

impl<T> CallbackConverter<Option<T>> for IterNextConverter
impl<T> CallbackConverter for IterNextConverter<T>
where
T: IntoPy<PyObject>,
{
type R = *mut ffi::PyObject;
type Source = Option<T>;
type Result = *mut ffi::PyObject;
const ERR_VALUE: Self::Result = ptr::null_mut();

fn convert(val: Option<T>, py: Python) -> *mut ffi::PyObject {
fn convert(val: Self::Source, py: Python) -> Self::Result {
match val {
Some(val) => val.into_py(py).into_ptr(),
None => unsafe {
Expand All @@ -131,9 +131,4 @@ where
},
}
}

#[inline]
fn error_value() -> *mut ffi::PyObject {
ptr::null_mut()
}
}
Loading

0 comments on commit c2a40fb

Please sign in to comment.