diff rust/hg-cpython/src/dirstate.rs @ 43208:1ca3823aeefd

rust-cpython: add wrapper around decapsule_make_dirstate_tuple() There are a couple of safety issues. First, the returned function pointer must be unsafe. Second, its return value must be a raw pointer (i.e. python27_sys::PyObject), not a cpython::PyObject. The wrapper function will address these issues.
author Yuya Nishihara <yuya@tcha.org>
date Sun, 13 Oct 2019 16:55:17 +0900
parents 7a01778bc7b7
children 8b355cbef16d
line wrap: on
line diff
--- a/rust/hg-cpython/src/dirstate.rs	Sun Oct 13 02:10:26 2019 +0200
+++ b/rust/hg-cpython/src/dirstate.rs	Sun Oct 13 16:55:17 2019 +0900
@@ -46,9 +46,7 @@
 /// This is largely a copy/paste from cindex.rs, pending the merge of a
 /// `py_capsule_fn!` macro in the rust-cpython project:
 /// https://github.com/dgrunwald/rust-cpython/pull/169
-pub fn decapsule_make_dirstate_tuple(
-    py: Python,
-) -> PyResult<MakeDirstateTupleFn> {
+fn decapsule_make_dirstate_tuple(py: Python) -> PyResult<MakeDirstateTupleFn> {
     unsafe {
         let caps_name = CStr::from_bytes_with_nul_unchecked(
             b"mercurial.cext.parsers.make_dirstate_tuple_CAPI\0",
@@ -61,6 +59,25 @@
     }
 }
 
+pub fn make_dirstate_tuple(
+    py: Python,
+    entry: &DirstateEntry,
+) -> PyResult<PyObject> {
+    let make = decapsule_make_dirstate_tuple(py)?;
+
+    let &DirstateEntry {
+        state,
+        mode,
+        size,
+        mtime,
+    } = entry;
+    // Explicitly go through u8 first, then cast to platform-specific `c_char`
+    // because Into<u8> has a specific implementation while `as c_char` would
+    // just do a naive enum cast.
+    let state_code: u8 = state.into();
+    Ok(make(state_code as c_char, mode, size, mtime))
+}
+
 pub fn extract_dirstate(py: Python, dmap: &PyDict) -> Result<StateMap, PyErr> {
     dmap.items(py)
         .iter()