Show More
@@ -9,23 +9,20 b'' | |||||
9 | //! |
|
9 | //! | |
10 | //! Ideally, we should use an Index entirely implemented in Rust, |
|
10 | //! Ideally, we should use an Index entirely implemented in Rust, | |
11 | //! but this will take some time to get there. |
|
11 | //! but this will take some time to get there. | |
12 | #[cfg(feature = "python27")] |
|
|||
13 | use python27_sys as python_sys; |
|
|||
14 | #[cfg(feature = "python3")] |
|
|||
15 | use python3_sys as python_sys; |
|
|||
16 |
|
12 | |||
17 |
use cpython::{PyClone |
|
13 | use cpython::{PyClone, PyObject, PyResult, Python}; | |
18 | use hg::{Graph, GraphError, Revision, WORKING_DIRECTORY_REVISION}; |
|
14 | use hg::{Graph, GraphError, Revision, WORKING_DIRECTORY_REVISION}; | |
19 | use libc::c_int; |
|
15 | use libc::c_int; | |
20 | use python_sys::PyCapsule_Import; |
|
|||
21 | use std::ffi::CStr; |
|
|||
22 | use std::mem::transmute; |
|
|||
23 |
|
16 | |||
24 | type IndexParentsFn = unsafe extern "C" fn( |
|
17 | py_capsule_fn!( | |
25 | index: *mut python_sys::PyObject, |
|
18 | from mercurial.cext.parsers import index_get_parents_CAPI | |
26 | rev: c_int, |
|
19 | as get_parents_capi | |
27 | ps: *mut [c_int; 2], |
|
20 | signature ( | |
28 | ) -> c_int; |
|
21 | index: *mut RawPyObject, | |
|
22 | rev: c_int, | |||
|
23 | ps: *mut [c_int; 2], | |||
|
24 | ) -> c_int | |||
|
25 | ); | |||
29 |
|
26 | |||
30 | /// A `Graph` backed up by objects and functions from revlog.c |
|
27 | /// A `Graph` backed up by objects and functions from revlog.c | |
31 | /// |
|
28 | /// | |
@@ -61,14 +58,14 b' type IndexParentsFn = unsafe extern "C" ' | |||||
61 | /// mechanisms in other contexts. |
|
58 | /// mechanisms in other contexts. | |
62 | pub struct Index { |
|
59 | pub struct Index { | |
63 | index: PyObject, |
|
60 | index: PyObject, | |
64 |
parents: |
|
61 | parents: get_parents_capi::CapsuleFn, | |
65 | } |
|
62 | } | |
66 |
|
63 | |||
67 | impl Index { |
|
64 | impl Index { | |
68 | pub fn new(py: Python, index: PyObject) -> PyResult<Self> { |
|
65 | pub fn new(py: Python, index: PyObject) -> PyResult<Self> { | |
69 | Ok(Index { |
|
66 | Ok(Index { | |
70 | index: index, |
|
67 | index: index, | |
71 |
parents: |
|
68 | parents: get_parents_capi::retrieve(py)?, | |
72 | }) |
|
69 | }) | |
73 | } |
|
70 | } | |
74 | } |
|
71 | } | |
@@ -103,31 +100,3 b' impl Graph for Index {' | |||||
103 | } |
|
100 | } | |
104 | } |
|
101 | } | |
105 | } |
|
102 | } | |
106 |
|
||||
107 | /// Return the `index_get_parents` function of the parsers C Extension module. |
|
|||
108 | /// |
|
|||
109 | /// A pointer to the function is stored in the `parsers` module as a |
|
|||
110 | /// standard [Python capsule](https://docs.python.org/2/c-api/capsule.html). |
|
|||
111 | /// |
|
|||
112 | /// This function retrieves the capsule and casts the function pointer |
|
|||
113 | /// |
|
|||
114 | /// Casting function pointers is one of the rare cases of |
|
|||
115 | /// legitimate use cases of `mem::transmute()` (see |
|
|||
116 | /// https://doc.rust-lang.org/std/mem/fn.transmute.html of |
|
|||
117 | /// `mem::transmute()`. |
|
|||
118 | /// It is inappropriate for architectures where |
|
|||
119 | /// function and data pointer sizes differ (so-called "Harvard |
|
|||
120 | /// architectures"), but these are nowadays mostly DSPs |
|
|||
121 | /// and microcontrollers, hence out of our scope. |
|
|||
122 | fn decapsule_parents_fn(py: Python) -> PyResult<IndexParentsFn> { |
|
|||
123 | unsafe { |
|
|||
124 | let caps_name = CStr::from_bytes_with_nul_unchecked( |
|
|||
125 | b"mercurial.cext.parsers.index_get_parents_CAPI\0", |
|
|||
126 | ); |
|
|||
127 | let from_caps = PyCapsule_Import(caps_name.as_ptr(), 0); |
|
|||
128 | if from_caps.is_null() { |
|
|||
129 | return Err(PyErr::fetch(py)); |
|
|||
130 | } |
|
|||
131 | Ok(transmute(from_caps)) |
|
|||
132 | } |
|
|||
133 | } |
|
@@ -22,14 +22,7 b' use hg::{' | |||||
22 | StateMap, |
|
22 | StateMap, | |
23 | }; |
|
23 | }; | |
24 | use libc::{c_char, c_int}; |
|
24 | use libc::{c_char, c_int}; | |
25 | #[cfg(feature = "python27")] |
|
|||
26 | use python27_sys as python_sys; |
|
|||
27 | #[cfg(feature = "python3")] |
|
|||
28 | use python3_sys as python_sys; |
|
|||
29 | use python_sys::PyCapsule_Import; |
|
|||
30 | use std::convert::TryFrom; |
|
25 | use std::convert::TryFrom; | |
31 | use std::ffi::CStr; |
|
|||
32 | use std::mem::transmute; |
|
|||
33 |
|
26 | |||
34 | // C code uses a custom `dirstate_tuple` type, checks in multiple instances |
|
27 | // C code uses a custom `dirstate_tuple` type, checks in multiple instances | |
35 | // for this type, and raises a Python `Exception` if the check does not pass. |
|
28 | // for this type, and raises a Python `Exception` if the check does not pass. | |
@@ -37,34 +30,23 b' use std::mem::transmute;' | |||||
37 | // would be a good idea in the near future to remove it entirely to allow |
|
30 | // would be a good idea in the near future to remove it entirely to allow | |
38 | // for a pure Python tuple of the same effective structure to be used, |
|
31 | // for a pure Python tuple of the same effective structure to be used, | |
39 | // rendering this type and the capsule below useless. |
|
32 | // rendering this type and the capsule below useless. | |
40 | type MakeDirstateTupleFn = unsafe extern "C" fn( |
|
33 | py_capsule_fn!( | |
41 | state: c_char, |
|
34 | from mercurial.cext.parsers import make_dirstate_tuple_CAPI | |
42 | mode: c_int, |
|
35 | as make_dirstate_tuple_capi | |
43 | size: c_int, |
|
36 | signature ( | |
44 | mtime: c_int, |
|
37 | state: c_char, | |
45 | ) -> *mut python_sys::PyObject; |
|
38 | mode: c_int, | |
46 |
|
39 | size: c_int, | ||
47 | // This is largely a copy/paste from cindex.rs, pending the merge of a |
|
40 | mtime: c_int, | |
48 | // `py_capsule_fn!` macro in the rust-cpython project: |
|
41 | ) -> *mut RawPyObject | |
49 | // https://github.com/dgrunwald/rust-cpython/pull/169 |
|
42 | ); | |
50 | fn decapsule_make_dirstate_tuple(py: Python) -> PyResult<MakeDirstateTupleFn> { |
|
|||
51 | unsafe { |
|
|||
52 | let caps_name = CStr::from_bytes_with_nul_unchecked( |
|
|||
53 | b"mercurial.cext.parsers.make_dirstate_tuple_CAPI\0", |
|
|||
54 | ); |
|
|||
55 | let from_caps = PyCapsule_Import(caps_name.as_ptr(), 0); |
|
|||
56 | if from_caps.is_null() { |
|
|||
57 | return Err(PyErr::fetch(py)); |
|
|||
58 | } |
|
|||
59 | Ok(transmute(from_caps)) |
|
|||
60 | } |
|
|||
61 | } |
|
|||
62 |
|
43 | |||
63 | pub fn make_dirstate_tuple( |
|
44 | pub fn make_dirstate_tuple( | |
64 | py: Python, |
|
45 | py: Python, | |
65 | entry: &DirstateEntry, |
|
46 | entry: &DirstateEntry, | |
66 | ) -> PyResult<PyObject> { |
|
47 | ) -> PyResult<PyObject> { | |
67 | let make = decapsule_make_dirstate_tuple(py)?; |
|
48 | // might be silly to retrieve capsule function in hot loop | |
|
49 | let make = make_dirstate_tuple_capi::retrieve(py)?; | |||
68 |
|
50 | |||
69 | let &DirstateEntry { |
|
51 | let &DirstateEntry { | |
70 | state, |
|
52 | state, |
General Comments 0
You need to be logged in to leave comments.
Login now