changeset 44505:d738b7a18438

rust-nodemap: add utils to create `Node`s from Python objects Differential Revision: https://phab.mercurial-scm.org/D8155
author Georges Racinet <georges.racinet@octobus.net>
date Tue, 11 Feb 2020 16:25:45 +0100
parents cefd130c98be
children 26dd35ac59b8
files rust/hg-cpython/src/utils.rs
diffstat 1 files changed, 35 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/rust/hg-cpython/src/utils.rs	Tue Feb 11 16:23:06 2020 +0100
+++ b/rust/hg-cpython/src/utils.rs	Tue Feb 11 16:25:45 2020 +0100
@@ -1,4 +1,7 @@
-use cpython::{PyDict, PyObject, PyResult, PyTuple, Python};
+use cpython::exc::ValueError;
+use cpython::{PyBytes, PyDict, PyErr, PyObject, PyResult, PyTuple, Python};
+use hg::revlog::Node;
+use std::convert::TryFrom;
 
 #[allow(unused)]
 pub fn print_python_trace(py: Python) -> PyResult<PyObject> {
@@ -11,3 +14,34 @@
     kwargs.set_item(py, "file", sys.get(py, "stderr")?)?;
     traceback.call(py, "print_stack", PyTuple::new(py, &[]), Some(&kwargs))
 }
+
+// Necessary evil for the time being, could maybe be moved to
+// a TryFrom in Node itself
+const NODE_BYTES_LENGTH: usize = 20;
+type NodeData = [u8; NODE_BYTES_LENGTH];
+
+/// Copy incoming Python bytes given as `PyObject` into `Node`,
+/// doing the necessary checks
+pub fn node_from_py_object<'a>(
+    py: Python,
+    bytes: &'a PyObject,
+) -> PyResult<Node> {
+    let as_py_bytes: &'a PyBytes = bytes.extract(py)?;
+    node_from_py_bytes(py, as_py_bytes)
+}
+
+/// Clone incoming Python bytes given as `PyBytes` as a `Node`,
+/// doing the necessary checks.
+pub fn node_from_py_bytes<'a>(
+    py: Python,
+    bytes: &'a PyBytes,
+) -> PyResult<Node> {
+    <NodeData>::try_from(bytes.data(py))
+        .map_err(|_| {
+            PyErr::new::<ValueError, _>(
+                py,
+                format!("{}-byte hash required", NODE_BYTES_LENGTH),
+            )
+        })
+        .map(|n| n.into())
+}