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>(UnknownReturnResultType<T>);
28pub struct UnknownReturnResultType<T>(UnknownReturnType<T>);
29pub struct UnknownReturnType<T>(PhantomData<T>);
30
31pub fn converter<T>(_: &T) -> Converter<T> {
32 Converter(EmptyTupleConverter(IntoPyObjectConverter(
33 UnknownReturnResultType(UnknownReturnType(PhantomData)),
34 )))
35}
36
37impl<T> Deref for Converter<T> {
38 type Target = EmptyTupleConverter<T>;
39 fn deref(&self) -> &Self::Target {
40 &self.0
41 }
42}
43
44impl<T> Deref for EmptyTupleConverter<T> {
45 type Target = IntoPyObjectConverter<T>;
46 fn deref(&self) -> &Self::Target {
47 &self.0
48 }
49}
50
51impl<T> Deref for IntoPyObjectConverter<T> {
52 type Target = UnknownReturnResultType<T>;
53 fn deref(&self) -> &Self::Target {
54 &self.0
55 }
56}
57
58impl<T> Deref for UnknownReturnResultType<T> {
59 type Target = UnknownReturnType<T>;
60 fn deref(&self) -> &Self::Target {
61 &self.0
62 }
63}
64
65impl EmptyTupleConverter<PyResult<()>> {
66 #[inline]
67 pub fn map_into_ptr(&self, py: Python<'_>, obj: PyResult<()>) -> PyResult<*mut ffi::PyObject> {
68 obj.map(|_| PyNone::get(py).to_owned().into_ptr())
69 }
70
71 #[inline]
72 pub fn map_into_pyobject(&self, py: Python<'_>, obj: PyResult<()>) -> PyResult<Py<PyAny>> {
73 obj.map(|_| PyNone::get(py).to_owned().into_any().unbind())
74 }
75}
76
77impl<'py, T: IntoPyObject<'py>> IntoPyObjectConverter<T> {
78 #[inline]
79 pub fn wrap(&self, obj: T) -> Result<T, Infallible> {
80 Ok(obj)
81 }
82}
83
84impl<'py, T: IntoPyObject<'py>, E> IntoPyObjectConverter<Result<T, E>> {
85 #[inline]
86 pub fn wrap(&self, obj: Result<T, E>) -> Result<T, E> {
87 obj
88 }
89
90 #[inline]
91 pub fn map_into_pyobject(&self, py: Python<'py>, obj: PyResult<T>) -> PyResult<Py<PyAny>>
92 where
93 T: IntoPyObject<'py>,
94 {
95 obj.and_then(|obj| obj.into_py_any(py))
96 }
97
98 #[inline]
99 pub fn map_into_ptr(&self, py: Python<'py>, obj: PyResult<T>) -> PyResult<*mut ffi::PyObject>
100 where
101 T: IntoPyObject<'py>,
102 {
103 obj.and_then(|obj| obj.into_bound_py_any(py))
104 .map(Bound::into_ptr)
105 }
106}
107
108impl<T, E> UnknownReturnResultType<Result<T, E>> {
109 #[inline]
110 pub fn wrap<'py>(&self, _: Result<T, E>) -> Result<T, E>
111 where
112 T: IntoPyObject<'py>,
113 {
114 unreachable!("should be handled by IntoPyObjectConverter")
115 }
116}
117
118impl<T> UnknownReturnType<T> {
119 #[inline]
120 pub fn wrap<'py>(&self, _: T) -> T
121 where
122 T: IntoPyObject<'py>,
123 {
124 unreachable!("should be handled by IntoPyObjectConverter")
125 }
126
127 #[inline]
128 pub fn map_into_pyobject<'py>(&self, _: Python<'py>, _: PyResult<T>) -> PyResult<Py<PyAny>>
129 where
130 T: IntoPyObject<'py>,
131 {
132 unreachable!("should be handled by IntoPyObjectConverter")
133 }
134
135 #[inline]
136 pub fn map_into_ptr<'py>(&self, _: Python<'py>, _: PyResult<T>) -> PyResult<*mut ffi::PyObject>
137 where
138 T: IntoPyObject<'py>,
139 {
140 unreachable!("should be handled by IntoPyObjectConverter")
141 }
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147
148 #[test]
149 fn wrap_option() {
150 let a: Option<u8> = SomeWrap::wrap(42);
151 assert_eq!(a, Some(42));
152
153 let b: Option<u8> = SomeWrap::wrap(None);
154 assert_eq!(b, None);
155 }
156}