##// END OF EJS Templates
rust: Make OwningDirstateMap generic and move it into hg-core...
Simon Sapin -
r48766:4afd6cc4 default
parent child Browse files
Show More
@@ -1,5 +1,7 b''
1 1 # This file is automatically @generated by Cargo.
2 2 # It is not intended for manual editing.
3 version = 3
4
3 5 [[package]]
4 6 name = "adler"
5 7 version = "0.2.3"
@@ -396,6 +398,7 b' dependencies = ['
396 398 "regex",
397 399 "same-file",
398 400 "sha-1",
401 "stable_deref_trait",
399 402 "tempfile",
400 403 "twox-hash",
401 404 "zstd",
@@ -411,6 +414,7 b' dependencies = ['
411 414 "hg-core",
412 415 "libc",
413 416 "log",
417 "stable_deref_trait",
414 418 ]
415 419
416 420 [[package]]
@@ -865,6 +869,12 b' dependencies = ['
865 869 ]
866 870
867 871 [[package]]
872 name = "stable_deref_trait"
873 version = "1.2.0"
874 source = "registry+https://github.com/rust-lang/crates.io-index"
875 checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
876
877 [[package]]
868 878 name = "static_assertions"
869 879 version = "1.1.0"
870 880 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -24,6 +24,7 b' regex = "1.3.9"'
24 24 sha-1 = "0.9.6"
25 25 twox-hash = "1.5.0"
26 26 same-file = "1.0.6"
27 stable_deref_trait = "1.2.0"
27 28 tempfile = "3.1.0"
28 29 crossbeam-channel = "0.4"
29 30 micro-timer = "0.3.0"
@@ -1,5 +1,7 b''
1 1 pub mod dirstate_map;
2 2 pub mod dispatch;
3 3 pub mod on_disk;
4 pub mod owning;
5 mod owning_dispatch;
4 6 pub mod path_with_basename;
5 7 pub mod status;
@@ -1,11 +1,9 b''
1 use cpython::PyBytes;
2 use cpython::Python;
3 use hg::dirstate_tree::dirstate_map::DirstateMap;
4 use hg::DirstateError;
5 use hg::DirstateParents;
1 use super::dirstate_map::DirstateMap;
2 use stable_deref_trait::StableDeref;
3 use std::ops::Deref;
6 4
7 5 /// Keep a `DirstateMap<'on_disk>` next to the `on_disk` buffer that it
8 /// borrows. This is similar to the owning-ref crate.
6 /// borrows.
9 7 ///
10 8 /// This is similar to [`OwningRef`] which is more limited because it
11 9 /// represents exactly one `&T` reference next to the value it borrows, as
@@ -13,11 +11,11 b' use hg::DirstateParents;'
13 11 /// arbitrarily-nested data structures.
14 12 ///
15 13 /// [`OwningRef`]: https://docs.rs/owning_ref/0.4.1/owning_ref/struct.OwningRef.html
16 pub(super) struct OwningDirstateMap {
14 pub struct OwningDirstateMap {
17 15 /// Owned handle to a bytes buffer with a stable address.
18 16 ///
19 17 /// See <https://docs.rs/owning_ref/0.4.1/owning_ref/trait.StableAddress.html>.
20 on_disk: PyBytes,
18 on_disk: Box<dyn Deref<Target = [u8]> + Send>,
21 19
22 20 /// Pointer for `Box<DirstateMap<'on_disk>>`, typed-erased because the
23 21 /// language cannot represent a lifetime referencing a sibling field.
@@ -28,12 +26,13 b' pub(super) struct OwningDirstateMap {'
28 26 }
29 27
30 28 impl OwningDirstateMap {
31 pub fn new_v1(
32 py: Python,
33 on_disk: PyBytes,
34 ) -> Result<(Self, Option<DirstateParents>), DirstateError> {
35 let bytes: &'_ [u8] = on_disk.data(py);
36 let (map, parents) = DirstateMap::new_v1(bytes)?;
29 pub fn new_empty<OnDisk>(on_disk: OnDisk) -> Self
30 where
31 OnDisk: Deref<Target = [u8]> + StableDeref + Send + 'static,
32 {
33 let on_disk = Box::new(on_disk);
34 let bytes: &'_ [u8] = &on_disk;
35 let map = DirstateMap::empty(bytes);
37 36
38 37 // Like in `bytes` above, this `'_` lifetime parameter borrows from
39 38 // the bytes buffer owned by `on_disk`.
@@ -42,30 +41,12 b' impl OwningDirstateMap {'
42 41 // Erase the pointed type entirely in order to erase the lifetime.
43 42 let ptr: *mut () = ptr.cast();
44 43
45 Ok((Self { on_disk, ptr }, parents))
44 Self { on_disk, ptr }
46 45 }
47 46
48 pub fn new_v2(
49 py: Python,
50 on_disk: PyBytes,
51 data_size: usize,
52 tree_metadata: PyBytes,
53 ) -> Result<Self, DirstateError> {
54 let bytes: &'_ [u8] = on_disk.data(py);
55 let map =
56 DirstateMap::new_v2(bytes, data_size, tree_metadata.data(py))?;
57
58 // Like in `bytes` above, this `'_` lifetime parameter borrows from
59 // the bytes buffer owned by `on_disk`.
60 let ptr: *mut DirstateMap<'_> = Box::into_raw(Box::new(map));
61
62 // Erase the pointed type entirely in order to erase the lifetime.
63 let ptr: *mut () = ptr.cast();
64
65 Ok(Self { on_disk, ptr })
66 }
67
68 pub fn get_mut<'a>(&'a mut self) -> &'a mut DirstateMap<'a> {
47 pub fn get_mut_pair<'a>(
48 &'a mut self,
49 ) -> (&'a [u8], &'a mut DirstateMap<'a>) {
69 50 // SAFETY: We cast the type-erased pointer back to the same type it had
70 51 // in `new`, except with a different lifetime parameter. This time we
71 52 // connect the lifetime to that of `self`. This cast is valid because
@@ -76,7 +57,11 b' impl OwningDirstateMap {'
76 57 // SAFETY: we dereference that pointer, connecting the lifetime of the
77 58 // new `&mut` to that of `self`. This is valid because the
78 59 // raw pointer is to a boxed value, and `self` owns that box.
79 unsafe { &mut *ptr }
60 (&self.on_disk, unsafe { &mut *ptr })
61 }
62
63 pub fn get_mut<'a>(&'a mut self) -> &'a mut DirstateMap<'a> {
64 self.get_mut_pair().1
80 65 }
81 66
82 67 pub fn get<'a>(&'a self) -> &'a DirstateMap<'a> {
@@ -84,6 +69,10 b' impl OwningDirstateMap {'
84 69 let ptr: *mut DirstateMap<'a> = self.ptr.cast();
85 70 unsafe { &*ptr }
86 71 }
72
73 pub fn on_disk<'a>(&'a self) -> &'a [u8] {
74 &self.on_disk
75 }
87 76 }
88 77
89 78 impl Drop for OwningDirstateMap {
@@ -105,13 +94,12 b' impl Drop for OwningDirstateMap {'
105 94 fn _static_assert_is_send<T: Send>() {}
106 95
107 96 fn _static_assert_fields_are_send() {
108 _static_assert_is_send::<PyBytes>();
109 97 _static_assert_is_send::<Box<DirstateMap<'_>>>();
110 98 }
111 99
112 100 // SAFETY: we don’t get this impl implicitly because `*mut (): !Send` because
113 101 // thread-safety of raw pointers is unknown in the general case. However this
114 102 // particular raw pointer represents a `Box<DirstateMap<'on_disk>>` that we
115 // own. Since that `Box` and `PyBytes` are both `Send` as shown in above, it
116 // is sound to mark this struct as `Send` too.
103 // own. Since that `Box` is `Send` as shown in above, it is sound to mark
104 // this struct as `Send` too.
117 105 unsafe impl Send for OwningDirstateMap {}
@@ -1,18 +1,18 b''
1 use crate::dirstate::owning::OwningDirstateMap;
2 use hg::dirstate::parsers::Timestamp;
3 use hg::dirstate_tree::dispatch::DirstateMapMethods;
4 use hg::dirstate_tree::on_disk::DirstateV2ParseError;
5 use hg::matchers::Matcher;
6 use hg::utils::hg_path::{HgPath, HgPathBuf};
7 use hg::CopyMapIter;
8 use hg::DirstateEntry;
9 use hg::DirstateError;
10 use hg::DirstateParents;
11 use hg::DirstateStatus;
12 use hg::PatternFileWarning;
13 use hg::StateMapIter;
14 use hg::StatusError;
15 use hg::StatusOptions;
1 use crate::dirstate::parsers::Timestamp;
2 use crate::dirstate_tree::dispatch::DirstateMapMethods;
3 use crate::dirstate_tree::on_disk::DirstateV2ParseError;
4 use crate::dirstate_tree::owning::OwningDirstateMap;
5 use crate::matchers::Matcher;
6 use crate::utils::hg_path::{HgPath, HgPathBuf};
7 use crate::CopyMapIter;
8 use crate::DirstateEntry;
9 use crate::DirstateError;
10 use crate::DirstateParents;
11 use crate::DirstateStatus;
12 use crate::PatternFileWarning;
13 use crate::StateMapIter;
14 use crate::StatusError;
15 use crate::StatusOptions;
16 16 use std::path::PathBuf;
17 17
18 18 impl DirstateMapMethods for OwningDirstateMap {
@@ -26,6 +26,7 b' hg-core = { path = "../hg-core"}'
26 26 libc = '*'
27 27 log = "0.4.8"
28 28 env_logger = "0.7.1"
29 stable_deref_trait = "1.2.0"
29 30
30 31 [dependencies.cpython]
31 32 version = "0.6.0"
@@ -12,9 +12,7 b''
12 12 mod copymap;
13 13 mod dirs_multiset;
14 14 mod dirstate_map;
15 mod dispatch;
16 15 mod non_normal_entries;
17 mod owning;
18 16 mod status;
19 17 use crate::{
20 18 dirstate::{
@@ -24,15 +24,17 b' use crate::{'
24 24 dirstate::non_normal_entries::{
25 25 NonNormalEntries, NonNormalEntriesIterator,
26 26 },
27 dirstate::owning::OwningDirstateMap,
28 27 parsers::dirstate_parents_to_pytuple,
28 pybytes_deref::PyBytesDeref,
29 29 };
30 30 use hg::{
31 31 dirstate::parsers::Timestamp,
32 32 dirstate::MTIME_UNSET,
33 33 dirstate::SIZE_NON_NORMAL,
34 dirstate_tree::dirstate_map::DirstateMap as TreeDirstateMap,
34 35 dirstate_tree::dispatch::DirstateMapMethods,
35 36 dirstate_tree::on_disk::DirstateV2ParseError,
37 dirstate_tree::owning::OwningDirstateMap,
36 38 revlog::Node,
37 39 utils::files::normalize_case,
38 40 utils::hg_path::{HgPath, HgPathBuf},
@@ -62,8 +64,13 b' py_class!(pub class DirstateMap |py| {'
62 64 on_disk: PyBytes,
63 65 ) -> PyResult<PyObject> {
64 66 let (inner, parents) = if use_dirstate_tree {
65 let (map, parents) = OwningDirstateMap::new_v1(py, on_disk)
67 let on_disk = PyBytesDeref::new(py, on_disk);
68 let mut map = OwningDirstateMap::new_empty(on_disk);
69 let (on_disk, map_placeholder) = map.get_mut_pair();
70
71 let (actual_map, parents) = TreeDirstateMap::new_v1(on_disk)
66 72 .map_err(|e| dirstate_error(py, e))?;
73 *map_placeholder = actual_map;
67 74 (Box::new(map) as _, parents)
68 75 } else {
69 76 let bytes = on_disk.data(py);
@@ -86,10 +93,13 b' py_class!(pub class DirstateMap |py| {'
86 93 let dirstate_error = |e: DirstateError| {
87 94 PyErr::new::<exc::OSError, _>(py, format!("Dirstate error: {:?}", e))
88 95 };
89 let inner = OwningDirstateMap::new_v2(
90 py, on_disk, data_size, tree_metadata,
96 let on_disk = PyBytesDeref::new(py, on_disk);
97 let mut map = OwningDirstateMap::new_empty(on_disk);
98 let (on_disk, map_placeholder) = map.get_mut_pair();
99 *map_placeholder = TreeDirstateMap::new_v2(
100 on_disk, data_size, tree_metadata.data(py),
91 101 ).map_err(dirstate_error)?;
92 let map = Self::create_instance(py, Box::new(inner))?;
102 let map = Self::create_instance(py, Box::new(map))?;
93 103 Ok(map.into_object())
94 104 }
95 105
@@ -1,4 +1,5 b''
1 1 use cpython::{PyBytes, Python};
2 use stable_deref_trait::StableDeref;
2 3
3 4 /// Safe abstraction over a `PyBytes` together with the `&[u8]` slice
4 5 /// that borrows it. Implements `Deref<Target = [u8]>`.
@@ -40,6 +41,8 b' impl std::ops::Deref for PyBytesDeref {'
40 41 }
41 42 }
42 43
44 unsafe impl StableDeref for PyBytesDeref {}
45
43 46 fn require_send<T: Send>() {}
44 47
45 48 #[allow(unused)]
General Comments 0
You need to be logged in to leave comments. Login now