diff rust/hg-pyo3/src/node.rs @ 52785:71ebe880f24a

hg-pyo3-revlog: Node conversion utilities Adapted from `rusthg::utils`. The `NodeData` intermediate type was no longer necessary, as the core `Node` now implements `TryFrom`. Leaving the original unchanged, as we intend to drop it at the end of the story.
author Georges Racinet <georges.racinet@cloudcrane.io>
date Wed, 25 Dec 2024 11:58:56 +0100
parents
children 4e34e8fd46d4
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rust/hg-pyo3/src/node.rs	Wed Dec 25 11:58:56 2024 +0100
@@ -0,0 +1,58 @@
+#![allow(dead_code)]
+use pyo3::exceptions::PyValueError;
+use pyo3::prelude::*;
+use pyo3::types::PyBytes;
+
+use hg::revlog::RevlogIndex;
+use hg::{
+    revlog::index::Index, revlog::node::NODE_BYTES_LENGTH, Node, NodePrefix,
+    Revision,
+};
+
+#[derive(Debug, Copy, Clone, PartialEq, derive_more::From)]
+pub struct PyNode(Node);
+
+/// Copy incoming Python binary Node ID into [`Node`]
+///
+/// # Python exceptions
+/// Raises `ValueError` if length is not as expected
+pub fn node_from_py_bytes(bytes: &Bound<'_, PyBytes>) -> PyResult<Node> {
+    Node::try_from(bytes.as_bytes()).map_err(|_| {
+        PyValueError::new_err(format!(
+            "{}-byte hash required",
+            NODE_BYTES_LENGTH
+        ))
+    })
+}
+
+/// Convert Python hexadecimal Node ID node or prefix given as `bytes` into
+/// [`NodePrefix`].
+///
+/// # Python exceptions
+/// Raises `ValueError` if the incoming `bytes` is invalid.
+pub fn node_prefix_from_py_bytes(
+    bytes: &Bound<'_, PyBytes>,
+) -> PyResult<NodePrefix> {
+    let as_bytes = bytes.as_bytes();
+    NodePrefix::from_hex(as_bytes).map_err(|_| {
+        PyValueError::new_err(format!(
+            "Invalid node or prefix '{}'",
+            String::from_utf8_lossy(as_bytes)
+        ))
+    })
+}
+
+/// Return the binary node from a checked revision
+///
+/// This is meant to be used on revisions already checked to exist,
+/// typically obtained from a NodeTree lookup.
+///
+/// # Panics
+/// Panics if the revision does not exist
+pub fn py_node_for_rev<'py>(
+    py: Python<'py>,
+    idx: &Index,
+    rev: Revision,
+) -> Bound<'py, PyBytes> {
+    PyBytes::new(py, idx.node(rev).expect("node should exist").as_bytes())
+}