Mercurial > public > mercurial-scm > hg
diff rust/hg-core/src/re2/re2.rs @ 44305:d8d4fa9a7f18
rust-re2: add wrapper for calling Re2 from Rust
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.
Differential Revision: https://phab.mercurial-scm.org/D7910
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Thu, 16 Jan 2020 13:34:04 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rust/hg-core/src/re2/re2.rs Thu Jan 16 13:34:04 2020 +0100 @@ -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<Re2, String> { + 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); + Err(String::from_utf8_lossy(std::slice::from_raw_parts( + data, len, + )) + .to_string()) + } + } + } + + pub fn is_match(&self, data: &[u8]) -> bool { + unsafe { rust_re2_match(self.0, data.as_ptr(), data.len(), 1) } + } +} + +impl Drop for Re2 { + fn drop(&mut self) { + unsafe { rust_re2_destroy(self.0) } + } +}