Mercurial > public > mercurial-scm > hg
view rust/hg-pyo3/src/revlog/index.rs @ 52795:adf91dfe6c04
rust-pyo3-index: _index_headrevs
This one demonstrates that why the `with_index_read` and similar
helpers are useful and was actually the main motivation for doing
them: if we kept the borrow used to grab the index before updating
the caches, there would be a panic when calling `borrow_mut`.
This was confirmed with an earlier version by the Python test.
There are perhaps some internal API clarifications to be made, as
the method updating the cache does a seemingly useless return), but
we are keeping it as it was in `hg-cpython`.
author | Georges Racinet <georges.racinet@cloudcrane.io> |
---|---|
date | Wed, 25 Dec 2024 19:06:59 +0100 |
parents | acae91fad6be |
children | bc095c0db77c |
line wrap: on
line source
// revlog/index.rs // // Copyright 2019-2020 Georges Racinet <georges.racinet@octobus.net> // 2020-2024 Raphaël Gomès <raphael.gomes@octobus.net> // 2024 Georges Racinet <georges.racinet@cloudcrane.io> // // This software may be used and distributed according to the terms of the // GNU General Public License version 2 or any later version. //! Utilities for dealing with the index at the Python boundary use pyo3::prelude::*; use pyo3::types::{PyBytes, PyTuple}; use hg::revlog::{ index::{Index, RevisionDataParams}, Node, Revision, RevlogIndex, }; #[derive(derive_more::From)] pub struct PySharedIndex { /// The underlying hg-core index inner: &'static Index, } impl PySharedIndex { /// Return a reference to the inner index, bound by `self` pub fn inner(&self) -> &Index { self.inner } /// Return an unsafe "faked" `'static` reference to the inner index, for /// the purposes of Python <-> Rust memory sharing. pub unsafe fn static_inner(&self) -> &'static Index { self.inner } } impl RevlogIndex for PySharedIndex { fn len(&self) -> usize { self.inner.len() } fn node(&self, rev: Revision) -> Option<&Node> { self.inner.node(rev) } } pub fn py_tuple_to_revision_data_params( tuple: &Bound<'_, PyTuple>, ) -> PyResult<RevisionDataParams> { // no need to check length: in PyO3 tup.get_item() does return // proper errors let offset_or_flags: u64 = tuple.get_item(0)?.extract()?; let node_id = tuple .get_item(7)? .downcast::<PyBytes>()? .as_bytes() .try_into() .expect("nodeid should be set"); let flags = (offset_or_flags & 0xFFFF) as u16; let data_offset = offset_or_flags >> 16; Ok(RevisionDataParams { flags, data_offset, data_compressed_length: tuple.get_item(1)?.extract()?, data_uncompressed_length: tuple.get_item(2)?.extract()?, data_delta_base: tuple.get_item(3)?.extract()?, link_rev: tuple.get_item(4)?.extract()?, parent_rev_1: tuple.get_item(5)?.extract()?, parent_rev_2: tuple.get_item(6)?.extract()?, node_id, ..Default::default() }) } pub fn revision_data_params_to_py_tuple( py: Python<'_>, params: RevisionDataParams, ) -> PyResult<Bound<'_, PyTuple>> { PyTuple::new( py, &[ params.data_offset.into_pyobject(py)?.into_any(), params.data_compressed_length.into_pyobject(py)?.into_any(), params .data_uncompressed_length .into_pyobject(py)? .into_any(), params.data_delta_base.into_pyobject(py)?.into_any(), params.link_rev.into_pyobject(py)?.into_any(), params.parent_rev_1.into_pyobject(py)?.into_any(), params.parent_rev_2.into_pyobject(py)?.into_any(), PyBytes::new(py, ¶ms.node_id).into_any().into_any(), params._sidedata_offset.into_pyobject(py)?.into_any(), params ._sidedata_compressed_length .into_pyobject(py)? .into_any(), params.data_compression_mode.into_pyobject(py)?.into_any(), params ._sidedata_compression_mode .into_pyobject(py)? .into_any(), params._rank.into_pyobject(py)?.into_any(), ], ) }