use std::borrow::Cow;
use widestring::WideStr;
use crate::{
err::{BindingErrorCode, ErrorKind, RegexError, Result},
tre, RegApproxMatch, RegApproxParams, Regex, RegexecFlags,
};
pub type RegApproxMatchWideStr<'a> = RegApproxMatch<&'a WideStr, Cow<'a, WideStr>>;
impl Regex {
pub fn regawexec<'a>(
&self,
string: &'a WideStr,
params: &RegApproxParams,
nmatches: usize,
flags: RegexecFlags,
) -> Result<RegApproxMatchWideStr<'a>> {
let Some(compiled_reg_obj) = self.get() else {
return Err(RegexError::new(
ErrorKind::Binding(BindingErrorCode::REGEX_VACANT),
"Attempted to unwrap a vacant Regex object",
));
};
let mut match_vec: Vec<tre::regmatch_t> =
vec![tre::regmatch_t { rm_so: 0, rm_eo: 0 }; nmatches];
let mut amatch = tre::regamatch_t {
nmatch: nmatches,
pmatch: match_vec.as_mut_ptr(),
..Default::default()
};
#[allow(clippy::cast_possible_wrap)]
let result = unsafe {
tre::tre_regawnexec(
compiled_reg_obj,
string.as_ptr().cast(),
string.len(),
&mut amatch,
*params.get(),
flags.get(),
)
};
if result != 0 {
return Err(self.regerror(result));
}
let mut result: Vec<Option<Cow<'a, WideStr>>> = Vec::with_capacity(nmatches);
for pmatch in match_vec {
if pmatch.rm_so < 0 || pmatch.rm_eo < 0 {
result.push(None);
continue;
}
#[allow(clippy::cast_sign_loss)]
let start_offset = pmatch.rm_so as usize;
#[allow(clippy::cast_sign_loss)]
let end_offset = pmatch.rm_eo as usize;
result.push(Some(Cow::Borrowed(&string[start_offset..end_offset])));
}
Ok(RegApproxMatchWideStr::new(string, result, amatch))
}
}
#[inline]
pub fn regawexec<'a>(
compiled_reg: &Regex,
string: &'a WideStr,
params: &RegApproxParams,
nmatches: usize,
flags: RegexecFlags,
) -> Result<RegApproxMatchWideStr<'a>> {
compiled_reg.regawexec(string, params, nmatches, flags)
}