D7910: rust-re2: add wrapper for calling Re2 from Rust

2020-02-10 Thread Raphaël Gomès
Closed by commit rHGcdf3e49a0572: rust-re2: add wrapper for calling Re2 from 
Rust (authored by Alphare).
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/D7910?vs=20040&id=20080

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D7910/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D7910

AFFECTED FILES
  rust/Cargo.lock
  rust/hg-core/Cargo.toml
  rust/hg-core/build.rs
  rust/hg-core/src/lib.rs
  rust/hg-core/src/re2/mod.rs
  rust/hg-core/src/re2/re2.rs
  rust/hg-core/src/re2/rust_re2.cpp
  rust/hg-cpython/Cargo.toml
  setup.py

CHANGE DETAILS

diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -1351,10 +1351,19 @@
 env['HOME'] = pwd.getpwuid(os.getuid()).pw_dir
 
 cargocmd = ['cargo', 'rustc', '-vv', '--release']
+
+feature_flags = []
+
 if sys.version_info[0] == 3 and self.py3_features is not None:
-cargocmd.extend(
-('--features', self.py3_features, '--no-default-features')
-)
+feature_flags.append(self.py3_features)
+cargocmd.append('--no-default-features')
+
+rust_features = env.get("HG_RUST_FEATURES")
+if rust_features:
+feature_flags.append(rust_features)
+
+cargocmd.extend(('--features', " ".join(feature_flags)))
+
 cargocmd.append('--')
 if sys.platform == 'darwin':
 cargocmd.extend(
diff --git a/rust/hg-cpython/Cargo.toml b/rust/hg-cpython/Cargo.toml
--- a/rust/hg-cpython/Cargo.toml
+++ b/rust/hg-cpython/Cargo.toml
@@ -10,6 +10,7 @@
 
 [features]
 default = ["python27"]
+with-re2 = ["hg-core/with-re2"]
 
 # Features to build an extension module:
 python27 = ["cpython/python27-sys", "cpython/extension-module-2-7"]
@@ -21,7 +22,7 @@
 python3-bin = ["cpython/python3-sys"]
 
 [dependencies]
-hg-core = { path = "../hg-core" }
+hg-core = { path = "../hg-core"}
 libc = '*'
 
 [dependencies.cpython]
diff --git a/rust/hg-core/src/re2/rust_re2.cpp 
b/rust/hg-core/src/re2/rust_re2.cpp
new file mode 100644
--- /dev/null
+++ b/rust/hg-core/src/re2/rust_re2.cpp
@@ -0,0 +1,49 @@
+/*
+rust_re2.cpp
+
+C ABI export of Re2's C++ interface for Rust FFI.
+
+Copyright 2020 Valentin Gatien-Baron
+
+This software may be used and distributed according to the terms of the
+GNU General Public License version 2 or any later version.
+*/
+
+#include 
+using namespace re2;
+
+extern "C" {
+   RE2* rust_re2_create(const char* data, size_t len) {
+   RE2::Options o;
+   o.set_encoding(RE2::Options::Encoding::EncodingLatin1);
+   o.set_log_errors(false);
+   o.set_max_mem(5000);
+
+   return new RE2(StringPiece(data, len), o);
+   }
+
+   void rust_re2_destroy(RE2* re) {
+   delete re;
+   }
+
+   bool rust_re2_ok(RE2* re) {
+   return re->ok();
+   }
+
+   void rust_re2_error(RE2* re, const char** outdata, size_t* outlen) {
+   const std::string& e = re->error();
+   *outdata = e.data();
+   *outlen = e.length();
+   }
+
+   bool rust_re2_match(RE2* re, char* data, size_t len, int ianchor) {
+   const StringPiece sp = StringPiece(data, len);
+
+   RE2::Anchor anchor =
+   ianchor == 0 ? RE2::Anchor::UNANCHORED :
+   (ianchor == 1 ? RE2::Anchor::ANCHOR_START :
+RE2::Anchor::ANCHOR_BOTH);
+
+   return re->Match(sp, 0, len, anchor, NULL, 0);
+   }
+}
diff --git a/rust/hg-core/src/re2/re2.rs b/rust/hg-core/src/re2/re2.rs
new file mode 100644
--- /dev/null
+++ b/rust/hg-core/src/re2/re2.rs
@@ -0,0 +1,66 @@
+/*
+re2.rs
+
+Rust FFI bindings to Re2.
+
+Copyright 2020 Valentin Gatien-Baron
+
+This software may be used and distributed according to the terms of the
+GNU General Public License version 2 or any later version.
+*/
+use libc::{c_int, c_void};
+
+type Re2Ptr = *const c_void;
+
+pub struct Re2(Re2Ptr);
+
+/// `re2.h` says:
+/// "An "RE2" object is safe for concurrent use by multiple threads."
+unsafe impl Sync for Re2 {}
+
+/// These bind to the C ABI in `rust_re2.cpp`.
+extern "C" {
+fn rust_re2_create(data: *const u8, len: usize) -> Re2Ptr;
+fn rust_re2_destroy(re2: Re2Ptr);
+fn rust_re2_ok(re2: Re2Ptr) -> bool;
+fn rust_re2_error(
+re2: Re2Ptr,
+outdata: *mut *const u8,
+outlen: *mut usize,
+) -> bool;
+fn rust_re2_match(
+re2: Re2Ptr,
+data: *const u8,
+len: usize,
+anchor: c_int,
+) -> bool;
+}
+
+impl Re2 {
+pub fn new(pattern: &[u8]) -> Result {
+unsafe {
+let re2 = rust_re2_create(pattern.as_ptr(), pattern.len());
+if rust_re2_ok(re2) {
+Ok(R

D7910: rust-re2: add wrapper for calling Re2 from Rust

2020-02-10 Thread Raphaël Gomès
Alphare updated this revision to Diff 20040.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D7910?vs=19938&id=20040

BRANCH
  default

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D7910/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D7910

AFFECTED FILES
  rust/Cargo.lock
  rust/hg-core/Cargo.toml
  rust/hg-core/build.rs
  rust/hg-core/src/lib.rs
  rust/hg-core/src/re2/mod.rs
  rust/hg-core/src/re2/re2.rs
  rust/hg-core/src/re2/rust_re2.cpp
  rust/hg-cpython/Cargo.toml
  setup.py

CHANGE DETAILS

diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -1351,10 +1351,19 @@
 env['HOME'] = pwd.getpwuid(os.getuid()).pw_dir
 
 cargocmd = ['cargo', 'rustc', '-vv', '--release']
+
+feature_flags = []
+
 if sys.version_info[0] == 3 and self.py3_features is not None:
-cargocmd.extend(
-('--features', self.py3_features, '--no-default-features')
-)
+feature_flags.append(self.py3_features)
+cargocmd.append('--no-default-features')
+
+rust_features = env.get("HG_RUST_FEATURES")
+if rust_features:
+feature_flags.append(rust_features)
+
+cargocmd.extend(('--features', " ".join(feature_flags)))
+
 cargocmd.append('--')
 if sys.platform == 'darwin':
 cargocmd.extend(
diff --git a/rust/hg-cpython/Cargo.toml b/rust/hg-cpython/Cargo.toml
--- a/rust/hg-cpython/Cargo.toml
+++ b/rust/hg-cpython/Cargo.toml
@@ -10,6 +10,7 @@
 
 [features]
 default = ["python27"]
+with-re2 = ["hg-core/with-re2"]
 
 # Features to build an extension module:
 python27 = ["cpython/python27-sys", "cpython/extension-module-2-7"]
@@ -21,7 +22,7 @@
 python3-bin = ["cpython/python3-sys"]
 
 [dependencies]
-hg-core = { path = "../hg-core" }
+hg-core = { path = "../hg-core"}
 libc = '*'
 
 [dependencies.cpython]
diff --git a/rust/hg-core/src/re2/rust_re2.cpp 
b/rust/hg-core/src/re2/rust_re2.cpp
new file mode 100644
--- /dev/null
+++ b/rust/hg-core/src/re2/rust_re2.cpp
@@ -0,0 +1,49 @@
+/*
+rust_re2.cpp
+
+C ABI export of Re2's C++ interface for Rust FFI.
+
+Copyright 2020 Valentin Gatien-Baron
+
+This software may be used and distributed according to the terms of the
+GNU General Public License version 2 or any later version.
+*/
+
+#include 
+using namespace re2;
+
+extern "C" {
+   RE2* rust_re2_create(const char* data, size_t len) {
+   RE2::Options o;
+   o.set_encoding(RE2::Options::Encoding::EncodingLatin1);
+   o.set_log_errors(false);
+   o.set_max_mem(5000);
+
+   return new RE2(StringPiece(data, len), o);
+   }
+
+   void rust_re2_destroy(RE2* re) {
+   delete re;
+   }
+
+   bool rust_re2_ok(RE2* re) {
+   return re->ok();
+   }
+
+   void rust_re2_error(RE2* re, const char** outdata, size_t* outlen) {
+   const std::string& e = re->error();
+   *outdata = e.data();
+   *outlen = e.length();
+   }
+
+   bool rust_re2_match(RE2* re, char* data, size_t len, int ianchor) {
+   const StringPiece sp = StringPiece(data, len);
+
+   RE2::Anchor anchor =
+   ianchor == 0 ? RE2::Anchor::UNANCHORED :
+   (ianchor == 1 ? RE2::Anchor::ANCHOR_START :
+RE2::Anchor::ANCHOR_BOTH);
+
+   return re->Match(sp, 0, len, anchor, NULL, 0);
+   }
+}
diff --git a/rust/hg-core/src/re2/re2.rs b/rust/hg-core/src/re2/re2.rs
new file mode 100644
--- /dev/null
+++ b/rust/hg-core/src/re2/re2.rs
@@ -0,0 +1,66 @@
+/*
+re2.rs
+
+Rust FFI bindings to Re2.
+
+Copyright 2020 Valentin Gatien-Baron
+
+This software may be used and distributed according to the terms of the
+GNU General Public License version 2 or any later version.
+*/
+use libc::{c_int, c_void};
+
+type Re2Ptr = *const c_void;
+
+pub struct Re2(Re2Ptr);
+
+/// `re2.h` says:
+/// "An "RE2" object is safe for concurrent use by multiple threads."
+unsafe impl Sync for Re2 {}
+
+/// These bind to the C ABI in `rust_re2.cpp`.
+extern "C" {
+fn rust_re2_create(data: *const u8, len: usize) -> Re2Ptr;
+fn rust_re2_destroy(re2: Re2Ptr);
+fn rust_re2_ok(re2: Re2Ptr) -> bool;
+fn rust_re2_error(
+re2: Re2Ptr,
+outdata: *mut *const u8,
+outlen: *mut usize,
+) -> bool;
+fn rust_re2_match(
+re2: Re2Ptr,
+data: *const u8,
+len: usize,
+anchor: c_int,
+) -> bool;
+}
+
+impl Re2 {
+pub fn new(pattern: &[u8]) -> Result {
+unsafe {
+let re2 = rust_re2_create(pattern.as_ptr(), pattern.len());
+if rust_re2_ok(re2) {
+Ok(Re2(re2))
+} else {
+let mut data: *const u8 = std::ptr::null();
+let mut len: usize = 0;
+rust_re2_error(re2, &mut data, &mut len);
+   

D7910: rust-re2: add wrapper for calling Re2 from Rust

2020-02-06 Thread Raphaël Gomès
Alphare updated this revision to Diff 19938.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D7910?vs=19546&id=19938

BRANCH
  default

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D7910/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D7910

AFFECTED FILES
  rust/Cargo.lock
  rust/hg-core/Cargo.toml
  rust/hg-core/build.rs
  rust/hg-core/src/lib.rs
  rust/hg-core/src/re2/mod.rs
  rust/hg-core/src/re2/re2.rs
  rust/hg-core/src/re2/rust_re2.cpp
  rust/hg-cpython/Cargo.toml
  setup.py

CHANGE DETAILS

diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -1351,10 +1351,19 @@
 env['HOME'] = pwd.getpwuid(os.getuid()).pw_dir
 
 cargocmd = ['cargo', 'rustc', '-vv', '--release']
+
+feature_flags = []
+
 if sys.version_info[0] == 3 and self.py3_features is not None:
-cargocmd.extend(
-('--features', self.py3_features, '--no-default-features')
-)
+feature_flags.append(self.py3_features)
+cargocmd.append('--no-default-features')
+
+rust_features = env.get("HG_RUST_FEATURES")
+if rust_features:
+feature_flags.append(rust_features)
+
+cargocmd.extend(('--features', " ".join(feature_flags)))
+
 cargocmd.append('--')
 if sys.platform == 'darwin':
 cargocmd.extend(
diff --git a/rust/hg-cpython/Cargo.toml b/rust/hg-cpython/Cargo.toml
--- a/rust/hg-cpython/Cargo.toml
+++ b/rust/hg-cpython/Cargo.toml
@@ -10,6 +10,7 @@
 
 [features]
 default = ["python27"]
+with-re2 = ["hg-core/with-re2"]
 
 # Features to build an extension module:
 python27 = ["cpython/python27-sys", "cpython/extension-module-2-7"]
@@ -21,7 +22,7 @@
 python3-bin = ["cpython/python3-sys"]
 
 [dependencies]
-hg-core = { path = "../hg-core" }
+hg-core = { path = "../hg-core"}
 libc = '*'
 
 [dependencies.cpython]
diff --git a/rust/hg-core/src/re2/rust_re2.cpp 
b/rust/hg-core/src/re2/rust_re2.cpp
new file mode 100644
--- /dev/null
+++ b/rust/hg-core/src/re2/rust_re2.cpp
@@ -0,0 +1,49 @@
+/*
+rust_re2.cpp
+
+C ABI export of Re2's C++ interface for Rust FFI.
+
+Copyright 2020 Valentin Gatien-Baron
+
+This software may be used and distributed according to the terms of the
+GNU General Public License version 2 or any later version.
+*/
+
+#include 
+using namespace re2;
+
+extern "C" {
+   RE2* rust_re2_create(const char* data, size_t len) {
+   RE2::Options o;
+   o.set_encoding(RE2::Options::Encoding::EncodingLatin1);
+   o.set_log_errors(false);
+   o.set_max_mem(5000);
+
+   return new RE2(StringPiece(data, len), o);
+   }
+
+   void rust_re2_destroy(RE2* re) {
+   delete re;
+   }
+
+   bool rust_re2_ok(RE2* re) {
+   return re->ok();
+   }
+
+   void rust_re2_error(RE2* re, const char** outdata, size_t* outlen) {
+   const std::string& e = re->error();
+   *outdata = e.data();
+   *outlen = e.length();
+   }
+
+   bool rust_re2_match(RE2* re, char* data, size_t len, int ianchor) {
+   const StringPiece sp = StringPiece(data, len);
+
+   RE2::Anchor anchor =
+   ianchor == 0 ? RE2::Anchor::UNANCHORED :
+   (ianchor == 1 ? RE2::Anchor::ANCHOR_START :
+RE2::Anchor::ANCHOR_BOTH);
+
+   return re->Match(sp, 0, len, anchor, NULL, 0);
+   }
+}
diff --git a/rust/hg-core/src/re2/re2.rs b/rust/hg-core/src/re2/re2.rs
new file mode 100644
--- /dev/null
+++ b/rust/hg-core/src/re2/re2.rs
@@ -0,0 +1,66 @@
+/*
+re2.rs
+
+Rust FFI bindings to Re2.
+
+Copyright 2020 Valentin Gatien-Baron
+
+This software may be used and distributed according to the terms of the
+GNU General Public License version 2 or any later version.
+*/
+use libc::{c_int, c_void};
+
+type Re2Ptr = *const c_void;
+
+pub struct Re2(Re2Ptr);
+
+/// `re2.h` says:
+/// "An "RE2" object is safe for concurrent use by multiple threads."
+unsafe impl Sync for Re2 {}
+
+/// These bind to the C ABI in `rust_re2.cpp`.
+extern "C" {
+fn rust_re2_create(data: *const u8, len: usize) -> Re2Ptr;
+fn rust_re2_destroy(re2: Re2Ptr);
+fn rust_re2_ok(re2: Re2Ptr) -> bool;
+fn rust_re2_error(
+re2: Re2Ptr,
+outdata: *mut *const u8,
+outlen: *mut usize,
+) -> bool;
+fn rust_re2_match(
+re2: Re2Ptr,
+data: *const u8,
+len: usize,
+anchor: c_int,
+) -> bool;
+}
+
+impl Re2 {
+pub fn new(pattern: &[u8]) -> Result {
+unsafe {
+let re2 = rust_re2_create(pattern.as_ptr(), pattern.len());
+if rust_re2_ok(re2) {
+Ok(Re2(re2))
+} else {
+let mut data: *const u8 = std::ptr::null();
+let mut len: usize = 0;
+rust_re2_error(re2, &mut data, &mut len);
+   

D7910: rust-re2: add wrapper for calling Re2 from Rust

2020-01-24 Thread Raphaël Gomès
Alphare updated this revision to Diff 19546.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D7910?vs=19399&id=19546

BRANCH
  default

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D7910/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D7910

AFFECTED FILES
  rust/Cargo.lock
  rust/hg-core/Cargo.toml
  rust/hg-core/build.rs
  rust/hg-core/src/lib.rs
  rust/hg-core/src/re2/mod.rs
  rust/hg-core/src/re2/re2.rs
  rust/hg-core/src/re2/rust_re2.cpp
  rust/hg-cpython/Cargo.toml
  setup.py

CHANGE DETAILS

diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -1351,10 +1351,19 @@
 env['HOME'] = pwd.getpwuid(os.getuid()).pw_dir
 
 cargocmd = ['cargo', 'rustc', '-vv', '--release']
+
+feature_flags = []
+
 if sys.version_info[0] == 3 and self.py3_features is not None:
-cargocmd.extend(
-('--features', self.py3_features, '--no-default-features')
-)
+feature_flags.append(self.py3_features)
+cargocmd.append('--no-default-features')
+
+rust_features = env.get("HG_RUST_FEATURES")
+if rust_features:
+feature_flags.append(rust_features)
+
+cargocmd.extend(('--features', " ".join(feature_flags)))
+
 cargocmd.append('--')
 if sys.platform == 'darwin':
 cargocmd.extend(
diff --git a/rust/hg-cpython/Cargo.toml b/rust/hg-cpython/Cargo.toml
--- a/rust/hg-cpython/Cargo.toml
+++ b/rust/hg-cpython/Cargo.toml
@@ -10,6 +10,7 @@
 
 [features]
 default = ["python27"]
+with-re2 = ["hg-core/with-re2"]
 
 # Features to build an extension module:
 python27 = ["cpython/python27-sys", "cpython/extension-module-2-7"]
@@ -21,7 +22,7 @@
 python3-bin = ["cpython/python3-sys"]
 
 [dependencies]
-hg-core = { path = "../hg-core" }
+hg-core = { path = "../hg-core"}
 libc = '*'
 
 [dependencies.cpython]
diff --git a/rust/hg-core/src/re2/rust_re2.cpp 
b/rust/hg-core/src/re2/rust_re2.cpp
new file mode 100644
--- /dev/null
+++ b/rust/hg-core/src/re2/rust_re2.cpp
@@ -0,0 +1,49 @@
+/*
+rust_re2.cpp
+
+C ABI export of Re2's C++ interface for Rust FFI.
+
+Copyright 2020 Valentin Gatien-Baron
+
+This software may be used and distributed according to the terms of the
+GNU General Public License version 2 or any later version.
+*/
+
+#include 
+using namespace re2;
+
+extern "C" {
+   RE2* rust_re2_create(const char* data, size_t len) {
+   RE2::Options o;
+   o.set_encoding(RE2::Options::Encoding::EncodingLatin1);
+   o.set_log_errors(false);
+   o.set_max_mem(5000);
+
+   return new RE2(StringPiece(data, len), o);
+   }
+
+   void rust_re2_destroy(RE2* re) {
+   delete re;
+   }
+
+   bool rust_re2_ok(RE2* re) {
+   return re->ok();
+   }
+
+   void rust_re2_error(RE2* re, const char** outdata, size_t* outlen) {
+   const std::string& e = re->error();
+   *outdata = e.data();
+   *outlen = e.length();
+   }
+
+   bool rust_re2_match(RE2* re, char* data, size_t len, int ianchor) {
+   const StringPiece sp = StringPiece(data, len);
+
+   RE2::Anchor anchor =
+   ianchor == 0 ? RE2::Anchor::UNANCHORED :
+   (ianchor == 1 ? RE2::Anchor::ANCHOR_START :
+RE2::Anchor::ANCHOR_BOTH);
+
+   return re->Match(sp, 0, len, anchor, NULL, 0);
+   }
+}
diff --git a/rust/hg-core/src/re2/re2.rs b/rust/hg-core/src/re2/re2.rs
new file mode 100644
--- /dev/null
+++ b/rust/hg-core/src/re2/re2.rs
@@ -0,0 +1,66 @@
+/*
+re2.rs
+
+Rust FFI bindings to Re2.
+
+Copyright 2020 Valentin Gatien-Baron
+
+This software may be used and distributed according to the terms of the
+GNU General Public License version 2 or any later version.
+*/
+use libc::{c_int, c_void};
+
+type Re2Ptr = *const c_void;
+
+pub struct Re2(Re2Ptr);
+
+/// `re2.h` says:
+/// "An "RE2" object is safe for concurrent use by multiple threads."
+unsafe impl Sync for Re2 {}
+
+/// These bind to the C ABI in `rust_re2.cpp`.
+extern "C" {
+fn rust_re2_create(data: *const u8, len: usize) -> Re2Ptr;
+fn rust_re2_destroy(re2: Re2Ptr);
+fn rust_re2_ok(re2: Re2Ptr) -> bool;
+fn rust_re2_error(
+re2: Re2Ptr,
+outdata: *mut *const u8,
+outlen: *mut usize,
+) -> bool;
+fn rust_re2_match(
+re2: Re2Ptr,
+data: *const u8,
+len: usize,
+anchor: c_int,
+) -> bool;
+}
+
+impl Re2 {
+pub fn new(pattern: &[u8]) -> Result {
+unsafe {
+let re2 = rust_re2_create(pattern.as_ptr(), pattern.len());
+if rust_re2_ok(re2) {
+Ok(Re2(re2))
+} else {
+let mut data: *const u8 = std::ptr::null();
+let mut len: usize = 0;
+rust_re2_error(re2, &mut data, &mut len);
+   

D7910: rust-re2: add wrapper for calling Re2 from Rust

2020-01-17 Thread Raphaël Gomès
Alphare updated this revision to Diff 19399.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D7910?vs=19386&id=19399

BRANCH
  default

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D7910/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D7910

AFFECTED FILES
  rust/Cargo.lock
  rust/hg-core/Cargo.toml
  rust/hg-core/build.rs
  rust/hg-core/src/lib.rs
  rust/hg-core/src/re2/mod.rs
  rust/hg-core/src/re2/re2.rs
  rust/hg-core/src/re2/rust_re2.cpp
  rust/hg-cpython/Cargo.toml
  setup.py

CHANGE DETAILS

diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -1351,10 +1351,19 @@
 env['HOME'] = pwd.getpwuid(os.getuid()).pw_dir
 
 cargocmd = ['cargo', 'rustc', '-vv', '--release']
+
+feature_flags = []
+
 if sys.version_info[0] == 3 and self.py3_features is not None:
-cargocmd.extend(
-('--features', self.py3_features, '--no-default-features')
-)
+feature_flags.append(self.py3_features)
+cargocmd.append('--no-default-features')
+
+rust_features = env.get("HG_RUST_FEATURES")
+if rust_features:
+feature_flags.append(rust_features)
+
+cargocmd.extend(('--features', " ".join(feature_flags)))
+
 cargocmd.append('--')
 if sys.platform == 'darwin':
 cargocmd.extend(
diff --git a/rust/hg-cpython/Cargo.toml b/rust/hg-cpython/Cargo.toml
--- a/rust/hg-cpython/Cargo.toml
+++ b/rust/hg-cpython/Cargo.toml
@@ -10,6 +10,7 @@
 
 [features]
 default = ["python27"]
+with-re2 = ["hg-core/with-re2"]
 
 # Features to build an extension module:
 python27 = ["cpython/python27-sys", "cpython/extension-module-2-7"]
@@ -21,7 +22,7 @@
 python3-bin = ["cpython/python3-sys"]
 
 [dependencies]
-hg-core = { path = "../hg-core" }
+hg-core = { path = "../hg-core"}
 libc = '*'
 
 [dependencies.cpython]
diff --git a/rust/hg-core/src/re2/rust_re2.cpp 
b/rust/hg-core/src/re2/rust_re2.cpp
new file mode 100644
--- /dev/null
+++ b/rust/hg-core/src/re2/rust_re2.cpp
@@ -0,0 +1,49 @@
+/*
+rust_re2.cpp
+
+C ABI export of Re2's C++ interface for Rust FFI.
+
+Copyright 2020 Valentin Gatien-Baron
+
+This software may be used and distributed according to the terms of the
+GNU General Public License version 2 or any later version.
+*/
+
+#include 
+using namespace re2;
+
+extern "C" {
+   RE2* rust_re2_create(const char* data, size_t len) {
+   RE2::Options o;
+   o.set_encoding(RE2::Options::Encoding::EncodingLatin1);
+   o.set_log_errors(false);
+   o.set_max_mem(5000);
+
+   return new RE2(StringPiece(data, len), o);
+   }
+
+   void rust_re2_destroy(RE2* re) {
+   delete re;
+   }
+
+   bool rust_re2_ok(RE2* re) {
+   return re->ok();
+   }
+
+   void rust_re2_error(RE2* re, const char** outdata, size_t* outlen) {
+   const std::string& e = re->error();
+   *outdata = e.data();
+   *outlen = e.length();
+   }
+
+   bool rust_re2_match(RE2* re, char* data, size_t len, int ianchor) {
+   const StringPiece sp = StringPiece(data, len);
+
+   RE2::Anchor anchor =
+   ianchor == 0 ? RE2::Anchor::UNANCHORED :
+   (ianchor == 1 ? RE2::Anchor::ANCHOR_START :
+RE2::Anchor::ANCHOR_BOTH);
+
+   return re->Match(sp, 0, len, anchor, NULL, 0);
+   }
+}
diff --git a/rust/hg-core/src/re2/re2.rs b/rust/hg-core/src/re2/re2.rs
new file mode 100644
--- /dev/null
+++ b/rust/hg-core/src/re2/re2.rs
@@ -0,0 +1,66 @@
+/*
+re2.rs
+
+Rust FFI bindings to Re2.
+
+Copyright 2020 Valentin Gatien-Baron
+
+This software may be used and distributed according to the terms of the
+GNU General Public License version 2 or any later version.
+*/
+use libc::{c_int, c_void};
+
+type Re2Ptr = *const c_void;
+
+pub struct Re2(Re2Ptr);
+
+/// `re2.h` says:
+/// "An "RE2" object is safe for concurrent use by multiple threads."
+unsafe impl Sync for Re2 {}
+
+/// These bind to the C ABI in `rust_re2.cpp`.
+extern "C" {
+fn rust_re2_create(data: *const u8, len: usize) -> Re2Ptr;
+fn rust_re2_destroy(re2: Re2Ptr);
+fn rust_re2_ok(re2: Re2Ptr) -> bool;
+fn rust_re2_error(
+re2: Re2Ptr,
+outdata: *mut *const u8,
+outlen: *mut usize,
+) -> bool;
+fn rust_re2_match(
+re2: Re2Ptr,
+data: *const u8,
+len: usize,
+anchor: c_int,
+) -> bool;
+}
+
+impl Re2 {
+pub fn new(pattern: &[u8]) -> Result {
+unsafe {
+let re2 = rust_re2_create(pattern.as_ptr(), pattern.len());
+if rust_re2_ok(re2) {
+Ok(Re2(re2))
+} else {
+let mut data: *const u8 = std::ptr::null();
+let mut len: usize = 0;
+rust_re2_error(re2, &mut data, &mut len);
+   

D7910: rust-re2: add wrapper for calling Re2 from Rust

2020-01-16 Thread Raphaël Gomès
Alphare marked an inline comment as done.
Alphare updated this revision to Diff 19386.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D7910?vs=19360&id=19386

BRANCH
  default

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D7910/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D7910

AFFECTED FILES
  rust/Cargo.lock
  rust/hg-core/Cargo.toml
  rust/hg-core/build.rs
  rust/hg-core/src/lib.rs
  rust/hg-core/src/re2/mod.rs
  rust/hg-core/src/re2/re2.rs
  rust/hg-core/src/re2/rust_re2.cpp
  rust/hg-cpython/Cargo.toml
  setup.py

CHANGE DETAILS

diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -1355,10 +1355,19 @@
 env['HOME'] = pwd.getpwuid(os.getuid()).pw_dir
 
 cargocmd = ['cargo', 'rustc', '-vv', '--release']
+
+feature_flags = []
+
 if sys.version_info[0] == 3 and self.py3_features is not None:
-cargocmd.extend(
-('--features', self.py3_features, '--no-default-features')
-)
+feature_flags.append(self.py3_features)
+cargocmd.append('--no-default-features')
+
+rust_features = env.get("HG_RUST_FEATURES")
+if rust_features:
+feature_flags.append(rust_features)
+
+cargocmd.extend(('--features', " ".join(feature_flags)))
+
 cargocmd.append('--')
 if sys.platform == 'darwin':
 cargocmd.extend(
diff --git a/rust/hg-cpython/Cargo.toml b/rust/hg-cpython/Cargo.toml
--- a/rust/hg-cpython/Cargo.toml
+++ b/rust/hg-cpython/Cargo.toml
@@ -10,6 +10,7 @@
 
 [features]
 default = ["python27"]
+with-re2 = ["hg-core/with-re2"]
 
 # Features to build an extension module:
 python27 = ["cpython/python27-sys", "cpython/extension-module-2-7"]
@@ -21,7 +22,7 @@
 python3-bin = ["cpython/python3-sys"]
 
 [dependencies]
-hg-core = { path = "../hg-core" }
+hg-core = { path = "../hg-core"}
 libc = '*'
 
 [dependencies.cpython]
diff --git a/rust/hg-core/src/re2/rust_re2.cpp 
b/rust/hg-core/src/re2/rust_re2.cpp
new file mode 100644
--- /dev/null
+++ b/rust/hg-core/src/re2/rust_re2.cpp
@@ -0,0 +1,49 @@
+/*
+rust_re2.cpp
+
+C ABI export of Re2's C++ interface for Rust FFI.
+
+Copyright 2020 Valentin Gatien-Baron
+
+This software may be used and distributed according to the terms of the
+GNU General Public License version 2 or any later version.
+*/
+
+#include 
+using namespace re2;
+
+extern "C" {
+   RE2* rust_re2_create(const char* data, size_t len) {
+   RE2::Options o;
+   o.set_encoding(RE2::Options::Encoding::EncodingLatin1);
+   o.set_log_errors(false);
+   o.set_max_mem(5000);
+
+   return new RE2(StringPiece(data, len), o);
+   }
+
+   void rust_re2_destroy(RE2* re) {
+   delete re;
+   }
+
+   bool rust_re2_ok(RE2* re) {
+   return re->ok();
+   }
+
+   void rust_re2_error(RE2* re, const char** outdata, size_t* outlen) {
+   const std::string& e = re->error();
+   *outdata = e.data();
+   *outlen = e.length();
+   }
+
+   bool rust_re2_match(RE2* re, char* data, size_t len, int ianchor) {
+   const StringPiece sp = StringPiece(data, len);
+
+   RE2::Anchor anchor =
+   ianchor == 0 ? RE2::Anchor::UNANCHORED :
+   (ianchor == 1 ? RE2::Anchor::ANCHOR_START :
+RE2::Anchor::ANCHOR_BOTH);
+
+   return re->Match(sp, 0, len, anchor, NULL, 0);
+   }
+}
diff --git a/rust/hg-core/src/re2/re2.rs b/rust/hg-core/src/re2/re2.rs
new file mode 100644
--- /dev/null
+++ b/rust/hg-core/src/re2/re2.rs
@@ -0,0 +1,66 @@
+/*
+re2.rs
+
+Rust FFI bindings to Re2.
+
+Copyright 2020 Valentin Gatien-Baron
+
+This software may be used and distributed according to the terms of the
+GNU General Public License version 2 or any later version.
+*/
+use libc::{c_int, c_void};
+
+type Re2Ptr = *const c_void;
+
+pub struct Re2(Re2Ptr);
+
+/// `re2.h` says:
+/// "An "RE2" object is safe for concurrent use by multiple threads."
+unsafe impl Sync for Re2 {}
+
+/// These bind to the C ABI in `rust_re2.cpp`.
+extern "C" {
+fn rust_re2_create(data: *const u8, len: usize) -> Re2Ptr;
+fn rust_re2_destroy(re2: Re2Ptr);
+fn rust_re2_ok(re2: Re2Ptr) -> bool;
+fn rust_re2_error(
+re2: Re2Ptr,
+outdata: *mut *const u8,
+outlen: *mut usize,
+) -> bool;
+fn rust_re2_match(
+re2: Re2Ptr,
+data: *const u8,
+len: usize,
+anchor: c_int,
+) -> bool;
+}
+
+impl Re2 {
+pub fn new(pattern: &[u8]) -> Result {
+unsafe {
+let re2 = rust_re2_create(pattern.as_ptr(), pattern.len());
+if rust_re2_ok(re2) {
+Ok(Re2(re2))
+} else {
+let mut data: *const u8 = std::ptr::null();
+let mut len: usize = 0;
+rust_re2

D7910: rust-re2: add wrapper for calling Re2 from Rust

2020-01-16 Thread kevincox (Kevin Cox)
kevincox added a comment.


  While I think the rust regex crate is heavily inspired by RE2 and uses a 
fairly compatible syntax I don't think there is a goal to be 100% compatible 
and I would be surprised if there weren't any differences. What I am trying to 
say is that if we are going to change engines we may as well change to `regex`. 
If we are using `RE2` for backwards compatibility then this change makes sense.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D7910/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D7910

To: Alphare, #hg-reviewers, kevincox
Cc: durin42, kevincox, mjpieters, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D7910: rust-re2: add wrapper for calling Re2 from Rust

2020-01-16 Thread durin42 (Augie Fackler)
durin42 added a comment.


  In D7910#116208 , @kevincox 
wrote:
  
  > Does mercurial currently use RE2? If not then can you explain why we don't 
just use the rust `regex` crate?
  
  We have support for using re2 iff the correct Python bindings are installed. 
That said, I thought the rust regex crate would be compatible with re2? If we 
can't use that, we should document why so that future hackers (like me) don't 
try and simplify

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D7910/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D7910

To: Alphare, #hg-reviewers, kevincox
Cc: durin42, kevincox, mjpieters, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D7910: rust-re2: add wrapper for calling Re2 from Rust

2020-01-16 Thread kevincox (Kevin Cox)
This revision now requires changes to proceed.
kevincox added inline comments.
kevincox requested changes to this revision.

INLINE COMMENTS

> rust_re2.cpp:22
> +
> + return new RE2(StringPiece(data, len), o);
> + }

This is never freed. Should we add a `Drop` implementation in rust?

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D7910/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D7910

To: Alphare, #hg-reviewers, kevincox
Cc: durin42, kevincox, mjpieters, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D7910: rust-re2: add wrapper for calling Re2 from Rust

2020-01-16 Thread kevincox (Kevin Cox)
kevincox added a comment.
kevincox accepted this revision.


  Does mercurial currently use RE2? If not then can you explain why we don't 
just use the rust `regex` crate?

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D7910/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D7910

To: Alphare, #hg-reviewers, kevincox
Cc: durin42, kevincox, mjpieters, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D7910: rust-re2: add wrapper for calling Re2 from Rust

2020-01-16 Thread Raphaël Gomès
Alphare created this revision.
Herald added subscribers: mercurial-devel, mjpieters, kevincox, durin42.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This assumes that Re2 is installed following Google's guide. I am not sure
  how we want to integrate it in the project, but I think a follow-up patch 
would
  be more appropriate for such work.
  As it stands, *not* having Re2 installed results in a compilation error, which
  is a problem as it breaks install compatibility. Hence, this is gated behind
  a non-default `with-re2` compilation feature.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D7910

AFFECTED FILES
  rust/Cargo.lock
  rust/hg-core/Cargo.toml
  rust/hg-core/build.rs
  rust/hg-core/src/lib.rs
  rust/hg-core/src/re2/mod.rs
  rust/hg-core/src/re2/re2.rs
  rust/hg-core/src/re2/rust_re2.cpp
  rust/hg-cpython/Cargo.toml
  setup.py

CHANGE DETAILS

diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -1355,10 +1355,19 @@
 env['HOME'] = pwd.getpwuid(os.getuid()).pw_dir
 
 cargocmd = ['cargo', 'rustc', '-vv', '--release']
+
+feature_flags = []
+
 if sys.version_info[0] == 3 and self.py3_features is not None:
-cargocmd.extend(
-('--features', self.py3_features, '--no-default-features')
-)
+feature_flags.append(self.py3_features)
+cargocmd.append('--no-default-features')
+
+rust_features = env.get("HG_RUST_FEATURES")
+if rust_features:
+feature_flags.append(rust_features)
+
+cargocmd.extend(('--features', " ".join(feature_flags)))
+
 cargocmd.append('--')
 if sys.platform == 'darwin':
 cargocmd.extend(
diff --git a/rust/hg-cpython/Cargo.toml b/rust/hg-cpython/Cargo.toml
--- a/rust/hg-cpython/Cargo.toml
+++ b/rust/hg-cpython/Cargo.toml
@@ -10,6 +10,7 @@
 
 [features]
 default = ["python27"]
+with-re2 = ["hg-core/with-re2"]
 
 # Features to build an extension module:
 python27 = ["cpython/python27-sys", "cpython/extension-module-2-7"]
@@ -21,7 +22,7 @@
 python3-bin = ["cpython/python3-sys"]
 
 [dependencies]
-hg-core = { path = "../hg-core" }
+hg-core = { path = "../hg-core"}
 libc = '*'
 
 [dependencies.cpython]
diff --git a/rust/hg-core/src/re2/rust_re2.cpp 
b/rust/hg-core/src/re2/rust_re2.cpp
new file mode 100644
--- /dev/null
+++ b/rust/hg-core/src/re2/rust_re2.cpp
@@ -0,0 +1,45 @@
+/*
+rust_re2.cpp
+
+C ABI export of Re2's C++ interface for Rust FFI.
+
+Copyright 2020 Valentin Gatien-Baron
+
+This software may be used and distributed according to the terms of the
+GNU General Public License version 2 or any later version.
+*/
+
+#include 
+using namespace re2;
+
+extern "C" {
+   RE2* rustre2_create(const char* data, size_t len) {
+   RE2::Options o;
+   o.set_encoding(RE2::Options::Encoding::EncodingLatin1);
+   o.set_log_errors(false);
+   o.set_max_mem(5000);
+
+   return new RE2(StringPiece(data, len), o);
+   }
+
+   bool rustre2_ok(RE2* re) {
+   return re->ok();
+   }
+
+   void rustre2_error(RE2* re, const char** outdata, size_t* outlen) {
+   const std::string& e = re->error();
+   *outdata = e.data();
+   *outlen = e.length();
+   }
+
+   bool rustre2_match(RE2* re, char* data, size_t len, int ianchor) {
+   const StringPiece sp = StringPiece(data, len);
+
+   RE2::Anchor anchor =
+   ianchor == 0 ? RE2::Anchor::UNANCHORED :
+   (ianchor == 1 ? RE2::Anchor::ANCHOR_START :
+RE2::Anchor::ANCHOR_BOTH);
+
+   return re->Match(sp, 0, len, anchor, NULL, 0);
+   }
+}
diff --git a/rust/hg-core/src/re2/re2.rs b/rust/hg-core/src/re2/re2.rs
new file mode 100644
--- /dev/null
+++ b/rust/hg-core/src/re2/re2.rs
@@ -0,0 +1,59 @@
+/*
+re2.rs
+
+Rust FFI bindings to Re2.
+
+Copyright 2020 Valentin Gatien-Baron
+
+This software may be used and distributed according to the terms of the
+GNU General Public License version 2 or any later version.
+*/
+use libc::{c_int, c_void};
+
+type Re2Ptr = *const c_void;
+
+pub struct Re2(Re2Ptr);
+
+/// `re2.h` says:
+/// "An "RE2" object is safe for concurrent use by multiple threads."
+unsafe impl Sync for Re2 {}
+
+/// These bind to the C ABI in `rust_re2.cpp`.
+extern "C" {
+fn rustre2_create(data: *const u8, len: usize) -> Re2Ptr;
+fn rustre2_ok(re2: Re2Ptr) -> bool;
+fn rustre2_error(
+re2: Re2Ptr,
+outdata: *mut *const u8,
+outlen: *mut usize,
+) -> bool;
+fn rustre2_match(
+re2: Re2Ptr,
+data: *const u8,
+len: usize,
+anchor: c_int,
+) -> bool;
+}
+
+impl Re2 {
+pub fn new(pattern: &[u8]) -> Result {
+unsafe {
+let re2 = rustre2_create(pattern.as_ptr(), pattern.len());
+if ru