use super::Matcher;
pub struct Repeat<T: Matcher>(T);
pub struct RepeatUntil<T: Matcher, U: Matcher> {
repeat: T,
until: U,
}
pub struct Repeat1<T: Matcher>(T);
pub struct Optional<T: Matcher>(T);
impl<T: Matcher> Repeat<T> {
pub fn new(repeat: T) -> Self {
Self(repeat)
}
}
impl<T: Matcher> Matcher for Repeat<T> {
fn match_with(&self, target: &str) -> Option<usize> {
let mut index = 0;
while let Some(len) = self.0.match_with(&target[index..])
&& len != 0
{
index += len;
}
Some(index)
}
fn capture<'a>(&self, target: &'a str) -> Option<(usize, Vec<&'a str>)> {
let mut index = 0;
let mut capture = Vec::new();
while let Some((len, mut cap)) = self.0.capture(&target[index..])
&& len != 0
{
index += len;
capture.append(&mut cap);
}
Some((index, capture))
}
}
impl<T: Matcher, U: Matcher> RepeatUntil<T, U> {
pub fn new(repeat: T, until: U) -> Self {
Self {
repeat: repeat,
until: until,
}
}
}
impl<T: Matcher, U: Matcher> Matcher for RepeatUntil<T, U> {
fn match_with(&self, target: &str) -> Option<usize> {
let mut index = 0;
loop {
if let Some(len) = self.until.match_with(&target[index..]) {
index += len;
break Some(index);
}
if let Some(len) = self.repeat.match_with(&target[index..])
&& len != 0
{
index += len;
} else {
break None;
}
}
}
fn capture<'a>(&self, target: &'a str) -> Option<(usize, Vec<&'a str>)> {
let mut captures = Vec::new();
let mut index = 0;
loop {
if let Some((len, mut cap)) = self.until.capture(&target[index..]) {
index += len;
captures.append(&mut cap);
break Some((index, captures));
}
if let Some((len, mut cap)) = self.repeat.capture(&target[index..])
&& len != 0
{
index += len;
captures.append(&mut cap);
} else {
break None;
}
}
}
}
impl<T: Matcher> Repeat1<T> {
pub fn new(repeat: T) -> Self {
Self(repeat)
}
}
impl<T: Matcher> Matcher for Repeat1<T> {
fn match_with(&self, target: &str) -> Option<usize> {
let mut index = 0;
while let Some(len) = self.0.match_with(&target[index..])
&& len != 0
{
index += len;
}
if index != 0 { Some(index) } else { None }
}
fn capture<'a>(&self, target: &'a str) -> Option<(usize, Vec<&'a str>)> {
let mut index = 0;
let mut capture = Vec::new();
while let Some((len, mut cap)) = self.0.capture(&target[index..])
&& len != 0
{
index += len;
capture.append(&mut cap);
}
if index != 0 {
Some((index, capture))
} else {
None
}
}
}
impl<T: Matcher> Optional<T> {
pub fn new(optional: T) -> Self {
Self(optional)
}
}
impl<T: Matcher> Matcher for Optional<T> {
fn match_with(&self, target: &str) -> Option<usize> {
self.0.match_with(target).or(Some(0))
}
fn capture<'a>(&self, target: &'a str) -> Option<(usize, Vec<&'a str>)> {
self.0.capture(target).or_else(|| Some((0, Vec::new())))
}
}