1use std::{convert::Infallible, marker::PhantomData, ops::Deref};
2
3use crate::{
4 ffi, types::PyNone, Bound, IntoPyObject, IntoPyObjectExt, Py, PyAny, PyResult, Python,
5};
6
7pub 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
24pub 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<Py<PyAny>>
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
111impl<T, E> UnknownReturnResultType<Result<T, E>> {
112 #[inline]
113 pub fn wrap<'py>(&self, _: Result<T, E>) -> Result<T, E>
114 where
115 T: IntoPyObject<'py>,
116 {
117 unreachable!("should be handled by IntoPyObjectConverter")
118 }
119}
120
121impl<T> UnknownReturnType<T> {
122 #[inline]
123 pub fn wrap<'py>(&self, _: T) -> T
124 where
125 T: IntoPyObject<'py>,
126 {
127 unreachable!("should be handled by IntoPyObjectConverter")
128 }
129
130 #[inline]
131 pub fn map_into_pyobject<'py>(&self, _: Python<'py>, _: PyResult<T>) -> PyResult<Py<PyAny>>
132 where
133 T: IntoPyObject<'py>,
134 {
135 unreachable!("should be handled by IntoPyObjectConverter")
136 }
137
138 #[inline]
139 pub fn map_into_ptr<'py>(&self, _: Python<'py>, _: PyResult<T>) -> PyResult<*mut ffi::PyObject>
140 where
141 T: IntoPyObject<'py>,
142 {
143 unreachable!("should be handled by IntoPyObjectConverter")
144 }
145}
146
147#[cfg(test)]
148mod tests {
149 use super::*;
150
151 #[test]
152 fn wrap_option() {
153 let a: Option<u8> = SomeWrap::wrap(42);
154 assert_eq!(a, Some(42));
155
156 let b: Option<u8> = SomeWrap::wrap(None);
157 assert_eq!(b, None);
158 }
159}