pyo3/impl_/
wrap.rs

1use std::{convert::Infallible, marker::PhantomData, ops::Deref};
2
3#[allow(deprecated)]
4use crate::IntoPy;
5use crate::{ffi, types::PyNone, Bound, IntoPyObject, IntoPyObjectExt, PyObject, PyResult, Python};
6
7/// Used to wrap values in `Option<T>` for default arguments.
8pub trait SomeWrap<T> {
9    fn wrap(self) -> Option<T>;
10}
11
12impl<T> SomeWrap<T> for T {
13    fn wrap(self) -> Option<T> {
14        Some(self)
15    }
16}
17
18impl<T> SomeWrap<T> for Option<T> {
19    fn wrap(self) -> Self {
20        self
21    }
22}
23
24// Hierarchy of conversions used in the `IntoPy` implementation
25pub struct Converter<T>(EmptyTupleConverter<T>);
26pub struct EmptyTupleConverter<T>(IntoPyObjectConverter<T>);
27pub struct IntoPyObjectConverter<T>(IntoPyConverter<T>);
28pub struct IntoPyConverter<T>(UnknownReturnResultType<T>);
29pub struct UnknownReturnResultType<T>(UnknownReturnType<T>);
30pub struct UnknownReturnType<T>(PhantomData<T>);
31
32pub fn converter<T>(_: &T) -> Converter<T> {
33    Converter(EmptyTupleConverter(IntoPyObjectConverter(IntoPyConverter(
34        UnknownReturnResultType(UnknownReturnType(PhantomData)),
35    ))))
36}
37
38impl<T> Deref for Converter<T> {
39    type Target = EmptyTupleConverter<T>;
40    fn deref(&self) -> &Self::Target {
41        &self.0
42    }
43}
44
45impl<T> Deref for EmptyTupleConverter<T> {
46    type Target = IntoPyObjectConverter<T>;
47    fn deref(&self) -> &Self::Target {
48        &self.0
49    }
50}
51
52impl<T> Deref for IntoPyObjectConverter<T> {
53    type Target = IntoPyConverter<T>;
54    fn deref(&self) -> &Self::Target {
55        &self.0
56    }
57}
58
59impl<T> Deref for IntoPyConverter<T> {
60    type Target = UnknownReturnResultType<T>;
61    fn deref(&self) -> &Self::Target {
62        &self.0
63    }
64}
65
66impl<T> Deref for UnknownReturnResultType<T> {
67    type Target = UnknownReturnType<T>;
68    fn deref(&self) -> &Self::Target {
69        &self.0
70    }
71}
72
73impl EmptyTupleConverter<PyResult<()>> {
74    #[inline]
75    pub fn map_into_ptr(&self, py: Python<'_>, obj: PyResult<()>) -> PyResult<*mut ffi::PyObject> {
76        obj.map(|_| PyNone::get(py).to_owned().into_ptr())
77    }
78}
79
80impl<'py, T: IntoPyObject<'py>> IntoPyObjectConverter<T> {
81    #[inline]
82    pub fn wrap(&self, obj: T) -> Result<T, Infallible> {
83        Ok(obj)
84    }
85}
86
87impl<'py, T: IntoPyObject<'py>, E> IntoPyObjectConverter<Result<T, E>> {
88    #[inline]
89    pub fn wrap(&self, obj: Result<T, E>) -> Result<T, E> {
90        obj
91    }
92
93    #[inline]
94    pub fn map_into_pyobject(&self, py: Python<'py>, obj: PyResult<T>) -> PyResult<PyObject>
95    where
96        T: IntoPyObject<'py>,
97    {
98        obj.and_then(|obj| obj.into_py_any(py))
99    }
100
101    #[inline]
102    pub fn map_into_ptr(&self, py: Python<'py>, obj: PyResult<T>) -> PyResult<*mut ffi::PyObject>
103    where
104        T: IntoPyObject<'py>,
105    {
106        obj.and_then(|obj| obj.into_bound_py_any(py))
107            .map(Bound::into_ptr)
108    }
109}
110
111#[allow(deprecated)]
112impl<T: IntoPy<PyObject>> IntoPyConverter<T> {
113    #[inline]
114    pub fn wrap(&self, obj: T) -> Result<T, Infallible> {
115        Ok(obj)
116    }
117}
118
119#[allow(deprecated)]
120impl<T: IntoPy<PyObject>, E> IntoPyConverter<Result<T, E>> {
121    #[inline]
122    pub fn wrap(&self, obj: Result<T, E>) -> Result<T, E> {
123        obj
124    }
125
126    #[inline]
127    pub fn map_into_pyobject(&self, py: Python<'_>, obj: PyResult<T>) -> PyResult<PyObject> {
128        obj.map(|obj| obj.into_py(py))
129    }
130
131    #[inline]
132    pub fn map_into_ptr(&self, py: Python<'_>, obj: PyResult<T>) -> PyResult<*mut ffi::PyObject> {
133        obj.map(|obj| obj.into_py(py).into_ptr())
134    }
135}
136
137impl<T, E> UnknownReturnResultType<Result<T, E>> {
138    #[inline]
139    pub fn wrap<'py>(&self, _: Result<T, E>) -> Result<T, E>
140    where
141        T: IntoPyObject<'py>,
142    {
143        unreachable!("should be handled by IntoPyObjectConverter")
144    }
145}
146
147impl<T> UnknownReturnType<T> {
148    #[inline]
149    pub fn wrap<'py>(&self, _: T) -> T
150    where
151        T: IntoPyObject<'py>,
152    {
153        unreachable!("should be handled by IntoPyObjectConverter")
154    }
155
156    #[inline]
157    pub fn map_into_pyobject<'py>(&self, _: Python<'py>, _: PyResult<T>) -> PyResult<PyObject>
158    where
159        T: IntoPyObject<'py>,
160    {
161        unreachable!("should be handled by IntoPyObjectConverter")
162    }
163
164    #[inline]
165    pub fn map_into_ptr<'py>(&self, _: Python<'py>, _: PyResult<T>) -> PyResult<*mut ffi::PyObject>
166    where
167        T: IntoPyObject<'py>,
168    {
169        unreachable!("should be handled by IntoPyObjectConverter")
170    }
171}
172
173#[cfg(test)]
174mod tests {
175    use super::*;
176
177    #[test]
178    fn wrap_option() {
179        let a: Option<u8> = SomeWrap::wrap(42);
180        assert_eq!(a, Some(42));
181
182        let b: Option<u8> = SomeWrap::wrap(None);
183        assert_eq!(b, None);
184    }
185}
⚠️ Internal Docs ⚠️ Not Public API 👉 Official Docs Here