use crate::{MatchAble, MatchBy, MatchResult, MatchSignal, MatchStatus, Matcher};
#[allow(unused_imports)]
use crate::{MatchError, matcher};
#[inline]
pub fn matcher_for<'a, T: MatchAble + ?Sized + MatchBy<&'a M>, M: ?Sized>(
matching: &'a M,
) -> impl Matcher<T> {
move |v, i, s| v.match_by(matching, i, s)
}
pub fn consume<'a, T: MatchAble + ?Sized>(
value: &'a T, matcher: impl Matcher<T>,
) -> MatchResult<(T::Slice<'a>, T::Slice<'a>)> {
let mut ind = 0;
let sig = matcher.do_match(value, &mut ind, &MatchStatus::default());
if sig == MatchSignal::Matched {
Ok((value.slice(0..ind), value.slice(ind..value.len())))
} else {
Err(sig.into_err(ind))
}
}
#[inline]
pub fn by<T: MatchAble + ?Sized, F: Fn(&T, &mut usize, &MatchStatus) -> MatchSignal>(
matcher: F,
) -> F {
matcher
}
#[inline]
pub fn test<T: MatchAble + ?Sized>(
predicate: impl Fn(&T, &mut usize, &MatchStatus) -> bool,
) -> impl Matcher<T> {
move |v, i, s| {
if predicate(v, i, s) { MatchSignal::Matched } else { MatchSignal::MisMatched }
}
}
#[inline]
pub fn touch<T: MatchAble + ?Sized>(fun: impl Fn(&T, &mut usize, &MatchStatus)) -> impl Matcher<T> {
move |v, i, s| {
fun(v, i, s);
MatchSignal::Matched
}
}
#[inline]
pub fn a<T: MatchAble + ?Sized>(predicate: impl Fn(T::Slice<'_>) -> bool) -> impl Matcher<T> {
move |v, i, s| {
let slice = match v.get_n(i, 1, s) {
Ok(slice) => slice,
Err(sig) => return sig,
};
if predicate(slice) { MatchSignal::Matched } else { MatchSignal::MisMatched }
}
}
#[inline]
pub fn an<T: MatchAble + ?Sized>(
n: usize, predicate: impl Fn(T::Slice<'_>) -> bool,
) -> impl Matcher<T> {
move |v, i, s| {
let slice = match v.get_n(i, n, s) {
Ok(slice) => slice,
Err(sig) => return sig,
};
if predicate(slice) { MatchSignal::Matched } else { MatchSignal::MisMatched }
}
}
#[inline]
pub fn list<T: MatchAble + ?Sized>(
value: &T, item: impl Matcher<T>, sep: impl Matcher<T>, ind: &mut usize, status: &MatchStatus,
) -> MatchSignal {
let mut is_first = true;
loop {
let start_ind = *ind;
if !is_first && sep.do_match(value, ind, status) != MatchSignal::Matched {
*ind = start_ind;
return MatchSignal::Matched;
}
if item.do_match(value, ind, status) != MatchSignal::Matched {
*ind = start_ind;
return MatchSignal::Matched;
}
is_first = false;
}
}
#[inline]
pub fn eof<T: MatchAble + ?Sized>(value: &T, ind: &mut usize, status: &MatchStatus) -> MatchSignal {
let _ = status;
if *ind == value.len() { MatchSignal::Matched } else { MatchSignal::InComplete }
}
#[inline]
pub fn noop<T: MatchAble + ?Sized>(
value: &T, ind: &mut usize, status: &MatchStatus,
) -> MatchSignal {
let _ = (value, ind, status);
MatchSignal::Matched
}
#[inline]
pub fn fail<T: MatchAble + ?Sized>(
value: &T, ind: &mut usize, status: &MatchStatus,
) -> MatchSignal {
let _ = (value, ind, status);
MatchSignal::MisMatched
}
#[inline]
pub fn fail_with<T: MatchAble + ?Sized>(msg: &str) -> impl Matcher<T> {
move |_, ind, _| MatchSignal::Error(format!("{msg} at {ind}"))
}