use crate::{
operation::{Operation, OperationControl},
re_flags::ReFlags,
re_matcher::ReMatcher,
};
#[derive(Debug, Clone)]
pub(crate) struct BackReference {
group_nr: usize,
}
impl BackReference {
pub(crate) fn new(group_nr: usize) -> Self {
Self { group_nr }
}
}
impl OperationControl for BackReference {
fn matches_empty_string(&self) -> u32 {
0
}
fn optimize(self, _flags: &ReFlags) -> Operation {
Operation::from(self)
}
fn matches_iter<'a>(
&self,
matcher: &'a ReMatcher,
position: usize,
) -> Box<dyn Iterator<Item = usize> + 'a> {
let s = matcher.start_backref(self.group_nr);
let e = matcher.end_backref(self.group_nr);
if let (Some(s), Some(e)) = (s, e) {
if s == e {
return Box::new(std::iter::once(position));
}
let l = e - s;
let search = &matcher.search;
if (position + l - 1) >= search.len() {
return Box::new(std::iter::empty());
}
if matcher.program.flags.is_case_independent() {
for i in 0..l {
if !matcher.equal_case_blind(search[position + i], search[s + i]) {
return Box::new(std::iter::empty());
}
}
} else {
for i in 0..l {
if search[position + i] != search[s + i] {
return Box::new(std::iter::empty());
}
}
}
Box::new(std::iter::once(position + l))
} else {
Box::new(std::iter::empty())
}
}
}