Mercurial > hg-stable
changeset 51240:8cb31833b486
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.
author | Georges Racinet <georges.racinet@octobus.net> |
---|---|
date | Sat, 30 Sep 2023 15:59:03 +0200 |
parents | 0112803e6c01 |
children | c817d9f626d3 |
files | rust/hg-cpython/src/revlog.rs |
diffstat | 1 files changed, 23 insertions(+), 25 deletions(-) [+] |
line wrap: on
line diff
--- 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()) + } } }