comparison rust/hg-cpython/src/cindex.rs @ 43959:f384d68d8ea8

revlog: made C Capsule an array of function pointers Although it's perfectly valid to put a function pointer in a capsule, as we've been doing since the start of rust/hg-cpython, an array of function pointers has several advantages: - it can hold several functions. That's our main motivation here. We plan to expose index_length() and index_node(), which will be needed for a Rust implementation of nodemap. - it could also have data - (probably minor in the case of Mercurial) proper support for architectures for which data and code pointers don't have the same size. Differential Revision: https://phab.mercurial-scm.org/D7543
author Georges Racinet <georges.racinet@octobus.net>
date Wed, 27 Nov 2019 17:59:58 +0100
parents 0246bbe1045d
children ab3fd8077f5e
comparison
equal deleted inserted replaced
43958:26cf356ae772 43959:f384d68d8ea8
12 12
13 use cpython::{PyClone, PyObject, PyResult, Python}; 13 use cpython::{PyClone, PyObject, PyResult, Python};
14 use hg::{Graph, GraphError, Revision, WORKING_DIRECTORY_REVISION}; 14 use hg::{Graph, GraphError, Revision, WORKING_DIRECTORY_REVISION};
15 use libc::c_int; 15 use libc::c_int;
16 16
17 py_capsule_fn!( 17 #[repr(C)]
18 from mercurial.cext.parsers import index_get_parents_CAPI 18 pub struct Revlog_CAPI {
19 as get_parents_capi 19 index_parents: unsafe extern "C" fn(
20 signature ( 20 index: *mut revlog_capi::RawPyObject,
21 index: *mut RawPyObject, 21 rev: c_int,
22 rev: c_int, 22 ps: *mut [c_int; 2],
23 ps: *mut [c_int; 2], 23 ) -> c_int,
24 ) -> c_int 24 }
25 ); 25
26 py_capsule!(
27 from mercurial.cext.parsers import revlog_CAPI
28 as revlog_capi for Revlog_CAPI);
26 29
27 /// A `Graph` backed up by objects and functions from revlog.c 30 /// A `Graph` backed up by objects and functions from revlog.c
28 /// 31 ///
29 /// This implementation of the `Graph` trait, relies on (pointers to) 32 /// This implementation of the `Graph` trait, relies on (pointers to)
30 /// - the C index object (`index` member) 33 /// - the C index object (`index` member)
56 /// the core API, that would be tied to `GILGuard` / `Python<'p>` 59 /// the core API, that would be tied to `GILGuard` / `Python<'p>`
57 /// in the case of the `cpython` crate bindings yet could leave room for other 60 /// in the case of the `cpython` crate bindings yet could leave room for other
58 /// mechanisms in other contexts. 61 /// mechanisms in other contexts.
59 pub struct Index { 62 pub struct Index {
60 index: PyObject, 63 index: PyObject,
61 parents: get_parents_capi::CapsuleFn, 64 capi: &'static Revlog_CAPI,
62 } 65 }
63 66
64 impl Index { 67 impl Index {
65 pub fn new(py: Python, index: PyObject) -> PyResult<Self> { 68 pub fn new(py: Python, index: PyObject) -> PyResult<Self> {
66 Ok(Index { 69 Ok(Index {
67 index: index, 70 index: index,
68 parents: get_parents_capi::retrieve(py)?, 71 capi: unsafe { revlog_capi::retrieve(py)? },
69 }) 72 })
70 } 73 }
71 } 74 }
72 75
73 impl Clone for Index { 76 impl Clone for Index {
74 fn clone(&self) -> Self { 77 fn clone(&self) -> Self {
75 let guard = Python::acquire_gil(); 78 let guard = Python::acquire_gil();
76 Index { 79 Index {
77 index: self.index.clone_ref(guard.python()), 80 index: self.index.clone_ref(guard.python()),
78 parents: self.parents.clone(), 81 capi: self.capi,
79 } 82 }
80 } 83 }
81 } 84 }
82 85
83 impl Graph for Index { 86 impl Graph for Index {
86 if rev == WORKING_DIRECTORY_REVISION { 89 if rev == WORKING_DIRECTORY_REVISION {
87 return Err(GraphError::WorkingDirectoryUnsupported); 90 return Err(GraphError::WorkingDirectoryUnsupported);
88 } 91 }
89 let mut res: [c_int; 2] = [0; 2]; 92 let mut res: [c_int; 2] = [0; 2];
90 let code = unsafe { 93 let code = unsafe {
91 (self.parents)( 94 (self.capi.index_parents)(
92 self.index.as_ptr(), 95 self.index.as_ptr(),
93 rev as c_int, 96 rev as c_int,
94 &mut res as *mut [c_int; 2], 97 &mut res as *mut [c_int; 2],
95 ) 98 )
96 }; 99 };