diff --git a/regex/regex.cc b/regex/regex.cc index 6489f21..1c4bc08 100644 --- a/regex/regex.cc +++ b/regex/regex.cc @@ -10,6 +10,7 @@ #include "support/rs_std/slice_ref.h" #include "support/rs_std/str_ref.h" +#include "support/rs_std/vec.h" #include "regex_internal.h" #include "crubit/rust.h" #include "absl/status/status.h" @@ -83,10 +84,10 @@ absl::StatusOr RewriteWithOptions(absl::string_view pattern, auto rewrite_result = std::move(rewriter).finish(); if (!rewrite_result.has_value()) { - const rust::VecU8& err = rewrite_result.err(); + const rs_std::Vec& err = rewrite_result.err(); return absl::InternalError(internal::AsStr(err)); } - const rust::VecU8& val = rewrite_result.value(); + const rs_std::Vec& val = rewrite_result.value(); result = internal::AsString(val); } return result; @@ -136,7 +137,7 @@ absl::StatusOr Regex::Compile(absl::string_view pattern, } auto result = std::move(builder).build(); if (!result.has_value()) { - const rust::VecU8& err = result.err(); + const rs_std::Vec& err = result.err(); return absl::InvalidArgumentError(internal::AsStr(err)); } return Regex(std::move(result).value()); @@ -263,7 +264,7 @@ absl::StatusOr RegexSet::Compile( } auto result = std::move(builder).build(); if (!result.has_value()) { - const rust::VecU8& err = result.err(); + const rs_std::Vec& err = result.err(); return absl::InvalidArgumentError(internal::AsStr(err)); } return RegexSet(std::move(result).value()); diff --git a/regex/regex_internal.h b/regex/regex_internal.h index 5c64f92..32edb7f 100644 --- a/regex/regex_internal.h +++ b/regex/regex_internal.h @@ -4,12 +4,14 @@ #include #include #include +#include #include #include #include #include #include "support/rs_std/slice_ref.h" +#include "support/rs_std/vec.h" #include "crubit/rust.h" #include "absl/log/check.h" #include "absl/strings/string_view.h" @@ -31,14 +33,14 @@ inline absl::string_view AsStringView(rs_std::SliceRef s) { return absl::string_view(reinterpret_cast(s.data()), s.size()); } -inline absl::string_view AsStr(const ::rust::VecU8& v) { - if (v.as_ptr() == nullptr) return {}; - return absl::string_view(reinterpret_cast(v.as_ptr()), v.len()); +inline absl::string_view AsStr(const rs_std::Vec& v) { + if (v.data() == nullptr) return {}; + return absl::string_view(reinterpret_cast(v.data()), v.size()); } -inline std::string AsString(const ::rust::VecU8& v) { - if (v.as_ptr() == nullptr) return {}; - return std::string(reinterpret_cast(v.as_ptr()), v.len()); +inline std::string AsString(const rs_std::Vec& v) { + if (v.data() == nullptr) return {}; + return std::string(reinterpret_cast(v.data()), v.size()); } template @@ -90,9 +92,9 @@ struct MapOptionalHelper -struct MapOptionalHelper { +struct MapOptionalHelper> { static std::optional Map( - std::optional<::rust::VecU8> opt) { + std::optional> opt) { if (opt.has_value()) { return AsString(*opt); } else { diff --git a/regex/rust/lib.rs b/regex/rust/lib.rs index a4e12da..cf80443 100644 --- a/regex/rust/lib.rs +++ b/regex/rust/lib.rs @@ -6,14 +6,12 @@ //! WARNING: This crate should never be used from Rust. Use regex directly. pub mod regex_rewrite; -mod vec_u8; macro_rules! error { ($($arg:tt)*) => { eprintln!($($arg)*); }; } use num_traits::Num; use regex_automata::{meta, util::syntax, MatchKind}; use std::option::Option; use std::sync::Arc; -pub use vec_u8::VecU8; // Wrapper structs for structs in the regex package that we need to expose. We use `Option` for the // inner object so that we can use `#[derive(Default)]` even when the inner types are not Default. @@ -65,39 +63,39 @@ impl<'h> Match<'h> { self.slice } - pub fn parse_as_i8(&self, radix: i32) -> Result { + pub fn parse_as_i8(&self, radix: i32) -> Result> { parse_integer(self.as_bytes(), radix).into() } - pub fn parse_as_u8(&self, radix: i32) -> Result { + pub fn parse_as_u8(&self, radix: i32) -> Result> { parse_integer(self.as_bytes(), radix).into() } - pub fn parse_as_i16(&self, radix: i32) -> Result { + pub fn parse_as_i16(&self, radix: i32) -> Result> { parse_integer(self.as_bytes(), radix).into() } - pub fn parse_as_u16(&self, radix: i32) -> Result { + pub fn parse_as_u16(&self, radix: i32) -> Result> { parse_integer(self.as_bytes(), radix).into() } - pub fn parse_as_i32(&self, radix: i32) -> Result { + pub fn parse_as_i32(&self, radix: i32) -> Result> { parse_integer(self.as_bytes(), radix).into() } - pub fn parse_as_u32(&self, radix: i32) -> Result { + pub fn parse_as_u32(&self, radix: i32) -> Result> { parse_integer(self.as_bytes(), radix).into() } - pub fn parse_as_i64(&self, radix: i32) -> Result { + pub fn parse_as_i64(&self, radix: i32) -> Result> { parse_integer(self.as_bytes(), radix).into() } - pub fn parse_as_u64(&self, radix: i32) -> Result { + pub fn parse_as_u64(&self, radix: i32) -> Result> { parse_integer(self.as_bytes(), radix).into() } - pub fn parse_as_f32(&self) -> Result { + pub fn parse_as_f32(&self) -> Result> { parse_float(self.as_bytes()).into() } - pub fn parse_as_f64(&self) -> Result { + pub fn parse_as_f64(&self) -> Result> { parse_float(self.as_bytes()).into() } } -fn parse_integer(slice: &[u8], mut radix: i32) -> Result +fn parse_integer(slice: &[u8], mut radix: i32) -> Result> where T: Num, ::FromStrRadixErr: std::fmt::Display, @@ -113,7 +111,7 @@ where // An ASCII string is always valid UTF-8. let string = - std::str::from_utf8(slice).map_err::(|_| "Invalid Utf8".to_string().into())?; + std::str::from_utf8(slice).map_err::, _>(|_| "Invalid Utf8".to_string().into())?; // RE2 doesn't allow leading spaces for integers. if string.starts_with(|c: char| c.is_whitespace()) { @@ -203,7 +201,7 @@ where }) } -fn parse_float(slice: &[u8]) -> Result +fn parse_float(slice: &[u8]) -> Result> where T: std::str::FromStr, ::Err: std::error::Error + Send + Sync + 'static, @@ -214,7 +212,7 @@ where } // An ASCII string is always valid UTF-8. let s = - std::str::from_utf8(slice).map_err::(|_| "Invalid Utf8".to_string().into())?; + std::str::from_utf8(slice).map_err::, _>(|_| "Invalid Utf8".to_string().into())?; // RE2 allows leading spaces for floats. s.trim_start().parse::().map_err(|e| { format!("Error parsing {} as a {}: {}", s, std::any::type_name::(), e).into() @@ -290,14 +288,14 @@ impl<'h> Captures<'h> { ) } - pub fn expand(&self, replacement: &[u8]) -> VecU8 { + pub fn expand(&self, replacement: &[u8]) -> Vec { let Some(inner) = &self.inner else { error!("Use of moved-from Captures"); - return VecU8::from(""); + return Vec::new(); }; let mut dst = Vec::::new(); inner.interpolate_bytes_into(self.haystack, replacement, &mut dst); - VecU8::from(dst) + dst } // NOTE(b/259749023): implement `extract` when crubit supports generic functions. @@ -444,11 +442,11 @@ impl<'r> CaptureNames<'r> { #[derive(Clone, Default, Debug, PartialEq)] pub struct ReplaceResult { count: usize, - result: VecU8, + result: Vec, } impl ReplaceResult { - pub fn new(count: usize, result: VecU8) -> Self { + pub fn new(count: usize, result: Vec) -> Self { Self { count, result } } @@ -456,11 +454,11 @@ impl ReplaceResult { self.count } - pub fn result(&self) -> &VecU8 { + pub fn result(&self) -> &Vec { &self.result } - pub fn into_result(self) -> VecU8 { + pub fn into_result(self) -> Vec { self.result } } @@ -476,7 +474,7 @@ pub struct Regex { impl Regex { // Disable the Clippy warning in order to follow the Regex API. #[allow(clippy::new_ret_no_self)] - pub fn new(val: &[u8]) -> Result { + pub fn new(val: &[u8]) -> Result> { let builder = RegexBuilder::new(val); builder.build() } @@ -570,11 +568,11 @@ impl Regex { // support `Cow`, so we always allocate a new string here for simplicity. // NOTE(b/469976097): The original `replace*` methods support passing a function to perform // replacements. Decide if we want to support this. - pub fn replace(&self, haystack: &[u8], rep: &[u8]) -> VecU8 { + pub fn replace(&self, haystack: &[u8], rep: &[u8]) -> Vec { self.replacen(haystack, 1, rep).into_result() } - pub fn replace_all(&self, haystack: &[u8], rep: &[u8]) -> VecU8 { + pub fn replace_all(&self, haystack: &[u8], rep: &[u8]) -> Vec { self.replacen(haystack, usize::MAX, rep).into_result() } @@ -604,7 +602,7 @@ impl Regex { } } new.extend_from_slice(&haystack[last_match..]); - return ReplaceResult { count, result: VecU8::from(new) }; + return ReplaceResult { count, result: new }; } let mut it = re.captures_iter(haystack); @@ -624,7 +622,7 @@ impl Regex { } } new.extend_from_slice(&haystack[last_match..]); - ReplaceResult { count, result: VecU8::from(new) } + ReplaceResult { count, result: new } } pub fn split<'r, 'h>(&'r self, haystack: &'h [u8]) -> Split<'r, 'h> { @@ -703,14 +701,14 @@ impl RegexBuilder { } } - pub fn build(self) -> Result { + pub fn build(self) -> Result> { if let Some(pattern) = self.pattern { let meta = meta::Builder::new() .configure(self.metac) // Parse in byte-oriented mode to support raw byte slices. .syntax(self.syntaxc.utf8(false)) .build(&pattern) - .map_err::(|err| err.to_string().into())?; + .map_err::, _>(|err| err.to_string().into())?; Ok(Regex { inner: Some(meta), pattern: Arc::from(pattern.as_str()) }) } else { Err("Invalid UTF-8 in pattern".to_string().into()) @@ -820,7 +818,7 @@ impl RegexSet { /// Creates a new regex set from the given patterns. If any of the patterns fails to compile, /// it returns an error. #[allow(clippy::new_ret_no_self)] // We need to return a Result because compilation can fail. - pub fn new(patterns: &[&[u8]]) -> Result { + pub fn new(patterns: &[&[u8]]) -> Result> { let builder = RegexSetBuilder::new(patterns); builder.build() } @@ -919,7 +917,7 @@ impl RegexSetBuilder { RegexSetBuilder { patterns: if ok { Some(exprs) } else { None }, ..Default::default() } } - pub fn build(self) -> Result { + pub fn build(self) -> Result> { if let Some(patterns) = self.patterns { let meta = meta::Builder::new() .configure( @@ -928,7 +926,7 @@ impl RegexSetBuilder { // Parse in byte-oriented mode to support raw byte slices. .syntax(self.syntaxc.utf8(false)) .build_many(&patterns) - .map_err::(|err| err.to_string().into())?; + .map_err::, _>(|err| err.to_string().into())?; Ok(RegexSet { inner: Some(meta) }) } else { Err("Invalid UTF-8 in pattern".to_string().into()) @@ -999,8 +997,9 @@ mod tests { macro_rules! check_bad_integer { ($type:ident, $radix:expr, $in:expr, $err: expr) => { expect_that!( - parse_integer::<$type>($in.as_bytes(), $radix), - err(displays_as(contains_substring($err))) + parse_integer::<$type>($in.as_bytes(), $radix) + .map_err(|e| String::from_utf8(e).unwrap()), + err(contains_substring($err)) ); }; } @@ -1156,8 +1155,8 @@ mod tests { macro_rules! check_bad_float { ($type:ident, $in:expr, $err: expr) => { expect_that!( - parse_float::<$type>($in.as_bytes()), - err(displays_as(contains_substring($err))) + parse_float::<$type>($in.as_bytes()).map_err(|e| String::from_utf8(e).unwrap()), + err(contains_substring($err)) ); }; } diff --git a/regex/rust/regex_rewrite.rs b/regex/rust/regex_rewrite.rs index a9f0528..19894fb 100644 --- a/regex/rust/regex_rewrite.rs +++ b/regex/rust/regex_rewrite.rs @@ -1,4 +1,3 @@ -use crate::VecU8; use regex_syntax::ast::parse::ParserBuilder; use regex_syntax::ast::print::Printer; use regex_syntax::ast::{ @@ -19,8 +18,8 @@ pub struct RewriteError { } impl RewriteError { - pub fn message(&self) -> VecU8 { - VecU8::from(self.message.as_bytes()) + pub fn message(&self) -> Vec { + self.message.clone().into() } } @@ -70,11 +69,11 @@ impl Rewriter { } /// Prints the AST back to a string. - pub fn finish(self) -> Result { + pub fn finish(self) -> Result, Vec> { let mut printer = Printer::new(); let mut dst = String::new(); - printer.print(&self.ast, &mut dst).map_err::(|err| err.to_string().into())?; - Ok(VecU8::from(dst.as_bytes())) + printer.print(&self.ast, &mut dst).map_err::, _>(|err| err.to_string().into())?; + Ok(dst.into()) } } @@ -288,7 +287,7 @@ mod tests { use super::*; use googletest::prelude::*; - fn rewrite(pattern: &str) -> VecU8 { + fn rewrite(pattern: &str) -> Vec { let rewriter = Rewriter::new(pattern.as_bytes(), false, false, 250); expect_true!(rewriter.is_ok()); let mut rewriter = rewriter.unwrap(); @@ -298,31 +297,31 @@ mod tests { #[gtest] fn test_rewrite_perl_digits() { - expect_eq!(rewrite("\\d"), VecU8::from("[[:digit:]]")); - expect_eq!(rewrite("\\s"), VecU8::from("[\\t\\n\\f\\r ]")); - expect_eq!(rewrite("\\w"), VecU8::from("[[:word:]]")); + expect_eq!(rewrite("\\d"), Vec::::from("[[:digit:]]")); + expect_eq!(rewrite("\\s"), Vec::::from("[\\t\\n\\f\\r ]")); + expect_eq!(rewrite("\\w"), Vec::::from("[[:word:]]")); } #[gtest] fn test_rewrite_perl_negated() { - expect_eq!(rewrite("\\D"), VecU8::from("[[:^digit:]]")); - expect_eq!(rewrite("\\S"), VecU8::from("[^\\t\\n\\f\\r ]")); - expect_eq!(rewrite("\\W"), VecU8::from("[[:^word:]]")); + expect_eq!(rewrite("\\D"), Vec::::from("[[:^digit:]]")); + expect_eq!(rewrite("\\S"), Vec::::from("[^\\t\\n\\f\\r ]")); + expect_eq!(rewrite("\\W"), Vec::::from("[[:^word:]]")); } #[gtest] fn test_rewrite_bracketed() { - expect_eq!(rewrite("[a-z\\d]"), VecU8::from("[a-z[:digit:]]")); - expect_eq!(rewrite("[^a-z\\d]"), VecU8::from("[^a-z[:digit:]]")); - expect_eq!(rewrite("[a-z\\s]"), VecU8::from("[a-z[\\t\\n\\f\\r ]]")); - expect_eq!(rewrite("[^a-z\\s]"), VecU8::from("[^a-z[\\t\\n\\f\\r ]]")); + expect_eq!(rewrite("[a-z\\d]"), Vec::::from("[a-z[:digit:]]")); + expect_eq!(rewrite("[^a-z\\d]"), Vec::::from("[^a-z[:digit:]]")); + expect_eq!(rewrite("[a-z\\s]"), Vec::::from("[a-z[\\t\\n\\f\\r ]]")); + expect_eq!(rewrite("[^a-z\\s]"), Vec::::from("[^a-z[\\t\\n\\f\\r ]]")); } #[gtest] fn test_rewrite_complex_nested() { expect_eq!( rewrite("^foo(?:bar[a-z\\s]+|baz(\\d))xyz$"), - VecU8::from("^foo(?:bar[a-z[\\t\\n\\f\\r ]]+|baz([[:digit:]]))xyz$") + Vec::::from("^foo(?:bar[a-z[\\t\\n\\f\\r ]]+|baz([[:digit:]]))xyz$") ); } @@ -332,13 +331,13 @@ mod tests { expect_true!(rewriter.is_ok()); let mut rewriter = rewriter.unwrap(); rewriter.rewrite_for_re2_compat(true); - expect_eq!(rewriter.finish().unwrap(), VecU8::from("[[:digit:]][[:digit:]]")); + expect_eq!(rewriter.finish().unwrap(), Vec::::from("[[:digit:]][[:digit:]]")); let rewriter = Rewriter::new("\\d \\d".as_bytes(), false, false, 250); expect_true!(rewriter.is_ok()); let mut rewriter = rewriter.unwrap(); rewriter.rewrite_for_re2_compat(true); - expect_eq!(rewriter.finish().unwrap(), VecU8::from("[[:digit:]] [[:digit:]]")); + expect_eq!(rewriter.finish().unwrap(), Vec::::from("[[:digit:]] [[:digit:]]")); } fn expect_anchored(pattern: &str, expected: &str, ignore_whitespace: bool) { @@ -346,7 +345,7 @@ mod tests { expect_true!(rewriter.is_ok()); let mut rewriter = rewriter.unwrap(); rewriter.add_begin_and_end_anchors(); - expect_eq!(rewriter.finish().unwrap(), VecU8::from(expected)); + expect_eq!(rewriter.finish().unwrap(), Vec::::from(expected)); } #[gtest] @@ -363,22 +362,24 @@ mod tests { #[gtest] fn test_rewrite_word_boundaries() { - expect_eq!(rewrite("\\b"), VecU8::from("(?-u:\\b)")); - expect_eq!(rewrite("\\B"), VecU8::from("(?-u:\\B)")); - expect_eq!(rewrite("\\bfoo\\B"), VecU8::from("(?-u:\\b)foo(?-u:\\B)")); + expect_eq!(rewrite("\\b"), Vec::::from("(?-u:\\b)")); + expect_eq!(rewrite("\\B"), Vec::::from("(?-u:\\B)")); + expect_eq!(rewrite("\\bfoo\\B"), Vec::::from("(?-u:\\b)foo(?-u:\\B)")); } #[gtest] fn test_rewrite_dot_flags() { expect_eq!( rewrite("."), - VecU8::from("(?:.|(?-u:[\\xE0-\\xEF][\\x80-\\xBF]{2}|[\\xF0-\\xF4][\\x80-\\xBF]{3}))") + Vec::::from( + "(?:.|(?-u:[\\xE0-\\xEF][\\x80-\\xBF]{2}|[\\xF0-\\xF4][\\x80-\\xBF]{3}))" + ) ); - expect_eq!(rewrite("(?-u:.)"), VecU8::from("(?-u:.)")); - expect_eq!(rewrite("(?-u)."), VecU8::from("(?-u).")); + expect_eq!(rewrite("(?-u:.)"), Vec::::from("(?-u:.)")); + expect_eq!(rewrite("(?-u)."), Vec::::from("(?-u).")); expect_eq!( rewrite("(?-u:.)."), - VecU8::from( + Vec::::from( "(?-u:.)(?:.|(?-u:[\\xE0-\\xEF][\\x80-\\xBF]{2}|[\\xF0-\\xF4][\\x80-\\xBF]{3}))" ) ); diff --git a/regex/rust/vec_u8.rs b/regex/rust/vec_u8.rs deleted file mode 100644 index fefdd50..0000000 --- a/regex/rust/vec_u8.rs +++ /dev/null @@ -1,48 +0,0 @@ -/// Minimal wrapper around `Vec` to allow passing a `Vec` from Rust to C++. -#[repr(C)] -#[derive(Default, Debug, Clone, PartialEq, PartialOrd)] -pub struct VecU8(Vec); - -impl VecU8 { - pub fn as_ptr(&self) -> *const u8 { - self.0.as_ptr() - } - - pub fn len(&self) -> usize { - self.0.len() - } - - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } -} - -impl From> for VecU8 { - fn from(val: Vec) -> Self { - Self(val) - } -} - -impl From for VecU8 { - fn from(val: String) -> Self { - Self(val.into_bytes()) - } -} - -impl From<&str> for VecU8 { - fn from(val: &str) -> Self { - Self(val.as_bytes().to_vec()) - } -} - -impl From<&[u8]> for VecU8 { - fn from(val: &[u8]) -> Self { - Self(val.to_vec()) - } -} - -impl std::fmt::Display for VecU8 { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(&String::from_utf8_lossy(&self.0)) - } -}