diff rust/hg-cpython/src/dirstate/dirstate_map.rs @ 47954:4afd6cc447b9

rust: Make OwningDirstateMap generic and move it into hg-core This will enable using it in rhg too. The `OwningDirstateMap::new_empty` constructor is generic and accepts a value of any type that gives acces to a bytes buffer. That buffer must stay valid as long as the value hasn’t been dropped, and must keep its memory address even if the value is moved. The `StableDeref` marker trait encodes those constraints. Previously no trait was needed because the value was always of type `PyBytes` which we know satisfies those constraints. The buffer type is ereased in the struct itself through boxing and dynamic dispatch, in order to simplify other signatures that mention `OwningDirstateMap`. Differential Revision: https://phab.mercurial-scm.org/D11396
author Simon Sapin <simon.sapin@octobus.net>
date Thu, 09 Sep 2021 18:07:40 +0200
parents e5fb14a07866
children 1194394510ba
line wrap: on
line diff
--- a/rust/hg-cpython/src/dirstate/dirstate_map.rs	Mon Sep 06 13:39:54 2021 +0200
+++ b/rust/hg-cpython/src/dirstate/dirstate_map.rs	Thu Sep 09 18:07:40 2021 +0200
@@ -24,15 +24,17 @@
     dirstate::non_normal_entries::{
         NonNormalEntries, NonNormalEntriesIterator,
     },
-    dirstate::owning::OwningDirstateMap,
     parsers::dirstate_parents_to_pytuple,
+    pybytes_deref::PyBytesDeref,
 };
 use hg::{
     dirstate::parsers::Timestamp,
     dirstate::MTIME_UNSET,
     dirstate::SIZE_NON_NORMAL,
+    dirstate_tree::dirstate_map::DirstateMap as TreeDirstateMap,
     dirstate_tree::dispatch::DirstateMapMethods,
     dirstate_tree::on_disk::DirstateV2ParseError,
+    dirstate_tree::owning::OwningDirstateMap,
     revlog::Node,
     utils::files::normalize_case,
     utils::hg_path::{HgPath, HgPathBuf},
@@ -62,8 +64,13 @@
         on_disk: PyBytes,
     ) -> PyResult<PyObject> {
         let (inner, parents) = if use_dirstate_tree {
-            let (map, parents) = OwningDirstateMap::new_v1(py, on_disk)
+            let on_disk = PyBytesDeref::new(py, on_disk);
+            let mut map = OwningDirstateMap::new_empty(on_disk);
+            let (on_disk, map_placeholder) = map.get_mut_pair();
+
+            let (actual_map, parents) = TreeDirstateMap::new_v1(on_disk)
                 .map_err(|e| dirstate_error(py, e))?;
+            *map_placeholder = actual_map;
             (Box::new(map) as _, parents)
         } else {
             let bytes = on_disk.data(py);
@@ -86,10 +93,13 @@
         let dirstate_error = |e: DirstateError| {
             PyErr::new::<exc::OSError, _>(py, format!("Dirstate error: {:?}", e))
         };
-        let inner = OwningDirstateMap::new_v2(
-            py, on_disk, data_size, tree_metadata,
+        let on_disk = PyBytesDeref::new(py, on_disk);
+        let mut map = OwningDirstateMap::new_empty(on_disk);
+        let (on_disk, map_placeholder) = map.get_mut_pair();
+        *map_placeholder = TreeDirstateMap::new_v2(
+            on_disk, data_size, tree_metadata.data(py),
         ).map_err(dirstate_error)?;
-        let map = Self::create_instance(py, Box::new(inner))?;
+        let map = Self::create_instance(py, Box::new(map))?;
         Ok(map.into_object())
     }