D8152: revlog: using two new functions in C capsule from Rust code

2020-03-11 Thread gracinet (Georges Racinet)
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

2020-03-10 Thread marmoute (Pierre-Yves David)
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

2020-03-10 Thread Raphaël Gomès
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

2020-02-26 Thread Raphaël Gomès
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