1- use crate :: { IntoPy , Py , PyAny , PyErr , PyObject , PyResult , Python } ;
1+ use std:: convert:: Infallible ;
2+
3+ use crate :: { ffi, IntoPy , PyObject , PyResult , Python } ;
24
35/// Used to wrap values in `Option<T>` for default arguments.
46pub trait SomeWrap < T > {
5- fn wrap ( self ) -> T ;
7+ fn wrap ( self ) -> Option < T > ;
68}
79
8- impl < T > SomeWrap < Option < T > > for T {
10+ impl < T > SomeWrap < T > for T {
911 fn wrap ( self ) -> Option < T > {
1012 Some ( self )
1113 }
1214}
1315
14- impl < T > SomeWrap < Option < T > > for Option < T > {
16+ impl < T > SomeWrap < T > for Option < T > {
1517 fn wrap ( self ) -> Self {
1618 self
1719 }
@@ -20,7 +22,7 @@ impl<T> SomeWrap<Option<T>> for Option<T> {
2022/// Used to wrap the result of `#[pyfunction]` and `#[pymethods]`.
2123pub trait OkWrap < T > {
2224 type Error ;
23- fn wrap ( self , py : Python < ' _ > ) -> Result < Py < PyAny > , Self :: Error > ;
25+ fn wrap ( self ) -> Result < T , Self :: Error > ;
2426}
2527
2628// The T: IntoPy<PyObject> bound here is necessary to prevent the
@@ -29,9 +31,10 @@ impl<T> OkWrap<T> for T
2931where
3032 T : IntoPy < PyObject > ,
3133{
32- type Error = PyErr ;
33- fn wrap ( self , py : Python < ' _ > ) -> PyResult < Py < PyAny > > {
34- Ok ( self . into_py ( py) )
34+ type Error = Infallible ;
35+ #[ inline]
36+ fn wrap ( self ) -> Result < T , Infallible > {
37+ Ok ( self )
3538 }
3639}
3740
@@ -40,11 +43,44 @@ where
4043 T : IntoPy < PyObject > ,
4144{
4245 type Error = E ;
43- fn wrap ( self , py : Python < ' _ > ) -> Result < Py < PyAny > , Self :: Error > {
44- self . map ( |o| o. into_py ( py) )
46+ #[ inline]
47+ fn wrap ( self ) -> Result < T , Self :: Error > {
48+ self
4549 }
4650}
4751
52+ /// This is a follow-up function to `OkWrap::wrap` that converts the result into
53+ /// a `*mut ffi::PyObject` pointer.
54+ pub fn map_result_into_ptr < T : IntoPy < PyObject > > (
55+ py : Python < ' _ > ,
56+ result : PyResult < T > ,
57+ ) -> PyResult < * mut ffi:: PyObject > {
58+ result. map ( |obj| obj. into_py ( py) . into_ptr ( ) )
59+ }
60+
61+ /// This is a follow-up function to `OkWrap::wrap` that converts the result into
62+ /// a safe wrapper.
63+ pub fn map_result_into_py < T : IntoPy < PyObject > > (
64+ py : Python < ' _ > ,
65+ result : PyResult < T > ,
66+ ) -> PyResult < PyObject > {
67+ result. map ( |err| err. into_py ( py) )
68+ }
69+
70+ /// Used to wrap the result of async `#[pyfunction]` and `#[pymethods]`.
71+ #[ cfg( feature = "macros" ) ]
72+ pub fn wrap_future < F , R , T > ( future : F ) -> crate :: coroutine:: Coroutine
73+ where
74+ F : std:: future:: Future < Output = R > + Send + ' static ,
75+ R : OkWrap < T > ,
76+ T : IntoPy < PyObject > ,
77+ crate :: PyErr : From < R :: Error > ,
78+ {
79+ crate :: coroutine:: Coroutine :: from_future :: < _ , T , crate :: PyErr > ( async move {
80+ OkWrap :: wrap ( future. await ) . map_err ( Into :: into)
81+ } )
82+ }
83+
4884#[ cfg( test) ]
4985mod tests {
5086 use super :: * ;
@@ -57,4 +93,16 @@ mod tests {
5793 let b: Option < u8 > = SomeWrap :: wrap ( None ) ;
5894 assert_eq ! ( b, None ) ;
5995 }
96+
97+ #[ test]
98+ fn wrap_result ( ) {
99+ let a: Result < u8 , _ > = OkWrap :: wrap ( 42u8 ) ;
100+ assert ! ( matches!( a, Ok ( 42 ) ) ) ;
101+
102+ let b: PyResult < u8 > = OkWrap :: wrap ( Ok ( 42u8 ) ) ;
103+ assert ! ( matches!( b, Ok ( 42 ) ) ) ;
104+
105+ let c: Result < u8 , & str > = OkWrap :: wrap ( Err ( "error" ) ) ;
106+ assert_eq ! ( c, Err ( "error" ) ) ;
107+ }
60108}
0 commit comments