use std::borrow::Cow;
use widestring::WideStr;
use crate::{err::{BindingErrorCode, ErrorKind, RegexError, Result}, flags::RegexecFlags, tre, Regex};
pub type RegMatchWideStr<'a> = Vec<Option<Cow<'a, WideStr>>>;
impl Regex {
pub fn regwexec<'a>(
&self,
string: &'a WideStr,
nmatches: usize,
flags: RegexecFlags,
) -> Result<RegMatchWideStr<'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];
#[allow(clippy::cast_possible_wrap)]
let result = unsafe {
tre::tre_regwnexec(
compiled_reg_obj,
string.as_ptr().cast(),
string.len(),
nmatches,
match_vec.as_mut_ptr(),
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(result)
}
}
pub fn regwexec<'a>(
compiled_reg: &Regex,
string: &'a WideStr,
nmatches: usize,
flags: RegexecFlags,
) -> Result<RegMatchWideStr<'a>> {
compiled_reg.regwexec(string, nmatches, flags)
}