# HG changeset patch # User Georges Racinet # Date 1581434745 -3600 # Node ID d738b7a18438c1164dd68fda4f3b805db3cee545 # Parent cefd130c98be41a57870af0c877ed1f860c48007 rust-nodemap: add utils to create `Node`s from Python objects Differential Revision: https://phab.mercurial-scm.org/D8155 diff -r cefd130c98be -r d738b7a18438 rust/hg-cpython/src/utils.rs --- 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 { @@ -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 { + 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 { + ::try_from(bytes.data(py)) + .map_err(|_| { + PyErr::new::( + py, + format!("{}-byte hash required", NODE_BYTES_LENGTH), + ) + }) + .map(|n| n.into()) +}