210 .try_borrow(py) |
210 .try_borrow(py) |
211 .map_err(|e| from_cpython_pyerr(py, e))? |
211 .map_err(|e| from_cpython_pyerr(py, e))? |
212 }; |
212 }; |
213 Ok(py_shared.inner) |
213 Ok(py_shared.inner) |
214 } |
214 } |
|
215 |
|
216 /// Error propagation for an [`UnsafePyLeaked`] wrapping a [`Result`] |
|
217 /// |
|
218 /// TODO (will consider when implementing UnsafePyLeaked in PyO3): |
|
219 /// It would be nice for UnsafePyLeaked to provide this directly as a variant |
|
220 /// of the `map` method with a signature such as: |
|
221 /// |
|
222 /// ``` |
|
223 /// unsafe fn map_or_err(&self, |
|
224 /// py: Python, |
|
225 /// f: impl FnOnce(T) -> Result(U, E), |
|
226 /// convert_err: impl FnOnce(E) -> PyErr) |
|
227 /// ``` |
|
228 /// |
|
229 /// This would spare users of the `cpython` crate the additional `unsafe` deref |
|
230 /// to inspect the error and return it outside `UnsafePyLeaked`, and the |
|
231 /// subsequent unwrapping that this function performs. |
|
232 #[allow(dead_code)] |
|
233 pub(crate) fn py_leaked_or_map_err<T, E: std::fmt::Debug + Copy>( |
|
234 py: cpython::Python, |
|
235 leaked: cpython::UnsafePyLeaked<Result<T, E>>, |
|
236 convert_err: impl FnOnce(E) -> PyErr, |
|
237 ) -> PyResult<cpython::UnsafePyLeaked<T>> { |
|
238 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
|
239 if let Err(e) = *unsafe { |
|
240 leaked |
|
241 .try_borrow(py) |
|
242 .map_err(|e| from_cpython_pyerr(py, e))? |
|
243 } { |
|
244 return Err(convert_err(e)); |
|
245 } |
|
246 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
|
247 Ok(unsafe { |
|
248 leaked.map(py, |res| { |
|
249 res.expect("Error case should have already be treated") |
|
250 }) |
|
251 }) |
|
252 } |