use libsugar::*;
use crate::*;
use std::ops::Range;
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Sub<T> {
sub: Vec<T>,
}
impl<T> Sub<T> {
#[inline]
pub const fn new(sub: Vec<T>) -> Self {
Self { sub }
}
}
impl<T, I: IntoIterator<Item = T>> From<I> for Sub<T> {
#[inline]
fn from(c: I) -> Self {
Self::new(c.into_iter().collect())
}
}
impl<I: TimeTravel, T> Parser<I> for Sub<T>
where
I::Item: PartialEq<T>,
{
type Output = Range<usize>;
fn parse(&self, mut input: I) -> Option<Self::Output> {
let from = input.save();
let pos: Option<usize> = {
let mut siter = self.sub.iter();
let mut i: usize = 0;
loop {
let io = input.next();
let so = siter.next();
bop!(!loop match && Some(a) = io, Some(b) = so => {
if PartialEq::<T>::ne(&a, b) {
break Some(i);
}
} else {
break None;
});
i += 1;
}
};
if let None = pos {
let pos = input.save() - from;
if self.sub.len() + 1 == pos {
return Some(from..input.save() - 1);
}
return if input.is_complete() {
if pos == self.sub.len() {
Some(input.make_range(from))
} else {
None
}
} else {
None
};
}
None
}
}
#[inline]
pub fn sub<T, I: IntoIterator<Item = T>>(c: I) -> Sub<T> {
Sub::from(c)
}
#[inline]
pub fn substr(c: &str) -> Sub<char> {
Sub::from(c.chars())
}
#[cfg(test)]
mod tests {
use crate::*;
#[test]
fn test() {
let code = "asd";
let span = code.span();
let x = substr("asd");
let r = x.parse(span);
println!("{:?}", r);
assert_eq!(r, Some(0..3));
}
#[test]
fn test_empty_code() {
let code = "";
let span = code.span();
let x = substr("asd");
let r = x.parse(span);
println!("{:?}", r);
assert_eq!(r, None);
}
#[test]
fn test_empty() {
let code = "asd";
let span = code.span();
let x = substr("");
let r = x.parse(span);
println!("{:?}", r);
assert_eq!(r, Some(0..0));
}
#[test]
fn test_one() {
let code = "asd";
let span = code.span();
let x = substr("a");
let r = x.parse(span);
println!("{:?}", r);
assert_eq!(r, Some(0..1));
}
#[test]
fn test_partial() {
let code = "asdqwe";
let span = code.span();
let x = substr("asd");
let r = x.parse(span);
println!("{:?}", r);
assert_eq!(r, Some(0..3));
}
#[test]
fn test_more() {
let code = "asd";
let span = code.span();
let x = substr("asdqwe");
let r = x.parse(span);
println!("{:?}", r);
assert_eq!(r, None);
}
#[test]
fn test_middle() {
let code = "asd";
let mut span = code.span();
let x = substr("s");
span.next();
let r = x.parse(span);
println!("{:?}", r);
assert_eq!(r, Some(1..2));
}
}