Mercurial > public > mercurial-scm > hg
view rust/hg-cpython/src/ref_sharing.rs @ 53042:cdd7bf612c7b stable tip
bundle-spec: properly format boolean parameter (issue6960)
This was breaking automatic clone bundle generation. This changeset fixes it and
add a test to catch it in the future.
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Tue, 11 Mar 2025 02:29:42 +0100 |
parents | 15011324a80b |
children |
line wrap: on
line source
// ref_sharing.rs // // Copyright 2019 Raphaël Gomès <rgomes@octobus.net> // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //! Macros for use in the `hg-cpython` bridge library. /// Defines a `py_class!` that acts as a Python iterator over a Rust iterator. /// /// TODO: this is a bit awkward to use, and a better (more complicated) /// procedural macro would simplify the interface a lot. /// /// # Parameters /// /// * `$name` is the identifier to give to the resulting Rust struct. /// * `$leaked` corresponds to `UnsafePyLeaked` in the matching `@shared data` /// declaration. /// * `$iterator_type` is the type of the Rust iterator. /// * `$success_func` is a function for processing the Rust `(key, value)` /// tuple on iteration success, turning it into something Python understands. /// * `$success_func` is the return type of `$success_func` /// /// # Safety /// /// `$success_func` may take a reference, but it's lifetime may be cheated. /// Do not copy it out of the function call. /// /// # Example /// ``` /// use cpython::*; /// use std::collections::hash_map::{HashMap, Iter as HashMapIter}; /// use rusthg::py_shared_iterator; /// /// pub struct MyStruct { /// inner: HashMap<Vec<u8>, Vec<u8>> /// } /// /// py_class!(pub class MyType |py| { /// @shared data inner_shared: MyStruct; /// /// def __iter__(&self) -> PyResult<MyTypeItemsIterator> { /// let leaked_ref = self.inner_shared(py).leak_immutable(); /// MyTypeItemsIterator::from_inner( /// py, /// unsafe { leaked_ref.map(py, |o| o.inner.iter()) }, /// ) /// } /// }); /// /// impl MyType { /// fn translate_key_value( /// py: Python, /// res: (&Vec<u8>, &Vec<u8>), /// ) -> PyResult<Option<(PyBytes, PyBytes)>> { /// let (f, entry) = res; /// Ok(Some(( /// PyBytes::new(py, f), /// PyBytes::new(py, entry), /// ))) /// } /// } /// /// py_shared_iterator!( /// MyTypeItemsIterator, /// UnsafePyLeaked<HashMapIter<'static, Vec<u8>, Vec<u8>>>, /// MyType::translate_key_value, /// Option<(PyBytes, PyBytes)> /// ); /// ``` #[macro_export] macro_rules! py_shared_iterator { ( $name: ident, $leaked: ty, $success_func: expr, $success_type: ty ) => { py_class!(pub class $name |py| { data inner: std::cell::RefCell<$leaked>; def __next__(&self) -> cpython::PyResult<$success_type> { let mut leaked = self.inner(py).borrow_mut(); let mut iter = unsafe { leaked.try_borrow_mut(py)? }; match iter.next() { None => Ok(None), // res may be a reference of cheated 'static lifetime Some(res) => $success_func(py, res), } } def __iter__(&self) -> cpython::PyResult<Self> { Ok(self.clone_ref(py)) } }); impl $name { pub fn from_inner( py: Python, leaked: $leaked, ) -> cpython::PyResult<Self> { Self::create_instance( py, std::cell::RefCell::new(leaked), ) } } }; }