rust-index: slicechunktodensity returns Rust result
authorGeorges Racinet <georges.racinet@octobus.net>
Sat, 30 Sep 2023 15:59:03 +0200
changeset 51219 8cb31833b486
parent 51218 0112803e6c01
child 51220 c817d9f626d3
rust-index: slicechunktodensity returns Rust result Ready for removal of the scaffolding. This time, we allow ourselves a minor optimization: we avoid allocating for each chunk. Instead, we reuse the same vector, and perform at most one allocation per chunk. The `PyList` constructor will copy the buffer anyway.
rust/hg-cpython/src/revlog.rs
--- a/rust/hg-cpython/src/revlog.rs	Thu Nov 02 11:40:23 2023 +0100
+++ b/rust/hg-cpython/src/revlog.rs	Sat Sep 30 15:59:03 2023 +0200
@@ -365,29 +365,8 @@
         )?;
 
         let c_res = self.call_cindex(py, "slicechunktodensity", args, kw)?;
-        assert_eq!(
-            rust_res.len(),
-            c_res.len(py)?,
-            "chunks differ {:?} {}",
-            rust_res, c_res
-        );
-        for (i, chunk) in rust_res.iter().enumerate() {
-            let c_chunk = c_res.get_item(py, i)?;
-            assert_eq!(
-                chunk.len(),
-                c_chunk.len(py)?,
-                "chunk {} length differ {:?} {}",
-                i,
-                chunk,
-                c_res
-            );
-            for (j, rev) in chunk.iter().enumerate() {
-                let c_chunk: BaseRevision
-                    = c_chunk.get_item(py, j)?.extract(py)?;
-                assert_eq!(c_chunk, rev.0);
-            }
-        }
-        Ok(c_res)
+        assert_py_eq(py, "slicechunktodensity", &rust_res, &c_res)?;
+        Ok(rust_res)
     }
 
     /// stats for the index
@@ -856,10 +835,29 @@
         revs: PyObject,
         target_density: f64,
         min_gap_size: usize,
-    ) -> PyResult<Vec<Vec<Revision>>> {
+    ) -> PyResult<PyObject> {
         let index = &mut *self.index(py).borrow_mut();
         let revs: Vec<_> = rev_pyiter_collect(py, &revs, index)?;
-        Ok(index.slice_chunk_to_density(&revs, target_density, min_gap_size))
+        let as_nested_vec =
+            index.slice_chunk_to_density(&revs, target_density, min_gap_size);
+        let mut res = Vec::with_capacity(as_nested_vec.len());
+        let mut py_chunk = Vec::new();
+        for chunk in as_nested_vec {
+            py_chunk.clear();
+            py_chunk.reserve_exact(chunk.len());
+            for rev in chunk {
+                py_chunk.push(
+                    PyRevision::from(rev).into_py_object(py).into_object(),
+                );
+            }
+            res.push(PyList::new(py, &py_chunk).into_object());
+        }
+        // This is just to do the same as C, not sure why it does this
+        if res.len() == 1 {
+            Ok(PyTuple::new(py, &res).into_object())
+        } else {
+            Ok(PyList::new(py, &res).into_object())
+        }
     }
 }