Mercurial > public > mercurial-scm > hg
comparison rust/hg-pyo3/src/convert_cpython.rs @ 52529:bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
This `py_leaked_or_map_err` is the PyO3 version of the function
of the same name in `hg-cpython/src/ancestors.rs`.
author | Georges Racinet <georges.racinet@cloudcrane.io> |
---|---|
date | Sat, 07 Dec 2024 18:18:09 +0100 |
parents | 1dd673c1ab3b |
children | 736551565871 |
comparison
equal
deleted
inserted
replaced
52528:1dd673c1ab3b | 52529:bd65cb043aa5 |
---|---|
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 } |