pub type Slot = Option<usize>;
#[doc(hidden)]
pub struct Locations(Vec<Slot>);
impl Locations {
pub fn pos(&self, i: usize) -> Option<(usize, usize)> {
let (s, e) = (i * 2, i * 2 + 1);
match (self.0.get(s), self.0.get(e)) {
(Some(&Some(s)), Some(&Some(e))) => Some((s, e)),
_ => None,
}
}
pub fn iter(&self) -> SubCapturesPosIter {
SubCapturesPosIter { idx: 0, locs: &self }
}
pub fn len(&self) -> usize {
self.0.len() / 2
}
}
pub fn as_slots(locs: &mut Locations) -> &mut [Slot] {
&mut locs.0
}
pub struct SubCapturesPosIter<'c> {
idx: usize,
locs: &'c Locations,
}
impl<'c> Iterator for SubCapturesPosIter<'c> {
type Item = Option<(usize, usize)>;
fn next(&mut self) -> Option<Option<(usize, usize)>> {
if self.idx >= self.locs.len() {
return None;
}
let x = match self.locs.pos(self.idx) {
None => Some(None),
Some((s, e)) => {
Some(Some((s, e)))
}
};
self.idx += 1;
x
}
}
pub trait RegularExpression: Sized {
type Text: ?Sized;
fn slots_len(&self) -> usize;
fn locations(&self) -> Locations {
Locations(vec![None; self.slots_len()])
}
fn next_after_empty(&self, text: &Self::Text, i: usize) -> usize;
fn shortest_match_at(
&self,
text: &Self::Text,
start: usize,
) -> Option<usize>;
fn is_match_at(
&self,
text: &Self::Text,
start: usize,
) -> bool;
fn find_at(
&self,
text: &Self::Text,
start: usize,
) -> Option<(usize, usize)>;
fn read_captures_at(
&self,
locs: &mut Locations,
text: &Self::Text,
start: usize,
) -> Option<(usize, usize)>;
fn find_iter<'t>(
self,
text: &'t Self::Text,
) -> Matches<'t, Self> {
Matches {
re: self,
text: text,
last_end: 0,
last_match: None,
}
}
fn captures_iter<'t>(
self,
text: &'t Self::Text,
) -> CaptureMatches<'t, Self> {
CaptureMatches(self.find_iter(text))
}
}
pub struct Matches<'t, R> where R: RegularExpression, R::Text: 't {
re: R,
text: &'t R::Text,
last_end: usize,
last_match: Option<usize>,
}
impl<'t, R> Matches<'t, R> where R: RegularExpression, R::Text: 't {
pub fn text(&self) -> &'t R::Text {
self.text
}
pub fn regex(&self) -> &R {
&self.re
}
}
impl<'t, R> Iterator for Matches<'t, R>
where R: RegularExpression, R::Text: 't + AsRef<[u8]> {
type Item = (usize, usize);
fn next(&mut self) -> Option<(usize, usize)> {
if self.last_end > self.text.as_ref().len() {
return None;
}
let (s, e) = match self.re.find_at(self.text, self.last_end) {
None => return None,
Some((s, e)) => (s, e),
};
if s == e {
self.last_end = self.re.next_after_empty(&self.text, e);
if Some(e) == self.last_match {
return self.next();
}
} else {
self.last_end = e;
}
self.last_match = Some(e);
Some((s, e))
}
}
pub struct CaptureMatches<'t, R>(Matches<'t, R>)
where R: RegularExpression, R::Text: 't;
impl<'t, R> CaptureMatches<'t, R> where R: RegularExpression, R::Text: 't {
pub fn text(&self) -> &'t R::Text {
self.0.text()
}
pub fn regex(&self) -> &R {
self.0.regex()
}
}
impl<'t, R> Iterator for CaptureMatches<'t, R>
where R: RegularExpression, R::Text: 't + AsRef<[u8]> {
type Item = Locations;
fn next(&mut self) -> Option<Locations> {
if self.0.last_end > self.0.text.as_ref().len() {
return None
}
let mut locs = self.0.re.locations();
let (s, e) = match self.0.re.read_captures_at(
&mut locs,
self.0.text,
self.0.last_end,
) {
None => return None,
Some((s, e)) => (s, e),
};
if s == e {
self.0.last_end = self.0.re.next_after_empty(&self.0.text, e);
if Some(e) == self.0.last_match {
return self.next();
}
} else {
self.0.last_end = e;
}
self.0.last_match = Some(e);
Some(locs)
}
}