D8152: revlog: using two new functions in C capsule from Rust code
Closed by commit rHG166349510398: revlog: using two new functions in C capsule from Rust code (authored by gracinet). This revision was automatically updated to reflect the committed changes. This revision was not accepted when it landed; it landed in state "Needs Review". REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D8152?vs=20678=20690 CHANGES SINCE LAST ACTION https://phab.mercurial-scm.org/D8152/new/ REVISION DETAIL https://phab.mercurial-scm.org/D8152 AFFECTED FILES mercurial/cext/revlog.c rust/hg-core/src/revlog/node.rs rust/hg-cpython/src/cindex.rs CHANGE DETAILS diff --git a/rust/hg-cpython/src/cindex.rs b/rust/hg-cpython/src/cindex.rs --- a/rust/hg-cpython/src/cindex.rs +++ b/rust/hg-cpython/src/cindex.rs @@ -11,14 +11,21 @@ //! but this will take some time to get there. use cpython::{exc::ImportError, PyClone, PyErr, PyObject, PyResult, Python}; +use hg::revlog::{Node, RevlogIndex}; use hg::{Graph, GraphError, Revision, WORKING_DIRECTORY_REVISION}; use libc::c_int; -const REVLOG_CABI_VERSION: c_int = 1; +const REVLOG_CABI_VERSION: c_int = 2; #[repr(C)] pub struct Revlog_CAPI { abi_version: c_int, +index_length: +unsafe extern "C" fn(index: *mut revlog_capi::RawPyObject) -> c_int, +index_node: unsafe extern "C" fn( +index: *mut revlog_capi::RawPyObject, +rev: c_int, +) -> *const Node, index_parents: unsafe extern "C" fn( index: *mut revlog_capi::RawPyObject, rev: c_int, @@ -131,3 +138,30 @@ } } } + +impl RevlogIndex for Index { +/// Note C return type is Py_ssize_t (hence signed), but we shall +/// force it to unsigned, because it's a length +fn len() -> usize { +unsafe { (self.capi.index_length)(self.index.as_ptr()) as usize } +} + +fn node<'a>(&'a self, rev: Revision) -> Option<&'a Node> { +let raw = unsafe { +(self.capi.index_node)(self.index.as_ptr(), rev as c_int) +}; +if raw.is_null() { +None +} else { +// TODO it would be much better for the C layer to give us +// a length, since the hash length will change in the near +// future, but that's probably out of scope for the nodemap +// patch series. +// +// The root of that unsafety relies in the signature of +// `capi.index_node()` itself: returning a `Node` pointer +// whereas it's a `char *` in the C counterpart. +Some(unsafe { &*raw }) +} +} +} diff --git a/rust/hg-core/src/revlog/node.rs b/rust/hg-core/src/revlog/node.rs --- a/rust/hg-core/src/revlog/node.rs +++ b/rust/hg-core/src/revlog/node.rs @@ -44,6 +44,7 @@ /// [`nybbles_len`]: #method.nybbles_len /// [`ExactLengthRequired`]: struct.NodeError#variant.ExactLengthRequired #[derive(Clone, Debug, PartialEq)] +#[repr(transparent)] pub struct Node { data: NodeData, } diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c --- a/mercurial/cext/revlog.c +++ b/mercurial/cext/revlog.c @@ -39,6 +39,8 @@ typedef struct { int abi_version; + Py_ssize_t (*index_length)(const indexObject *); + const char *(*index_node)(indexObject *, Py_ssize_t); int (*index_parents)(PyObject *, int, int *); } Revlog_CAPI; @@ -2877,7 +2879,9 @@ static Revlog_CAPI CAPI = { /* increment the abi_version field upon each change in the Revlog_CAPI struct or in the ABI of the listed functions */ -1, +2, +index_length, +index_node, HgRevlogIndex_GetParents, }; To: Alphare, #hg-reviewers Cc: marmoute, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D8152: revlog: using two new functions in C capsule from Rust code
marmoute added a comment. marmoute updated this revision to Diff 20678. rebase above latest default up to landed-D8182 REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D8152?vs=20651=20678 BRANCH default CHANGES SINCE LAST ACTION https://phab.mercurial-scm.org/D8152/new/ REVISION DETAIL https://phab.mercurial-scm.org/D8152 AFFECTED FILES mercurial/cext/revlog.c rust/hg-core/src/revlog/node.rs rust/hg-cpython/src/cindex.rs CHANGE DETAILS diff --git a/rust/hg-cpython/src/cindex.rs b/rust/hg-cpython/src/cindex.rs --- a/rust/hg-cpython/src/cindex.rs +++ b/rust/hg-cpython/src/cindex.rs @@ -11,14 +11,21 @@ //! but this will take some time to get there. use cpython::{exc::ImportError, PyClone, PyErr, PyObject, PyResult, Python}; +use hg::revlog::{Node, RevlogIndex}; use hg::{Graph, GraphError, Revision, WORKING_DIRECTORY_REVISION}; use libc::c_int; -const REVLOG_CABI_VERSION: c_int = 1; +const REVLOG_CABI_VERSION: c_int = 2; #[repr(C)] pub struct Revlog_CAPI { abi_version: c_int, +index_length: +unsafe extern "C" fn(index: *mut revlog_capi::RawPyObject) -> c_int, +index_node: unsafe extern "C" fn( +index: *mut revlog_capi::RawPyObject, +rev: c_int, +) -> *const Node, index_parents: unsafe extern "C" fn( index: *mut revlog_capi::RawPyObject, rev: c_int, @@ -131,3 +138,30 @@ } } } + +impl RevlogIndex for Index { +/// Note C return type is Py_ssize_t (hence signed), but we shall +/// force it to unsigned, because it's a length +fn len() -> usize { +unsafe { (self.capi.index_length)(self.index.as_ptr()) as usize } +} + +fn node<'a>(&'a self, rev: Revision) -> Option<&'a Node> { +let raw = unsafe { +(self.capi.index_node)(self.index.as_ptr(), rev as c_int) +}; +if raw.is_null() { +None +} else { +// TODO it would be much better for the C layer to give us +// a length, since the hash length will change in the near +// future, but that's probably out of scope for the nodemap +// patch series. +// +// The root of that unsafety relies in the signature of +// `capi.index_node()` itself: returning a `Node` pointer +// whereas it's a `char *` in the C counterpart. +Some(unsafe { &*raw }) +} +} +} diff --git a/rust/hg-core/src/revlog/node.rs b/rust/hg-core/src/revlog/node.rs --- a/rust/hg-core/src/revlog/node.rs +++ b/rust/hg-core/src/revlog/node.rs @@ -44,6 +44,7 @@ /// [`nybbles_len`]: #method.nybbles_len /// [`ExactLengthRequired`]: struct.NodeError#variant.ExactLengthRequired #[derive(Clone, Debug, PartialEq)] +#[repr(transparent)] pub struct Node { data: NodeData, } diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c --- a/mercurial/cext/revlog.c +++ b/mercurial/cext/revlog.c @@ -39,6 +39,8 @@ typedef struct { int abi_version; + Py_ssize_t (*index_length)(const indexObject *); + const char *(*index_node)(indexObject *, Py_ssize_t); int (*index_parents)(PyObject *, int, int *); } Revlog_CAPI; @@ -2877,7 +2879,9 @@ static Revlog_CAPI CAPI = { /* increment the abi_version field upon each change in the Revlog_CAPI struct or in the ABI of the listed functions */ -1, +2, +index_length, +index_node, HgRevlogIndex_GetParents, }; To: Alphare, #hg-reviewers Cc: marmoute, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D8152: revlog: using two new functions in C capsule from Rust code
Alphare updated this revision to Diff 20651. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D8152?vs=20327=20651 BRANCH default CHANGES SINCE LAST ACTION https://phab.mercurial-scm.org/D8152/new/ REVISION DETAIL https://phab.mercurial-scm.org/D8152 AFFECTED FILES mercurial/cext/revlog.c rust/hg-core/src/revlog/node.rs rust/hg-cpython/src/cindex.rs CHANGE DETAILS diff --git a/rust/hg-cpython/src/cindex.rs b/rust/hg-cpython/src/cindex.rs --- a/rust/hg-cpython/src/cindex.rs +++ b/rust/hg-cpython/src/cindex.rs @@ -11,14 +11,21 @@ //! but this will take some time to get there. use cpython::{exc::ImportError, PyClone, PyErr, PyObject, PyResult, Python}; +use hg::revlog::{Node, RevlogIndex}; use hg::{Graph, GraphError, Revision, WORKING_DIRECTORY_REVISION}; use libc::c_int; -const REVLOG_CABI_VERSION: c_int = 1; +const REVLOG_CABI_VERSION: c_int = 2; #[repr(C)] pub struct Revlog_CAPI { abi_version: c_int, +index_length: +unsafe extern "C" fn(index: *mut revlog_capi::RawPyObject) -> c_int, +index_node: unsafe extern "C" fn( +index: *mut revlog_capi::RawPyObject, +rev: c_int, +) -> *const Node, index_parents: unsafe extern "C" fn( index: *mut revlog_capi::RawPyObject, rev: c_int, @@ -131,3 +138,30 @@ } } } + +impl RevlogIndex for Index { +/// Note C return type is Py_ssize_t (hence signed), but we shall +/// force it to unsigned, because it's a length +fn len() -> usize { +unsafe { (self.capi.index_length)(self.index.as_ptr()) as usize } +} + +fn node<'a>(&'a self, rev: Revision) -> Option<&'a Node> { +let raw = unsafe { +(self.capi.index_node)(self.index.as_ptr(), rev as c_int) +}; +if raw.is_null() { +None +} else { +// TODO it would be much better for the C layer to give us +// a length, since the hash length will change in the near +// future, but that's probably out of scope for the nodemap +// patch series. +// +// The root of that unsafety relies in the signature of +// `capi.index_node()` itself: returning a `Node` pointer +// whereas it's a `char *` in the C counterpart. +Some(unsafe { &*raw }) +} +} +} diff --git a/rust/hg-core/src/revlog/node.rs b/rust/hg-core/src/revlog/node.rs --- a/rust/hg-core/src/revlog/node.rs +++ b/rust/hg-core/src/revlog/node.rs @@ -44,6 +44,7 @@ /// [`nybbles_len`]: #method.nybbles_len /// [`ExactLengthRequired`]: struct.NodeError#variant.ExactLengthRequired #[derive(Clone, Debug, PartialEq)] +#[repr(transparent)] pub struct Node { data: NodeData, } diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c --- a/mercurial/cext/revlog.c +++ b/mercurial/cext/revlog.c @@ -39,6 +39,8 @@ typedef struct { int abi_version; + Py_ssize_t (*index_length)(const indexObject *); + const char *(*index_node)(indexObject *, Py_ssize_t); int (*index_parents)(PyObject *, int, int *); } Revlog_CAPI; @@ -3040,7 +3042,9 @@ static Revlog_CAPI CAPI = { /* increment the abi_version field upon each change in the Revlog_CAPI struct or in the ABI of the listed functions */ -1, +2, +index_length, +index_node, HgRevlogIndex_GetParents, }; To: Alphare, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D8152: revlog: using two new functions in C capsule from Rust code
Alphare created this revision. Herald added a subscriber: mercurial-devel. Herald added a reviewer: hg-reviewers. REVISION SUMMARY We expose `index_length` and `index_node` in the C capsule, so that the Rust representation of the C index can implement the `RevlogIndex` trait. Because our `Node` is actually a one-field struct, we have to decorate it for direct FFI exchange with the C `char*` It would be a good thing to get a length from the C layer, but doing so right now would probably interfere with the upcoming changes that will happen there for the hash length. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D8152 AFFECTED FILES mercurial/cext/revlog.c rust/hg-core/src/revlog/node.rs rust/hg-cpython/src/cindex.rs CHANGE DETAILS diff --git a/rust/hg-cpython/src/cindex.rs b/rust/hg-cpython/src/cindex.rs --- a/rust/hg-cpython/src/cindex.rs +++ b/rust/hg-cpython/src/cindex.rs @@ -11,14 +11,21 @@ //! but this will take some time to get there. use cpython::{exc::ImportError, PyClone, PyErr, PyObject, PyResult, Python}; +use hg::revlog::{Node, RevlogIndex}; use hg::{Graph, GraphError, Revision, WORKING_DIRECTORY_REVISION}; use libc::c_int; -const REVLOG_CABI_VERSION: c_int = 1; +const REVLOG_CABI_VERSION: c_int = 2; #[repr(C)] pub struct Revlog_CAPI { abi_version: c_int, +index_length: +unsafe extern "C" fn(index: *mut revlog_capi::RawPyObject) -> c_int, +index_node: unsafe extern "C" fn( +index: *mut revlog_capi::RawPyObject, +rev: c_int, +) -> *const Node, index_parents: unsafe extern "C" fn( index: *mut revlog_capi::RawPyObject, rev: c_int, @@ -131,3 +138,30 @@ } } } + +impl RevlogIndex for Index { +/// Note C return type is Py_ssize_t (hence signed), but we shall +/// force it to unsigned, because it's a length +fn len() -> usize { +unsafe { (self.capi.index_length)(self.index.as_ptr()) as usize } +} + +fn node<'a>(&'a self, rev: Revision) -> Option<&'a Node> { +let raw = unsafe { +(self.capi.index_node)(self.index.as_ptr(), rev as c_int) +}; +if raw.is_null() { +None +} else { +// TODO it would be much better for the C layer to give us +// a length, since the hash length will change in the near +// future, but that's probably out of scope for the nodemap +// patch series. +// +// The root of that unsafety relies in the signature of +// `capi.index_node()` itself: returning a `Node` pointer +// whereas it's a `char *` in the C counterpart. +Some(unsafe { &*raw }) +} +} +} diff --git a/rust/hg-core/src/revlog/node.rs b/rust/hg-core/src/revlog/node.rs --- a/rust/hg-core/src/revlog/node.rs +++ b/rust/hg-core/src/revlog/node.rs @@ -44,6 +44,7 @@ /// [`nybbles_len`]: #method.nybbles_len /// [`ExactLengthRequired`]: struct.NodeError#variant.ExactLengthRequired #[derive(Clone, Debug, PartialEq)] +#[repr(transparent)] pub struct Node { data: NodeData, } diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c --- a/mercurial/cext/revlog.c +++ b/mercurial/cext/revlog.c @@ -39,6 +39,8 @@ typedef struct { int abi_version; + Py_ssize_t (*index_length)(const indexObject *); + const char *(*index_node)(indexObject *, Py_ssize_t); int (*index_parents)(PyObject *, int, int *); } Revlog_CAPI; @@ -3040,7 +3042,9 @@ static Revlog_CAPI CAPI = { /* increment the abi_version field upon each change in the Revlog_CAPI struct or in the ABI of the listed functions */ -1, +2, +index_length, +index_node, HgRevlogIndex_GetParents, }; To: Alphare, #hg-reviewers Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel